Coverage Report

Created: 2024-11-21 23:27

/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.5k
    Roaring() : roaring{} {
76
        // The empty constructor roaring{} silences warnings from pedantic static analyzers.
77
46.5k
        api::roaring_bitmap_init_cleared(&roaring);
78
46.5k
    }
79
80
    /**
81
     * Construct a bitmap from a list of 32-bit integer values.
82
     */
83
    Roaring(size_t n, const uint32_t *data) : Roaring() {
84
        api::roaring_bitmap_add_many(&roaring, n, data);
85
    }
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
24.2k
    explicit Roaring(roaring_bitmap_t *s) noexcept : roaring (*s) {
129
24.2k
        roaring_free(s);  // deallocate the passed-in pointer
130
24.2k
    }
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.89M
    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
    bool containsBulk(BulkContext& context, uint32_t x) const noexcept {
212
        return api::roaring_bitmap_contains_bulk(&roaring, &context.context_, x);
213
    }
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
121k
    ~Roaring() {
272
121k
        if (!(roaring.high_low_container.flags & ROARING_FLAG_FROZEN)) {
273
121k
            api::roaring_bitmap_clear(&roaring);
274
121k
        } 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
121k
    }
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.08k
    Roaring &operator=(Roaring &&r) noexcept {
308
3.08k
        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.08k
        roaring = r.roaring;
313
3.08k
        api::roaring_bitmap_init_cleared(&r.roaring);
314
315
3.08k
        return *this;
316
3.08k
    }
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
    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
40.4k
    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
    void iterate(api::roaring_iterator iterator, void *ptr) const {
474
        api::roaring_iterate(&roaring, iterator, ptr);
475
    }
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
0
    uint64_t rank(uint32_t x) const noexcept {
545
0
        return api::roaring_bitmap_rank(&roaring, x);
546
0
    }
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
41.7k
    size_t write(char *buf, bool portable = true) const noexcept {
607
41.7k
        if (portable) {
608
17.7k
            return api::roaring_bitmap_portable_serialize(&roaring, buf);
609
24.0k
        } else {
610
24.0k
            return api::roaring_bitmap_serialize(&roaring, buf);
611
24.0k
        }
612
41.7k
    }
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
24.2k
    static Roaring read(const char *buf, bool portable = true) {
631
24.2k
        roaring_bitmap_t * r = portable
632
24.2k
            ? api::roaring_bitmap_portable_deserialize(buf)
633
24.2k
            : api::roaring_bitmap_deserialize(buf);
634
24.2k
        if (r == NULL) {
635
0
            ROARING_TERMINATE("failed alloc while reading");
636
0
        }
637
24.2k
        return Roaring(r);
638
24.2k
    }
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
    static Roaring readSafe(const char *buf, size_t maxbytes) {
662
        roaring_bitmap_t * r =
663
            api::roaring_bitmap_portable_deserialize_safe(buf,maxbytes);
664
        if (r == NULL) {
665
            ROARING_TERMINATE("failed alloc while reading");
666
        }
667
        return Roaring(r);
668
    }
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
70.5k
    size_t getSizeInBytes(bool portable = true) const noexcept {
679
70.5k
        if (portable) {
680
23.9k
            return api::roaring_bitmap_portable_size_in_bytes(&roaring);
681
46.5k
        } else {
682
46.5k
            return api::roaring_bitmap_size_in_bytes(&roaring);
683
46.5k
        }
684
70.5k
    }
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
    Roaring operator&(const Roaring &o) const {
726
        roaring_bitmap_t *r = api::roaring_bitmap_and(&roaring, &o.roaring);
727
        if (r == NULL) {
728
            ROARING_TERMINATE("failed materalization in and");
729
        }
730
        return Roaring(r);
731
    }
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
    Roaring operator-(const Roaring &o) const {
739
        roaring_bitmap_t *r = api::roaring_bitmap_andnot(&roaring, &o.roaring);
740
        if (r == NULL) {
741
            ROARING_TERMINATE("failed materalization in andnot");
742
        }
743
        return Roaring(r);
744
    }
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
    Roaring operator|(const Roaring &o) const {
752
        roaring_bitmap_t *r = api::roaring_bitmap_or(&roaring, &o.roaring);
753
        if (r == NULL) {
754
            ROARING_TERMINATE("failed materalization in or");
755
        }
756
        return Roaring(r);
757
    }
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
    std::string toString() const noexcept {
788
        struct iter_data {
789
            std::string str{}; // The empty constructor silences warnings from pedantic static analyzers.
790
            char first_char = '{';
791
        } outer_iter_data;
792
        if (!isEmpty()) {
793
            iterate(
794
                [](uint32_t value, void *inner_iter_data) -> bool {
795
                    ((iter_data *)inner_iter_data)->str +=
796
                        ((iter_data *)inner_iter_data)->first_char;
797
                    ((iter_data *)inner_iter_data)->str +=
798
                        std::to_string(value);
799
                    ((iter_data *)inner_iter_data)->first_char = ',';
800
                    return true;
801
                },
802
                (void *)&outer_iter_data);
803
        } else
804
            outer_iter_data.str = '{';
805
        outer_iter_data.str += '}';
806
        return outer_iter_data.str;
807
    }
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
322k
    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
160k
    type_of_iterator &operator++() {  // ++i, must returned inc. value
910
160k
        api::roaring_advance_uint32_iterator(&i);
911
160k
        return *this;
912
160k
    }
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
    bool operator==(const RoaringSetBitForwardIterator &o) const {
932
        return i.current_value == *o && i.has_value == o.i.has_value;
933
    }
934
935
161k
    bool operator!=(const RoaringSetBitForwardIterator &o) const {
936
161k
        return i.current_value != *o || i.has_value != o.i.has_value;
937
161k
    }
938
939
    explicit RoaringSetBitForwardIterator(const Roaring &parent,
940
110
                                          bool exhausted = false) {
941
110
        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
109
        } else {
947
109
            api::roaring_init_iterator(&parent.roaring, &i);
948
109
        }
949
110
    }
950
951
    api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers.
952
};
953
954
109
inline RoaringSetBitForwardIterator Roaring::begin() const {
955
109
    return RoaringSetBitForwardIterator(*this);
956
109
}
957
958
110
inline RoaringSetBitForwardIterator &Roaring::end() const {
959
110
    static RoaringSetBitForwardIterator e(*this, true);
960
110
    return e;
961
110
}
962
963
}  // namespace roaring
964
965
#endif /* INCLUDE_ROARING_HH_ */