| 1 |  | 
|---|
| 2 | #include <roaring/containers/containers.h> | 
|---|
| 3 |  | 
|---|
| 4 | extern inline const void *container_unwrap_shared( | 
|---|
| 5 | const void *candidate_shared_container, uint8_t *type); | 
|---|
| 6 | extern inline void *container_mutable_unwrap_shared( | 
|---|
| 7 | void *candidate_shared_container, uint8_t *type); | 
|---|
| 8 |  | 
|---|
| 9 | extern inline const char *get_container_name(uint8_t typecode); | 
|---|
| 10 |  | 
|---|
| 11 | extern inline int container_get_cardinality(const void *container, uint8_t typecode); | 
|---|
| 12 |  | 
|---|
| 13 | extern inline void *container_iand(void *c1, uint8_t type1, const void *c2, | 
|---|
| 14 | uint8_t type2, uint8_t *result_type); | 
|---|
| 15 |  | 
|---|
| 16 | extern inline void *container_ior(void *c1, uint8_t type1, const void *c2, | 
|---|
| 17 | uint8_t type2, uint8_t *result_type); | 
|---|
| 18 |  | 
|---|
| 19 | extern inline void *container_ixor(void *c1, uint8_t type1, const void *c2, | 
|---|
| 20 | uint8_t type2, uint8_t *result_type); | 
|---|
| 21 |  | 
|---|
| 22 | extern inline void *container_iandnot(void *c1, uint8_t type1, const void *c2, | 
|---|
| 23 | uint8_t type2, uint8_t *result_type); | 
|---|
| 24 |  | 
|---|
| 25 | void container_free(void *container, uint8_t typecode) { | 
|---|
| 26 | switch (typecode) { | 
|---|
| 27 | case BITSET_CONTAINER_TYPE_CODE: | 
|---|
| 28 | bitset_container_free((bitset_container_t *)container); | 
|---|
| 29 | break; | 
|---|
| 30 | case ARRAY_CONTAINER_TYPE_CODE: | 
|---|
| 31 | array_container_free((array_container_t *)container); | 
|---|
| 32 | break; | 
|---|
| 33 | case RUN_CONTAINER_TYPE_CODE: | 
|---|
| 34 | run_container_free((run_container_t *)container); | 
|---|
| 35 | break; | 
|---|
| 36 | case SHARED_CONTAINER_TYPE_CODE: | 
|---|
| 37 | shared_container_free((shared_container_t *)container); | 
|---|
| 38 | break; | 
|---|
| 39 | default: | 
|---|
| 40 | assert(false); | 
|---|
| 41 | __builtin_unreachable(); | 
|---|
| 42 | } | 
|---|
| 43 | } | 
|---|
| 44 |  | 
|---|
| 45 | void container_printf(const void *container, uint8_t typecode) { | 
|---|
| 46 | container = container_unwrap_shared(container, &typecode); | 
|---|
| 47 | switch (typecode) { | 
|---|
| 48 | case BITSET_CONTAINER_TYPE_CODE: | 
|---|
| 49 | bitset_container_printf((const bitset_container_t *)container); | 
|---|
| 50 | return; | 
|---|
| 51 | case ARRAY_CONTAINER_TYPE_CODE: | 
|---|
| 52 | array_container_printf((const array_container_t *)container); | 
|---|
| 53 | return; | 
|---|
| 54 | case RUN_CONTAINER_TYPE_CODE: | 
|---|
| 55 | run_container_printf((const run_container_t *)container); | 
|---|
| 56 | return; | 
|---|
| 57 | default: | 
|---|
| 58 | __builtin_unreachable(); | 
|---|
| 59 | } | 
|---|
| 60 | } | 
|---|
| 61 |  | 
|---|
| 62 | void container_printf_as_uint32_array(const void *container, uint8_t typecode, | 
|---|
| 63 | uint32_t base) { | 
|---|
| 64 | container = container_unwrap_shared(container, &typecode); | 
|---|
| 65 | switch (typecode) { | 
|---|
| 66 | case BITSET_CONTAINER_TYPE_CODE: | 
|---|
| 67 | bitset_container_printf_as_uint32_array( | 
|---|
| 68 | (const bitset_container_t *)container, base); | 
|---|
| 69 | return; | 
|---|
| 70 | case ARRAY_CONTAINER_TYPE_CODE: | 
|---|
| 71 | array_container_printf_as_uint32_array( | 
|---|
| 72 | (const array_container_t *)container, base); | 
|---|
| 73 | return; | 
|---|
| 74 | case RUN_CONTAINER_TYPE_CODE: | 
|---|
| 75 | run_container_printf_as_uint32_array( | 
|---|
| 76 | (const run_container_t *)container, base); | 
|---|
| 77 | return; | 
|---|
| 78 | return; | 
|---|
| 79 | default: | 
|---|
| 80 | __builtin_unreachable(); | 
|---|
| 81 | } | 
|---|
| 82 | } | 
|---|
| 83 |  | 
|---|
| 84 | int32_t container_serialize(const void *container, uint8_t typecode, | 
|---|
| 85 | char *buf) { | 
|---|
| 86 | container = container_unwrap_shared(container, &typecode); | 
|---|
| 87 | switch (typecode) { | 
|---|
| 88 | case BITSET_CONTAINER_TYPE_CODE: | 
|---|
| 89 | return (bitset_container_serialize((const bitset_container_t *)container, | 
|---|
| 90 | buf)); | 
|---|
| 91 | case ARRAY_CONTAINER_TYPE_CODE: | 
|---|
| 92 | return ( | 
|---|
| 93 | array_container_serialize((const array_container_t *)container, buf)); | 
|---|
| 94 | case RUN_CONTAINER_TYPE_CODE: | 
|---|
| 95 | return (run_container_serialize((const run_container_t *)container, buf)); | 
|---|
| 96 | default: | 
|---|
| 97 | assert(0); | 
|---|
| 98 | __builtin_unreachable(); | 
|---|
| 99 | return (-1); | 
|---|
| 100 | } | 
|---|
| 101 | } | 
|---|
| 102 |  | 
|---|
| 103 | uint32_t container_serialization_len(const void *container, uint8_t typecode) { | 
|---|
| 104 | container = container_unwrap_shared(container, &typecode); | 
|---|
| 105 | switch (typecode) { | 
|---|
| 106 | case BITSET_CONTAINER_TYPE_CODE: | 
|---|
| 107 | return bitset_container_serialization_len(); | 
|---|
| 108 | case ARRAY_CONTAINER_TYPE_CODE: | 
|---|
| 109 | return array_container_serialization_len( | 
|---|
| 110 | (const array_container_t *)container); | 
|---|
| 111 | case RUN_CONTAINER_TYPE_CODE: | 
|---|
| 112 | return run_container_serialization_len( | 
|---|
| 113 | (const run_container_t *)container); | 
|---|
| 114 | default: | 
|---|
| 115 | assert(0); | 
|---|
| 116 | __builtin_unreachable(); | 
|---|
| 117 | return (0); | 
|---|
| 118 | } | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|
| 121 | void *container_deserialize(uint8_t typecode, const char *buf, size_t buf_len) { | 
|---|
| 122 | switch (typecode) { | 
|---|
| 123 | case BITSET_CONTAINER_TYPE_CODE: | 
|---|
| 124 | return (bitset_container_deserialize(buf, buf_len)); | 
|---|
| 125 | case ARRAY_CONTAINER_TYPE_CODE: | 
|---|
| 126 | return (array_container_deserialize(buf, buf_len)); | 
|---|
| 127 | case RUN_CONTAINER_TYPE_CODE: | 
|---|
| 128 | return (run_container_deserialize(buf, buf_len)); | 
|---|
| 129 | case SHARED_CONTAINER_TYPE_CODE: | 
|---|
| 130 | printf( "this should never happen.\n"); | 
|---|
| 131 | assert(0); | 
|---|
| 132 | __builtin_unreachable(); | 
|---|
| 133 | return (NULL); | 
|---|
| 134 | default: | 
|---|
| 135 | assert(0); | 
|---|
| 136 | __builtin_unreachable(); | 
|---|
| 137 | return (NULL); | 
|---|
| 138 | } | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | extern inline bool container_nonzero_cardinality(const void *container, | 
|---|
| 142 | uint8_t typecode); | 
|---|
| 143 |  | 
|---|
| 144 |  | 
|---|
| 145 | extern inline int container_to_uint32_array(uint32_t *output, const void *container, | 
|---|
| 146 | uint8_t typecode, uint32_t base); | 
|---|
| 147 |  | 
|---|
| 148 | extern inline void *container_add(void *container, uint16_t val, uint8_t typecode, | 
|---|
| 149 | uint8_t *new_typecode); | 
|---|
| 150 |  | 
|---|
| 151 | extern inline bool container_contains(const void *container, uint16_t val, | 
|---|
| 152 | uint8_t typecode); | 
|---|
| 153 |  | 
|---|
| 154 | extern inline void *container_clone(const void *container, uint8_t typecode); | 
|---|
| 155 |  | 
|---|
| 156 | extern inline void *container_and(const void *c1, uint8_t type1, const void *c2, | 
|---|
| 157 | uint8_t type2, uint8_t *result_type); | 
|---|
| 158 |  | 
|---|
| 159 | extern inline void *container_or(const void *c1, uint8_t type1, const void *c2, | 
|---|
| 160 | uint8_t type2, uint8_t *result_type); | 
|---|
| 161 |  | 
|---|
| 162 | extern inline void *container_xor(const void *c1, uint8_t type1, const void *c2, | 
|---|
| 163 | uint8_t type2, uint8_t *result_type); | 
|---|
| 164 |  | 
|---|
| 165 | void *get_copy_of_container(void *container, uint8_t *typecode, | 
|---|
| 166 | bool copy_on_write) { | 
|---|
| 167 | if (copy_on_write) { | 
|---|
| 168 | shared_container_t *shared_container; | 
|---|
| 169 | if (*typecode == SHARED_CONTAINER_TYPE_CODE) { | 
|---|
| 170 | shared_container = (shared_container_t *)container; | 
|---|
| 171 | shared_container->counter += 1; | 
|---|
| 172 | return shared_container; | 
|---|
| 173 | } | 
|---|
| 174 | assert(*typecode != SHARED_CONTAINER_TYPE_CODE); | 
|---|
| 175 |  | 
|---|
| 176 | if ((shared_container = (shared_container_t *)malloc( | 
|---|
| 177 | sizeof(shared_container_t))) == NULL) { | 
|---|
| 178 | return NULL; | 
|---|
| 179 | } | 
|---|
| 180 |  | 
|---|
| 181 | shared_container->container = container; | 
|---|
| 182 | shared_container->typecode = *typecode; | 
|---|
| 183 |  | 
|---|
| 184 | shared_container->counter = 2; | 
|---|
| 185 | *typecode = SHARED_CONTAINER_TYPE_CODE; | 
|---|
| 186 |  | 
|---|
| 187 | return shared_container; | 
|---|
| 188 | }  // copy_on_write | 
|---|
| 189 | // otherwise, no copy on write... | 
|---|
| 190 | const void *actualcontainer = | 
|---|
| 191 | container_unwrap_shared((const void *)container, typecode); | 
|---|
| 192 | assert(*typecode != SHARED_CONTAINER_TYPE_CODE); | 
|---|
| 193 | return container_clone(actualcontainer, *typecode); | 
|---|
| 194 | } | 
|---|
| 195 | /** | 
|---|
| 196 | * Copies a container, requires a typecode. This allocates new memory, caller | 
|---|
| 197 | * is responsible for deallocation. | 
|---|
| 198 | */ | 
|---|
| 199 | void *container_clone(const void *container, uint8_t typecode) { | 
|---|
| 200 | container = container_unwrap_shared(container, &typecode); | 
|---|
| 201 | switch (typecode) { | 
|---|
| 202 | case BITSET_CONTAINER_TYPE_CODE: | 
|---|
| 203 | return bitset_container_clone((const bitset_container_t *)container); | 
|---|
| 204 | case ARRAY_CONTAINER_TYPE_CODE: | 
|---|
| 205 | return array_container_clone((const array_container_t *)container); | 
|---|
| 206 | case RUN_CONTAINER_TYPE_CODE: | 
|---|
| 207 | return run_container_clone((const run_container_t *)container); | 
|---|
| 208 | case SHARED_CONTAINER_TYPE_CODE: | 
|---|
| 209 | printf( "shared containers are not cloneable\n"); | 
|---|
| 210 | assert(false); | 
|---|
| 211 | return NULL; | 
|---|
| 212 | default: | 
|---|
| 213 | assert(false); | 
|---|
| 214 | __builtin_unreachable(); | 
|---|
| 215 | return NULL; | 
|---|
| 216 | } | 
|---|
| 217 | } | 
|---|
| 218 |  | 
|---|
| 219 | void *(shared_container_t *container, | 
|---|
| 220 | uint8_t *typecode) { | 
|---|
| 221 | assert(container->counter > 0); | 
|---|
| 222 | assert(container->typecode != SHARED_CONTAINER_TYPE_CODE); | 
|---|
| 223 | container->counter--; | 
|---|
| 224 | *typecode = container->typecode; | 
|---|
| 225 | void *answer; | 
|---|
| 226 | if (container->counter == 0) { | 
|---|
| 227 | answer = container->container; | 
|---|
| 228 | container->container = NULL;  // paranoid | 
|---|
| 229 | free(container); | 
|---|
| 230 | } else { | 
|---|
| 231 | answer = container_clone(container->container, *typecode); | 
|---|
| 232 | } | 
|---|
| 233 | assert(*typecode != SHARED_CONTAINER_TYPE_CODE); | 
|---|
| 234 | return answer; | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | void shared_container_free(shared_container_t *container) { | 
|---|
| 238 | assert(container->counter > 0); | 
|---|
| 239 | container->counter--; | 
|---|
| 240 | if (container->counter == 0) { | 
|---|
| 241 | assert(container->typecode != SHARED_CONTAINER_TYPE_CODE); | 
|---|
| 242 | container_free(container->container, container->typecode); | 
|---|
| 243 | container->container = NULL;  // paranoid | 
|---|
| 244 | free(container); | 
|---|
| 245 | } | 
|---|
| 246 | } | 
|---|
| 247 |  | 
|---|
| 248 | extern inline void *container_not(const void *c1, uint8_t type1, uint8_t *result_type); | 
|---|
| 249 |  | 
|---|
| 250 | extern inline void *container_not_range(const void *c1, uint8_t type1, | 
|---|
| 251 | uint32_t range_start, uint32_t range_end, | 
|---|
| 252 | uint8_t *result_type); | 
|---|
| 253 |  | 
|---|
| 254 | extern inline void *container_inot(void *c1, uint8_t type1, uint8_t *result_type); | 
|---|
| 255 |  | 
|---|
| 256 | extern inline void *container_inot_range(void *c1, uint8_t type1, uint32_t range_start, | 
|---|
| 257 | uint32_t range_end, uint8_t *result_type); | 
|---|
| 258 |  | 
|---|
| 259 | extern inline void *container_range_of_ones(uint32_t range_start, uint32_t range_end, | 
|---|
| 260 | uint8_t *result_type); | 
|---|
| 261 |  | 
|---|
| 262 | // where are the correponding things for union and intersection?? | 
|---|
| 263 | extern inline void *container_lazy_xor(const void *c1, uint8_t type1, const void *c2, | 
|---|
| 264 | uint8_t type2, uint8_t *result_type); | 
|---|
| 265 |  | 
|---|
| 266 | extern inline void *container_lazy_ixor(void *c1, uint8_t type1, const void *c2, | 
|---|
| 267 | uint8_t type2, uint8_t *result_type); | 
|---|
| 268 |  | 
|---|
| 269 | extern inline void *container_andnot(const void *c1, uint8_t type1, const void *c2, | 
|---|
| 270 | uint8_t type2, uint8_t *result_type); | 
|---|
| 271 |  | 
|---|