Coverage Report

Created: 2026-05-30 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/croaring/include/roaring/containers/containers.h
Line
Count
Source
1
/*
2
 * containers.h
3
 *
4
 * This header is the central internal interface for Roaring container
5
 * operations. It ties together the concrete container types (array, bitset,
6
 * run, and shared containers), their type codes, common helper functions, and
7
 * the mixed-operation headers used to combine different representations.
8
 *
9
 * In practice, it acts as the dispatch layer that lets higher-level bitmap
10
 * code manipulate containers through a uniform interface while still selecting
11
 * type-specific implementations when needed.
12
 */
13
#ifndef CONTAINERS_CONTAINERS_H
14
#define CONTAINERS_CONTAINERS_H
15
16
#include <assert.h>
17
#include <stdbool.h>
18
#include <stdio.h>
19
20
#include <roaring/bitset_util.h>
21
#include <roaring/containers/array.h>
22
#include <roaring/containers/bitset.h>
23
#include <roaring/containers/convert.h>
24
#include <roaring/containers/mixed_andnot.h>
25
#include <roaring/containers/mixed_equal.h>
26
#include <roaring/containers/mixed_intersection.h>
27
#include <roaring/containers/mixed_negation.h>
28
#include <roaring/containers/mixed_subset.h>
29
#include <roaring/containers/mixed_union.h>
30
#include <roaring/containers/mixed_xor.h>
31
#include <roaring/containers/run.h>
32
33
#ifdef __cplusplus
34
extern "C" {
35
namespace roaring {
36
namespace internal {
37
#endif
38
39
// would enum be possible or better?
40
41
/**
42
 * The switch case statements follow
43
 * BITSET_CONTAINER_TYPE -- ARRAY_CONTAINER_TYPE -- RUN_CONTAINER_TYPE
44
 * so it makes more sense to number them 1, 2, 3 (in the vague hope that the
45
 * compiler might exploit this ordering).
46
 */
47
48
0
#define BITSET_CONTAINER_TYPE 1
49
0
#define ARRAY_CONTAINER_TYPE 2
50
0
#define RUN_CONTAINER_TYPE 3
51
0
#define SHARED_CONTAINER_TYPE 4
52
53
/**
54
 * Macros for pairing container type codes, suitable for switch statements.
55
 * Use PAIR_CONTAINER_TYPES() for the switch, CONTAINER_PAIR() for the cases:
56
 *
57
 *     switch (PAIR_CONTAINER_TYPES(type1, type2)) {
58
 *        case CONTAINER_PAIR(BITSET,ARRAY):
59
 *        ...
60
 *     }
61
 */
62
0
#define PAIR_CONTAINER_TYPES(type1, type2) (4 * (type1) + (type2))
63
64
#define CONTAINER_PAIR(name1, name2) \
65
0
    (4 * (name1##_CONTAINER_TYPE) + (name2##_CONTAINER_TYPE))
66
67
/**
68
 * A shared container is a wrapper around a container
69
 * with reference counting.
70
 */
71
STRUCT_CONTAINER(shared_container_s) {
72
    container_t *container;
73
    uint8_t typecode;
74
    croaring_refcount_t counter;  // to be managed atomically
75
};
76
77
typedef struct shared_container_s shared_container_t;
78
79
0
#define CAST_shared(c) CAST(shared_container_t *, c)  // safer downcast
80
0
#define const_CAST_shared(c) CAST(const shared_container_t *, c)
81
#define movable_CAST_shared(c) movable_CAST(shared_container_t **, c)
82
83
/*
84
 * With copy_on_write = true
85
 *  Create a new shared container if the typecode is not SHARED_CONTAINER_TYPE,
86
 * otherwise, increase the count
87
 * If copy_on_write = false, then clone.
88
 * Return NULL in case of failure.
89
 **/
90
container_t *get_copy_of_container(container_t *container, uint8_t *typecode,
91
                                   bool copy_on_write);
92
93
/* Frees a shared container (actually decrement its counter and only frees when
94
 * the counter falls to zero). */
95
void shared_container_free(shared_container_t *container);
96
97
/* extract a copy from the shared container, freeing the shared container if
98
there is just one instance left,
99
clone instances when the counter is higher than one
100
*/
101
container_t *shared_container_extract_copy(shared_container_t *container,
102
                                           uint8_t *typecode);
103
104
/* access to container underneath */
105
static inline const container_t *container_unwrap_shared(
106
0
    const container_t *candidate_shared_container, uint8_t *type) {
107
0
    if (*type == SHARED_CONTAINER_TYPE) {
108
0
        *type = const_CAST_shared(candidate_shared_container)->typecode;
109
0
        assert(*type != SHARED_CONTAINER_TYPE);
110
0
        return const_CAST_shared(candidate_shared_container)->container;
111
0
    } else {
112
0
        return candidate_shared_container;
113
0
    }
114
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_unwrap_shared
Unexecuted instantiation: containers.c:container_unwrap_shared
Unexecuted instantiation: roaring.c:container_unwrap_shared
Unexecuted instantiation: roaring64.c:container_unwrap_shared
Unexecuted instantiation: roaring_array.c:container_unwrap_shared
Unexecuted instantiation: convert.c:container_unwrap_shared
Unexecuted instantiation: mixed_negation.c:container_unwrap_shared
Unexecuted instantiation: mixed_xor.c:container_unwrap_shared
Unexecuted instantiation: mixed_andnot.c:container_unwrap_shared
115
116
/* access to container underneath */
117
static inline container_t *container_mutable_unwrap_shared(container_t *c,
118
0
                                                           uint8_t *type) {
119
0
    if (*type == SHARED_CONTAINER_TYPE) {  // the passed in container is shared
120
0
        *type = CAST_shared(c)->typecode;
121
0
        assert(*type != SHARED_CONTAINER_TYPE);
122
0
        return CAST_shared(c)->container;  // return the enclosed container
123
0
    } else {
124
0
        return c;  // wasn't shared, so return as-is
125
0
    }
126
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_mutable_unwrap_shared
Unexecuted instantiation: containers.c:container_mutable_unwrap_shared
Unexecuted instantiation: roaring.c:container_mutable_unwrap_shared
Unexecuted instantiation: roaring64.c:container_mutable_unwrap_shared
Unexecuted instantiation: roaring_array.c:container_mutable_unwrap_shared
Unexecuted instantiation: convert.c:container_mutable_unwrap_shared
Unexecuted instantiation: mixed_negation.c:container_mutable_unwrap_shared
Unexecuted instantiation: mixed_xor.c:container_mutable_unwrap_shared
Unexecuted instantiation: mixed_andnot.c:container_mutable_unwrap_shared
127
128
/* access to container underneath and queries its type */
129
0
static inline uint8_t get_container_type(const container_t *c, uint8_t type) {
130
0
    if (type == SHARED_CONTAINER_TYPE) {
131
0
        return const_CAST_shared(c)->typecode;
132
0
    } else {
133
0
        return type;
134
0
    }
135
0
}
Unexecuted instantiation: croaring_fuzzer.c:get_container_type
Unexecuted instantiation: containers.c:get_container_type
Unexecuted instantiation: roaring.c:get_container_type
Unexecuted instantiation: roaring64.c:get_container_type
Unexecuted instantiation: roaring_array.c:get_container_type
Unexecuted instantiation: convert.c:get_container_type
Unexecuted instantiation: mixed_negation.c:get_container_type
Unexecuted instantiation: mixed_xor.c:get_container_type
Unexecuted instantiation: mixed_andnot.c:get_container_type
136
137
/**
138
 * Copies a container, requires a typecode. This allocates new memory, caller
139
 * is responsible for deallocation. If the container is not shared, then it is
140
 * physically cloned. Sharable containers are not cloneable.
141
 */
142
container_t *container_clone(const container_t *container, uint8_t typecode);
143
144
/* access to container underneath, cloning it if needed */
145
static inline container_t *get_writable_copy_if_shared(container_t *c,
146
0
                                                       uint8_t *type) {
147
0
    if (*type == SHARED_CONTAINER_TYPE) {  // shared, return enclosed container
148
0
        return shared_container_extract_copy(CAST_shared(c), type);
149
0
    } else {
150
0
        return c;  // not shared, so return as-is
151
0
    }
152
0
}
Unexecuted instantiation: croaring_fuzzer.c:get_writable_copy_if_shared
Unexecuted instantiation: containers.c:get_writable_copy_if_shared
Unexecuted instantiation: roaring.c:get_writable_copy_if_shared
Unexecuted instantiation: roaring64.c:get_writable_copy_if_shared
Unexecuted instantiation: roaring_array.c:get_writable_copy_if_shared
Unexecuted instantiation: convert.c:get_writable_copy_if_shared
Unexecuted instantiation: mixed_negation.c:get_writable_copy_if_shared
Unexecuted instantiation: mixed_xor.c:get_writable_copy_if_shared
Unexecuted instantiation: mixed_andnot.c:get_writable_copy_if_shared
153
154
/**
155
 * End of shared container code
156
 */
157
158
static const char *container_names[] = {"bitset", "array", "run", "shared"};
159
static const char *shared_container_names[] = {
160
    "bitset (shared)", "array (shared)", "run (shared)"};
161
162
// no matter what the initial container was, convert it to a bitset
163
// if a new container is produced, caller responsible for freeing the previous
164
// one
165
// container should not be a shared container
166
static inline bitset_container_t *container_to_bitset(container_t *c,
167
0
                                                      uint8_t typecode) {
168
0
    bitset_container_t *result = NULL;
169
0
    switch (typecode) {
170
0
        case BITSET_CONTAINER_TYPE:
171
0
            return CAST_bitset(c);  // nothing to do
172
0
        case ARRAY_CONTAINER_TYPE:
173
0
            result = bitset_container_from_array(CAST_array(c));
174
0
            return result;
175
0
        case RUN_CONTAINER_TYPE:
176
0
            result = bitset_container_from_run(CAST_run(c));
177
0
            return result;
178
0
        case SHARED_CONTAINER_TYPE:
179
0
            assert(false);
180
0
            roaring_unreachable;
181
0
    }
182
0
    assert(false);
183
0
    roaring_unreachable;
184
0
    return 0;  // unreached
185
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_to_bitset
Unexecuted instantiation: containers.c:container_to_bitset
Unexecuted instantiation: roaring.c:container_to_bitset
Unexecuted instantiation: roaring64.c:container_to_bitset
Unexecuted instantiation: roaring_array.c:container_to_bitset
Unexecuted instantiation: convert.c:container_to_bitset
Unexecuted instantiation: mixed_negation.c:container_to_bitset
Unexecuted instantiation: mixed_xor.c:container_to_bitset
Unexecuted instantiation: mixed_andnot.c:container_to_bitset
186
187
/**
188
 * Get the container name from the typecode
189
 * (unused at time of writing)
190
 */
191
/*static inline const char *get_container_name(uint8_t typecode) {
192
    switch (typecode) {
193
        case BITSET_CONTAINER_TYPE:
194
            return container_names[0];
195
        case ARRAY_CONTAINER_TYPE:
196
            return container_names[1];
197
        case RUN_CONTAINER_TYPE:
198
            return container_names[2];
199
        case SHARED_CONTAINER_TYPE:
200
            return container_names[3];
201
        default:
202
            assert(false);
203
            roaring_unreachable;
204
            return "unknown";
205
    }
206
}*/
207
208
static inline const char *get_full_container_name(const container_t *c,
209
0
                                                  uint8_t typecode) {
210
0
    switch (typecode) {
211
0
        case BITSET_CONTAINER_TYPE:
212
0
            return container_names[0];
213
0
        case ARRAY_CONTAINER_TYPE:
214
0
            return container_names[1];
215
0
        case RUN_CONTAINER_TYPE:
216
0
            return container_names[2];
217
0
        case SHARED_CONTAINER_TYPE:
218
0
            switch (const_CAST_shared(c)->typecode) {
219
0
                case BITSET_CONTAINER_TYPE:
220
0
                    return shared_container_names[0];
221
0
                case ARRAY_CONTAINER_TYPE:
222
0
                    return shared_container_names[1];
223
0
                case RUN_CONTAINER_TYPE:
224
0
                    return shared_container_names[2];
225
0
                default:
226
0
                    assert(false);
227
0
                    roaring_unreachable;
228
0
                    return "unknown";
229
0
            }
230
0
            break;
231
0
        default:
232
0
            assert(false);
233
0
            roaring_unreachable;
234
0
            return "unknown";
235
0
    }
236
0
    roaring_unreachable;
237
0
    return NULL;
238
0
}
Unexecuted instantiation: croaring_fuzzer.c:get_full_container_name
Unexecuted instantiation: containers.c:get_full_container_name
Unexecuted instantiation: roaring.c:get_full_container_name
Unexecuted instantiation: roaring64.c:get_full_container_name
Unexecuted instantiation: roaring_array.c:get_full_container_name
Unexecuted instantiation: convert.c:get_full_container_name
Unexecuted instantiation: mixed_negation.c:get_full_container_name
Unexecuted instantiation: mixed_xor.c:get_full_container_name
Unexecuted instantiation: mixed_andnot.c:get_full_container_name
239
240
/**
241
 * Get the container cardinality (number of elements), requires a  typecode
242
 */
243
static inline int container_get_cardinality(const container_t *c,
244
0
                                            uint8_t typecode) {
245
0
    c = container_unwrap_shared(c, &typecode);
246
0
    switch (typecode) {
247
0
        case BITSET_CONTAINER_TYPE:
248
0
            return bitset_container_cardinality(const_CAST_bitset(c));
249
0
        case ARRAY_CONTAINER_TYPE:
250
0
            return array_container_cardinality(const_CAST_array(c));
251
0
        case RUN_CONTAINER_TYPE:
252
0
            return run_container_cardinality(const_CAST_run(c));
253
0
    }
254
0
    assert(false);
255
0
    roaring_unreachable;
256
0
    return 0;  // unreached
257
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_get_cardinality
Unexecuted instantiation: containers.c:container_get_cardinality
Unexecuted instantiation: roaring.c:container_get_cardinality
Unexecuted instantiation: roaring64.c:container_get_cardinality
Unexecuted instantiation: roaring_array.c:container_get_cardinality
Unexecuted instantiation: convert.c:container_get_cardinality
Unexecuted instantiation: mixed_negation.c:container_get_cardinality
Unexecuted instantiation: mixed_xor.c:container_get_cardinality
Unexecuted instantiation: mixed_andnot.c:container_get_cardinality
258
259
// returns true if a container is known to be full. Note that a lazy bitset
260
// container
261
// might be full without us knowing
262
0
static inline bool container_is_full(const container_t *c, uint8_t typecode) {
263
0
    c = container_unwrap_shared(c, &typecode);
264
0
    switch (typecode) {
265
0
        case BITSET_CONTAINER_TYPE:
266
0
            return bitset_container_cardinality(const_CAST_bitset(c)) ==
267
0
                   (1 << 16);
268
0
        case ARRAY_CONTAINER_TYPE:
269
0
            return array_container_cardinality(const_CAST_array(c)) ==
270
0
                   (1 << 16);
271
0
        case RUN_CONTAINER_TYPE:
272
0
            return run_container_is_full(const_CAST_run(c));
273
0
    }
274
0
    assert(false);
275
0
    roaring_unreachable;
276
0
    return 0;  // unreached
277
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_is_full
Unexecuted instantiation: containers.c:container_is_full
Unexecuted instantiation: roaring.c:container_is_full
Unexecuted instantiation: roaring64.c:container_is_full
Unexecuted instantiation: roaring_array.c:container_is_full
Unexecuted instantiation: convert.c:container_is_full
Unexecuted instantiation: mixed_negation.c:container_is_full
Unexecuted instantiation: mixed_xor.c:container_is_full
Unexecuted instantiation: mixed_andnot.c:container_is_full
278
279
0
static inline int container_shrink_to_fit(container_t *c, uint8_t type) {
280
0
    c = container_mutable_unwrap_shared(c, &type);
281
0
    switch (type) {
282
0
        case BITSET_CONTAINER_TYPE:
283
0
            return 0;  // no shrinking possible
284
0
        case ARRAY_CONTAINER_TYPE:
285
0
            return array_container_shrink_to_fit(CAST_array(c));
286
0
        case RUN_CONTAINER_TYPE:
287
0
            return run_container_shrink_to_fit(CAST_run(c));
288
0
    }
289
0
    assert(false);
290
0
    roaring_unreachable;
291
0
    return 0;  // unreached
292
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_shrink_to_fit
Unexecuted instantiation: containers.c:container_shrink_to_fit
Unexecuted instantiation: roaring.c:container_shrink_to_fit
Unexecuted instantiation: roaring64.c:container_shrink_to_fit
Unexecuted instantiation: roaring_array.c:container_shrink_to_fit
Unexecuted instantiation: convert.c:container_shrink_to_fit
Unexecuted instantiation: mixed_negation.c:container_shrink_to_fit
Unexecuted instantiation: mixed_xor.c:container_shrink_to_fit
Unexecuted instantiation: mixed_andnot.c:container_shrink_to_fit
293
294
/**
295
 * make a container with a run of ones
296
 */
297
/* initially always use a run container, even if an array might be
298
 * marginally
299
 * smaller */
300
static inline container_t *container_range_of_ones(uint32_t range_start,
301
                                                   uint32_t range_end,
302
0
                                                   uint8_t *result_type) {
303
0
    assert(range_end >= range_start);
304
0
    uint64_t cardinality = range_end - range_start + 1;
305
0
    if (cardinality <= 2) {
306
0
        *result_type = ARRAY_CONTAINER_TYPE;
307
0
        return array_container_create_range(range_start, range_end);
308
0
    } else {
309
0
        *result_type = RUN_CONTAINER_TYPE;
310
0
        return run_container_create_range(range_start, range_end);
311
0
    }
312
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_range_of_ones
Unexecuted instantiation: containers.c:container_range_of_ones
Unexecuted instantiation: roaring.c:container_range_of_ones
Unexecuted instantiation: roaring64.c:container_range_of_ones
Unexecuted instantiation: roaring_array.c:container_range_of_ones
Unexecuted instantiation: convert.c:container_range_of_ones
Unexecuted instantiation: mixed_negation.c:container_range_of_ones
Unexecuted instantiation: mixed_xor.c:container_range_of_ones
Unexecuted instantiation: mixed_andnot.c:container_range_of_ones
313
314
/*  Create a container with all the values between in [min,max) at a
315
    distance k*step from min. */
316
static inline container_t *container_from_range(uint8_t *type, uint32_t min,
317
0
                                                uint32_t max, uint16_t step) {
318
0
    if (step == 0) return NULL;  // being paranoid
319
0
    if (step == 1) {
320
0
        return container_range_of_ones(min, max, type);
321
        // Note: the result is not always a run (need to check the cardinality)
322
        //*type = RUN_CONTAINER_TYPE;
323
        // return run_container_create_range(min, max);
324
0
    }
325
0
    int size = (max - min + step - 1) / step;
326
0
    if (size <= DEFAULT_MAX_SIZE) {  // array container
327
0
        *type = ARRAY_CONTAINER_TYPE;
328
0
        array_container_t *array = array_container_create_given_capacity(size);
329
0
        array_container_add_from_range(array, min, max, step);
330
0
        assert(array->cardinality == size);
331
0
        return array;
332
0
    } else {  // bitset container
333
0
        *type = BITSET_CONTAINER_TYPE;
334
0
        bitset_container_t *bitset = bitset_container_create();
335
0
        bitset_container_add_from_range(bitset, min, max, step);
336
0
        assert(bitset->cardinality == size);
337
0
        return bitset;
338
0
    }
339
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_from_range
Unexecuted instantiation: containers.c:container_from_range
Unexecuted instantiation: roaring.c:container_from_range
Unexecuted instantiation: roaring64.c:container_from_range
Unexecuted instantiation: roaring_array.c:container_from_range
Unexecuted instantiation: convert.c:container_from_range
Unexecuted instantiation: mixed_negation.c:container_from_range
Unexecuted instantiation: mixed_xor.c:container_from_range
Unexecuted instantiation: mixed_andnot.c:container_from_range
340
341
/**
342
 * "repair" the container after lazy operations.
343
 */
344
static inline container_t *container_repair_after_lazy(container_t *c,
345
0
                                                       uint8_t *type) {
346
0
    c = get_writable_copy_if_shared(c, type);  // !!! unnecessary cloning
347
0
    container_t *result = NULL;
348
0
    switch (*type) {
349
0
        case BITSET_CONTAINER_TYPE: {
350
0
            bitset_container_t *bc = CAST_bitset(c);
351
0
            bc->cardinality = bitset_container_compute_cardinality(bc);
352
0
            if (bc->cardinality <= DEFAULT_MAX_SIZE) {
353
0
                result = array_container_from_bitset(bc);
354
0
                bitset_container_free(bc);
355
0
                *type = ARRAY_CONTAINER_TYPE;
356
0
                return result;
357
0
            }
358
0
            return c;
359
0
        }
360
0
        case ARRAY_CONTAINER_TYPE:
361
0
            return c;  // nothing to do
362
0
        case RUN_CONTAINER_TYPE:
363
0
            return convert_run_to_efficient_container_and_free(CAST_run(c),
364
0
                                                               type);
365
0
        case SHARED_CONTAINER_TYPE:
366
0
            assert(false);
367
0
    }
368
0
    assert(false);
369
0
    roaring_unreachable;
370
0
    return 0;  // unreached
371
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_repair_after_lazy
Unexecuted instantiation: containers.c:container_repair_after_lazy
Unexecuted instantiation: roaring.c:container_repair_after_lazy
Unexecuted instantiation: roaring64.c:container_repair_after_lazy
Unexecuted instantiation: roaring_array.c:container_repair_after_lazy
Unexecuted instantiation: convert.c:container_repair_after_lazy
Unexecuted instantiation: mixed_negation.c:container_repair_after_lazy
Unexecuted instantiation: mixed_xor.c:container_repair_after_lazy
Unexecuted instantiation: mixed_andnot.c:container_repair_after_lazy
372
373
/**
374
 * Writes the underlying array to buf, outputs how many bytes were written.
375
 * This is meant to be byte-by-byte compatible with the Java and Go versions of
376
 * Roaring.
377
 * The number of bytes written should be
378
 * container_write(container, buf).
379
 *
380
 */
381
static inline int32_t container_write(const container_t *c, uint8_t typecode,
382
0
                                      char *buf) {
383
0
    c = container_unwrap_shared(c, &typecode);
384
0
    switch (typecode) {
385
0
        case BITSET_CONTAINER_TYPE:
386
0
            return bitset_container_write(const_CAST_bitset(c), buf);
387
0
        case ARRAY_CONTAINER_TYPE:
388
0
            return array_container_write(const_CAST_array(c), buf);
389
0
        case RUN_CONTAINER_TYPE:
390
0
            return run_container_write(const_CAST_run(c), buf);
391
0
    }
392
0
    assert(false);
393
0
    roaring_unreachable;
394
0
    return 0;  // unreached
395
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_write
Unexecuted instantiation: containers.c:container_write
Unexecuted instantiation: roaring.c:container_write
Unexecuted instantiation: roaring64.c:container_write
Unexecuted instantiation: roaring_array.c:container_write
Unexecuted instantiation: convert.c:container_write
Unexecuted instantiation: mixed_negation.c:container_write
Unexecuted instantiation: mixed_xor.c:container_write
Unexecuted instantiation: mixed_andnot.c:container_write
396
397
/**
398
 * Get the container size in bytes under portable serialization (see
399
 * container_write), requires a
400
 * typecode
401
 */
402
static inline int32_t container_size_in_bytes(const container_t *c,
403
0
                                              uint8_t typecode) {
404
0
    c = container_unwrap_shared(c, &typecode);
405
0
    switch (typecode) {
406
0
        case BITSET_CONTAINER_TYPE:
407
0
            return bitset_container_size_in_bytes(const_CAST_bitset(c));
408
0
        case ARRAY_CONTAINER_TYPE:
409
0
            return array_container_size_in_bytes(const_CAST_array(c));
410
0
        case RUN_CONTAINER_TYPE:
411
0
            return run_container_size_in_bytes(const_CAST_run(c));
412
0
    }
413
0
    assert(false);
414
0
    roaring_unreachable;
415
0
    return 0;  // unreached
416
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_size_in_bytes
Unexecuted instantiation: containers.c:container_size_in_bytes
Unexecuted instantiation: roaring.c:container_size_in_bytes
Unexecuted instantiation: roaring64.c:container_size_in_bytes
Unexecuted instantiation: roaring_array.c:container_size_in_bytes
Unexecuted instantiation: convert.c:container_size_in_bytes
Unexecuted instantiation: mixed_negation.c:container_size_in_bytes
Unexecuted instantiation: mixed_xor.c:container_size_in_bytes
Unexecuted instantiation: mixed_andnot.c:container_size_in_bytes
417
418
/**
419
 * print the container (useful for debugging), requires a  typecode
420
 */
421
void container_printf(const container_t *container, uint8_t typecode);
422
423
/**
424
 * print the content of the container as a comma-separated list of 32-bit values
425
 * starting at base, requires a  typecode
426
 */
427
void container_printf_as_uint32_array(const container_t *container,
428
                                      uint8_t typecode, uint32_t base);
429
430
bool container_internal_validate(const container_t *container, uint8_t typecode,
431
                                 const char **reason);
432
433
/**
434
 * Checks whether a container is not empty, requires a  typecode
435
 */
436
static inline bool container_nonzero_cardinality(const container_t *c,
437
0
                                                 uint8_t typecode) {
438
0
    c = container_unwrap_shared(c, &typecode);
439
0
    switch (typecode) {
440
0
        case BITSET_CONTAINER_TYPE:
441
0
            return bitset_container_const_nonzero_cardinality(
442
0
                const_CAST_bitset(c));
443
0
        case ARRAY_CONTAINER_TYPE:
444
0
            return array_container_nonzero_cardinality(const_CAST_array(c));
445
0
        case RUN_CONTAINER_TYPE:
446
0
            return run_container_nonzero_cardinality(const_CAST_run(c));
447
0
    }
448
0
    assert(false);
449
0
    roaring_unreachable;
450
0
    return 0;  // unreached
451
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_nonzero_cardinality
Unexecuted instantiation: containers.c:container_nonzero_cardinality
Unexecuted instantiation: roaring.c:container_nonzero_cardinality
Unexecuted instantiation: roaring64.c:container_nonzero_cardinality
Unexecuted instantiation: roaring_array.c:container_nonzero_cardinality
Unexecuted instantiation: convert.c:container_nonzero_cardinality
Unexecuted instantiation: mixed_negation.c:container_nonzero_cardinality
Unexecuted instantiation: mixed_xor.c:container_nonzero_cardinality
Unexecuted instantiation: mixed_andnot.c:container_nonzero_cardinality
452
453
/**
454
 * Recover memory from a container, requires a  typecode
455
 */
456
void container_free(container_t *container, uint8_t typecode);
457
458
/**
459
 * Convert a container to an array of values, requires a  typecode as well as a
460
 * "base" (most significant values)
461
 * Returns number of ints added.
462
 */
463
static inline int container_to_uint32_array(uint32_t *output,
464
                                            const container_t *c,
465
0
                                            uint8_t typecode, uint32_t base) {
466
0
    c = container_unwrap_shared(c, &typecode);
467
0
    switch (typecode) {
468
0
        case BITSET_CONTAINER_TYPE:
469
0
            return bitset_container_to_uint32_array(output,
470
0
                                                    const_CAST_bitset(c), base);
471
0
        case ARRAY_CONTAINER_TYPE:
472
0
            return array_container_to_uint32_array(output, const_CAST_array(c),
473
0
                                                   base);
474
0
        case RUN_CONTAINER_TYPE:
475
0
            return run_container_to_uint32_array(output, const_CAST_run(c),
476
0
                                                 base);
477
0
    }
478
0
    assert(false);
479
0
    roaring_unreachable;
480
0
    return 0;  // unreached
481
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_to_uint32_array
Unexecuted instantiation: containers.c:container_to_uint32_array
Unexecuted instantiation: roaring.c:container_to_uint32_array
Unexecuted instantiation: roaring64.c:container_to_uint32_array
Unexecuted instantiation: roaring_array.c:container_to_uint32_array
Unexecuted instantiation: convert.c:container_to_uint32_array
Unexecuted instantiation: mixed_negation.c:container_to_uint32_array
Unexecuted instantiation: mixed_xor.c:container_to_uint32_array
Unexecuted instantiation: mixed_andnot.c:container_to_uint32_array
482
483
/**
484
 * Add a value to a container, requires a  typecode, fills in new_typecode and
485
 * return (possibly different) container.
486
 * This function may allocate a new container, and caller is responsible for
487
 * memory deallocation
488
 */
489
static inline container_t *container_add(
490
    container_t *c, uint16_t val,
491
    uint8_t typecode,  // !!! should be second argument?
492
0
    uint8_t *new_typecode) {
493
0
    c = get_writable_copy_if_shared(c, &typecode);
494
0
    switch (typecode) {
495
0
        case BITSET_CONTAINER_TYPE:
496
0
            bitset_container_set(CAST_bitset(c), val);
497
0
            *new_typecode = BITSET_CONTAINER_TYPE;
498
0
            return c;
499
0
        case ARRAY_CONTAINER_TYPE: {
500
0
            array_container_t *ac = CAST_array(c);
501
0
            if (array_container_try_add(ac, val, DEFAULT_MAX_SIZE) != -1) {
502
0
                *new_typecode = ARRAY_CONTAINER_TYPE;
503
0
                return ac;
504
0
            } else {
505
0
                bitset_container_t *bitset = bitset_container_from_array(ac);
506
0
                bitset_container_add(bitset, val);
507
0
                *new_typecode = BITSET_CONTAINER_TYPE;
508
0
                return bitset;
509
0
            }
510
0
        } break;
511
0
        case RUN_CONTAINER_TYPE:
512
            // per Java, no container type adjustments are done (revisit?)
513
0
            run_container_add(CAST_run(c), val);
514
0
            *new_typecode = RUN_CONTAINER_TYPE;
515
0
            return c;
516
0
        default:
517
0
            assert(false);
518
0
            roaring_unreachable;
519
0
            return NULL;
520
0
    }
521
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_add
Unexecuted instantiation: containers.c:container_add
Unexecuted instantiation: roaring.c:container_add
Unexecuted instantiation: roaring64.c:container_add
Unexecuted instantiation: roaring_array.c:container_add
Unexecuted instantiation: convert.c:container_add
Unexecuted instantiation: mixed_negation.c:container_add
Unexecuted instantiation: mixed_xor.c:container_add
Unexecuted instantiation: mixed_andnot.c:container_add
522
523
/**
524
 * Remove a value from a container, requires a  typecode, fills in new_typecode
525
 * and
526
 * return (possibly different) container.
527
 * This function may allocate a new container, and caller is responsible for
528
 * memory deallocation
529
 */
530
static inline container_t *container_remove(
531
    container_t *c, uint16_t val,
532
    uint8_t typecode,  // !!! should be second argument?
533
0
    uint8_t *new_typecode) {
534
0
    c = get_writable_copy_if_shared(c, &typecode);
535
0
    switch (typecode) {
536
0
        case BITSET_CONTAINER_TYPE:
537
0
            if (bitset_container_remove(CAST_bitset(c), val)) {
538
0
                int card = bitset_container_cardinality(CAST_bitset(c));
539
0
                if (card <= DEFAULT_MAX_SIZE) {
540
0
                    *new_typecode = ARRAY_CONTAINER_TYPE;
541
0
                    return array_container_from_bitset(CAST_bitset(c));
542
0
                }
543
0
            }
544
0
            *new_typecode = typecode;
545
0
            return c;
546
0
        case ARRAY_CONTAINER_TYPE:
547
0
            *new_typecode = typecode;
548
0
            array_container_remove(CAST_array(c), val);
549
0
            return c;
550
0
        case RUN_CONTAINER_TYPE:
551
            // per Java, no container type adjustments are done (revisit?)
552
0
            run_container_remove(CAST_run(c), val);
553
0
            *new_typecode = RUN_CONTAINER_TYPE;
554
0
            return c;
555
0
        default:
556
0
            assert(false);
557
0
            roaring_unreachable;
558
0
            return NULL;
559
0
    }
560
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_remove
Unexecuted instantiation: containers.c:container_remove
Unexecuted instantiation: roaring.c:container_remove
Unexecuted instantiation: roaring64.c:container_remove
Unexecuted instantiation: roaring_array.c:container_remove
Unexecuted instantiation: convert.c:container_remove
Unexecuted instantiation: mixed_negation.c:container_remove
Unexecuted instantiation: mixed_xor.c:container_remove
Unexecuted instantiation: mixed_andnot.c:container_remove
561
562
/**
563
 * Check whether a value is in a container, requires a typecode
564
 */
565
inline bool container_contains(
566
    const container_t *c, uint16_t val,
567
    uint8_t typecode  // !!! should be second argument?
568
0
) {
569
0
    if (typecode == SHARED_CONTAINER_TYPE) {
570
0
        typecode = const_CAST_shared(c)->typecode;
571
0
        assert(typecode != SHARED_CONTAINER_TYPE);
572
0
        c = const_CAST_shared(c)->container;
573
0
    }
574
575
0
    switch (typecode) {
576
0
        case BITSET_CONTAINER_TYPE:
577
0
            return bitset_container_get(const_CAST_bitset(c), val);
578
0
        case ARRAY_CONTAINER_TYPE:
579
0
            return array_container_contains(const_CAST_array(c), val);
580
0
        case RUN_CONTAINER_TYPE:
581
0
            return run_container_contains(const_CAST_run(c), val);
582
0
        default:
583
0
            assert(false);
584
0
            roaring_unreachable;
585
0
            return false;
586
0
    }
587
0
}
588
589
/**
590
 * Check whether a range of values from range_start (included) to range_end
591
 * (excluded) is in a container, requires a typecode
592
 */
593
static inline bool container_contains_range(
594
    const container_t *c, uint32_t range_start, uint32_t range_end,
595
    uint8_t typecode  // !!! should be second argument?
596
0
) {
597
0
    c = container_unwrap_shared(c, &typecode);
598
0
    switch (typecode) {
599
0
        case BITSET_CONTAINER_TYPE:
600
0
            return bitset_container_get_range(const_CAST_bitset(c), range_start,
601
0
                                              range_end);
602
0
        case ARRAY_CONTAINER_TYPE:
603
0
            return array_container_contains_range(const_CAST_array(c),
604
0
                                                  range_start, range_end);
605
0
        case RUN_CONTAINER_TYPE:
606
0
            return run_container_contains_range(const_CAST_run(c), range_start,
607
0
                                                range_end);
608
0
        default:
609
0
            assert(false);
610
0
            roaring_unreachable;
611
0
            return false;
612
0
    }
613
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_contains_range
Unexecuted instantiation: containers.c:container_contains_range
Unexecuted instantiation: roaring.c:container_contains_range
Unexecuted instantiation: roaring64.c:container_contains_range
Unexecuted instantiation: roaring_array.c:container_contains_range
Unexecuted instantiation: convert.c:container_contains_range
Unexecuted instantiation: mixed_negation.c:container_contains_range
Unexecuted instantiation: mixed_xor.c:container_contains_range
Unexecuted instantiation: mixed_andnot.c:container_contains_range
614
615
/**
616
 * Returns true if the two containers have the same content. Note that
617
 * two containers having different types can be "equal" in this sense.
618
 */
619
static inline bool container_equals(const container_t *c1, uint8_t type1,
620
0
                                    const container_t *c2, uint8_t type2) {
621
0
    c1 = container_unwrap_shared(c1, &type1);
622
0
    c2 = container_unwrap_shared(c2, &type2);
623
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
624
0
        case CONTAINER_PAIR(BITSET, BITSET):
625
0
            return bitset_container_equals(const_CAST_bitset(c1),
626
0
                                           const_CAST_bitset(c2));
627
628
0
        case CONTAINER_PAIR(BITSET, RUN):
629
0
            return run_container_equals_bitset(const_CAST_run(c2),
630
0
                                               const_CAST_bitset(c1));
631
632
0
        case CONTAINER_PAIR(RUN, BITSET):
633
0
            return run_container_equals_bitset(const_CAST_run(c1),
634
0
                                               const_CAST_bitset(c2));
635
636
0
        case CONTAINER_PAIR(BITSET, ARRAY):
637
            // java would always return false?
638
0
            return array_container_equal_bitset(const_CAST_array(c2),
639
0
                                                const_CAST_bitset(c1));
640
641
0
        case CONTAINER_PAIR(ARRAY, BITSET):
642
            // java would always return false?
643
0
            return array_container_equal_bitset(const_CAST_array(c1),
644
0
                                                const_CAST_bitset(c2));
645
646
0
        case CONTAINER_PAIR(ARRAY, RUN):
647
0
            return run_container_equals_array(const_CAST_run(c2),
648
0
                                              const_CAST_array(c1));
649
650
0
        case CONTAINER_PAIR(RUN, ARRAY):
651
0
            return run_container_equals_array(const_CAST_run(c1),
652
0
                                              const_CAST_array(c2));
653
654
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
655
0
            return array_container_equals(const_CAST_array(c1),
656
0
                                          const_CAST_array(c2));
657
658
0
        case CONTAINER_PAIR(RUN, RUN):
659
0
            return run_container_equals(const_CAST_run(c1), const_CAST_run(c2));
660
661
0
        default:
662
0
            assert(false);
663
0
            roaring_unreachable;
664
0
            return false;
665
0
    }
666
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_equals
Unexecuted instantiation: containers.c:container_equals
Unexecuted instantiation: roaring.c:container_equals
Unexecuted instantiation: roaring64.c:container_equals
Unexecuted instantiation: roaring_array.c:container_equals
Unexecuted instantiation: convert.c:container_equals
Unexecuted instantiation: mixed_negation.c:container_equals
Unexecuted instantiation: mixed_xor.c:container_equals
Unexecuted instantiation: mixed_andnot.c:container_equals
667
668
/**
669
 * Returns true if the container c1 is a subset of the container c2. Note that
670
 * c1 can be a subset of c2 even if they have a different type.
671
 */
672
static inline bool container_is_subset(const container_t *c1, uint8_t type1,
673
0
                                       const container_t *c2, uint8_t type2) {
674
0
    c1 = container_unwrap_shared(c1, &type1);
675
0
    c2 = container_unwrap_shared(c2, &type2);
676
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
677
0
        case CONTAINER_PAIR(BITSET, BITSET):
678
0
            return bitset_container_is_subset(const_CAST_bitset(c1),
679
0
                                              const_CAST_bitset(c2));
680
681
0
        case CONTAINER_PAIR(BITSET, RUN):
682
0
            return bitset_container_is_subset_run(const_CAST_bitset(c1),
683
0
                                                  const_CAST_run(c2));
684
685
0
        case CONTAINER_PAIR(RUN, BITSET):
686
0
            return run_container_is_subset_bitset(const_CAST_run(c1),
687
0
                                                  const_CAST_bitset(c2));
688
689
0
        case CONTAINER_PAIR(BITSET, ARRAY):
690
0
            return false;  // by construction, size(c1) > size(c2)
691
692
0
        case CONTAINER_PAIR(ARRAY, BITSET):
693
0
            return array_container_is_subset_bitset(const_CAST_array(c1),
694
0
                                                    const_CAST_bitset(c2));
695
696
0
        case CONTAINER_PAIR(ARRAY, RUN):
697
0
            return array_container_is_subset_run(const_CAST_array(c1),
698
0
                                                 const_CAST_run(c2));
699
700
0
        case CONTAINER_PAIR(RUN, ARRAY):
701
0
            return run_container_is_subset_array(const_CAST_run(c1),
702
0
                                                 const_CAST_array(c2));
703
704
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
705
0
            return array_container_is_subset(const_CAST_array(c1),
706
0
                                             const_CAST_array(c2));
707
708
0
        case CONTAINER_PAIR(RUN, RUN):
709
0
            return run_container_is_subset(const_CAST_run(c1),
710
0
                                           const_CAST_run(c2));
711
712
0
        default:
713
0
            assert(false);
714
0
            roaring_unreachable;
715
0
            return false;
716
0
    }
717
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_is_subset
Unexecuted instantiation: containers.c:container_is_subset
Unexecuted instantiation: roaring.c:container_is_subset
Unexecuted instantiation: roaring64.c:container_is_subset
Unexecuted instantiation: roaring_array.c:container_is_subset
Unexecuted instantiation: convert.c:container_is_subset
Unexecuted instantiation: mixed_negation.c:container_is_subset
Unexecuted instantiation: mixed_xor.c:container_is_subset
Unexecuted instantiation: mixed_andnot.c:container_is_subset
718
719
// macro-izations possibilities for generic non-inplace binary-op dispatch
720
721
/**
722
 * Compute intersection between two containers, generate a new container (having
723
 * type result_type), requires a typecode. This allocates new memory, caller
724
 * is responsible for deallocation.
725
 */
726
static inline container_t *container_and(const container_t *c1, uint8_t type1,
727
                                         const container_t *c2, uint8_t type2,
728
0
                                         uint8_t *result_type) {
729
0
    c1 = container_unwrap_shared(c1, &type1);
730
0
    c2 = container_unwrap_shared(c2, &type2);
731
0
    container_t *result = NULL;
732
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
733
0
        case CONTAINER_PAIR(BITSET, BITSET):
734
0
            *result_type =
735
0
                bitset_bitset_container_intersection(
736
0
                    const_CAST_bitset(c1), const_CAST_bitset(c2), &result)
737
0
                    ? BITSET_CONTAINER_TYPE
738
0
                    : ARRAY_CONTAINER_TYPE;
739
0
            return result;
740
741
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
742
0
            result = array_container_create();
743
0
            array_container_intersection(
744
0
                const_CAST_array(c1), const_CAST_array(c2), CAST_array(result));
745
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
746
0
            return result;
747
748
0
        case CONTAINER_PAIR(RUN, RUN):
749
0
            result = run_container_create();
750
0
            run_container_intersection(const_CAST_run(c1), const_CAST_run(c2),
751
0
                                       CAST_run(result));
752
0
            return convert_run_to_efficient_container_and_free(CAST_run(result),
753
0
                                                               result_type);
754
755
0
        case CONTAINER_PAIR(BITSET, ARRAY):
756
0
            result = array_container_create();
757
0
            array_bitset_container_intersection(const_CAST_array(c2),
758
0
                                                const_CAST_bitset(c1),
759
0
                                                CAST_array(result));
760
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
761
0
            return result;
762
763
0
        case CONTAINER_PAIR(ARRAY, BITSET):
764
0
            result = array_container_create();
765
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
766
0
            array_bitset_container_intersection(const_CAST_array(c1),
767
0
                                                const_CAST_bitset(c2),
768
0
                                                CAST_array(result));
769
0
            return result;
770
771
0
        case CONTAINER_PAIR(BITSET, RUN):
772
0
            *result_type =
773
0
                run_bitset_container_intersection(
774
0
                    const_CAST_run(c2), const_CAST_bitset(c1), &result)
775
0
                    ? BITSET_CONTAINER_TYPE
776
0
                    : ARRAY_CONTAINER_TYPE;
777
0
            return result;
778
779
0
        case CONTAINER_PAIR(RUN, BITSET):
780
0
            *result_type =
781
0
                run_bitset_container_intersection(
782
0
                    const_CAST_run(c1), const_CAST_bitset(c2), &result)
783
0
                    ? BITSET_CONTAINER_TYPE
784
0
                    : ARRAY_CONTAINER_TYPE;
785
0
            return result;
786
787
0
        case CONTAINER_PAIR(ARRAY, RUN):
788
0
            result = array_container_create();
789
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
790
0
            array_run_container_intersection(
791
0
                const_CAST_array(c1), const_CAST_run(c2), CAST_array(result));
792
0
            return result;
793
794
0
        case CONTAINER_PAIR(RUN, ARRAY):
795
0
            result = array_container_create();
796
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
797
0
            array_run_container_intersection(
798
0
                const_CAST_array(c2), const_CAST_run(c1), CAST_array(result));
799
0
            return result;
800
801
0
        default:
802
0
            assert(false);
803
0
            roaring_unreachable;
804
0
            return NULL;
805
0
    }
806
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_and
Unexecuted instantiation: containers.c:container_and
Unexecuted instantiation: roaring.c:container_and
Unexecuted instantiation: roaring64.c:container_and
Unexecuted instantiation: roaring_array.c:container_and
Unexecuted instantiation: convert.c:container_and
Unexecuted instantiation: mixed_negation.c:container_and
Unexecuted instantiation: mixed_xor.c:container_and
Unexecuted instantiation: mixed_andnot.c:container_and
807
808
/**
809
 * Compute the size of the intersection between two containers.
810
 */
811
static inline int container_and_cardinality(const container_t *c1,
812
                                            uint8_t type1,
813
                                            const container_t *c2,
814
0
                                            uint8_t type2) {
815
0
    c1 = container_unwrap_shared(c1, &type1);
816
0
    c2 = container_unwrap_shared(c2, &type2);
817
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
818
0
        case CONTAINER_PAIR(BITSET, BITSET):
819
0
            return bitset_container_and_justcard(const_CAST_bitset(c1),
820
0
                                                 const_CAST_bitset(c2));
821
822
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
823
0
            return array_container_intersection_cardinality(
824
0
                const_CAST_array(c1), const_CAST_array(c2));
825
826
0
        case CONTAINER_PAIR(RUN, RUN):
827
0
            return run_container_intersection_cardinality(const_CAST_run(c1),
828
0
                                                          const_CAST_run(c2));
829
830
0
        case CONTAINER_PAIR(BITSET, ARRAY):
831
0
            return array_bitset_container_intersection_cardinality(
832
0
                const_CAST_array(c2), const_CAST_bitset(c1));
833
834
0
        case CONTAINER_PAIR(ARRAY, BITSET):
835
0
            return array_bitset_container_intersection_cardinality(
836
0
                const_CAST_array(c1), const_CAST_bitset(c2));
837
838
0
        case CONTAINER_PAIR(BITSET, RUN):
839
0
            return run_bitset_container_intersection_cardinality(
840
0
                const_CAST_run(c2), const_CAST_bitset(c1));
841
842
0
        case CONTAINER_PAIR(RUN, BITSET):
843
0
            return run_bitset_container_intersection_cardinality(
844
0
                const_CAST_run(c1), const_CAST_bitset(c2));
845
846
0
        case CONTAINER_PAIR(ARRAY, RUN):
847
0
            return array_run_container_intersection_cardinality(
848
0
                const_CAST_array(c1), const_CAST_run(c2));
849
850
0
        case CONTAINER_PAIR(RUN, ARRAY):
851
0
            return array_run_container_intersection_cardinality(
852
0
                const_CAST_array(c2), const_CAST_run(c1));
853
854
0
        default:
855
0
            assert(false);
856
0
            roaring_unreachable;
857
0
            return 0;
858
0
    }
859
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_and_cardinality
Unexecuted instantiation: containers.c:container_and_cardinality
Unexecuted instantiation: roaring.c:container_and_cardinality
Unexecuted instantiation: roaring64.c:container_and_cardinality
Unexecuted instantiation: roaring_array.c:container_and_cardinality
Unexecuted instantiation: convert.c:container_and_cardinality
Unexecuted instantiation: mixed_negation.c:container_and_cardinality
Unexecuted instantiation: mixed_xor.c:container_and_cardinality
Unexecuted instantiation: mixed_andnot.c:container_and_cardinality
860
861
/**
862
 * Check whether two containers intersect.
863
 */
864
static inline bool container_intersect(const container_t *c1, uint8_t type1,
865
0
                                       const container_t *c2, uint8_t type2) {
866
0
    c1 = container_unwrap_shared(c1, &type1);
867
0
    c2 = container_unwrap_shared(c2, &type2);
868
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
869
0
        case CONTAINER_PAIR(BITSET, BITSET):
870
0
            return bitset_container_intersect(const_CAST_bitset(c1),
871
0
                                              const_CAST_bitset(c2));
872
873
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
874
0
            return array_container_intersect(const_CAST_array(c1),
875
0
                                             const_CAST_array(c2));
876
877
0
        case CONTAINER_PAIR(RUN, RUN):
878
0
            return run_container_intersect(const_CAST_run(c1),
879
0
                                           const_CAST_run(c2));
880
881
0
        case CONTAINER_PAIR(BITSET, ARRAY):
882
0
            return array_bitset_container_intersect(const_CAST_array(c2),
883
0
                                                    const_CAST_bitset(c1));
884
885
0
        case CONTAINER_PAIR(ARRAY, BITSET):
886
0
            return array_bitset_container_intersect(const_CAST_array(c1),
887
0
                                                    const_CAST_bitset(c2));
888
889
0
        case CONTAINER_PAIR(BITSET, RUN):
890
0
            return run_bitset_container_intersect(const_CAST_run(c2),
891
0
                                                  const_CAST_bitset(c1));
892
893
0
        case CONTAINER_PAIR(RUN, BITSET):
894
0
            return run_bitset_container_intersect(const_CAST_run(c1),
895
0
                                                  const_CAST_bitset(c2));
896
897
0
        case CONTAINER_PAIR(ARRAY, RUN):
898
0
            return array_run_container_intersect(const_CAST_array(c1),
899
0
                                                 const_CAST_run(c2));
900
901
0
        case CONTAINER_PAIR(RUN, ARRAY):
902
0
            return array_run_container_intersect(const_CAST_array(c2),
903
0
                                                 const_CAST_run(c1));
904
905
0
        default:
906
0
            assert(false);
907
0
            roaring_unreachable;
908
0
            return 0;
909
0
    }
910
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_intersect
Unexecuted instantiation: containers.c:container_intersect
Unexecuted instantiation: roaring.c:container_intersect
Unexecuted instantiation: roaring64.c:container_intersect
Unexecuted instantiation: roaring_array.c:container_intersect
Unexecuted instantiation: convert.c:container_intersect
Unexecuted instantiation: mixed_negation.c:container_intersect
Unexecuted instantiation: mixed_xor.c:container_intersect
Unexecuted instantiation: mixed_andnot.c:container_intersect
911
912
/**
913
 * Compute intersection between two containers, with result in the first
914
 container if possible. If the returned pointer is identical to c1,
915
 then the container has been modified. If the returned pointer is different
916
 from c1, then a new container has been created and the caller is responsible
917
 for freeing it.
918
 The type of the first container may change. Returns the modified
919
 (and possibly new) container.
920
*/
921
static inline container_t *container_iand(container_t *c1, uint8_t type1,
922
                                          const container_t *c2, uint8_t type2,
923
0
                                          uint8_t *result_type) {
924
0
    c1 = get_writable_copy_if_shared(c1, &type1);
925
0
    c2 = container_unwrap_shared(c2, &type2);
926
0
    container_t *result = NULL;
927
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
928
0
        case CONTAINER_PAIR(BITSET, BITSET):
929
0
            *result_type = bitset_bitset_container_intersection_inplace(
930
0
                               CAST_bitset(c1), const_CAST_bitset(c2), &result)
931
0
                               ? BITSET_CONTAINER_TYPE
932
0
                               : ARRAY_CONTAINER_TYPE;
933
0
            return result;
934
935
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
936
0
            array_container_intersection_inplace(CAST_array(c1),
937
0
                                                 const_CAST_array(c2));
938
0
            *result_type = ARRAY_CONTAINER_TYPE;
939
0
            return c1;
940
941
0
        case CONTAINER_PAIR(RUN, RUN):
942
0
            result = run_container_create();
943
0
            run_container_intersection(const_CAST_run(c1), const_CAST_run(c2),
944
0
                                       CAST_run(result));
945
            // as of January 2016, Java code used non-in-place intersection for
946
            // two runcontainers
947
0
            return convert_run_to_efficient_container_and_free(CAST_run(result),
948
0
                                                               result_type);
949
950
0
        case CONTAINER_PAIR(BITSET, ARRAY):
951
            // c1 is a bitmap so no inplace possible
952
0
            result = array_container_create();
953
0
            array_bitset_container_intersection(const_CAST_array(c2),
954
0
                                                const_CAST_bitset(c1),
955
0
                                                CAST_array(result));
956
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
957
0
            return result;
958
959
0
        case CONTAINER_PAIR(ARRAY, BITSET):
960
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
961
0
            array_bitset_container_intersection(
962
0
                const_CAST_array(c1), const_CAST_bitset(c2),
963
0
                CAST_array(c1));  // result is allowed to be same as c1
964
0
            return c1;
965
966
0
        case CONTAINER_PAIR(BITSET, RUN):
967
            // will attempt in-place computation
968
0
            *result_type = run_bitset_container_intersection(
969
0
                               const_CAST_run(c2), const_CAST_bitset(c1), &c1)
970
0
                               ? BITSET_CONTAINER_TYPE
971
0
                               : ARRAY_CONTAINER_TYPE;
972
0
            return c1;
973
974
0
        case CONTAINER_PAIR(RUN, BITSET):
975
0
            *result_type =
976
0
                run_bitset_container_intersection(
977
0
                    const_CAST_run(c1), const_CAST_bitset(c2), &result)
978
0
                    ? BITSET_CONTAINER_TYPE
979
0
                    : ARRAY_CONTAINER_TYPE;
980
0
            return result;
981
982
0
        case CONTAINER_PAIR(ARRAY, RUN):
983
0
            result = array_container_create();
984
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
985
0
            array_run_container_intersection(
986
0
                const_CAST_array(c1), const_CAST_run(c2), CAST_array(result));
987
0
            return result;
988
989
0
        case CONTAINER_PAIR(RUN, ARRAY):
990
0
            result = array_container_create();
991
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
992
0
            array_run_container_intersection(
993
0
                const_CAST_array(c2), const_CAST_run(c1), CAST_array(result));
994
0
            return result;
995
996
0
        default:
997
0
            assert(false);
998
0
            roaring_unreachable;
999
0
            return NULL;
1000
0
    }
1001
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_iand
Unexecuted instantiation: containers.c:container_iand
Unexecuted instantiation: roaring.c:container_iand
Unexecuted instantiation: roaring64.c:container_iand
Unexecuted instantiation: roaring_array.c:container_iand
Unexecuted instantiation: convert.c:container_iand
Unexecuted instantiation: mixed_negation.c:container_iand
Unexecuted instantiation: mixed_xor.c:container_iand
Unexecuted instantiation: mixed_andnot.c:container_iand
1002
1003
/**
1004
 * Compute union between two containers, generate a new container (having type
1005
 * result_type), requires a typecode. This allocates new memory, caller
1006
 * is responsible for deallocation.
1007
 */
1008
static inline container_t *container_or(const container_t *c1, uint8_t type1,
1009
                                        const container_t *c2, uint8_t type2,
1010
0
                                        uint8_t *result_type) {
1011
0
    c1 = container_unwrap_shared(c1, &type1);
1012
0
    c2 = container_unwrap_shared(c2, &type2);
1013
0
    container_t *result = NULL;
1014
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1015
0
        case CONTAINER_PAIR(BITSET, BITSET):
1016
0
            result = bitset_container_create();
1017
0
            bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
1018
0
                                CAST_bitset(result));
1019
0
            *result_type = BITSET_CONTAINER_TYPE;
1020
0
            return result;
1021
1022
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1023
0
            *result_type =
1024
0
                array_array_container_union(const_CAST_array(c1),
1025
0
                                            const_CAST_array(c2), &result)
1026
0
                    ? BITSET_CONTAINER_TYPE
1027
0
                    : ARRAY_CONTAINER_TYPE;
1028
0
            return result;
1029
1030
0
        case CONTAINER_PAIR(RUN, RUN):
1031
0
            result = run_container_create();
1032
0
            run_container_union(const_CAST_run(c1), const_CAST_run(c2),
1033
0
                                CAST_run(result));
1034
0
            *result_type = RUN_CONTAINER_TYPE;
1035
            // todo: could be optimized since will never convert to array
1036
0
            result = convert_run_to_efficient_container_and_free(
1037
0
                CAST_run(result), result_type);
1038
0
            return result;
1039
1040
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1041
0
            result = bitset_container_create();
1042
0
            array_bitset_container_union(const_CAST_array(c2),
1043
0
                                         const_CAST_bitset(c1),
1044
0
                                         CAST_bitset(result));
1045
0
            *result_type = BITSET_CONTAINER_TYPE;
1046
0
            return result;
1047
1048
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1049
0
            result = bitset_container_create();
1050
0
            array_bitset_container_union(const_CAST_array(c1),
1051
0
                                         const_CAST_bitset(c2),
1052
0
                                         CAST_bitset(result));
1053
0
            *result_type = BITSET_CONTAINER_TYPE;
1054
0
            return result;
1055
1056
0
        case CONTAINER_PAIR(BITSET, RUN):
1057
0
            if (run_container_is_full(const_CAST_run(c2))) {
1058
0
                result = run_container_create();
1059
0
                *result_type = RUN_CONTAINER_TYPE;
1060
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1061
0
                return result;
1062
0
            }
1063
0
            result = bitset_container_create();
1064
0
            run_bitset_container_union(
1065
0
                const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result));
1066
0
            *result_type = BITSET_CONTAINER_TYPE;
1067
0
            return result;
1068
1069
0
        case CONTAINER_PAIR(RUN, BITSET):
1070
0
            if (run_container_is_full(const_CAST_run(c1))) {
1071
0
                result = run_container_create();
1072
0
                *result_type = RUN_CONTAINER_TYPE;
1073
0
                run_container_copy(const_CAST_run(c1), CAST_run(result));
1074
0
                return result;
1075
0
            }
1076
0
            result = bitset_container_create();
1077
0
            run_bitset_container_union(
1078
0
                const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
1079
0
            *result_type = BITSET_CONTAINER_TYPE;
1080
0
            return result;
1081
1082
0
        case CONTAINER_PAIR(ARRAY, RUN):
1083
0
            result = run_container_create();
1084
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1085
0
                                      CAST_run(result));
1086
0
            result = convert_run_to_efficient_container_and_free(
1087
0
                CAST_run(result), result_type);
1088
0
            return result;
1089
1090
0
        case CONTAINER_PAIR(RUN, ARRAY):
1091
0
            result = run_container_create();
1092
0
            array_run_container_union(const_CAST_array(c2), const_CAST_run(c1),
1093
0
                                      CAST_run(result));
1094
0
            result = convert_run_to_efficient_container_and_free(
1095
0
                CAST_run(result), result_type);
1096
0
            return result;
1097
1098
0
        default:
1099
0
            assert(false);
1100
0
            roaring_unreachable;
1101
0
            return NULL;  // unreached
1102
0
    }
1103
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_or
Unexecuted instantiation: containers.c:container_or
Unexecuted instantiation: roaring.c:container_or
Unexecuted instantiation: roaring64.c:container_or
Unexecuted instantiation: roaring_array.c:container_or
Unexecuted instantiation: convert.c:container_or
Unexecuted instantiation: mixed_negation.c:container_or
Unexecuted instantiation: mixed_xor.c:container_or
Unexecuted instantiation: mixed_andnot.c:container_or
1104
1105
/**
1106
 * Compute union between two containers, generate a new container (having type
1107
 * result_type), requires a typecode. This allocates new memory, caller
1108
 * is responsible for deallocation.
1109
 *
1110
 * This lazy version delays some operations such as the maintenance of the
1111
 * cardinality. It requires repair later on the generated containers.
1112
 */
1113
static inline container_t *container_lazy_or(const container_t *c1,
1114
                                             uint8_t type1,
1115
                                             const container_t *c2,
1116
                                             uint8_t type2,
1117
0
                                             uint8_t *result_type) {
1118
0
    c1 = container_unwrap_shared(c1, &type1);
1119
0
    c2 = container_unwrap_shared(c2, &type2);
1120
0
    container_t *result = NULL;
1121
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1122
0
        case CONTAINER_PAIR(BITSET, BITSET):
1123
0
            result = bitset_container_create();
1124
0
            bitset_container_or_nocard(const_CAST_bitset(c1),
1125
0
                                       const_CAST_bitset(c2),
1126
0
                                       CAST_bitset(result));  // is lazy
1127
0
            *result_type = BITSET_CONTAINER_TYPE;
1128
0
            return result;
1129
1130
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1131
0
            *result_type =
1132
0
                array_array_container_lazy_union(const_CAST_array(c1),
1133
0
                                                 const_CAST_array(c2), &result)
1134
0
                    ? BITSET_CONTAINER_TYPE
1135
0
                    : ARRAY_CONTAINER_TYPE;
1136
0
            return result;
1137
1138
0
        case CONTAINER_PAIR(RUN, RUN):
1139
0
            result = run_container_create();
1140
0
            run_container_union(const_CAST_run(c1), const_CAST_run(c2),
1141
0
                                CAST_run(result));
1142
0
            *result_type = RUN_CONTAINER_TYPE;
1143
            // we are being lazy
1144
0
            result = convert_run_to_efficient_container_and_free(
1145
0
                CAST_run(result), result_type);
1146
0
            return result;
1147
1148
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1149
0
            result = bitset_container_create();
1150
0
            array_bitset_container_lazy_union(const_CAST_array(c2),
1151
0
                                              const_CAST_bitset(c1),
1152
0
                                              CAST_bitset(result));  // is lazy
1153
0
            *result_type = BITSET_CONTAINER_TYPE;
1154
0
            return result;
1155
1156
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1157
0
            result = bitset_container_create();
1158
0
            array_bitset_container_lazy_union(const_CAST_array(c1),
1159
0
                                              const_CAST_bitset(c2),
1160
0
                                              CAST_bitset(result));  // is lazy
1161
0
            *result_type = BITSET_CONTAINER_TYPE;
1162
0
            return result;
1163
1164
0
        case CONTAINER_PAIR(BITSET, RUN):
1165
0
            if (run_container_is_full(const_CAST_run(c2))) {
1166
0
                result = run_container_create();
1167
0
                *result_type = RUN_CONTAINER_TYPE;
1168
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1169
0
                return result;
1170
0
            }
1171
0
            result = bitset_container_create();
1172
0
            run_bitset_container_lazy_union(const_CAST_run(c2),
1173
0
                                            const_CAST_bitset(c1),
1174
0
                                            CAST_bitset(result));  // is lazy
1175
0
            *result_type = BITSET_CONTAINER_TYPE;
1176
0
            return result;
1177
1178
0
        case CONTAINER_PAIR(RUN, BITSET):
1179
0
            if (run_container_is_full(const_CAST_run(c1))) {
1180
0
                result = run_container_create();
1181
0
                *result_type = RUN_CONTAINER_TYPE;
1182
0
                run_container_copy(const_CAST_run(c1), CAST_run(result));
1183
0
                return result;
1184
0
            }
1185
0
            result = bitset_container_create();
1186
0
            run_bitset_container_lazy_union(const_CAST_run(c1),
1187
0
                                            const_CAST_bitset(c2),
1188
0
                                            CAST_bitset(result));  // is lazy
1189
0
            *result_type = BITSET_CONTAINER_TYPE;
1190
0
            return result;
1191
1192
0
        case CONTAINER_PAIR(ARRAY, RUN):
1193
0
            result = run_container_create();
1194
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1195
0
                                      CAST_run(result));
1196
0
            *result_type = RUN_CONTAINER_TYPE;
1197
            // next line skipped since we are lazy
1198
            // result = convert_run_to_efficient_container(result, result_type);
1199
0
            return result;
1200
1201
0
        case CONTAINER_PAIR(RUN, ARRAY):
1202
0
            result = run_container_create();
1203
0
            array_run_container_union(const_CAST_array(c2), const_CAST_run(c1),
1204
0
                                      CAST_run(result));  // TODO make lazy
1205
0
            *result_type = RUN_CONTAINER_TYPE;
1206
            // next line skipped since we are lazy
1207
            // result = convert_run_to_efficient_container(result, result_type);
1208
0
            return result;
1209
1210
0
        default:
1211
0
            assert(false);
1212
0
            roaring_unreachable;
1213
0
            return NULL;  // unreached
1214
0
    }
1215
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_lazy_or
Unexecuted instantiation: containers.c:container_lazy_or
Unexecuted instantiation: roaring.c:container_lazy_or
Unexecuted instantiation: roaring64.c:container_lazy_or
Unexecuted instantiation: roaring_array.c:container_lazy_or
Unexecuted instantiation: convert.c:container_lazy_or
Unexecuted instantiation: mixed_negation.c:container_lazy_or
Unexecuted instantiation: mixed_xor.c:container_lazy_or
Unexecuted instantiation: mixed_andnot.c:container_lazy_or
1216
1217
/**
1218
 * Compute the union between two containers, with result in the first container.
1219
 * If the returned pointer is identical to c1, then the container has been
1220
 * modified.
1221
 * If the returned pointer is different from c1, then a new container has been
1222
 * created and the caller is responsible for freeing it.
1223
 * The type of the first container may change. Returns the modified
1224
 * (and possibly new) container
1225
 */
1226
static inline container_t *container_ior(container_t *c1, uint8_t type1,
1227
                                         const container_t *c2, uint8_t type2,
1228
0
                                         uint8_t *result_type) {
1229
0
    c1 = get_writable_copy_if_shared(c1, &type1);
1230
0
    c2 = container_unwrap_shared(c2, &type2);
1231
0
    container_t *result = NULL;
1232
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1233
0
        case CONTAINER_PAIR(BITSET, BITSET):
1234
0
            bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
1235
0
                                CAST_bitset(c1));
1236
0
#ifdef OR_BITSET_CONVERSION_TO_FULL
1237
0
            if (CAST_bitset(c1)->cardinality == (1 << 16)) {  // we convert
1238
0
                result = run_container_create_range(0, (1 << 16));
1239
0
                *result_type = RUN_CONTAINER_TYPE;
1240
0
                return result;
1241
0
            }
1242
0
#endif
1243
0
            *result_type = BITSET_CONTAINER_TYPE;
1244
0
            return c1;
1245
1246
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1247
0
            *result_type = array_array_container_inplace_union(
1248
0
                               CAST_array(c1), const_CAST_array(c2), &result)
1249
0
                               ? BITSET_CONTAINER_TYPE
1250
0
                               : ARRAY_CONTAINER_TYPE;
1251
0
            if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) {
1252
0
                return c1;  // the computation was done in-place!
1253
0
            }
1254
0
            return result;
1255
1256
0
        case CONTAINER_PAIR(RUN, RUN):
1257
0
            run_container_union_inplace(CAST_run(c1), const_CAST_run(c2));
1258
0
            return convert_run_to_efficient_container(CAST_run(c1),
1259
0
                                                      result_type);
1260
1261
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1262
0
            array_bitset_container_union(
1263
0
                const_CAST_array(c2), const_CAST_bitset(c1), CAST_bitset(c1));
1264
0
            *result_type = BITSET_CONTAINER_TYPE;  // never array
1265
0
            return c1;
1266
1267
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1268
            // c1 is an array, so no in-place possible
1269
0
            result = bitset_container_create();
1270
0
            *result_type = BITSET_CONTAINER_TYPE;
1271
0
            array_bitset_container_union(const_CAST_array(c1),
1272
0
                                         const_CAST_bitset(c2),
1273
0
                                         CAST_bitset(result));
1274
0
            return result;
1275
1276
0
        case CONTAINER_PAIR(BITSET, RUN):
1277
0
            if (run_container_is_full(const_CAST_run(c2))) {
1278
0
                result = run_container_create();
1279
0
                *result_type = RUN_CONTAINER_TYPE;
1280
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1281
0
                return result;
1282
0
            }
1283
0
            run_bitset_container_union(const_CAST_run(c2),
1284
0
                                       const_CAST_bitset(c1),
1285
0
                                       CAST_bitset(c1));  // allowed
1286
0
            *result_type = BITSET_CONTAINER_TYPE;
1287
0
            return c1;
1288
1289
0
        case CONTAINER_PAIR(RUN, BITSET):
1290
0
            if (run_container_is_full(const_CAST_run(c1))) {
1291
0
                *result_type = RUN_CONTAINER_TYPE;
1292
0
                return c1;
1293
0
            }
1294
0
            result = bitset_container_create();
1295
0
            run_bitset_container_union(
1296
0
                const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
1297
0
            *result_type = BITSET_CONTAINER_TYPE;
1298
0
            return result;
1299
1300
0
        case CONTAINER_PAIR(ARRAY, RUN):
1301
0
            result = run_container_create();
1302
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1303
0
                                      CAST_run(result));
1304
0
            result = convert_run_to_efficient_container_and_free(
1305
0
                CAST_run(result), result_type);
1306
0
            return result;
1307
1308
0
        case CONTAINER_PAIR(RUN, ARRAY):
1309
0
            array_run_container_inplace_union(const_CAST_array(c2),
1310
0
                                              CAST_run(c1));
1311
0
            c1 = convert_run_to_efficient_container(CAST_run(c1), result_type);
1312
0
            return c1;
1313
1314
0
        default:
1315
0
            assert(false);
1316
0
            roaring_unreachable;
1317
0
            return NULL;
1318
0
    }
1319
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_ior
Unexecuted instantiation: containers.c:container_ior
Unexecuted instantiation: roaring.c:container_ior
Unexecuted instantiation: roaring64.c:container_ior
Unexecuted instantiation: roaring_array.c:container_ior
Unexecuted instantiation: convert.c:container_ior
Unexecuted instantiation: mixed_negation.c:container_ior
Unexecuted instantiation: mixed_xor.c:container_ior
Unexecuted instantiation: mixed_andnot.c:container_ior
1320
1321
/**
1322
 * Compute the union between two containers, with result in the first container.
1323
 * If the returned pointer is identical to c1, then the container has been
1324
 * modified.
1325
 * If the returned pointer is different from c1, then a new container has been
1326
 * created and the caller is responsible for freeing it.
1327
 * The type of the first container may change. Returns the modified
1328
 * (and possibly new) container
1329
 *
1330
 * This lazy version delays some operations such as the maintenance of the
1331
 * cardinality. It requires repair later on the generated containers.
1332
 */
1333
static inline container_t *container_lazy_ior(container_t *c1, uint8_t type1,
1334
                                              const container_t *c2,
1335
                                              uint8_t type2,
1336
0
                                              uint8_t *result_type) {
1337
0
    assert(type1 != SHARED_CONTAINER_TYPE);
1338
    // c1 = get_writable_copy_if_shared(c1,&type1);
1339
0
    c2 = container_unwrap_shared(c2, &type2);
1340
0
    container_t *result = NULL;
1341
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1342
0
        case CONTAINER_PAIR(BITSET, BITSET):
1343
0
#ifdef LAZY_OR_BITSET_CONVERSION_TO_FULL
1344
            // if we have two bitsets, we might as well compute the cardinality
1345
0
            bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
1346
0
                                CAST_bitset(c1));
1347
            // it is possible that two bitsets can lead to a full container
1348
0
            if (CAST_bitset(c1)->cardinality == (1 << 16)) {  // we convert
1349
0
                result = run_container_create_range(0, (1 << 16));
1350
0
                *result_type = RUN_CONTAINER_TYPE;
1351
0
                return result;
1352
0
            }
1353
#else
1354
            bitset_container_or_nocard(const_CAST_bitset(c1),
1355
                                       const_CAST_bitset(c2), CAST_bitset(c1));
1356
1357
#endif
1358
0
            *result_type = BITSET_CONTAINER_TYPE;
1359
0
            return c1;
1360
1361
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1362
0
            *result_type = array_array_container_lazy_inplace_union(
1363
0
                               CAST_array(c1), const_CAST_array(c2), &result)
1364
0
                               ? BITSET_CONTAINER_TYPE
1365
0
                               : ARRAY_CONTAINER_TYPE;
1366
0
            if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) {
1367
0
                return c1;  // the computation was done in-place!
1368
0
            }
1369
0
            return result;
1370
1371
0
        case CONTAINER_PAIR(RUN, RUN):
1372
0
            run_container_union_inplace(CAST_run(c1), const_CAST_run(c2));
1373
0
            *result_type = RUN_CONTAINER_TYPE;
1374
0
            return convert_run_to_efficient_container(CAST_run(c1),
1375
0
                                                      result_type);
1376
1377
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1378
0
            array_bitset_container_lazy_union(const_CAST_array(c2),
1379
0
                                              const_CAST_bitset(c1),
1380
0
                                              CAST_bitset(c1));  // is lazy
1381
0
            *result_type = BITSET_CONTAINER_TYPE;                // never array
1382
0
            return c1;
1383
1384
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1385
            // c1 is an array, so no in-place possible
1386
0
            result = bitset_container_create();
1387
0
            *result_type = BITSET_CONTAINER_TYPE;
1388
0
            array_bitset_container_lazy_union(const_CAST_array(c1),
1389
0
                                              const_CAST_bitset(c2),
1390
0
                                              CAST_bitset(result));  // is lazy
1391
0
            return result;
1392
1393
0
        case CONTAINER_PAIR(BITSET, RUN):
1394
0
            if (run_container_is_full(const_CAST_run(c2))) {
1395
0
                result = run_container_create();
1396
0
                *result_type = RUN_CONTAINER_TYPE;
1397
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1398
0
                return result;
1399
0
            }
1400
0
            run_bitset_container_lazy_union(
1401
0
                const_CAST_run(c2), const_CAST_bitset(c1),
1402
0
                CAST_bitset(c1));  // allowed //  lazy
1403
0
            *result_type = BITSET_CONTAINER_TYPE;
1404
0
            return c1;
1405
1406
0
        case CONTAINER_PAIR(RUN, BITSET):
1407
0
            if (run_container_is_full(const_CAST_run(c1))) {
1408
0
                *result_type = RUN_CONTAINER_TYPE;
1409
0
                return c1;
1410
0
            }
1411
0
            result = bitset_container_create();
1412
0
            run_bitset_container_lazy_union(const_CAST_run(c1),
1413
0
                                            const_CAST_bitset(c2),
1414
0
                                            CAST_bitset(result));  //  lazy
1415
0
            *result_type = BITSET_CONTAINER_TYPE;
1416
0
            return result;
1417
1418
0
        case CONTAINER_PAIR(ARRAY, RUN):
1419
0
            result = run_container_create();
1420
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1421
0
                                      CAST_run(result));
1422
0
            *result_type = RUN_CONTAINER_TYPE;
1423
            // next line skipped since we are lazy
1424
            // result = convert_run_to_efficient_container_and_free(result,
1425
            // result_type);
1426
0
            return result;
1427
1428
0
        case CONTAINER_PAIR(RUN, ARRAY):
1429
0
            array_run_container_inplace_union(const_CAST_array(c2),
1430
0
                                              CAST_run(c1));
1431
0
            *result_type = RUN_CONTAINER_TYPE;
1432
            // next line skipped since we are lazy
1433
            // result = convert_run_to_efficient_container_and_free(result,
1434
            // result_type);
1435
0
            return c1;
1436
1437
0
        default:
1438
0
            assert(false);
1439
0
            roaring_unreachable;
1440
0
            return NULL;
1441
0
    }
1442
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_lazy_ior
Unexecuted instantiation: containers.c:container_lazy_ior
Unexecuted instantiation: roaring.c:container_lazy_ior
Unexecuted instantiation: roaring64.c:container_lazy_ior
Unexecuted instantiation: roaring_array.c:container_lazy_ior
Unexecuted instantiation: convert.c:container_lazy_ior
Unexecuted instantiation: mixed_negation.c:container_lazy_ior
Unexecuted instantiation: mixed_xor.c:container_lazy_ior
Unexecuted instantiation: mixed_andnot.c:container_lazy_ior
1443
1444
/**
1445
 * Compute symmetric difference (xor) between two containers, generate a new
1446
 * container (having type result_type), requires a typecode. This allocates new
1447
 * memory, caller is responsible for deallocation.
1448
 */
1449
static inline container_t *container_xor(const container_t *c1, uint8_t type1,
1450
                                         const container_t *c2, uint8_t type2,
1451
0
                                         uint8_t *result_type) {
1452
0
    c1 = container_unwrap_shared(c1, &type1);
1453
0
    c2 = container_unwrap_shared(c2, &type2);
1454
0
    container_t *result = NULL;
1455
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1456
0
        case CONTAINER_PAIR(BITSET, BITSET):
1457
0
            *result_type =
1458
0
                bitset_bitset_container_xor(const_CAST_bitset(c1),
1459
0
                                            const_CAST_bitset(c2), &result)
1460
0
                    ? BITSET_CONTAINER_TYPE
1461
0
                    : ARRAY_CONTAINER_TYPE;
1462
0
            return result;
1463
1464
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1465
0
            *result_type =
1466
0
                array_array_container_xor(const_CAST_array(c1),
1467
0
                                          const_CAST_array(c2), &result)
1468
0
                    ? BITSET_CONTAINER_TYPE
1469
0
                    : ARRAY_CONTAINER_TYPE;
1470
0
            return result;
1471
1472
0
        case CONTAINER_PAIR(RUN, RUN):
1473
0
            *result_type = (uint8_t)run_run_container_xor(
1474
0
                const_CAST_run(c1), const_CAST_run(c2), &result);
1475
0
            return result;
1476
1477
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1478
0
            *result_type =
1479
0
                array_bitset_container_xor(const_CAST_array(c2),
1480
0
                                           const_CAST_bitset(c1), &result)
1481
0
                    ? BITSET_CONTAINER_TYPE
1482
0
                    : ARRAY_CONTAINER_TYPE;
1483
0
            return result;
1484
1485
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1486
0
            *result_type =
1487
0
                array_bitset_container_xor(const_CAST_array(c1),
1488
0
                                           const_CAST_bitset(c2), &result)
1489
0
                    ? BITSET_CONTAINER_TYPE
1490
0
                    : ARRAY_CONTAINER_TYPE;
1491
0
            return result;
1492
1493
0
        case CONTAINER_PAIR(BITSET, RUN):
1494
0
            *result_type =
1495
0
                run_bitset_container_xor(const_CAST_run(c2),
1496
0
                                         const_CAST_bitset(c1), &result)
1497
0
                    ? BITSET_CONTAINER_TYPE
1498
0
                    : ARRAY_CONTAINER_TYPE;
1499
0
            return result;
1500
1501
0
        case CONTAINER_PAIR(RUN, BITSET):
1502
0
            *result_type =
1503
0
                run_bitset_container_xor(const_CAST_run(c1),
1504
0
                                         const_CAST_bitset(c2), &result)
1505
0
                    ? BITSET_CONTAINER_TYPE
1506
0
                    : ARRAY_CONTAINER_TYPE;
1507
0
            return result;
1508
1509
0
        case CONTAINER_PAIR(ARRAY, RUN):
1510
0
            *result_type = (uint8_t)array_run_container_xor(
1511
0
                const_CAST_array(c1), const_CAST_run(c2), &result);
1512
0
            return result;
1513
1514
0
        case CONTAINER_PAIR(RUN, ARRAY):
1515
0
            *result_type = (uint8_t)array_run_container_xor(
1516
0
                const_CAST_array(c2), const_CAST_run(c1), &result);
1517
0
            return result;
1518
1519
0
        default:
1520
0
            assert(false);
1521
0
            roaring_unreachable;
1522
0
            return NULL;  // unreached
1523
0
    }
1524
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_xor
Unexecuted instantiation: containers.c:container_xor
Unexecuted instantiation: roaring.c:container_xor
Unexecuted instantiation: roaring64.c:container_xor
Unexecuted instantiation: roaring_array.c:container_xor
Unexecuted instantiation: convert.c:container_xor
Unexecuted instantiation: mixed_negation.c:container_xor
Unexecuted instantiation: mixed_xor.c:container_xor
Unexecuted instantiation: mixed_andnot.c:container_xor
1525
1526
/* Applies an offset to the non-empty container 'c'.
1527
 * The results are stored in new containers returned via 'lo' and 'hi', for the
1528
 * low and high halves of the result (where the low half matches the original
1529
 * key and the high one corresponds to values for the following key). Either one
1530
 * of 'lo' and 'hi' are allowed to be 'NULL', but not both. Whenever one of them
1531
 * is not 'NULL', it should point to a 'NULL' container. Whenever one of them is
1532
 * 'NULL' the shifted elements for that part will not be computed. If either of
1533
 * the resulting containers turns out to be empty, the pointed container will
1534
 * remain 'NULL'.
1535
 */
1536
static inline void container_add_offset(const container_t *c, uint8_t type,
1537
                                        container_t **lo, container_t **hi,
1538
0
                                        uint16_t offset) {
1539
0
    assert(offset != 0);
1540
0
    assert(container_nonzero_cardinality(c, type));
1541
0
    assert(lo != NULL || hi != NULL);
1542
0
    assert(lo == NULL || *lo == NULL);
1543
0
    assert(hi == NULL || *hi == NULL);
1544
1545
0
    switch (type) {
1546
0
        case BITSET_CONTAINER_TYPE:
1547
0
            bitset_container_offset(const_CAST_bitset(c), lo, hi, offset);
1548
0
            break;
1549
0
        case ARRAY_CONTAINER_TYPE:
1550
0
            array_container_offset(const_CAST_array(c), lo, hi, offset);
1551
0
            break;
1552
0
        case RUN_CONTAINER_TYPE:
1553
0
            run_container_offset(const_CAST_run(c), lo, hi, offset);
1554
0
            break;
1555
0
        default:
1556
0
            assert(false);
1557
0
            roaring_unreachable;
1558
0
            break;
1559
0
    }
1560
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_add_offset
Unexecuted instantiation: containers.c:container_add_offset
Unexecuted instantiation: roaring.c:container_add_offset
Unexecuted instantiation: roaring64.c:container_add_offset
Unexecuted instantiation: roaring_array.c:container_add_offset
Unexecuted instantiation: convert.c:container_add_offset
Unexecuted instantiation: mixed_negation.c:container_add_offset
Unexecuted instantiation: mixed_xor.c:container_add_offset
Unexecuted instantiation: mixed_andnot.c:container_add_offset
1561
1562
/**
1563
 * Compute xor between two containers, generate a new container (having type
1564
 * result_type), requires a typecode. This allocates new memory, caller
1565
 * is responsible for deallocation.
1566
 *
1567
 * This lazy version delays some operations such as the maintenance of the
1568
 * cardinality. It requires repair later on the generated containers.
1569
 */
1570
static inline container_t *container_lazy_xor(const container_t *c1,
1571
                                              uint8_t type1,
1572
                                              const container_t *c2,
1573
                                              uint8_t type2,
1574
0
                                              uint8_t *result_type) {
1575
0
    c1 = container_unwrap_shared(c1, &type1);
1576
0
    c2 = container_unwrap_shared(c2, &type2);
1577
0
    container_t *result = NULL;
1578
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1579
0
        case CONTAINER_PAIR(BITSET, BITSET):
1580
0
            result = bitset_container_create();
1581
0
            bitset_container_xor_nocard(const_CAST_bitset(c1),
1582
0
                                        const_CAST_bitset(c2),
1583
0
                                        CAST_bitset(result));  // is lazy
1584
0
            *result_type = BITSET_CONTAINER_TYPE;
1585
0
            return result;
1586
1587
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1588
0
            *result_type =
1589
0
                array_array_container_lazy_xor(const_CAST_array(c1),
1590
0
                                               const_CAST_array(c2), &result)
1591
0
                    ? BITSET_CONTAINER_TYPE
1592
0
                    : ARRAY_CONTAINER_TYPE;
1593
0
            return result;
1594
1595
0
        case CONTAINER_PAIR(RUN, RUN):
1596
            // nothing special done yet.
1597
0
            *result_type = (uint8_t)run_run_container_xor(
1598
0
                const_CAST_run(c1), const_CAST_run(c2), &result);
1599
0
            return result;
1600
1601
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1602
0
            result = bitset_container_create();
1603
0
            *result_type = BITSET_CONTAINER_TYPE;
1604
0
            array_bitset_container_lazy_xor(const_CAST_array(c2),
1605
0
                                            const_CAST_bitset(c1),
1606
0
                                            CAST_bitset(result));
1607
0
            return result;
1608
1609
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1610
0
            result = bitset_container_create();
1611
0
            *result_type = BITSET_CONTAINER_TYPE;
1612
0
            array_bitset_container_lazy_xor(const_CAST_array(c1),
1613
0
                                            const_CAST_bitset(c2),
1614
0
                                            CAST_bitset(result));
1615
0
            return result;
1616
1617
0
        case CONTAINER_PAIR(BITSET, RUN):
1618
0
            result = bitset_container_create();
1619
0
            run_bitset_container_lazy_xor(
1620
0
                const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result));
1621
0
            *result_type = BITSET_CONTAINER_TYPE;
1622
0
            return result;
1623
1624
0
        case CONTAINER_PAIR(RUN, BITSET):
1625
0
            result = bitset_container_create();
1626
0
            run_bitset_container_lazy_xor(
1627
0
                const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
1628
0
            *result_type = BITSET_CONTAINER_TYPE;
1629
0
            return result;
1630
1631
0
        case CONTAINER_PAIR(ARRAY, RUN):
1632
0
            result = run_container_create();
1633
0
            array_run_container_lazy_xor(const_CAST_array(c1),
1634
0
                                         const_CAST_run(c2), CAST_run(result));
1635
0
            *result_type = RUN_CONTAINER_TYPE;
1636
            // next line skipped since we are lazy
1637
            // result = convert_run_to_efficient_container(result, result_type);
1638
0
            return result;
1639
1640
0
        case CONTAINER_PAIR(RUN, ARRAY):
1641
0
            result = run_container_create();
1642
0
            array_run_container_lazy_xor(const_CAST_array(c2),
1643
0
                                         const_CAST_run(c1), CAST_run(result));
1644
0
            *result_type = RUN_CONTAINER_TYPE;
1645
            // next line skipped since we are lazy
1646
            // result = convert_run_to_efficient_container(result, result_type);
1647
0
            return result;
1648
1649
0
        default:
1650
0
            assert(false);
1651
0
            roaring_unreachable;
1652
0
            return NULL;  // unreached
1653
0
    }
1654
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_lazy_xor
Unexecuted instantiation: containers.c:container_lazy_xor
Unexecuted instantiation: roaring.c:container_lazy_xor
Unexecuted instantiation: roaring64.c:container_lazy_xor
Unexecuted instantiation: roaring_array.c:container_lazy_xor
Unexecuted instantiation: convert.c:container_lazy_xor
Unexecuted instantiation: mixed_negation.c:container_lazy_xor
Unexecuted instantiation: mixed_xor.c:container_lazy_xor
Unexecuted instantiation: mixed_andnot.c:container_lazy_xor
1655
1656
/**
1657
 * Compute the xor between two containers, with result in the first container.
1658
 * If the returned pointer is identical to c1, then the container has been
1659
 * modified.
1660
 * If the returned pointer is different from c1, then a new container has been
1661
 * created. The original container is freed by container_ixor.
1662
 * The type of the first container may change. Returns the modified (and
1663
 * possibly new) container.
1664
 */
1665
static inline container_t *container_ixor(container_t *c1, uint8_t type1,
1666
                                          const container_t *c2, uint8_t type2,
1667
0
                                          uint8_t *result_type) {
1668
0
    c1 = get_writable_copy_if_shared(c1, &type1);
1669
0
    c2 = container_unwrap_shared(c2, &type2);
1670
0
    container_t *result = NULL;
1671
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1672
0
        case CONTAINER_PAIR(BITSET, BITSET):
1673
0
            *result_type = bitset_bitset_container_ixor(
1674
0
                               CAST_bitset(c1), const_CAST_bitset(c2), &result)
1675
0
                               ? BITSET_CONTAINER_TYPE
1676
0
                               : ARRAY_CONTAINER_TYPE;
1677
0
            return result;
1678
1679
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1680
0
            *result_type = array_array_container_ixor(
1681
0
                               CAST_array(c1), const_CAST_array(c2), &result)
1682
0
                               ? BITSET_CONTAINER_TYPE
1683
0
                               : ARRAY_CONTAINER_TYPE;
1684
0
            return result;
1685
1686
0
        case CONTAINER_PAIR(RUN, RUN):
1687
0
            *result_type = (uint8_t)run_run_container_ixor(
1688
0
                CAST_run(c1), const_CAST_run(c2), &result);
1689
0
            return result;
1690
1691
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1692
0
            *result_type = bitset_array_container_ixor(
1693
0
                               CAST_bitset(c1), const_CAST_array(c2), &result)
1694
0
                               ? BITSET_CONTAINER_TYPE
1695
0
                               : ARRAY_CONTAINER_TYPE;
1696
0
            return result;
1697
1698
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1699
0
            *result_type = array_bitset_container_ixor(
1700
0
                               CAST_array(c1), const_CAST_bitset(c2), &result)
1701
0
                               ? BITSET_CONTAINER_TYPE
1702
0
                               : ARRAY_CONTAINER_TYPE;
1703
0
            return result;
1704
1705
0
        case CONTAINER_PAIR(BITSET, RUN):
1706
0
            *result_type = bitset_run_container_ixor(
1707
0
                               CAST_bitset(c1), const_CAST_run(c2), &result)
1708
0
                               ? BITSET_CONTAINER_TYPE
1709
0
                               : ARRAY_CONTAINER_TYPE;
1710
1711
0
            return result;
1712
1713
0
        case CONTAINER_PAIR(RUN, BITSET):
1714
0
            *result_type = run_bitset_container_ixor(
1715
0
                               CAST_run(c1), const_CAST_bitset(c2), &result)
1716
0
                               ? BITSET_CONTAINER_TYPE
1717
0
                               : ARRAY_CONTAINER_TYPE;
1718
0
            return result;
1719
1720
0
        case CONTAINER_PAIR(ARRAY, RUN):
1721
0
            *result_type = (uint8_t)array_run_container_ixor(
1722
0
                CAST_array(c1), const_CAST_run(c2), &result);
1723
0
            return result;
1724
1725
0
        case CONTAINER_PAIR(RUN, ARRAY):
1726
0
            *result_type = (uint8_t)run_array_container_ixor(
1727
0
                CAST_run(c1), const_CAST_array(c2), &result);
1728
0
            return result;
1729
1730
0
        default:
1731
0
            assert(false);
1732
0
            roaring_unreachable;
1733
0
            return NULL;
1734
0
    }
1735
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_ixor
Unexecuted instantiation: containers.c:container_ixor
Unexecuted instantiation: roaring.c:container_ixor
Unexecuted instantiation: roaring64.c:container_ixor
Unexecuted instantiation: roaring_array.c:container_ixor
Unexecuted instantiation: convert.c:container_ixor
Unexecuted instantiation: mixed_negation.c:container_ixor
Unexecuted instantiation: mixed_xor.c:container_ixor
Unexecuted instantiation: mixed_andnot.c:container_ixor
1736
1737
/**
1738
 * Compute the xor between two containers, with result in the first container.
1739
 * If the returned pointer is identical to c1, then the container has been
1740
 * modified.
1741
 * If the returned pointer is different from c1, then a new container has been
1742
 * created and the caller is responsible for freeing it.
1743
 * The type of the first container may change. Returns the modified
1744
 * (and possibly new) container
1745
 *
1746
 * This lazy version delays some operations such as the maintenance of the
1747
 * cardinality. It requires repair later on the generated containers.
1748
 */
1749
static inline container_t *container_lazy_ixor(container_t *c1, uint8_t type1,
1750
                                               const container_t *c2,
1751
                                               uint8_t type2,
1752
0
                                               uint8_t *result_type) {
1753
0
    assert(type1 != SHARED_CONTAINER_TYPE);
1754
    // c1 = get_writable_copy_if_shared(c1,&type1);
1755
0
    c2 = container_unwrap_shared(c2, &type2);
1756
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1757
0
        case CONTAINER_PAIR(BITSET, BITSET):
1758
0
            bitset_container_xor_nocard(CAST_bitset(c1), const_CAST_bitset(c2),
1759
0
                                        CAST_bitset(c1));  // is lazy
1760
0
            *result_type = BITSET_CONTAINER_TYPE;
1761
0
            return c1;
1762
1763
        // TODO: other cases being lazy, esp. when we know inplace not likely
1764
        // could see the corresponding code for union
1765
0
        default:
1766
            // we may have a dirty bitset (without a precomputed cardinality)
1767
            // and calling container_ixor on it might be unsafe.
1768
0
            if (type1 == BITSET_CONTAINER_TYPE) {
1769
0
                bitset_container_t *bc = CAST_bitset(c1);
1770
0
                if (bc->cardinality == BITSET_UNKNOWN_CARDINALITY) {
1771
0
                    bc->cardinality = bitset_container_compute_cardinality(bc);
1772
0
                }
1773
0
            }
1774
0
            return container_ixor(c1, type1, c2, type2, result_type);
1775
0
    }
1776
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_lazy_ixor
Unexecuted instantiation: containers.c:container_lazy_ixor
Unexecuted instantiation: roaring.c:container_lazy_ixor
Unexecuted instantiation: roaring64.c:container_lazy_ixor
Unexecuted instantiation: roaring_array.c:container_lazy_ixor
Unexecuted instantiation: convert.c:container_lazy_ixor
Unexecuted instantiation: mixed_negation.c:container_lazy_ixor
Unexecuted instantiation: mixed_xor.c:container_lazy_ixor
Unexecuted instantiation: mixed_andnot.c:container_lazy_ixor
1777
1778
/**
1779
 * Compute difference (andnot) between two containers, generate a new
1780
 * container (having type result_type), requires a typecode. This allocates new
1781
 * memory, caller is responsible for deallocation.
1782
 */
1783
static inline container_t *container_andnot(const container_t *c1,
1784
                                            uint8_t type1,
1785
                                            const container_t *c2,
1786
                                            uint8_t type2,
1787
0
                                            uint8_t *result_type) {
1788
0
    c1 = container_unwrap_shared(c1, &type1);
1789
0
    c2 = container_unwrap_shared(c2, &type2);
1790
0
    container_t *result = NULL;
1791
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1792
0
        case CONTAINER_PAIR(BITSET, BITSET):
1793
0
            *result_type =
1794
0
                bitset_bitset_container_andnot(const_CAST_bitset(c1),
1795
0
                                               const_CAST_bitset(c2), &result)
1796
0
                    ? BITSET_CONTAINER_TYPE
1797
0
                    : ARRAY_CONTAINER_TYPE;
1798
0
            return result;
1799
1800
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1801
0
            result = array_container_create();
1802
0
            array_array_container_andnot(
1803
0
                const_CAST_array(c1), const_CAST_array(c2), CAST_array(result));
1804
0
            *result_type = ARRAY_CONTAINER_TYPE;
1805
0
            return result;
1806
1807
0
        case CONTAINER_PAIR(RUN, RUN):
1808
0
            if (run_container_is_full(const_CAST_run(c2))) {
1809
0
                result = array_container_create();
1810
0
                *result_type = ARRAY_CONTAINER_TYPE;
1811
0
                return result;
1812
0
            }
1813
0
            *result_type = (uint8_t)run_run_container_andnot(
1814
0
                const_CAST_run(c1), const_CAST_run(c2), &result);
1815
0
            return result;
1816
1817
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1818
0
            *result_type =
1819
0
                bitset_array_container_andnot(const_CAST_bitset(c1),
1820
0
                                              const_CAST_array(c2), &result)
1821
0
                    ? BITSET_CONTAINER_TYPE
1822
0
                    : ARRAY_CONTAINER_TYPE;
1823
0
            return result;
1824
1825
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1826
0
            result = array_container_create();
1827
0
            array_bitset_container_andnot(const_CAST_array(c1),
1828
0
                                          const_CAST_bitset(c2),
1829
0
                                          CAST_array(result));
1830
0
            *result_type = ARRAY_CONTAINER_TYPE;
1831
0
            return result;
1832
1833
0
        case CONTAINER_PAIR(BITSET, RUN):
1834
0
            if (run_container_is_full(const_CAST_run(c2))) {
1835
0
                result = array_container_create();
1836
0
                *result_type = ARRAY_CONTAINER_TYPE;
1837
0
                return result;
1838
0
            }
1839
0
            *result_type =
1840
0
                bitset_run_container_andnot(const_CAST_bitset(c1),
1841
0
                                            const_CAST_run(c2), &result)
1842
0
                    ? BITSET_CONTAINER_TYPE
1843
0
                    : ARRAY_CONTAINER_TYPE;
1844
0
            return result;
1845
1846
0
        case CONTAINER_PAIR(RUN, BITSET):
1847
0
            *result_type =
1848
0
                run_bitset_container_andnot(const_CAST_run(c1),
1849
0
                                            const_CAST_bitset(c2), &result)
1850
0
                    ? BITSET_CONTAINER_TYPE
1851
0
                    : ARRAY_CONTAINER_TYPE;
1852
0
            return result;
1853
1854
0
        case CONTAINER_PAIR(ARRAY, RUN):
1855
0
            if (run_container_is_full(const_CAST_run(c2))) {
1856
0
                result = array_container_create();
1857
0
                *result_type = ARRAY_CONTAINER_TYPE;
1858
0
                return result;
1859
0
            }
1860
0
            result = array_container_create();
1861
0
            array_run_container_andnot(const_CAST_array(c1), const_CAST_run(c2),
1862
0
                                       CAST_array(result));
1863
0
            *result_type = ARRAY_CONTAINER_TYPE;
1864
0
            return result;
1865
1866
0
        case CONTAINER_PAIR(RUN, ARRAY):
1867
0
            *result_type = (uint8_t)run_array_container_andnot(
1868
0
                const_CAST_run(c1), const_CAST_array(c2), &result);
1869
0
            return result;
1870
1871
0
        default:
1872
0
            assert(false);
1873
0
            roaring_unreachable;
1874
0
            return NULL;  // unreached
1875
0
    }
1876
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_andnot
Unexecuted instantiation: containers.c:container_andnot
Unexecuted instantiation: roaring.c:container_andnot
Unexecuted instantiation: roaring64.c:container_andnot
Unexecuted instantiation: roaring_array.c:container_andnot
Unexecuted instantiation: convert.c:container_andnot
Unexecuted instantiation: mixed_negation.c:container_andnot
Unexecuted instantiation: mixed_xor.c:container_andnot
Unexecuted instantiation: mixed_andnot.c:container_andnot
1877
1878
/**
1879
 * Compute the andnot between two containers, with result in the first
1880
 * container.
1881
 * If the returned pointer is identical to c1, then the container has been
1882
 * modified.
1883
 * If the returned pointer is different from c1, then a new container has been
1884
 * created. The original container is freed by container_iandnot.
1885
 * The type of the first container may change. Returns the modified (and
1886
 * possibly new) container.
1887
 */
1888
static inline container_t *container_iandnot(container_t *c1, uint8_t type1,
1889
                                             const container_t *c2,
1890
                                             uint8_t type2,
1891
0
                                             uint8_t *result_type) {
1892
0
    c1 = get_writable_copy_if_shared(c1, &type1);
1893
0
    c2 = container_unwrap_shared(c2, &type2);
1894
0
    container_t *result = NULL;
1895
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1896
0
        case CONTAINER_PAIR(BITSET, BITSET):
1897
0
            *result_type = bitset_bitset_container_iandnot(
1898
0
                               CAST_bitset(c1), const_CAST_bitset(c2), &result)
1899
0
                               ? BITSET_CONTAINER_TYPE
1900
0
                               : ARRAY_CONTAINER_TYPE;
1901
0
            return result;
1902
1903
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1904
0
            array_array_container_iandnot(CAST_array(c1), const_CAST_array(c2));
1905
0
            *result_type = ARRAY_CONTAINER_TYPE;
1906
0
            return c1;
1907
1908
0
        case CONTAINER_PAIR(RUN, RUN):
1909
0
            *result_type = (uint8_t)run_run_container_iandnot(
1910
0
                CAST_run(c1), const_CAST_run(c2), &result);
1911
0
            return result;
1912
1913
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1914
0
            *result_type = bitset_array_container_iandnot(
1915
0
                               CAST_bitset(c1), const_CAST_array(c2), &result)
1916
0
                               ? BITSET_CONTAINER_TYPE
1917
0
                               : ARRAY_CONTAINER_TYPE;
1918
0
            return result;
1919
1920
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1921
0
            *result_type = ARRAY_CONTAINER_TYPE;
1922
0
            array_bitset_container_iandnot(CAST_array(c1),
1923
0
                                           const_CAST_bitset(c2));
1924
0
            return c1;
1925
1926
0
        case CONTAINER_PAIR(BITSET, RUN):
1927
0
            *result_type = bitset_run_container_iandnot(
1928
0
                               CAST_bitset(c1), const_CAST_run(c2), &result)
1929
0
                               ? BITSET_CONTAINER_TYPE
1930
0
                               : ARRAY_CONTAINER_TYPE;
1931
0
            return result;
1932
1933
0
        case CONTAINER_PAIR(RUN, BITSET):
1934
0
            *result_type = run_bitset_container_iandnot(
1935
0
                               CAST_run(c1), const_CAST_bitset(c2), &result)
1936
0
                               ? BITSET_CONTAINER_TYPE
1937
0
                               : ARRAY_CONTAINER_TYPE;
1938
0
            return result;
1939
1940
0
        case CONTAINER_PAIR(ARRAY, RUN):
1941
0
            *result_type = ARRAY_CONTAINER_TYPE;
1942
0
            array_run_container_iandnot(CAST_array(c1), const_CAST_run(c2));
1943
0
            return c1;
1944
1945
0
        case CONTAINER_PAIR(RUN, ARRAY):
1946
0
            *result_type = (uint8_t)run_array_container_iandnot(
1947
0
                CAST_run(c1), const_CAST_array(c2), &result);
1948
0
            return result;
1949
1950
0
        default:
1951
0
            assert(false);
1952
0
            roaring_unreachable;
1953
0
            return NULL;
1954
0
    }
1955
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_iandnot
Unexecuted instantiation: containers.c:container_iandnot
Unexecuted instantiation: roaring.c:container_iandnot
Unexecuted instantiation: roaring64.c:container_iandnot
Unexecuted instantiation: roaring_array.c:container_iandnot
Unexecuted instantiation: convert.c:container_iandnot
Unexecuted instantiation: mixed_negation.c:container_iandnot
Unexecuted instantiation: mixed_xor.c:container_iandnot
Unexecuted instantiation: mixed_andnot.c:container_iandnot
1956
1957
/**
1958
 * Visit all values x of the container once, passing (base+x,ptr)
1959
 * to iterator. You need to specify a container and its type.
1960
 * Returns true if the iteration should continue.
1961
 */
1962
static inline bool container_iterate(const container_t *c, uint8_t type,
1963
                                     uint32_t base, roaring_iterator iterator,
1964
0
                                     void *ptr) {
1965
0
    c = container_unwrap_shared(c, &type);
1966
0
    switch (type) {
1967
0
        case BITSET_CONTAINER_TYPE:
1968
0
            return bitset_container_iterate(const_CAST_bitset(c), base,
1969
0
                                            iterator, ptr);
1970
0
        case ARRAY_CONTAINER_TYPE:
1971
0
            return array_container_iterate(const_CAST_array(c), base, iterator,
1972
0
                                           ptr);
1973
0
        case RUN_CONTAINER_TYPE:
1974
0
            return run_container_iterate(const_CAST_run(c), base, iterator,
1975
0
                                         ptr);
1976
0
        default:
1977
0
            assert(false);
1978
0
            roaring_unreachable;
1979
0
    }
1980
0
    assert(false);
1981
0
    roaring_unreachable;
1982
0
    return false;
1983
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_iterate
Unexecuted instantiation: containers.c:container_iterate
Unexecuted instantiation: roaring.c:container_iterate
Unexecuted instantiation: roaring64.c:container_iterate
Unexecuted instantiation: roaring_array.c:container_iterate
Unexecuted instantiation: convert.c:container_iterate
Unexecuted instantiation: mixed_negation.c:container_iterate
Unexecuted instantiation: mixed_xor.c:container_iterate
Unexecuted instantiation: mixed_andnot.c:container_iterate
1984
1985
static inline bool container_iterate64(const container_t *c, uint8_t type,
1986
                                       uint32_t base,
1987
                                       roaring_iterator64 iterator,
1988
0
                                       uint64_t high_bits, void *ptr) {
1989
0
    c = container_unwrap_shared(c, &type);
1990
0
    switch (type) {
1991
0
        case BITSET_CONTAINER_TYPE:
1992
0
            return bitset_container_iterate64(const_CAST_bitset(c), base,
1993
0
                                              iterator, high_bits, ptr);
1994
0
        case ARRAY_CONTAINER_TYPE:
1995
0
            return array_container_iterate64(const_CAST_array(c), base,
1996
0
                                             iterator, high_bits, ptr);
1997
0
        case RUN_CONTAINER_TYPE:
1998
0
            return run_container_iterate64(const_CAST_run(c), base, iterator,
1999
0
                                           high_bits, ptr);
2000
0
        default:
2001
0
            assert(false);
2002
0
            roaring_unreachable;
2003
0
    }
2004
0
    assert(false);
2005
0
    roaring_unreachable;
2006
0
    return false;
2007
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_iterate64
Unexecuted instantiation: containers.c:container_iterate64
Unexecuted instantiation: roaring.c:container_iterate64
Unexecuted instantiation: roaring64.c:container_iterate64
Unexecuted instantiation: roaring_array.c:container_iterate64
Unexecuted instantiation: convert.c:container_iterate64
Unexecuted instantiation: mixed_negation.c:container_iterate64
Unexecuted instantiation: mixed_xor.c:container_iterate64
Unexecuted instantiation: mixed_andnot.c:container_iterate64
2008
2009
static inline container_t *container_not(const container_t *c, uint8_t type,
2010
0
                                         uint8_t *result_type) {
2011
0
    c = container_unwrap_shared(c, &type);
2012
0
    container_t *result = NULL;
2013
0
    switch (type) {
2014
0
        case BITSET_CONTAINER_TYPE:
2015
0
            *result_type =
2016
0
                bitset_container_negation(const_CAST_bitset(c), &result)
2017
0
                    ? BITSET_CONTAINER_TYPE
2018
0
                    : ARRAY_CONTAINER_TYPE;
2019
0
            return result;
2020
0
        case ARRAY_CONTAINER_TYPE:
2021
0
            result = bitset_container_create();
2022
0
            *result_type = BITSET_CONTAINER_TYPE;
2023
0
            array_container_negation(const_CAST_array(c), CAST_bitset(result));
2024
0
            return result;
2025
0
        case RUN_CONTAINER_TYPE:
2026
0
            *result_type =
2027
0
                (uint8_t)run_container_negation(const_CAST_run(c), &result);
2028
0
            return result;
2029
2030
0
        default:
2031
0
            assert(false);
2032
0
            roaring_unreachable;
2033
0
    }
2034
0
    assert(false);
2035
0
    roaring_unreachable;
2036
0
    return NULL;
2037
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_not
Unexecuted instantiation: containers.c:container_not
Unexecuted instantiation: roaring.c:container_not
Unexecuted instantiation: roaring64.c:container_not
Unexecuted instantiation: roaring_array.c:container_not
Unexecuted instantiation: convert.c:container_not
Unexecuted instantiation: mixed_negation.c:container_not
Unexecuted instantiation: mixed_xor.c:container_not
Unexecuted instantiation: mixed_andnot.c:container_not
2038
2039
static inline container_t *container_not_range(const container_t *c,
2040
                                               uint8_t type,
2041
                                               uint32_t range_start,
2042
                                               uint32_t range_end,
2043
0
                                               uint8_t *result_type) {
2044
0
    c = container_unwrap_shared(c, &type);
2045
0
    container_t *result = NULL;
2046
0
    switch (type) {
2047
0
        case BITSET_CONTAINER_TYPE:
2048
0
            *result_type =
2049
0
                bitset_container_negation_range(const_CAST_bitset(c),
2050
0
                                                range_start, range_end, &result)
2051
0
                    ? BITSET_CONTAINER_TYPE
2052
0
                    : ARRAY_CONTAINER_TYPE;
2053
0
            return result;
2054
0
        case ARRAY_CONTAINER_TYPE:
2055
0
            *result_type =
2056
0
                array_container_negation_range(const_CAST_array(c), range_start,
2057
0
                                               range_end, &result)
2058
0
                    ? BITSET_CONTAINER_TYPE
2059
0
                    : ARRAY_CONTAINER_TYPE;
2060
0
            return result;
2061
0
        case RUN_CONTAINER_TYPE:
2062
0
            *result_type = (uint8_t)run_container_negation_range(
2063
0
                const_CAST_run(c), range_start, range_end, &result);
2064
0
            return result;
2065
2066
0
        default:
2067
0
            assert(false);
2068
0
            roaring_unreachable;
2069
0
    }
2070
0
    assert(false);
2071
0
    roaring_unreachable;
2072
0
    return NULL;
2073
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_not_range
Unexecuted instantiation: containers.c:container_not_range
Unexecuted instantiation: roaring.c:container_not_range
Unexecuted instantiation: roaring64.c:container_not_range
Unexecuted instantiation: roaring_array.c:container_not_range
Unexecuted instantiation: convert.c:container_not_range
Unexecuted instantiation: mixed_negation.c:container_not_range
Unexecuted instantiation: mixed_xor.c:container_not_range
Unexecuted instantiation: mixed_andnot.c:container_not_range
2074
2075
static inline container_t *container_inot(container_t *c, uint8_t type,
2076
0
                                          uint8_t *result_type) {
2077
0
    c = get_writable_copy_if_shared(c, &type);
2078
0
    container_t *result = NULL;
2079
0
    switch (type) {
2080
0
        case BITSET_CONTAINER_TYPE:
2081
0
            *result_type =
2082
0
                bitset_container_negation_inplace(CAST_bitset(c), &result)
2083
0
                    ? BITSET_CONTAINER_TYPE
2084
0
                    : ARRAY_CONTAINER_TYPE;
2085
0
            return result;
2086
0
        case ARRAY_CONTAINER_TYPE:
2087
            // will never be inplace
2088
0
            result = bitset_container_create();
2089
0
            *result_type = BITSET_CONTAINER_TYPE;
2090
0
            array_container_negation(CAST_array(c), CAST_bitset(result));
2091
0
            array_container_free(CAST_array(c));
2092
0
            return result;
2093
0
        case RUN_CONTAINER_TYPE:
2094
0
            *result_type =
2095
0
                (uint8_t)run_container_negation_inplace(CAST_run(c), &result);
2096
0
            return result;
2097
2098
0
        default:
2099
0
            assert(false);
2100
0
            roaring_unreachable;
2101
0
    }
2102
0
    assert(false);
2103
0
    roaring_unreachable;
2104
0
    return NULL;
2105
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_inot
Unexecuted instantiation: containers.c:container_inot
Unexecuted instantiation: roaring.c:container_inot
Unexecuted instantiation: roaring64.c:container_inot
Unexecuted instantiation: roaring_array.c:container_inot
Unexecuted instantiation: convert.c:container_inot
Unexecuted instantiation: mixed_negation.c:container_inot
Unexecuted instantiation: mixed_xor.c:container_inot
Unexecuted instantiation: mixed_andnot.c:container_inot
2106
2107
static inline container_t *container_inot_range(container_t *c, uint8_t type,
2108
                                                uint32_t range_start,
2109
                                                uint32_t range_end,
2110
0
                                                uint8_t *result_type) {
2111
0
    c = get_writable_copy_if_shared(c, &type);
2112
0
    container_t *result = NULL;
2113
0
    switch (type) {
2114
0
        case BITSET_CONTAINER_TYPE:
2115
0
            *result_type = bitset_container_negation_range_inplace(
2116
0
                               CAST_bitset(c), range_start, range_end, &result)
2117
0
                               ? BITSET_CONTAINER_TYPE
2118
0
                               : ARRAY_CONTAINER_TYPE;
2119
0
            return result;
2120
0
        case ARRAY_CONTAINER_TYPE:
2121
0
            *result_type = array_container_negation_range_inplace(
2122
0
                               CAST_array(c), range_start, range_end, &result)
2123
0
                               ? BITSET_CONTAINER_TYPE
2124
0
                               : ARRAY_CONTAINER_TYPE;
2125
0
            return result;
2126
0
        case RUN_CONTAINER_TYPE:
2127
0
            *result_type = (uint8_t)run_container_negation_range_inplace(
2128
0
                CAST_run(c), range_start, range_end, &result);
2129
0
            return result;
2130
2131
0
        default:
2132
0
            assert(false);
2133
0
            roaring_unreachable;
2134
0
    }
2135
0
    assert(false);
2136
0
    roaring_unreachable;
2137
0
    return NULL;
2138
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_inot_range
Unexecuted instantiation: containers.c:container_inot_range
Unexecuted instantiation: roaring.c:container_inot_range
Unexecuted instantiation: roaring64.c:container_inot_range
Unexecuted instantiation: roaring_array.c:container_inot_range
Unexecuted instantiation: convert.c:container_inot_range
Unexecuted instantiation: mixed_negation.c:container_inot_range
Unexecuted instantiation: mixed_xor.c:container_inot_range
Unexecuted instantiation: mixed_andnot.c:container_inot_range
2139
2140
/**
2141
 * If the element of given rank is in this container, supposing that
2142
 * the first
2143
 * element has rank start_rank, then the function returns true and
2144
 * sets element
2145
 * accordingly.
2146
 * Otherwise, it returns false and update start_rank.
2147
 */
2148
static inline bool container_select(const container_t *c, uint8_t type,
2149
                                    uint32_t *start_rank, uint32_t rank,
2150
0
                                    uint32_t *element) {
2151
0
    c = container_unwrap_shared(c, &type);
2152
0
    switch (type) {
2153
0
        case BITSET_CONTAINER_TYPE:
2154
0
            return bitset_container_select(const_CAST_bitset(c), start_rank,
2155
0
                                           rank, element);
2156
0
        case ARRAY_CONTAINER_TYPE:
2157
0
            return array_container_select(const_CAST_array(c), start_rank, rank,
2158
0
                                          element);
2159
0
        case RUN_CONTAINER_TYPE:
2160
0
            return run_container_select(const_CAST_run(c), start_rank, rank,
2161
0
                                        element);
2162
0
        default:
2163
0
            assert(false);
2164
0
            roaring_unreachable;
2165
0
    }
2166
0
    assert(false);
2167
0
    roaring_unreachable;
2168
0
    return false;
2169
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_select
Unexecuted instantiation: containers.c:container_select
Unexecuted instantiation: roaring.c:container_select
Unexecuted instantiation: roaring64.c:container_select
Unexecuted instantiation: roaring_array.c:container_select
Unexecuted instantiation: convert.c:container_select
Unexecuted instantiation: mixed_negation.c:container_select
Unexecuted instantiation: mixed_xor.c:container_select
Unexecuted instantiation: mixed_andnot.c:container_select
2170
2171
0
static inline uint16_t container_maximum(const container_t *c, uint8_t type) {
2172
0
    c = container_unwrap_shared(c, &type);
2173
0
    switch (type) {
2174
0
        case BITSET_CONTAINER_TYPE:
2175
0
            return bitset_container_maximum(const_CAST_bitset(c));
2176
0
        case ARRAY_CONTAINER_TYPE:
2177
0
            return array_container_maximum(const_CAST_array(c));
2178
0
        case RUN_CONTAINER_TYPE:
2179
0
            return run_container_maximum(const_CAST_run(c));
2180
0
        default:
2181
0
            assert(false);
2182
0
            roaring_unreachable;
2183
0
    }
2184
0
    assert(false);
2185
0
    roaring_unreachable;
2186
0
    return false;
2187
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_maximum
Unexecuted instantiation: containers.c:container_maximum
Unexecuted instantiation: roaring.c:container_maximum
Unexecuted instantiation: roaring64.c:container_maximum
Unexecuted instantiation: roaring_array.c:container_maximum
Unexecuted instantiation: convert.c:container_maximum
Unexecuted instantiation: mixed_negation.c:container_maximum
Unexecuted instantiation: mixed_xor.c:container_maximum
Unexecuted instantiation: mixed_andnot.c:container_maximum
2188
2189
0
static inline uint16_t container_minimum(const container_t *c, uint8_t type) {
2190
0
    c = container_unwrap_shared(c, &type);
2191
0
    switch (type) {
2192
0
        case BITSET_CONTAINER_TYPE:
2193
0
            return bitset_container_minimum(const_CAST_bitset(c));
2194
0
        case ARRAY_CONTAINER_TYPE:
2195
0
            return array_container_minimum(const_CAST_array(c));
2196
0
        case RUN_CONTAINER_TYPE:
2197
0
            return run_container_minimum(const_CAST_run(c));
2198
0
        default:
2199
0
            assert(false);
2200
0
            roaring_unreachable;
2201
0
    }
2202
0
    assert(false);
2203
0
    roaring_unreachable;
2204
0
    return false;
2205
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_minimum
Unexecuted instantiation: containers.c:container_minimum
Unexecuted instantiation: roaring.c:container_minimum
Unexecuted instantiation: roaring64.c:container_minimum
Unexecuted instantiation: roaring_array.c:container_minimum
Unexecuted instantiation: convert.c:container_minimum
Unexecuted instantiation: mixed_negation.c:container_minimum
Unexecuted instantiation: mixed_xor.c:container_minimum
Unexecuted instantiation: mixed_andnot.c:container_minimum
2206
2207
// number of values smaller or equal to x
2208
static inline int container_rank(const container_t *c, uint8_t type,
2209
0
                                 uint16_t x) {
2210
0
    c = container_unwrap_shared(c, &type);
2211
0
    switch (type) {
2212
0
        case BITSET_CONTAINER_TYPE:
2213
0
            return bitset_container_rank(const_CAST_bitset(c), x);
2214
0
        case ARRAY_CONTAINER_TYPE:
2215
0
            return array_container_rank(const_CAST_array(c), x);
2216
0
        case RUN_CONTAINER_TYPE:
2217
0
            return run_container_rank(const_CAST_run(c), x);
2218
0
        default:
2219
0
            assert(false);
2220
0
            roaring_unreachable;
2221
0
    }
2222
0
    assert(false);
2223
0
    roaring_unreachable;
2224
0
    return false;
2225
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_rank
Unexecuted instantiation: containers.c:container_rank
Unexecuted instantiation: roaring.c:container_rank
Unexecuted instantiation: roaring64.c:container_rank
Unexecuted instantiation: roaring_array.c:container_rank
Unexecuted instantiation: convert.c:container_rank
Unexecuted instantiation: mixed_negation.c:container_rank
Unexecuted instantiation: mixed_xor.c:container_rank
Unexecuted instantiation: mixed_andnot.c:container_rank
2226
2227
// bulk version of container_rank(); return number of consumed elements
2228
static inline uint32_t container_rank_many(const container_t *c, uint8_t type,
2229
                                           uint64_t start_rank,
2230
                                           const uint32_t *begin,
2231
0
                                           const uint32_t *end, uint64_t *ans) {
2232
0
    c = container_unwrap_shared(c, &type);
2233
0
    switch (type) {
2234
0
        case BITSET_CONTAINER_TYPE:
2235
0
            return bitset_container_rank_many(const_CAST_bitset(c), start_rank,
2236
0
                                              begin, end, ans);
2237
0
        case ARRAY_CONTAINER_TYPE:
2238
0
            return array_container_rank_many(const_CAST_array(c), start_rank,
2239
0
                                             begin, end, ans);
2240
0
        case RUN_CONTAINER_TYPE:
2241
0
            return run_container_rank_many(const_CAST_run(c), start_rank, begin,
2242
0
                                           end, ans);
2243
0
        default:
2244
0
            assert(false);
2245
0
            roaring_unreachable;
2246
0
    }
2247
0
    assert(false);
2248
0
    roaring_unreachable;
2249
0
    return 0;
2250
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_rank_many
Unexecuted instantiation: containers.c:container_rank_many
Unexecuted instantiation: roaring.c:container_rank_many
Unexecuted instantiation: roaring64.c:container_rank_many
Unexecuted instantiation: roaring_array.c:container_rank_many
Unexecuted instantiation: convert.c:container_rank_many
Unexecuted instantiation: mixed_negation.c:container_rank_many
Unexecuted instantiation: mixed_xor.c:container_rank_many
Unexecuted instantiation: mixed_andnot.c:container_rank_many
2251
2252
// return the index of x, if not exsist return -1
2253
static inline int container_get_index(const container_t *c, uint8_t type,
2254
0
                                      uint16_t x) {
2255
0
    c = container_unwrap_shared(c, &type);
2256
0
    switch (type) {
2257
0
        case BITSET_CONTAINER_TYPE:
2258
0
            return bitset_container_get_index(const_CAST_bitset(c), x);
2259
0
        case ARRAY_CONTAINER_TYPE:
2260
0
            return array_container_get_index(const_CAST_array(c), x);
2261
0
        case RUN_CONTAINER_TYPE:
2262
0
            return run_container_get_index(const_CAST_run(c), x);
2263
0
        default:
2264
0
            assert(false);
2265
0
            roaring_unreachable;
2266
0
    }
2267
0
    assert(false);
2268
0
    roaring_unreachable;
2269
0
    return false;
2270
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_get_index
Unexecuted instantiation: containers.c:container_get_index
Unexecuted instantiation: roaring.c:container_get_index
Unexecuted instantiation: roaring64.c:container_get_index
Unexecuted instantiation: roaring_array.c:container_get_index
Unexecuted instantiation: convert.c:container_get_index
Unexecuted instantiation: mixed_negation.c:container_get_index
Unexecuted instantiation: mixed_xor.c:container_get_index
Unexecuted instantiation: mixed_andnot.c:container_get_index
2271
2272
/**
2273
 * Add all values in range [min, max] to a given container.
2274
 *
2275
 * If the returned pointer is different from $container, then a new container
2276
 * has been created and the caller is responsible for freeing it.
2277
 * The type of the first container may change. Returns the modified
2278
 * (and possibly new) container.
2279
 */
2280
static inline container_t *container_add_range(container_t *c, uint8_t type,
2281
                                               uint32_t min, uint32_t max,
2282
0
                                               uint8_t *result_type) {
2283
    // NB: when selecting new container type, we perform only inexpensive checks
2284
0
    switch (type) {
2285
0
        case BITSET_CONTAINER_TYPE: {
2286
0
            bitset_container_t *bitset = CAST_bitset(c);
2287
2288
0
            int32_t union_cardinality = 0;
2289
0
            union_cardinality += bitset->cardinality;
2290
0
            union_cardinality += max - min + 1;
2291
0
            union_cardinality -=
2292
0
                bitset_lenrange_cardinality(bitset->words, min, max - min);
2293
2294
0
            if (union_cardinality == INT32_C(0x10000)) {
2295
0
                *result_type = RUN_CONTAINER_TYPE;
2296
0
                return run_container_create_range(0, INT32_C(0x10000));
2297
0
            } else {
2298
0
                *result_type = BITSET_CONTAINER_TYPE;
2299
0
                bitset_set_lenrange(bitset->words, min, max - min);
2300
0
                bitset->cardinality = union_cardinality;
2301
0
                return bitset;
2302
0
            }
2303
0
        }
2304
0
        case ARRAY_CONTAINER_TYPE: {
2305
0
            array_container_t *array = CAST_array(c);
2306
2307
0
            int32_t nvals_greater =
2308
0
                count_greater(array->array, array->cardinality, (uint16_t)max);
2309
0
            int32_t nvals_less =
2310
0
                count_less(array->array, array->cardinality - nvals_greater,
2311
0
                           (uint16_t)min);
2312
0
            int32_t union_cardinality =
2313
0
                nvals_less + (max - min + 1) + nvals_greater;
2314
2315
0
            if (union_cardinality == INT32_C(0x10000)) {
2316
0
                *result_type = RUN_CONTAINER_TYPE;
2317
0
                return run_container_create_range(0, INT32_C(0x10000));
2318
0
            } else if (union_cardinality <= DEFAULT_MAX_SIZE) {
2319
0
                *result_type = ARRAY_CONTAINER_TYPE;
2320
0
                array_container_add_range_nvals(array, min, max, nvals_less,
2321
0
                                                nvals_greater);
2322
0
                return array;
2323
0
            } else {
2324
0
                *result_type = BITSET_CONTAINER_TYPE;
2325
0
                bitset_container_t *bitset = bitset_container_from_array(array);
2326
0
                bitset_set_lenrange(bitset->words, min, max - min);
2327
0
                bitset->cardinality = union_cardinality;
2328
0
                return bitset;
2329
0
            }
2330
0
        }
2331
0
        case RUN_CONTAINER_TYPE: {
2332
0
            run_container_t *run = CAST_run(c);
2333
2334
0
            int32_t nruns_greater =
2335
0
                rle16_count_greater(run->runs, run->n_runs, (uint16_t)max);
2336
0
            int32_t nruns_less = rle16_count_less(
2337
0
                run->runs, run->n_runs - nruns_greater, (uint16_t)min);
2338
2339
0
            int32_t run_size_bytes =
2340
0
                (nruns_less + 1 + nruns_greater) * sizeof(rle16_t);
2341
0
            int32_t bitset_size_bytes =
2342
0
                BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
2343
2344
0
            if (run_size_bytes <= bitset_size_bytes) {
2345
0
                run_container_add_range_nruns(run, min, max, nruns_less,
2346
0
                                              nruns_greater);
2347
0
                *result_type = RUN_CONTAINER_TYPE;
2348
0
                return run;
2349
0
            } else {
2350
0
                return container_from_run_range(run, min, max, result_type);
2351
0
            }
2352
0
        }
2353
0
        default:
2354
0
            roaring_unreachable;
2355
0
    }
2356
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_add_range
Unexecuted instantiation: containers.c:container_add_range
Unexecuted instantiation: roaring.c:container_add_range
Unexecuted instantiation: roaring64.c:container_add_range
Unexecuted instantiation: roaring_array.c:container_add_range
Unexecuted instantiation: convert.c:container_add_range
Unexecuted instantiation: mixed_negation.c:container_add_range
Unexecuted instantiation: mixed_xor.c:container_add_range
Unexecuted instantiation: mixed_andnot.c:container_add_range
2357
2358
/*
2359
 * Removes all elements in range [min, max].
2360
 * Returns one of:
2361
 *   - NULL if no elements left
2362
 *   - pointer to the original container
2363
 *   - pointer to a newly-allocated container (if it is more efficient)
2364
 *
2365
 * If the returned pointer is different from $container, then a new container
2366
 * has been created and the caller is responsible for freeing the original
2367
 * container.
2368
 */
2369
static inline container_t *container_remove_range(container_t *c, uint8_t type,
2370
                                                  uint32_t min, uint32_t max,
2371
0
                                                  uint8_t *result_type) {
2372
0
    switch (type) {
2373
0
        case BITSET_CONTAINER_TYPE: {
2374
0
            bitset_container_t *bitset = CAST_bitset(c);
2375
2376
0
            int32_t result_cardinality =
2377
0
                bitset->cardinality -
2378
0
                bitset_lenrange_cardinality(bitset->words, min, max - min);
2379
2380
0
            if (result_cardinality == 0) {
2381
0
                return NULL;
2382
0
            } else if (result_cardinality <= DEFAULT_MAX_SIZE) {
2383
0
                *result_type = ARRAY_CONTAINER_TYPE;
2384
0
                bitset_reset_range(bitset->words, min, max + 1);
2385
0
                bitset->cardinality = result_cardinality;
2386
0
                return array_container_from_bitset(bitset);
2387
0
            } else {
2388
0
                *result_type = BITSET_CONTAINER_TYPE;
2389
0
                bitset_reset_range(bitset->words, min, max + 1);
2390
0
                bitset->cardinality = result_cardinality;
2391
0
                return bitset;
2392
0
            }
2393
0
        }
2394
0
        case ARRAY_CONTAINER_TYPE: {
2395
0
            array_container_t *array = CAST_array(c);
2396
2397
0
            int32_t nvals_greater =
2398
0
                count_greater(array->array, array->cardinality, (uint16_t)max);
2399
0
            int32_t nvals_less =
2400
0
                count_less(array->array, array->cardinality - nvals_greater,
2401
0
                           (uint16_t)min);
2402
0
            int32_t result_cardinality = nvals_less + nvals_greater;
2403
2404
0
            if (result_cardinality == 0) {
2405
0
                return NULL;
2406
0
            } else {
2407
0
                *result_type = ARRAY_CONTAINER_TYPE;
2408
0
                array_container_remove_range(
2409
0
                    array, nvals_less, array->cardinality - result_cardinality);
2410
0
                return array;
2411
0
            }
2412
0
        }
2413
0
        case RUN_CONTAINER_TYPE: {
2414
0
            run_container_t *run = CAST_run(c);
2415
2416
0
            if (run->n_runs == 0) {
2417
0
                return NULL;
2418
0
            }
2419
0
            if (min <= run_container_minimum(run) &&
2420
0
                max >= run_container_maximum(run)) {
2421
0
                return NULL;
2422
0
            }
2423
2424
0
            run_container_remove_range(run, min, max);
2425
0
            return convert_run_to_efficient_container(run, result_type);
2426
0
        }
2427
0
        default:
2428
0
            roaring_unreachable;
2429
0
    }
2430
0
}
Unexecuted instantiation: croaring_fuzzer.c:container_remove_range
Unexecuted instantiation: containers.c:container_remove_range
Unexecuted instantiation: roaring.c:container_remove_range
Unexecuted instantiation: roaring64.c:container_remove_range
Unexecuted instantiation: roaring_array.c:container_remove_range
Unexecuted instantiation: convert.c:container_remove_range
Unexecuted instantiation: mixed_negation.c:container_remove_range
Unexecuted instantiation: mixed_xor.c:container_remove_range
Unexecuted instantiation: mixed_andnot.c:container_remove_range
2431
2432
#ifdef __cplusplus
2433
using api::roaring_container_iterator_t;
2434
#endif
2435
2436
/**
2437
 * Initializes the iterator at the first entry in the container.
2438
 */
2439
roaring_container_iterator_t container_init_iterator(const container_t *c,
2440
                                                     uint8_t typecode,
2441
                                                     uint16_t *value);
2442
2443
/**
2444
 * Initializes the iterator at the last entry in the container.
2445
 */
2446
roaring_container_iterator_t container_init_iterator_last(const container_t *c,
2447
                                                          uint8_t typecode,
2448
                                                          uint16_t *value);
2449
2450
/**
2451
 * Moves the iterator to the next entry. Returns true and sets `value` if a
2452
 * value is present.
2453
 */
2454
inline bool container_iterator_next(const container_t *c, uint8_t typecode,
2455
                                    roaring_container_iterator_t *it,
2456
0
                                    uint16_t *value) {
2457
0
    switch (typecode) {
2458
0
        case BITSET_CONTAINER_TYPE: {
2459
0
            const bitset_container_t *bc = const_CAST_bitset(c);
2460
0
            it->index++;
2461
2462
0
            uint32_t wordindex = it->index / 64;
2463
0
            if (wordindex >= BITSET_CONTAINER_SIZE_IN_WORDS) {
2464
0
                return false;
2465
0
            }
2466
2467
0
            uint64_t word =
2468
0
                bc->words[wordindex] & (UINT64_MAX << (it->index % 64));
2469
            // next part could be optimized/simplified
2470
0
            while (word == 0 &&
2471
0
                   (wordindex + 1 < BITSET_CONTAINER_SIZE_IN_WORDS)) {
2472
0
                wordindex++;
2473
0
                word = bc->words[wordindex];
2474
0
            }
2475
0
            if (word != 0) {
2476
0
                it->index = wordindex * 64 + roaring_trailing_zeroes(word);
2477
0
                *value = it->index;
2478
0
                return true;
2479
0
            }
2480
0
            return false;
2481
0
        }
2482
0
        case ARRAY_CONTAINER_TYPE: {
2483
0
            const array_container_t *ac = const_CAST_array(c);
2484
0
            it->index++;
2485
0
            if (it->index < ac->cardinality) {
2486
0
                *value = ac->array[it->index];
2487
0
                return true;
2488
0
            }
2489
0
            return false;
2490
0
        }
2491
0
        case RUN_CONTAINER_TYPE: {
2492
0
            if (*value == UINT16_MAX) {  // Avoid overflow to zero
2493
0
                return false;
2494
0
            }
2495
2496
0
            const run_container_t *rc = const_CAST_run(c);
2497
0
            uint32_t limit =
2498
0
                rc->runs[it->index].value + rc->runs[it->index].length;
2499
0
            if (*value < limit) {
2500
0
                (*value)++;
2501
0
                return true;
2502
0
            }
2503
2504
0
            it->index++;
2505
0
            if (it->index < rc->n_runs) {
2506
0
                *value = rc->runs[it->index].value;
2507
0
                return true;
2508
0
            }
2509
0
            return false;
2510
0
        }
2511
0
        default:
2512
0
            assert(false);
2513
0
            roaring_unreachable;
2514
0
            return false;
2515
0
    }
2516
0
}
2517
2518
/**
2519
 * Moves the iterator to the previous entry. Returns true and sets `value` if a
2520
 * value is present.
2521
 */
2522
inline bool container_iterator_prev(const container_t *c, uint8_t typecode,
2523
                                    roaring_container_iterator_t *it,
2524
0
                                    uint16_t *value) {
2525
0
    switch (typecode) {
2526
0
        case BITSET_CONTAINER_TYPE: {
2527
0
            if (--it->index < 0) {
2528
0
                return false;
2529
0
            }
2530
2531
0
            const bitset_container_t *bc = const_CAST_bitset(c);
2532
0
            int32_t wordindex = it->index / 64;
2533
0
            uint64_t word =
2534
0
                bc->words[wordindex] & (UINT64_MAX >> (63 - (it->index % 64)));
2535
2536
0
            while (word == 0 && --wordindex >= 0) {
2537
0
                word = bc->words[wordindex];
2538
0
            }
2539
0
            if (word == 0) {
2540
0
                return false;
2541
0
            }
2542
2543
0
            it->index = (wordindex * 64) + (63 - roaring_leading_zeroes(word));
2544
0
            *value = it->index;
2545
0
            return true;
2546
0
        }
2547
0
        case ARRAY_CONTAINER_TYPE: {
2548
0
            if (--it->index < 0) {
2549
0
                return false;
2550
0
            }
2551
0
            const array_container_t *ac = const_CAST_array(c);
2552
0
            *value = ac->array[it->index];
2553
0
            return true;
2554
0
        }
2555
0
        case RUN_CONTAINER_TYPE: {
2556
0
            if (*value == 0) {
2557
0
                return false;
2558
0
            }
2559
2560
0
            const run_container_t *rc = const_CAST_run(c);
2561
0
            (*value)--;
2562
0
            if (*value >= rc->runs[it->index].value) {
2563
0
                return true;
2564
0
            }
2565
2566
0
            if (--it->index < 0) {
2567
0
                return false;
2568
0
            }
2569
2570
0
            *value = rc->runs[it->index].value + rc->runs[it->index].length;
2571
0
            return true;
2572
0
        }
2573
0
        default:
2574
0
            assert(false);
2575
0
            roaring_unreachable;
2576
0
            return false;
2577
0
    }
2578
0
}
2579
2580
/**
2581
 * Moves the iterator to the smallest entry that is greater than or equal to
2582
 * `val`. Returns true and sets `value_out` if a value is present. `value_out`
2583
 * should be initialized to a value.
2584
 */
2585
bool container_iterator_lower_bound(const container_t *c, uint8_t typecode,
2586
                                    roaring_container_iterator_t *it,
2587
                                    uint16_t *value_out, uint16_t val);
2588
2589
/**
2590
 * Reads up to `count` entries from the container, and writes them into `buf`
2591
 * as `high16 | entry`. Returns true and sets `value_out` if a value is present
2592
 * after reading the entries. Sets `consumed` to the number of values read.
2593
 * `count` should be greater than zero.
2594
 */
2595
bool container_iterator_read_into_uint32(const container_t *c, uint8_t typecode,
2596
                                         roaring_container_iterator_t *it,
2597
                                         uint32_t high16, uint32_t *buf,
2598
                                         uint32_t count, uint32_t *consumed,
2599
                                         uint16_t *value_out);
2600
2601
/**
2602
 * Reads up to `count` entries from the container, and writes them into `buf`
2603
 * as `high48 | entry`. Returns true and sets `value_out` if a value is present
2604
 * after reading the entries. Sets `consumed` to the number of values read.
2605
 * `count` should be greater than zero.
2606
 */
2607
bool container_iterator_read_into_uint64(const container_t *c, uint8_t typecode,
2608
                                         roaring_container_iterator_t *it,
2609
                                         uint64_t high48, uint64_t *buf,
2610
                                         uint32_t count, uint32_t *consumed,
2611
                                         uint16_t *value_out);
2612
2613
/**
2614
 * Reads up to `count` entries backward from the container, writing them into
2615
 * `buf` as `high16 | entry` in descending order. Returns true and sets
2616
 * `value_out` if a value is present before the entries read. Sets `consumed`
2617
 * to the number of values read. `count` should be greater than zero.
2618
 *
2619
 * `value_out` must be initialized to the current value yielded by the iterator.
2620
 */
2621
bool container_iterator_read_backward_into_uint32(
2622
    const container_t *c, uint8_t typecode, roaring_container_iterator_t *it,
2623
    uint32_t high16, uint32_t *buf, uint32_t count, uint32_t *consumed,
2624
    uint16_t *value_out);
2625
2626
/**
2627
 * Reads up to `count` entries backward from the container, writing them into
2628
 * `buf` as `high48 | entry` in descending order. Returns true and sets
2629
 * `value_out` if a value is present before the entries read. Sets `consumed`
2630
 * to the number of values read. `count` should be greater than zero.
2631
 *
2632
 * `value_out` must be initialized to the current value yielded by the iterator.
2633
 */
2634
bool container_iterator_read_backward_into_uint64(
2635
    const container_t *c, uint8_t typecode, roaring_container_iterator_t *it,
2636
    uint64_t high48, uint64_t *buf, uint32_t count, uint32_t *consumed,
2637
    uint16_t *value_out);
2638
2639
/**
2640
 * Skips the next `skip_count` entries in the container iterator. Returns true
2641
 * and sets `value_out` if a value is present after skipping. Returns false if
2642
 * the end of the container is reached during the skip operation. Sets
2643
 * consumed_count to the number of values actually skipped (which may be less
2644
 * than skip_count if the end of the container is reached).
2645
 *
2646
 * value_out must be initialized to the previous value yielded by the iterator.
2647
 *
2648
 * skip_count must be greater than zero.
2649
 */
2650
bool container_iterator_skip(const container_t *c, uint8_t typecode,
2651
                             roaring_container_iterator_t *it,
2652
                             uint32_t skip_count, uint32_t *consumed_count,
2653
                             uint16_t *value_out);
2654
2655
/**
2656
 * Skips the previous `skip_count` entries in the container iterator (moves
2657
 * backwards). Returns true and sets `value_out` if a value is present after
2658
 * skipping backwards. Returns false if the beginning of the container is
2659
 * reached during the skip operation. Sets consumed_count to the number of
2660
 * values actually skipped backwards (which may be less than skip_count if
2661
 * the beginning of the container is reached).
2662
 *
2663
 * value_out must be initialized to the current value yielded by the iterator.
2664
 *
2665
 * skip_count must be greater than zero.
2666
 */
2667
bool container_iterator_skip_backward(const container_t *c, uint8_t typecode,
2668
                                      roaring_container_iterator_t *it,
2669
                                      uint32_t skip_count,
2670
                                      uint32_t *consumed_count,
2671
                                      uint16_t *value_out);
2672
2673
/**
2674
 * Finds the end of the consecutive run starting at the current iterator
2675
 * position within a container. Returns the low16 of the last consecutive
2676
 * value. If there are more values in the container after the run,
2677
 * *has_more is set to true, the iterator is positioned at the next value,
2678
 * and *value is updated to that value. Otherwise *has_more is set to false.
2679
 *
2680
 * *value must be the low 16 bits of the current value at the iterator's
2681
 * position on entry.
2682
 */
2683
uint16_t container_iterator_find_run_end(const container_t *c, uint8_t typecode,
2684
                                         roaring_container_iterator_t *it,
2685
                                         uint16_t *value, bool *has_more);
2686
2687
/**
2688
 * Finds the start of the consecutive run ending at the current iterator
2689
 * position within a container. Returns the low16 of the first consecutive
2690
 * value. If there are more values in the container before the run,
2691
 * *has_more is set to true, the iterator is positioned at the previous value,
2692
 * and *value is updated to that value. Otherwise *has_more is set to false.
2693
 *
2694
 * *value must be the low 16 bits of the current value at the iterator's
2695
 * position on entry.
2696
 */
2697
uint16_t container_iterator_find_run_start(const container_t *c,
2698
                                           uint8_t typecode,
2699
                                           roaring_container_iterator_t *it,
2700
                                           uint16_t *value, bool *has_more);
2701
2702
#ifdef __cplusplus
2703
}
2704
}
2705
}  // extern "C" { namespace roaring { namespace internal {
2706
#endif
2707
2708
#endif