1
2#include <roaring/containers/containers.h>
3
4extern inline const void *container_unwrap_shared(
5 const void *candidate_shared_container, uint8_t *type);
6extern inline void *container_mutable_unwrap_shared(
7 void *candidate_shared_container, uint8_t *type);
8
9extern inline const char *get_container_name(uint8_t typecode);
10
11extern inline int container_get_cardinality(const void *container, uint8_t typecode);
12
13extern inline void *container_iand(void *c1, uint8_t type1, const void *c2,
14 uint8_t type2, uint8_t *result_type);
15
16extern inline void *container_ior(void *c1, uint8_t type1, const void *c2,
17 uint8_t type2, uint8_t *result_type);
18
19extern inline void *container_ixor(void *c1, uint8_t type1, const void *c2,
20 uint8_t type2, uint8_t *result_type);
21
22extern inline void *container_iandnot(void *c1, uint8_t type1, const void *c2,
23 uint8_t type2, uint8_t *result_type);
24
25void 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
45void 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
62void 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
84int32_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
103uint32_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
121void *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
141extern inline bool container_nonzero_cardinality(const void *container,
142 uint8_t typecode);
143
144
145extern inline int container_to_uint32_array(uint32_t *output, const void *container,
146 uint8_t typecode, uint32_t base);
147
148extern inline void *container_add(void *container, uint16_t val, uint8_t typecode,
149 uint8_t *new_typecode);
150
151extern inline bool container_contains(const void *container, uint16_t val,
152 uint8_t typecode);
153
154extern inline void *container_clone(const void *container, uint8_t typecode);
155
156extern inline void *container_and(const void *c1, uint8_t type1, const void *c2,
157 uint8_t type2, uint8_t *result_type);
158
159extern inline void *container_or(const void *c1, uint8_t type1, const void *c2,
160 uint8_t type2, uint8_t *result_type);
161
162extern inline void *container_xor(const void *c1, uint8_t type1, const void *c2,
163 uint8_t type2, uint8_t *result_type);
164
165void *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 */
199void *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
219void *shared_container_extract_copy(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
237void 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
248extern inline void *container_not(const void *c1, uint8_t type1, uint8_t *result_type);
249
250extern 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
254extern inline void *container_inot(void *c1, uint8_t type1, uint8_t *result_type);
255
256extern inline void *container_inot_range(void *c1, uint8_t type1, uint32_t range_start,
257 uint32_t range_end, uint8_t *result_type);
258
259extern 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??
263extern inline void *container_lazy_xor(const void *c1, uint8_t type1, const void *c2,
264 uint8_t type2, uint8_t *result_type);
265
266extern inline void *container_lazy_ixor(void *c1, uint8_t type1, const void *c2,
267 uint8_t type2, uint8_t *result_type);
268
269extern inline void *container_andnot(const void *c1, uint8_t type1, const void *c2,
270 uint8_t type2, uint8_t *result_type);
271