/var/local/thirdparty/installed/include/roaring/roaring.hh
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | A C++ header for Roaring Bitmaps. |
3 | | */ |
4 | | #ifndef INCLUDE_ROARING_HH_ |
5 | | #define INCLUDE_ROARING_HH_ |
6 | | |
7 | | #include <cstdarg> |
8 | | |
9 | | #include <algorithm> |
10 | | #include <initializer_list> |
11 | | #include <new> |
12 | | #include <stdexcept> |
13 | | #include <string> |
14 | | |
15 | | #if !defined(ROARING_EXCEPTIONS) |
16 | | // __cpp_exceptions is required by C++98 and we require C++11 or better. |
17 | | #ifndef __cpp_exceptions |
18 | | #error "__cpp_exceptions should be defined" |
19 | | #endif |
20 | | # if __cpp_exceptions |
21 | | # define ROARING_EXCEPTIONS 1 |
22 | | # else |
23 | | # define ROARING_EXCEPTIONS 0 |
24 | | # endif |
25 | | #endif |
26 | | |
27 | | #ifndef ROARING_TERMINATE |
28 | | # if ROARING_EXCEPTIONS |
29 | 0 | # define ROARING_TERMINATE(_s) throw std::runtime_error(_s) |
30 | | # else |
31 | | # define ROARING_TERMINATE(_s) std::terminate() |
32 | | # endif |
33 | | #endif |
34 | | |
35 | | #define ROARING_API_NOT_IN_GLOBAL_NAMESPACE // see remarks in roaring.h |
36 | | #include <roaring/roaring.h> |
37 | | #undef ROARING_API_NOT_IN_GLOBAL_NAMESPACE |
38 | | |
39 | | #include <roaring/roaring_array.h> // roaring::internal array functions used |
40 | | |
41 | | namespace roaring { |
42 | | |
43 | | class RoaringSetBitForwardIterator; |
44 | | |
45 | | /** |
46 | | * A bit of context usable with `*Bulk()` functions. |
47 | | * |
48 | | * A context may only be used with a single bitmap, and any modification to a bitmap |
49 | | * (other than modifications performed with `Bulk()` functions with the context |
50 | | * passed) will invalidate any contexts associated with that bitmap. |
51 | | */ |
52 | | class BulkContext { |
53 | | public: |
54 | | friend class Roaring; |
55 | | using roaring_bitmap_bulk_context_t = api::roaring_bulk_context_t; |
56 | 0 | BulkContext() : context_{nullptr, 0, 0, 0} {} |
57 | | |
58 | | BulkContext(const BulkContext&) = delete; |
59 | | BulkContext& operator=(const BulkContext&) = delete; |
60 | | BulkContext(BulkContext&&) noexcept = default; |
61 | | BulkContext& operator=(BulkContext&&) noexcept = default; |
62 | | |
63 | | private: |
64 | | roaring_bitmap_bulk_context_t context_; |
65 | | }; |
66 | | |
67 | | class Roaring { |
68 | | typedef api::roaring_bitmap_t roaring_bitmap_t; // class-local name alias |
69 | | |
70 | | public: |
71 | | /** |
72 | | * Create an empty bitmap in the existing memory for the class. |
73 | | * The bitmap will be in the "clear" state with no auxiliary allocations. |
74 | | */ |
75 | 46.0k | Roaring() : roaring{} { |
76 | | // The empty constructor roaring{} silences warnings from pedantic static analyzers. |
77 | 46.0k | api::roaring_bitmap_init_cleared(&roaring); |
78 | 46.0k | } |
79 | | |
80 | | /** |
81 | | * Construct a bitmap from a list of 32-bit integer values. |
82 | | */ |
83 | 0 | Roaring(size_t n, const uint32_t *data) : Roaring() { |
84 | 0 | api::roaring_bitmap_add_many(&roaring, n, data); |
85 | 0 | } |
86 | | |
87 | | /** |
88 | | * Construct a bitmap from an initializer list. |
89 | | */ |
90 | 0 | Roaring(std::initializer_list<uint32_t> l) : Roaring() { |
91 | 0 | addMany(l.size(), l.begin()); |
92 | 0 | } |
93 | | |
94 | | /** |
95 | | * Copy constructor. |
96 | | * It may throw std::runtime_error if there is insufficient memory. |
97 | | */ |
98 | | Roaring(const Roaring &r) : Roaring() { |
99 | | if (!api::roaring_bitmap_overwrite(&roaring, &r.roaring)) { |
100 | | ROARING_TERMINATE("failed roaring_bitmap_overwrite in constructor"); |
101 | | } |
102 | | api::roaring_bitmap_set_copy_on_write( |
103 | | &roaring, |
104 | | api::roaring_bitmap_get_copy_on_write(&r.roaring)); |
105 | | } |
106 | | |
107 | | /** |
108 | | * Move constructor. The moved-from object remains valid but empty, i.e. |
109 | | * it behaves as though it was just freshly constructed. |
110 | | */ |
111 | | Roaring(Roaring &&r) noexcept : roaring(r.roaring) { |
112 | | // |
113 | | // !!! This clones the bits of the roaring structure to a new location |
114 | | // and then overwrites the old bits...assuming that this will still |
115 | | // work. There are scenarios where this could break; e.g. if some of |
116 | | // those bits were pointers into the structure memory itself. If such |
117 | | // things were possible, a roaring_bitmap_move() API would be needed. |
118 | | // |
119 | | api::roaring_bitmap_init_cleared(&r.roaring); |
120 | | } |
121 | | |
122 | | /** |
123 | | * Construct a roaring object by taking control of a malloc()'d C struct. |
124 | | * |
125 | | * Passing a NULL pointer is unsafe. |
126 | | * The pointer to the C struct will be invalid after the call. |
127 | | */ |
128 | 23.1k | explicit Roaring(roaring_bitmap_t *s) noexcept : roaring (*s) { |
129 | 23.1k | roaring_free(s); // deallocate the passed-in pointer |
130 | 23.1k | } |
131 | | |
132 | | /** |
133 | | * Construct a bitmap from a list of uint32_t values. |
134 | | */ |
135 | | static Roaring bitmapOf(size_t n, ...) { |
136 | | Roaring ans; |
137 | | va_list vl; |
138 | | va_start(vl, n); |
139 | | for (size_t i = 0; i < n; i++) { |
140 | | ans.add(va_arg(vl, uint32_t)); |
141 | | } |
142 | | va_end(vl); |
143 | | return ans; |
144 | | } |
145 | | |
146 | | /** |
147 | | * Construct a bitmap from a list of uint32_t values. |
148 | | * E.g., bitmapOfList({1,2,3}). |
149 | | */ |
150 | 0 | static Roaring bitmapOfList(std::initializer_list<uint32_t> l) { |
151 | 0 | Roaring ans; |
152 | 0 | ans.addMany(l.size(), l.begin()); |
153 | 0 | return ans; |
154 | 0 | } |
155 | | |
156 | | /** |
157 | | * Add value x |
158 | | */ |
159 | 3.11M | void add(uint32_t x) noexcept { api::roaring_bitmap_add(&roaring, x); } |
160 | | |
161 | | /** |
162 | | * Add value x |
163 | | * Returns true if a new value was added, false if the value was already |
164 | | * existing. |
165 | | */ |
166 | 0 | bool addChecked(uint32_t x) noexcept { |
167 | 0 | return api::roaring_bitmap_add_checked(&roaring, x); |
168 | 0 | } |
169 | | |
170 | | /** |
171 | | * Add all values in range [min, max) |
172 | | */ |
173 | | void addRange(const uint64_t min, const uint64_t max) noexcept { |
174 | | return api::roaring_bitmap_add_range(&roaring, min, max); |
175 | | } |
176 | | |
177 | | /** |
178 | | * Add all values in range [min, max] |
179 | | */ |
180 | 0 | void addRangeClosed(const uint32_t min, const uint32_t max) noexcept { |
181 | 0 | return api::roaring_bitmap_add_range_closed(&roaring, min, max); |
182 | 0 | } |
183 | | |
184 | | /** |
185 | | * Add value n_args from pointer vals |
186 | | */ |
187 | | void addMany(size_t n_args, const uint32_t *vals) noexcept { |
188 | | api::roaring_bitmap_add_many(&roaring, n_args, vals); |
189 | | } |
190 | | |
191 | | /** |
192 | | * Add value val, using context from a previous insert for speed |
193 | | * optimization. |
194 | | * |
195 | | * `context` will be used to store information between calls to make bulk |
196 | | * operations faster. `context` should be default-initialized before the |
197 | | * first call to this function. |
198 | | */ |
199 | 0 | void addBulk(BulkContext &context, uint32_t x) noexcept { |
200 | 0 | api::roaring_bitmap_add_bulk(&roaring, &context.context_, x); |
201 | 0 | } |
202 | | |
203 | | /** |
204 | | * Check if item x is present, using context from a previous insert or search |
205 | | * for speed optimization. |
206 | | * |
207 | | * `context` will be used to store information between calls to make bulk |
208 | | * operations faster. `context` should be default-initialized before the |
209 | | * first call to this function. |
210 | | */ |
211 | 0 | bool containsBulk(BulkContext& context, uint32_t x) const noexcept { |
212 | 0 | return api::roaring_bitmap_contains_bulk(&roaring, &context.context_, x); |
213 | 0 | } |
214 | | |
215 | | /** |
216 | | * Remove value x |
217 | | */ |
218 | | void remove(uint32_t x) noexcept { api::roaring_bitmap_remove(&roaring, x); } |
219 | | |
220 | | /** |
221 | | * Remove value x |
222 | | * Returns true if a new value was removed, false if the value was not |
223 | | * existing. |
224 | | */ |
225 | 0 | bool removeChecked(uint32_t x) noexcept { |
226 | 0 | return api::roaring_bitmap_remove_checked(&roaring, x); |
227 | 0 | } |
228 | | |
229 | | /** |
230 | | * Remove all values in range [min, max) |
231 | | */ |
232 | 0 | void removeRange(uint64_t min, uint64_t max) noexcept { |
233 | 0 | return api::roaring_bitmap_remove_range(&roaring, min, max); |
234 | 0 | } |
235 | | |
236 | | /** |
237 | | * Remove all values in range [min, max] |
238 | | */ |
239 | 0 | void removeRangeClosed(uint32_t min, uint32_t max) noexcept { |
240 | 0 | return api::roaring_bitmap_remove_range_closed(&roaring, min, max); |
241 | 0 | } |
242 | | |
243 | | /** |
244 | | * Return the largest value (if not empty) |
245 | | */ |
246 | | uint32_t maximum() const noexcept { return api::roaring_bitmap_maximum(&roaring); } |
247 | | |
248 | | /** |
249 | | * Return the smallest value (if not empty) |
250 | | */ |
251 | | uint32_t minimum() const noexcept { return api::roaring_bitmap_minimum(&roaring); } |
252 | | |
253 | | /** |
254 | | * Check if value x is present |
255 | | */ |
256 | | bool contains(uint32_t x) const noexcept { |
257 | | return api::roaring_bitmap_contains(&roaring, x); |
258 | | } |
259 | | |
260 | | /** |
261 | | * Check if all values from x (included) to y (excluded) are present |
262 | | */ |
263 | 0 | bool containsRange(const uint64_t x, const uint64_t y) const noexcept { |
264 | 0 | return api::roaring_bitmap_contains_range(&roaring, x, y); |
265 | 0 | } |
266 | | |
267 | | /** |
268 | | * Destructor. By contract, calling roaring_bitmap_clear() is enough to |
269 | | * release all auxiliary memory used by the structure. |
270 | | */ |
271 | 119k | ~Roaring() { |
272 | 119k | if (!(roaring.high_low_container.flags & ROARING_FLAG_FROZEN)) { |
273 | 119k | api::roaring_bitmap_clear(&roaring); |
274 | 119k | } else { |
275 | | // The roaring member variable copies the `roaring_bitmap_t` and |
276 | | // nested `roaring_array_t` structures by value and is freed in the |
277 | | // constructor, however the underlying memory arena used for the |
278 | | // container data is not freed with it. Here we derive the arena |
279 | | // pointer from the second arena allocation in |
280 | | // `roaring_bitmap_frozen_view` and free it as well. |
281 | 0 | roaring_bitmap_free( |
282 | 0 | (roaring_bitmap_t *)((char *) |
283 | 0 | roaring.high_low_container.containers - |
284 | 0 | sizeof(roaring_bitmap_t))); |
285 | 0 | } |
286 | 119k | } |
287 | | |
288 | | /** |
289 | | * Copies the content of the provided bitmap, and |
290 | | * discard the current content. |
291 | | * It may throw std::runtime_error if there is insufficient memory. |
292 | | */ |
293 | | Roaring &operator=(const Roaring &r) { |
294 | | if (!api::roaring_bitmap_overwrite(&roaring, &r.roaring)) { |
295 | | ROARING_TERMINATE("failed memory alloc in assignment"); |
296 | | } |
297 | | api::roaring_bitmap_set_copy_on_write( |
298 | | &roaring, |
299 | | api::roaring_bitmap_get_copy_on_write(&r.roaring)); |
300 | | return *this; |
301 | | } |
302 | | |
303 | | /** |
304 | | * Moves the content of the provided bitmap, and |
305 | | * discard the current content. |
306 | | */ |
307 | 3.07k | Roaring &operator=(Roaring &&r) noexcept { |
308 | 3.07k | api::roaring_bitmap_clear(&roaring); // free this class's allocations |
309 | | |
310 | | // !!! See notes in the Move Constructor regarding roaring_bitmap_move() |
311 | | // |
312 | 3.07k | roaring = r.roaring; |
313 | 3.07k | api::roaring_bitmap_init_cleared(&r.roaring); |
314 | | |
315 | 3.07k | return *this; |
316 | 3.07k | } |
317 | | |
318 | | /** |
319 | | * Assignment from an initializer list. |
320 | | */ |
321 | 0 | Roaring &operator=(std::initializer_list<uint32_t> l) { |
322 | 0 | // Delegate to move assignment operator |
323 | 0 | *this = Roaring(l); |
324 | 0 | return *this; |
325 | 0 | } |
326 | | |
327 | | /** |
328 | | * Compute the intersection between the current bitmap and the provided |
329 | | * bitmap, writing the result in the current bitmap. The provided bitmap |
330 | | * is not modified. |
331 | | * |
332 | | * Performance hint: if you are computing the intersection between several |
333 | | * bitmaps, two-by-two, it is best to start with the smallest bitmap. |
334 | | */ |
335 | | Roaring &operator&=(const Roaring &r) noexcept { |
336 | | api::roaring_bitmap_and_inplace(&roaring, &r.roaring); |
337 | | return *this; |
338 | | } |
339 | | |
340 | | /** |
341 | | * Compute the difference between the current bitmap and the provided |
342 | | * bitmap, writing the result in the current bitmap. The provided bitmap |
343 | | * is not modified. |
344 | | */ |
345 | | Roaring &operator-=(const Roaring &r) noexcept { |
346 | | api::roaring_bitmap_andnot_inplace(&roaring, &r.roaring); |
347 | | return *this; |
348 | | } |
349 | | |
350 | | /** |
351 | | * Compute the union between the current bitmap and the provided bitmap, |
352 | | * writing the result in the current bitmap. The provided bitmap is not |
353 | | * modified. |
354 | | * |
355 | | * See also the fastunion function to aggregate many bitmaps more quickly. |
356 | | */ |
357 | | Roaring &operator|=(const Roaring &r) noexcept { |
358 | | api::roaring_bitmap_or_inplace(&roaring, &r.roaring); |
359 | | return *this; |
360 | | } |
361 | | |
362 | | /** |
363 | | * Compute the symmetric union between the current bitmap and the provided |
364 | | * bitmap, writing the result in the current bitmap. The provided bitmap |
365 | | * is not modified. |
366 | | */ |
367 | | Roaring &operator^=(const Roaring &r) noexcept { |
368 | | api::roaring_bitmap_xor_inplace(&roaring, &r.roaring); |
369 | | return *this; |
370 | | } |
371 | | |
372 | | /** |
373 | | * Exchange the content of this bitmap with another. |
374 | | */ |
375 | 0 | void swap(Roaring &r) noexcept { std::swap(r.roaring, roaring); } |
376 | | |
377 | | /** |
378 | | * Get the cardinality of the bitmap (number of elements). |
379 | | */ |
380 | | uint64_t cardinality() const noexcept { |
381 | | return api::roaring_bitmap_get_cardinality(&roaring); |
382 | | } |
383 | | |
384 | | /** |
385 | | * Returns true if the bitmap is empty (cardinality is zero). |
386 | | */ |
387 | | bool isEmpty() const noexcept { return api::roaring_bitmap_is_empty(&roaring); } |
388 | | |
389 | | /** |
390 | | * Returns true if the bitmap is subset of the other. |
391 | | */ |
392 | 0 | bool isSubset(const Roaring &r) const noexcept { |
393 | 0 | return api::roaring_bitmap_is_subset(&roaring, &r.roaring); |
394 | 0 | } |
395 | | |
396 | | /** |
397 | | * Returns true if the bitmap is strict subset of the other. |
398 | | */ |
399 | 0 | bool isStrictSubset(const Roaring &r) const noexcept { |
400 | 0 | return api::roaring_bitmap_is_strict_subset(&roaring, &r.roaring); |
401 | 0 | } |
402 | | |
403 | | /** |
404 | | * Convert the bitmap to an array. Write the output to "ans", caller is |
405 | | * responsible to ensure that there is enough memory allocated |
406 | | * (e.g., ans = new uint32[mybitmap.cardinality()];) |
407 | | */ |
408 | 0 | void toUint32Array(uint32_t *ans) const noexcept { |
409 | 0 | api::roaring_bitmap_to_uint32_array(&roaring, ans); |
410 | 0 | } |
411 | | /** |
412 | | * To int array with pagination |
413 | | */ |
414 | 0 | void rangeUint32Array(uint32_t *ans, size_t offset, size_t limit) const noexcept { |
415 | 0 | api::roaring_bitmap_range_uint32_array(&roaring, offset, limit, ans); |
416 | 0 | } |
417 | | |
418 | | /** |
419 | | * Return true if the two bitmaps contain the same elements. |
420 | | */ |
421 | | bool operator==(const Roaring &r) const noexcept { |
422 | | return api::roaring_bitmap_equals(&roaring, &r.roaring); |
423 | | } |
424 | | |
425 | | /** |
426 | | * Compute the negation of the roaring bitmap within the half-open interval |
427 | | * [range_start, range_end). Areas outside the interval are unchanged. |
428 | | */ |
429 | 0 | void flip(uint64_t range_start, uint64_t range_end) noexcept { |
430 | 0 | api::roaring_bitmap_flip_inplace(&roaring, range_start, range_end); |
431 | 0 | } |
432 | | |
433 | | /** |
434 | | * Compute the negation of the roaring bitmap within the closed interval |
435 | | * [range_start, range_end]. Areas outside the interval are unchanged. |
436 | | */ |
437 | 0 | void flipClosed(uint32_t range_start, uint32_t range_end) noexcept { |
438 | 0 | api::roaring_bitmap_flip_inplace( |
439 | 0 | &roaring, range_start, uint64_t(range_end) + 1); |
440 | 0 | } |
441 | | |
442 | | /** |
443 | | * Remove run-length encoding even when it is more space efficient. |
444 | | * Return whether a change was applied. |
445 | | */ |
446 | 0 | bool removeRunCompression() noexcept { |
447 | 0 | return api::roaring_bitmap_remove_run_compression(&roaring); |
448 | 0 | } |
449 | | |
450 | | /** |
451 | | * Convert array and bitmap containers to run containers when it is more |
452 | | * efficient; also convert from run containers when more space efficient. |
453 | | * Returns true if the result has at least one run container. Additional |
454 | | * savings might be possible by calling shrinkToFit(). |
455 | | */ |
456 | 35.9k | bool runOptimize() noexcept { return api::roaring_bitmap_run_optimize(&roaring); } |
457 | | |
458 | | /** |
459 | | * If needed, reallocate memory to shrink the memory usage. Returns |
460 | | * the number of bytes saved. |
461 | | */ |
462 | | size_t shrinkToFit() noexcept { return api::roaring_bitmap_shrink_to_fit(&roaring); } |
463 | | |
464 | | /** |
465 | | * Iterate over the bitmap elements. The function iterator is called once |
466 | | * for all the values with ptr (can be NULL) as the second parameter of |
467 | | * each call. |
468 | | * |
469 | | * roaring_iterator is simply a pointer to a function that returns bool |
470 | | * (true means that the iteration should continue while false means that it |
471 | | * should stop), and takes (uint32_t,void*) as inputs. |
472 | | */ |
473 | 0 | void iterate(api::roaring_iterator iterator, void *ptr) const { |
474 | 0 | api::roaring_iterate(&roaring, iterator, ptr); |
475 | 0 | } |
476 | | |
477 | | /** |
478 | | * Selects the value at index rnk in the bitmap, where the smallest value |
479 | | * is at index 0. |
480 | | * |
481 | | * If the size of the roaring bitmap is strictly greater than rank, then |
482 | | * this function returns true and sets element to the element of given rank. |
483 | | * Otherwise, it returns false. |
484 | | */ |
485 | 0 | bool select(uint32_t rnk, uint32_t *element) const noexcept { |
486 | 0 | return api::roaring_bitmap_select(&roaring, rnk, element); |
487 | 0 | } |
488 | | |
489 | | /** |
490 | | * Computes the size of the intersection between two bitmaps. |
491 | | */ |
492 | | uint64_t and_cardinality(const Roaring &r) const noexcept { |
493 | | return api::roaring_bitmap_and_cardinality(&roaring, &r.roaring); |
494 | | } |
495 | | |
496 | | /** |
497 | | * Check whether the two bitmaps intersect. |
498 | | */ |
499 | 0 | bool intersect(const Roaring &r) const noexcept { |
500 | 0 | return api::roaring_bitmap_intersect(&roaring, &r.roaring); |
501 | 0 | } |
502 | | |
503 | | /** |
504 | | * Computes the Jaccard index between two bitmaps. (Also known as the |
505 | | * Tanimoto distance, |
506 | | * or the Jaccard similarity coefficient) |
507 | | * |
508 | | * The Jaccard index is undefined if both bitmaps are empty. |
509 | | */ |
510 | 0 | double jaccard_index(const Roaring &r) const noexcept { |
511 | 0 | return api::roaring_bitmap_jaccard_index(&roaring, &r.roaring); |
512 | 0 | } |
513 | | |
514 | | /** |
515 | | * Computes the size of the union between two bitmaps. |
516 | | */ |
517 | | uint64_t or_cardinality(const Roaring &r) const noexcept { |
518 | | return api::roaring_bitmap_or_cardinality(&roaring, &r.roaring); |
519 | | } |
520 | | |
521 | | /** |
522 | | * Computes the size of the difference (andnot) between two bitmaps. |
523 | | */ |
524 | 0 | uint64_t andnot_cardinality(const Roaring &r) const noexcept { |
525 | 0 | return api::roaring_bitmap_andnot_cardinality(&roaring, &r.roaring); |
526 | 0 | } |
527 | | |
528 | | /** |
529 | | * Computes the size of the symmetric difference (andnot) between two |
530 | | * bitmaps. |
531 | | */ |
532 | 0 | uint64_t xor_cardinality(const Roaring &r) const noexcept { |
533 | 0 | return api::roaring_bitmap_xor_cardinality(&roaring, &r.roaring); |
534 | 0 | } |
535 | | |
536 | | /** |
537 | | * Returns the number of integers that are smaller or equal to x. |
538 | | * Thus the rank of the smallest element is one. If |
539 | | * x is smaller than the smallest element, this function will return 0. |
540 | | * The rank and select functions differ in convention: this function returns |
541 | | * 1 when ranking the smallest value, but the select function returns the |
542 | | * smallest value when using index 0. |
543 | | */ |
544 | | uint64_t rank(uint32_t x) const noexcept { |
545 | | return api::roaring_bitmap_rank(&roaring, x); |
546 | | } |
547 | | |
548 | | /** |
549 | | * Get `rank()` values in bulk. The values in `[begin .. end)` must be in Ascending order. |
550 | | * possible implementation: for(auto* iter = begin; iter != end; ++iter) *(ans++) = rank(*iter); |
551 | | */ |
552 | 0 | void rank_many(const uint32_t* begin, const uint32_t* end, uint64_t* ans) const noexcept { |
553 | 0 | return api::roaring_bitmap_rank_many(&roaring, begin, end, ans); |
554 | 0 | } |
555 | | |
556 | | /** |
557 | | * Returns the index of x in the set, index start from 0. |
558 | | * If the set doesn't contain x , this function will return -1. |
559 | | * The difference with rank function is that this function will return -1 |
560 | | * when x isn't in the set, but the rank function will return a |
561 | | * non-negative number. |
562 | | */ |
563 | 0 | int64_t getIndex(uint32_t x) const noexcept { |
564 | 0 | return api::roaring_bitmap_get_index(&roaring, x); |
565 | 0 | } |
566 | | |
567 | | /** |
568 | | * Write a bitmap to a char buffer. This is meant to be compatible with |
569 | | * the Java and Go versions. Returns how many bytes were written which |
570 | | * should be getSizeInBytes(). |
571 | | * |
572 | | * Setting the portable flag to false enable a custom format that |
573 | | * can save space compared to the portable format (e.g., for very |
574 | | * sparse bitmaps). |
575 | | * |
576 | | * Boost users can serialize bitmaps in this manner: |
577 | | * |
578 | | * BOOST_SERIALIZATION_SPLIT_FREE(Roaring) |
579 | | * namespace boost { |
580 | | * namespace serialization { |
581 | | * |
582 | | * template <class Archive> |
583 | | * void save(Archive& ar, const Roaring& bitmask, |
584 | | * const unsigned int version) { |
585 | | * std::size_t expected_size_in_bytes = bitmask.getSizeInBytes(); |
586 | | * std::vector<char> buffer(expected_size_in_bytes); |
587 | | * std::size_t size_in_bytes = bitmask.write(buffer.data()); |
588 | | * |
589 | | * ar& size_in_bytes; |
590 | | * ar& boost::serialization::make_binary_object(buffer.data(), |
591 | | * size_in_bytes); |
592 | | * } |
593 | | * template <class Archive> |
594 | | * void load(Archive& ar, Roaring& bitmask, |
595 | | * const unsigned int version) { |
596 | | * std::size_t size_in_bytes = 0; |
597 | | * ar& size_in_bytes; |
598 | | * std::vector<char> buffer(size_in_bytes); |
599 | | * ar& boost::serialization::make_binary_object(buffer.data(), |
600 | | * size_in_bytes); |
601 | | * bitmask = Roaring::readSafe(buffer.data(), size_in_bytes); |
602 | | * } |
603 | | * } // namespace serialization |
604 | | * } // namespace boost |
605 | | */ |
606 | 39.3k | size_t write(char *buf, bool portable = true) const noexcept { |
607 | 39.3k | if (portable) { |
608 | 15.7k | return api::roaring_bitmap_portable_serialize(&roaring, buf); |
609 | 23.5k | } else { |
610 | 23.5k | return api::roaring_bitmap_serialize(&roaring, buf); |
611 | 23.5k | } |
612 | 39.3k | } |
613 | | |
614 | | /** |
615 | | * Read a bitmap from a serialized version. This is meant to be compatible |
616 | | * with the Java and Go versions. |
617 | | * |
618 | | * Setting the portable flag to false enable a custom format that |
619 | | * can save space compared to the portable format (e.g., for very |
620 | | * sparse bitmaps). |
621 | | * |
622 | | * This function is unsafe in the sense that if you provide bad data, |
623 | | * many, many bytes could be read. See also readSafe. |
624 | | * |
625 | | * The function may throw std::runtime_error if a bitmap could not be read. Not that even |
626 | | * if it does not throw, the bitmap could still be unusable if the loaded |
627 | | * data does not match the portable Roaring specification: you should |
628 | | * ensure that the data you load come from a serialized bitmap. |
629 | | */ |
630 | 23.1k | static Roaring read(const char *buf, bool portable = true) { |
631 | 23.1k | roaring_bitmap_t * r = portable |
632 | 23.1k | ? api::roaring_bitmap_portable_deserialize(buf) |
633 | 23.1k | : api::roaring_bitmap_deserialize(buf); |
634 | 23.1k | if (r == NULL) { |
635 | 0 | ROARING_TERMINATE("failed alloc while reading"); |
636 | 0 | } |
637 | 23.1k | return Roaring(r); |
638 | 23.1k | } |
639 | | |
640 | | /** |
641 | | * Read a bitmap from a serialized version, reading no more than maxbytes |
642 | | * bytes. This is meant to be compatible with the Java and Go versions. |
643 | | * The function itself is safe in the sense that it will not cause buffer overflows. |
644 | | * However, for correct operations, it is assumed that the bitmap read was once |
645 | | * serialized from a valid bitmap. If you provided an incorrect input (garbage), then the |
646 | | * bitmap read may not be in a valid state and following operations may not lead |
647 | | * to sensible results. It is your responsability to ensure that the input bytes |
648 | | * follow the format specification if you want a usable bitmap: |
649 | | * https://github.com/RoaringBitmap/RoaringFormatSpec |
650 | | * In particular, the serialized array containers need to be in sorted order, and the |
651 | | * run containers should be in sorted non-overlapping order. This is is guaranteed to |
652 | | * happen when serializing an existing bitmap, but not for random inputs. |
653 | | * Note that this function assumes that your bitmap was serialized in *portable* mode |
654 | | * (which is the default with the 'write' method). |
655 | | * |
656 | | * The function may throw std::runtime_error if a bitmap could not be read. Not that even |
657 | | * if it does not throw, the bitmap could still be unusable if the loaded |
658 | | * data does not match the portable Roaring specification: you should |
659 | | * ensure that the data you load come from a serialized bitmap. |
660 | | */ |
661 | 0 | static Roaring readSafe(const char *buf, size_t maxbytes) { |
662 | 0 | roaring_bitmap_t * r = |
663 | 0 | api::roaring_bitmap_portable_deserialize_safe(buf,maxbytes); |
664 | 0 | if (r == NULL) { |
665 | 0 | ROARING_TERMINATE("failed alloc while reading"); |
666 | 0 | } |
667 | 0 | return Roaring(r); |
668 | 0 | } |
669 | | |
670 | | /** |
671 | | * How many bytes are required to serialize this bitmap (meant to be |
672 | | * compatible with Java and Go versions) |
673 | | * |
674 | | * Setting the portable flag to false enable a custom format that |
675 | | * can save space compared to the portable format (e.g., for very |
676 | | * sparse bitmaps). |
677 | | */ |
678 | 66.0k | size_t getSizeInBytes(bool portable = true) const noexcept { |
679 | 66.0k | if (portable) { |
680 | 19.8k | return api::roaring_bitmap_portable_size_in_bytes(&roaring); |
681 | 46.1k | } else { |
682 | 46.1k | return api::roaring_bitmap_size_in_bytes(&roaring); |
683 | 46.1k | } |
684 | 66.0k | } |
685 | | |
686 | | /** |
687 | | * For advanced users. |
688 | | * This function may throw std::runtime_error. |
689 | | */ |
690 | 0 | static const Roaring frozenView(const char *buf, size_t length) { |
691 | 0 | const roaring_bitmap_t *s = |
692 | 0 | api::roaring_bitmap_frozen_view(buf, length); |
693 | 0 | if (s == NULL) { |
694 | 0 | ROARING_TERMINATE("failed to read frozen bitmap"); |
695 | 0 | } |
696 | 0 | Roaring r; |
697 | 0 | r.roaring = *s; |
698 | 0 | return r; |
699 | 0 | } |
700 | | |
701 | | /** |
702 | | * For advanced users. |
703 | | */ |
704 | 0 | void writeFrozen(char *buf) const noexcept { |
705 | 0 | roaring_bitmap_frozen_serialize(&roaring, buf); |
706 | 0 | } |
707 | | |
708 | | /** |
709 | | * For advanced users. |
710 | | */ |
711 | 0 | size_t getFrozenSizeInBytes() const noexcept { |
712 | 0 | return roaring_bitmap_frozen_size_in_bytes(&roaring); |
713 | 0 | } |
714 | | |
715 | | /** |
716 | | * Computes the intersection between two bitmaps and returns new bitmap. |
717 | | * The current bitmap and the provided bitmap are unchanged. |
718 | | * |
719 | | * Performance hint: if you are computing the intersection between several |
720 | | * bitmaps, two-by-two, it is best to start with the smallest bitmap. |
721 | | * Consider also using the operator &= to avoid needlessly creating |
722 | | * many temporary bitmaps. |
723 | | * This function may throw std::runtime_error. |
724 | | */ |
725 | 0 | Roaring operator&(const Roaring &o) const { |
726 | 0 | roaring_bitmap_t *r = api::roaring_bitmap_and(&roaring, &o.roaring); |
727 | 0 | if (r == NULL) { |
728 | 0 | ROARING_TERMINATE("failed materalization in and"); |
729 | 0 | } |
730 | 0 | return Roaring(r); |
731 | 0 | } |
732 | | |
733 | | /** |
734 | | * Computes the difference between two bitmaps and returns new bitmap. |
735 | | * The current bitmap and the provided bitmap are unchanged. |
736 | | * This function may throw std::runtime_error. |
737 | | */ |
738 | 0 | Roaring operator-(const Roaring &o) const { |
739 | 0 | roaring_bitmap_t *r = api::roaring_bitmap_andnot(&roaring, &o.roaring); |
740 | 0 | if (r == NULL) { |
741 | 0 | ROARING_TERMINATE("failed materalization in andnot"); |
742 | 0 | } |
743 | 0 | return Roaring(r); |
744 | 0 | } |
745 | | |
746 | | /** |
747 | | * Computes the union between two bitmaps and returns new bitmap. |
748 | | * The current bitmap and the provided bitmap are unchanged. |
749 | | * This function may throw std::runtime_error. |
750 | | */ |
751 | 0 | Roaring operator|(const Roaring &o) const { |
752 | 0 | roaring_bitmap_t *r = api::roaring_bitmap_or(&roaring, &o.roaring); |
753 | 0 | if (r == NULL) { |
754 | 0 | ROARING_TERMINATE("failed materalization in or"); |
755 | 0 | } |
756 | 0 | return Roaring(r); |
757 | 0 | } |
758 | | |
759 | | /** |
760 | | * Computes the symmetric union between two bitmaps and returns new bitmap. |
761 | | * The current bitmap and the provided bitmap are unchanged. |
762 | | * This function may throw std::runtime_error. |
763 | | */ |
764 | 0 | Roaring operator^(const Roaring &o) const { |
765 | 0 | roaring_bitmap_t *r = api::roaring_bitmap_xor(&roaring, &o.roaring); |
766 | 0 | if (r == NULL) { |
767 | 0 | ROARING_TERMINATE("failed materalization in xor"); |
768 | 0 | } |
769 | 0 | return Roaring(r); |
770 | 0 | } |
771 | | |
772 | | /** |
773 | | * Whether or not we apply copy and write. |
774 | | */ |
775 | | void setCopyOnWrite(bool val) noexcept { |
776 | | api::roaring_bitmap_set_copy_on_write(&roaring, val); |
777 | | } |
778 | | |
779 | | /** |
780 | | * Print the content of the bitmap |
781 | | */ |
782 | 0 | void printf() const noexcept { api::roaring_bitmap_printf(&roaring); } |
783 | | |
784 | | /** |
785 | | * Print the content of the bitmap into a string |
786 | | */ |
787 | 0 | std::string toString() const noexcept { |
788 | 0 | struct iter_data { |
789 | 0 | std::string str{}; // The empty constructor silences warnings from pedantic static analyzers. |
790 | 0 | char first_char = '{'; |
791 | 0 | } outer_iter_data; |
792 | 0 | if (!isEmpty()) { |
793 | 0 | iterate( |
794 | 0 | [](uint32_t value, void *inner_iter_data) -> bool { |
795 | 0 | ((iter_data *)inner_iter_data)->str += |
796 | 0 | ((iter_data *)inner_iter_data)->first_char; |
797 | 0 | ((iter_data *)inner_iter_data)->str += |
798 | 0 | std::to_string(value); |
799 | 0 | ((iter_data *)inner_iter_data)->first_char = ','; |
800 | 0 | return true; |
801 | 0 | }, |
802 | 0 | (void *)&outer_iter_data); |
803 | 0 | } else |
804 | 0 | outer_iter_data.str = '{'; |
805 | 0 | outer_iter_data.str += '}'; |
806 | 0 | return outer_iter_data.str; |
807 | 0 | } |
808 | | |
809 | | /** |
810 | | * Whether or not copy and write is active. |
811 | | */ |
812 | 0 | bool getCopyOnWrite() const noexcept { |
813 | 0 | return api::roaring_bitmap_get_copy_on_write(&roaring); |
814 | 0 | } |
815 | | |
816 | | /** |
817 | | * Computes the logical or (union) between "n" bitmaps (referenced by a |
818 | | * pointer). |
819 | | * This function may throw std::runtime_error. |
820 | | */ |
821 | 0 | static Roaring fastunion(size_t n, const Roaring **inputs) { |
822 | 0 | const roaring_bitmap_t **x = |
823 | 0 | (const roaring_bitmap_t **)roaring_malloc(n * sizeof(roaring_bitmap_t *)); |
824 | 0 | if (x == NULL) { |
825 | 0 | ROARING_TERMINATE("failed memory alloc in fastunion"); |
826 | 0 | } |
827 | 0 | for (size_t k = 0; k < n; ++k) x[k] = &inputs[k]->roaring; |
828 | 0 |
|
829 | 0 | roaring_bitmap_t *c_ans = api::roaring_bitmap_or_many(n, x); |
830 | 0 | if (c_ans == NULL) { |
831 | 0 | roaring_free(x); |
832 | 0 | ROARING_TERMINATE("failed memory alloc in fastunion"); |
833 | 0 | } |
834 | 0 | Roaring ans(c_ans); |
835 | 0 | roaring_free(x); |
836 | 0 | return ans; |
837 | 0 | } |
838 | | |
839 | | typedef RoaringSetBitForwardIterator const_iterator; |
840 | | |
841 | | /** |
842 | | * Returns an iterator that can be used to access the position of the set |
843 | | * bits. The running time complexity of a full scan is proportional to the |
844 | | * number of set bits: be aware that if you have long strings of 1s, this |
845 | | * can be very inefficient. |
846 | | * |
847 | | * It can be much faster to use the toArray method if you want to retrieve |
848 | | * the set bits. |
849 | | */ |
850 | | const_iterator begin() const; |
851 | | |
852 | | /** |
853 | | * A bogus iterator that can be used together with begin() |
854 | | * for constructions such as for (auto i = b.begin(); * i!=b.end(); ++i) {} |
855 | | */ |
856 | | const_iterator &end() const; |
857 | | |
858 | | roaring_bitmap_t roaring; |
859 | | }; |
860 | | |
861 | | /** |
862 | | * Used to go through the set bits. Not optimally fast, but convenient. |
863 | | */ |
864 | | class RoaringSetBitForwardIterator final { |
865 | | public: |
866 | | typedef std::forward_iterator_tag iterator_category; |
867 | | typedef uint32_t *pointer; |
868 | | typedef uint32_t &reference_type; |
869 | | typedef uint32_t value_type; |
870 | | typedef int32_t difference_type; |
871 | | typedef RoaringSetBitForwardIterator type_of_iterator; |
872 | | |
873 | | /** |
874 | | * Provides the location of the set bit. |
875 | | */ |
876 | 325k | value_type operator*() const { return i.current_value; } |
877 | | |
878 | 0 | bool operator<(const type_of_iterator &o) const { |
879 | 0 | if (!i.has_value) return false; |
880 | 0 | if (!o.i.has_value) return true; |
881 | 0 | return i.current_value < *o; |
882 | 0 | } |
883 | | |
884 | 0 | bool operator<=(const type_of_iterator &o) const { |
885 | 0 | if (!o.i.has_value) return true; |
886 | 0 | if (!i.has_value) return false; |
887 | 0 | return i.current_value <= *o; |
888 | 0 | } |
889 | | |
890 | 0 | bool operator>(const type_of_iterator &o) const { |
891 | 0 | if (!o.i.has_value) return false; |
892 | 0 | if (!i.has_value) return true; |
893 | 0 | return i.current_value > *o; |
894 | 0 | } |
895 | | |
896 | 0 | bool operator>=(const type_of_iterator &o) const { |
897 | 0 | if (!i.has_value) return true; |
898 | 0 | if (!o.i.has_value) return false; |
899 | 0 | return i.current_value >= *o; |
900 | 0 | } |
901 | | |
902 | | /** |
903 | | * Move the iterator to the first value >= val. |
904 | | */ |
905 | 0 | void equalorlarger(uint32_t val) { |
906 | 0 | api::roaring_move_uint32_iterator_equalorlarger(&i,val); |
907 | 0 | } |
908 | | |
909 | 162k | type_of_iterator &operator++() { // ++i, must returned inc. value |
910 | 162k | api::roaring_advance_uint32_iterator(&i); |
911 | 162k | return *this; |
912 | 162k | } |
913 | | |
914 | 0 | type_of_iterator operator++(int) { // i++, must return orig. value |
915 | 0 | RoaringSetBitForwardIterator orig(*this); |
916 | 0 | api::roaring_advance_uint32_iterator(&i); |
917 | 0 | return orig; |
918 | 0 | } |
919 | | |
920 | 0 | type_of_iterator& operator--() { // prefix -- |
921 | 0 | api::roaring_previous_uint32_iterator(&i); |
922 | 0 | return *this; |
923 | 0 | } |
924 | | |
925 | 0 | type_of_iterator operator--(int) { // postfix -- |
926 | 0 | RoaringSetBitForwardIterator orig(*this); |
927 | 0 | api::roaring_previous_uint32_iterator(&i); |
928 | 0 | return orig; |
929 | 0 | } |
930 | | |
931 | 0 | bool operator==(const RoaringSetBitForwardIterator &o) const { |
932 | 0 | return i.current_value == *o && i.has_value == o.i.has_value; |
933 | 0 | } |
934 | | |
935 | 162k | bool operator!=(const RoaringSetBitForwardIterator &o) const { |
936 | 162k | return i.current_value != *o || i.has_value != o.i.has_value; |
937 | 162k | } |
938 | | |
939 | | explicit RoaringSetBitForwardIterator(const Roaring &parent, |
940 | 91 | bool exhausted = false) { |
941 | 91 | if (exhausted) { |
942 | 1 | i.parent = &parent.roaring; |
943 | 1 | i.container_index = INT32_MAX; |
944 | 1 | i.has_value = false; |
945 | 1 | i.current_value = UINT32_MAX; |
946 | 90 | } else { |
947 | 90 | api::roaring_init_iterator(&parent.roaring, &i); |
948 | 90 | } |
949 | 91 | } |
950 | | |
951 | | api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers. |
952 | | }; |
953 | | |
954 | 90 | inline RoaringSetBitForwardIterator Roaring::begin() const { |
955 | 90 | return RoaringSetBitForwardIterator(*this); |
956 | 90 | } |
957 | | |
958 | 90 | inline RoaringSetBitForwardIterator &Roaring::end() const { |
959 | 90 | static RoaringSetBitForwardIterator e(*this, true); |
960 | 90 | return e; |
961 | 90 | } |
962 | | |
963 | | } // namespace roaring |
964 | | |
965 | | #endif /* INCLUDE_ROARING_HH_ */ |