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 | |