Coverage Report

Created: 2026-06-10 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/croaring/include/roaring/roaring_array.h
Line
Count
Source
1
/*
2
 * roaring_array.h
3
 *
4
 * This file declares the roaring_array helper structure and the operations
5
 * used to manage it. A roaring array is the top-level index used by a 32-bit
6
 * Roaring bitmap: it stores sorted 16-bit high keys alongside the container
7
 * pointers and type codes associated with each key.
8
 *
9
 * In effect, it is the directory that maps each populated 16-bit chunk of the
10
 * 32-bit value space to the container holding that chunk's low 16-bit values.
11
 * The functions in this header handle allocation, lookup, insertion,
12
 * replacement, copying, serialization support, and structural updates on that
13
 * directory.
14
 */
15
#ifndef INCLUDE_ROARING_ARRAY_H
16
#define INCLUDE_ROARING_ARRAY_H
17
18
#include <assert.h>
19
#include <stdbool.h>
20
#include <stdint.h>
21
22
#include <roaring/array_util.h>
23
#include <roaring/containers/containers.h>  // get_writable_copy_if_shared()
24
25
#ifdef __cplusplus
26
extern "C" {
27
namespace roaring {
28
29
// Note: in pure C++ code, you should avoid putting `using` in header files
30
using api::roaring_array_t;
31
32
namespace internal {
33
#endif
34
35
enum {
36
    SERIAL_COOKIE_NO_RUNCONTAINER = 12346,
37
    SERIAL_COOKIE = 12347,
38
    FROZEN_COOKIE = 13766,
39
    NO_OFFSET_THRESHOLD = 4
40
};
41
42
/**
43
 * Create a new roaring array
44
 */
45
roaring_array_t *ra_create(void);
46
47
/**
48
 * Initialize an existing roaring array with the specified capacity (in number
49
 * of containers)
50
 */
51
bool ra_init_with_capacity(roaring_array_t *new_ra, uint32_t cap);
52
53
/**
54
 * Initialize with zero capacity
55
 */
56
void ra_init(roaring_array_t *t);
57
58
/**
59
 * Copies this roaring array, we assume that dest is not initialized
60
 */
61
bool ra_copy(const roaring_array_t *source, roaring_array_t *dest,
62
             bool copy_on_write);
63
64
/*
65
 * Shrinks the capacity, returns the number of bytes saved.
66
 */
67
int ra_shrink_to_fit(roaring_array_t *ra);
68
69
/**
70
 * Copies this roaring array, we assume that dest is initialized
71
 */
72
bool ra_overwrite(const roaring_array_t *source, roaring_array_t *dest,
73
                  bool copy_on_write);
74
75
/**
76
 * Frees the memory used by a roaring array
77
 */
78
void ra_clear(roaring_array_t *r);
79
80
/**
81
 * Frees the memory used by a roaring array, but does not free the containers
82
 */
83
void ra_clear_without_containers(roaring_array_t *r);
84
85
/**
86
 * Frees just the containers
87
 */
88
void ra_clear_containers(roaring_array_t *ra);
89
90
/**
91
 * Get the index corresponding to a 16-bit key
92
 */
93
87.2k
inline int32_t ra_get_index(const roaring_array_t *ra, uint16_t x) {
94
87.2k
    if ((ra->size == 0) || ra->keys[ra->size - 1] == x) return ra->size - 1;
95
42.0k
    return binarySearch(ra->keys, (int32_t)ra->size, x);
96
87.2k
}
97
98
/**
99
 * Retrieves the container at index i, filling in the typecode
100
 */
101
inline container_t *ra_get_container_at_index(const roaring_array_t *ra,
102
573k
                                              uint16_t i, uint8_t *typecode) {
103
573k
    *typecode = ra->typecodes[i];
104
573k
    return ra->containers[i];
105
573k
}
106
107
/**
108
 * Retrieves the key at index i
109
 */
110
430k
inline uint16_t ra_get_key_at_index(const roaring_array_t *ra, uint16_t i) {
111
430k
    return ra->keys[i];
112
430k
}
113
114
/**
115
 * Add a new key-value pair at index i
116
 */
117
void ra_insert_new_key_value_at(roaring_array_t *ra, int32_t i, uint16_t key,
118
                                container_t *c, uint8_t typecode);
119
120
/**
121
 * Append a new key-value pair
122
 */
123
void ra_append(roaring_array_t *ra, uint16_t key, container_t *c,
124
               uint8_t typecode);
125
126
/**
127
 * Append a new key-value pair to ra, cloning (in COW sense) a value from sa
128
 * at index index
129
 */
130
void ra_append_copy(roaring_array_t *ra, const roaring_array_t *sa,
131
                    uint16_t index, bool copy_on_write);
132
133
/**
134
 * Append new key-value pairs to ra, cloning (in COW sense)  values from sa
135
 * at indexes
136
 * [start_index, end_index)
137
 */
138
void ra_append_copy_range(roaring_array_t *ra, const roaring_array_t *sa,
139
                          int32_t start_index, int32_t end_index,
140
                          bool copy_on_write);
141
142
/** appends from sa to ra, ending with the greatest key that is
143
 * is less or equal stopping_key
144
 */
145
void ra_append_copies_until(roaring_array_t *ra, const roaring_array_t *sa,
146
                            uint16_t stopping_key, bool copy_on_write);
147
148
/** appends from sa to ra, starting with the smallest key that is
149
 * is strictly greater than before_start
150
 */
151
152
void ra_append_copies_after(roaring_array_t *ra, const roaring_array_t *sa,
153
                            uint16_t before_start, bool copy_on_write);
154
155
/**
156
 * Move the key-value pairs to ra from sa at indexes
157
 * [start_index, end_index), old array should not be freed
158
 * (use ra_clear_without_containers)
159
 **/
160
void ra_append_move_range(roaring_array_t *ra, roaring_array_t *sa,
161
                          int32_t start_index, int32_t end_index);
162
/**
163
 * Append new key-value pairs to ra,  from sa at indexes
164
 * [start_index, end_index)
165
 */
166
void ra_append_range(roaring_array_t *ra, roaring_array_t *sa,
167
                     int32_t start_index, int32_t end_index,
168
                     bool copy_on_write);
169
170
/**
171
 * Set the container at the corresponding index using the specified
172
 * typecode.
173
 */
174
inline void ra_set_container_at_index(const roaring_array_t *ra, int32_t i,
175
113k
                                      container_t *c, uint8_t typecode) {
176
113k
    assert(i < ra->size);
177
113k
    ra->containers[i] = c;
178
113k
    ra->typecodes[i] = typecode;
179
113k
}
180
181
container_t *ra_get_container(roaring_array_t *ra, uint16_t x,
182
                              uint8_t *typecode);
183
184
/**
185
 * If needed, increase the capacity of the array so that it can fit k values
186
 * (at
187
 * least);
188
 */
189
bool extend_array(roaring_array_t *ra, int32_t k);
190
191
13.5k
inline int32_t ra_get_size(const roaring_array_t *ra) { return ra->size; }
192
193
static inline int32_t ra_advance_until(const roaring_array_t *ra, uint16_t x,
194
497
                                       int32_t pos) {
195
497
    return advanceUntil(ra->keys, pos, ra->size, x);
196
497
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::ra_advance_until(roaring::api::roaring_array_s const*, unsigned short, int)
roaring.c:ra_advance_until
Line
Count
Source
194
497
                                       int32_t pos) {
195
497
    return advanceUntil(ra->keys, pos, ra->size, x);
196
497
}
Unexecuted instantiation: roaring_array.c:ra_advance_until
Unexecuted instantiation: croaring_fuzzer.c:ra_advance_until
Unexecuted instantiation: roaring64.c:ra_advance_until
197
198
int32_t ra_advance_until_freeing(roaring_array_t *ra, uint16_t x, int32_t pos);
199
200
void ra_downsize(roaring_array_t *ra, int32_t new_length);
201
202
inline void ra_replace_key_and_container_at_index(roaring_array_t *ra,
203
                                                  int32_t i, uint16_t key,
204
                                                  container_t *c,
205
155k
                                                  uint8_t typecode) {
206
155k
    assert(i < ra->size);
207
208
155k
    ra->keys[i] = key;
209
155k
    ra->containers[i] = c;
210
155k
    ra->typecodes[i] = typecode;
211
155k
}
212
213
// write set bits to an array
214
void ra_to_uint32_array(const roaring_array_t *ra, uint32_t *ans);
215
216
/**
217
 * write a bitmap to a buffer. This is meant to be compatible with
218
 * the
219
 * Java and Go versions. Return the size in bytes of the serialized
220
 * output (which should be ra_portable_size_in_bytes(ra)).
221
 */
222
size_t ra_portable_serialize(const roaring_array_t *ra, char *buf);
223
224
/**
225
 * read a bitmap from a serialized version. This is meant to be compatible
226
 * with the Java and Go versions.
227
 * maxbytes  indicates how many bytes available from buf.
228
 * When the function returns true, roaring_array_t is populated with the data
229
 * and *readbytes indicates how many bytes were read. In all cases, if the
230
 * function returns true, then maxbytes >= *readbytes.
231
 */
232
bool ra_portable_deserialize(roaring_array_t *ra, const char *buf,
233
                             const size_t maxbytes, size_t *readbytes);
234
235
/**
236
 * Quickly checks whether there is a serialized bitmap at the pointer,
237
 * not exceeding size "maxbytes" in bytes. This function does not allocate
238
 * memory dynamically.
239
 *
240
 * This function returns 0 if and only if no valid bitmap is found.
241
 * Otherwise, it returns how many bytes are occupied by the bitmap data.
242
 */
243
size_t ra_portable_deserialize_size(const char *buf, const size_t maxbytes);
244
245
/**
246
 * How many bytes are required to serialize this bitmap (meant to be
247
 * compatible
248
 * with Java and Go versions)
249
 */
250
size_t ra_portable_size_in_bytes(const roaring_array_t *ra);
251
252
/**
253
 * return true if it contains at least one run container.
254
 */
255
bool ra_has_run_container(const roaring_array_t *ra);
256
257
/**
258
 * Size of the header when serializing (meant to be compatible
259
 * with Java and Go versions)
260
 */
261
uint32_t ra_portable_header_size(const roaring_array_t *ra);
262
263
/**
264
 * If the container at the index i is share, unshare it (creating a local
265
 * copy if needed).
266
 */
267
static inline void ra_unshare_container_at_index(roaring_array_t *ra,
268
64.7k
                                                 uint16_t i) {
269
    assert(i < ra->size);
270
64.7k
    ra->containers[i] =
271
64.7k
        get_writable_copy_if_shared(ra->containers[i], &ra->typecodes[i]);
272
64.7k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::ra_unshare_container_at_index(roaring::api::roaring_array_s*, unsigned short)
roaring.c:ra_unshare_container_at_index
Line
Count
Source
268
64.7k
                                                 uint16_t i) {
269
    assert(i < ra->size);
270
64.7k
    ra->containers[i] =
271
64.7k
        get_writable_copy_if_shared(ra->containers[i], &ra->typecodes[i]);
272
64.7k
}
Unexecuted instantiation: roaring_array.c:ra_unshare_container_at_index
Unexecuted instantiation: croaring_fuzzer.c:ra_unshare_container_at_index
Unexecuted instantiation: roaring64.c:ra_unshare_container_at_index
273
274
/**
275
 * remove at index i, sliding over all entries after i
276
 */
277
void ra_remove_at_index(roaring_array_t *ra, int32_t i);
278
279
/**
280
 * clears all containers, sets the size at 0 and shrinks the memory usage.
281
 */
282
void ra_reset(roaring_array_t *ra);
283
284
/**
285
 * remove at index i, sliding over all entries after i. Free removed container.
286
 */
287
void ra_remove_at_index_and_free(roaring_array_t *ra, int32_t i);
288
289
/**
290
 * remove a chunk of indices, sliding over entries after it
291
 */
292
// void ra_remove_index_range(roaring_array_t *ra, int32_t begin, int32_t end);
293
294
// used in inplace andNot only, to slide left the containers from
295
// the mutated RoaringBitmap that are after the largest container of
296
// the argument RoaringBitmap.  It is followed by a call to resize.
297
//
298
void ra_copy_range(roaring_array_t *ra, uint32_t begin, uint32_t end,
299
                   uint32_t new_begin);
300
301
/**
302
 * Shifts rightmost $count containers to the left (distance < 0) or
303
 * to the right (distance > 0).
304
 * Allocates memory if necessary.
305
 * This function doesn't free or create new containers.
306
 * Caller is responsible for that.
307
 */
308
void ra_shift_tail(roaring_array_t *ra, int32_t count, int32_t distance);
309
310
#ifdef __cplusplus
311
}  // namespace internal
312
}
313
}  // extern "C" { namespace roaring {
314
#endif
315
316
#endif