roaring 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,2016 +0,0 @@
1
- // !!! DO NOT EDIT - THIS IS AN AUTO-GENERATED FILE !!!
2
- // Created by amalgamation.sh on Wed 20 Jul 2022 16:25:25 EDT
3
-
4
- /*
5
- * The CRoaring project is under a dual license (Apache/MIT).
6
- * Users of the library may choose one or the other license.
7
- */
8
- /*
9
- * Copyright 2016-2022 The CRoaring authors
10
- *
11
- * Licensed under the Apache License, Version 2.0 (the "License");
12
- * you may not use this file except in compliance with the License.
13
- * You may obtain a copy of the License at
14
- *
15
- * http://www.apache.org/licenses/LICENSE-2.0
16
- *
17
- * Unless required by applicable law or agreed to in writing, software
18
- * distributed under the License is distributed on an "AS IS" BASIS,
19
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
- * See the License for the specific language governing permissions and
21
- * limitations under the License.
22
- *
23
- * SPDX-License-Identifier: Apache-2.0
24
- */
25
- /*
26
- * MIT License
27
- *
28
- * Copyright 2016-2022 The CRoaring authors
29
- *
30
- * Permission is hereby granted, free of charge, to any
31
- * person obtaining a copy of this software and associated
32
- * documentation files (the "Software"), to deal in the
33
- * Software without restriction, including without
34
- * limitation the rights to use, copy, modify, merge,
35
- * publish, distribute, sublicense, and/or sell copies of
36
- * the Software, and to permit persons to whom the Software
37
- * is furnished to do so, subject to the following
38
- * conditions:
39
- *
40
- * The above copyright notice and this permission notice
41
- * shall be included in all copies or substantial portions
42
- * of the Software.
43
- *
44
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
45
- * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
46
- * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
47
- * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
48
- * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
49
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
51
- * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
52
- * DEALINGS IN THE SOFTWARE
53
- *
54
- * SPDX-License-Identifier: MIT
55
- */
56
-
57
- #define ROARING_API_NOT_IN_GLOBAL_NAMESPACE // see remarks in roaring.h
58
- #include "roaring.h"
59
- #undef ROARING_API_NOT_IN_GLOBAL_NAMESPACE
60
- /* begin file cpp/roaring.hh */
61
- /*
62
- A C++ header for Roaring Bitmaps.
63
- */
64
- #ifndef INCLUDE_ROARING_HH_
65
- #define INCLUDE_ROARING_HH_
66
-
67
- #include <stdarg.h>
68
-
69
- #include <algorithm>
70
- #include <new>
71
- #include <stdexcept>
72
- #include <string>
73
-
74
- #if !defined(ROARING_EXCEPTIONS)
75
- // __cpp_exceptions is required by C++98 and we require C++11 or better.
76
- #ifndef __cpp_exceptions
77
- #error "__cpp_exceptions should be defined"
78
- #endif
79
- # if __cpp_exceptions
80
- # define ROARING_EXCEPTIONS 1
81
- # else
82
- # define ROARING_EXCEPTIONS 0
83
- # endif
84
- #endif
85
-
86
- #ifndef ROARING_TERMINATE
87
- # if ROARING_EXCEPTIONS
88
- # define ROARING_TERMINATE(_s) throw std::runtime_error(_s)
89
- # else
90
- # define ROARING_TERMINATE(_s) std::terminate()
91
- # endif
92
- #endif
93
-
94
- #define ROARING_API_NOT_IN_GLOBAL_NAMESPACE // see remarks in roaring.h
95
- #undef ROARING_API_NOT_IN_GLOBAL_NAMESPACE
96
-
97
-
98
- namespace roaring {
99
-
100
- class RoaringSetBitForwardIterator;
101
-
102
- class Roaring {
103
- typedef api::roaring_bitmap_t roaring_bitmap_t; // class-local name alias
104
-
105
- public:
106
- /**
107
- * Create an empty bitmap in the existing memory for the class.
108
- * The bitmap will be in the "clear" state with no auxiliary allocations.
109
- */
110
- Roaring() : roaring{} {
111
- // The empty constructor roaring{} silences warnings from pedantic static analyzers.
112
- api::roaring_bitmap_init_cleared(&roaring);
113
- }
114
-
115
- /**
116
- * Construct a bitmap from a list of integer values.
117
- */
118
- Roaring(size_t n, const uint32_t *data) : Roaring() {
119
- api::roaring_bitmap_add_many(&roaring, n, data);
120
- }
121
-
122
- /**
123
- * Copy constructor
124
- */
125
- Roaring(const Roaring &r) : Roaring() {
126
- if (!api::roaring_bitmap_overwrite(&roaring, &r.roaring)) {
127
- ROARING_TERMINATE("failed roaring_bitmap_overwrite in constructor");
128
- }
129
- api::roaring_bitmap_set_copy_on_write(
130
- &roaring,
131
- api::roaring_bitmap_get_copy_on_write(&r.roaring));
132
- }
133
-
134
- /**
135
- * Move constructor. The moved object remains valid, i.e.
136
- * all methods can still be called on it.
137
- */
138
- explicit Roaring(Roaring &&r) noexcept : roaring(r.roaring) {
139
- //
140
- // !!! This clones the bits of the roaring structure to a new location
141
- // and then overwrites the old bits...assuming that this will still
142
- // work. There are scenarios where this could break; e.g. if some of
143
- // those bits were pointers into the structure memory itself. If such
144
- // things were possible, a roaring_bitmap_move() API would be needed.
145
- //
146
- api::roaring_bitmap_init_cleared(&r.roaring);
147
- }
148
-
149
- /**
150
- * Construct a roaring object by taking control of a malloc()'d C struct.
151
- *
152
- * Passing a NULL pointer is unsafe.
153
- * The pointer to the C struct will be invalid after the call.
154
- */
155
- explicit Roaring(roaring_bitmap_t *s) noexcept : roaring (*s) {
156
- roaring_free(s); // deallocate the passed-in pointer
157
- }
158
-
159
- /**
160
- * Construct a bitmap from a list of integer values.
161
- */
162
- static Roaring bitmapOf(size_t n, ...) {
163
- Roaring ans;
164
- va_list vl;
165
- va_start(vl, n);
166
- for (size_t i = 0; i < n; i++) {
167
- ans.add(va_arg(vl, uint32_t));
168
- }
169
- va_end(vl);
170
- return ans;
171
- }
172
-
173
- /**
174
- * Add value x
175
- */
176
- void add(uint32_t x) { api::roaring_bitmap_add(&roaring, x); }
177
-
178
- /**
179
- * Add value x
180
- * Returns true if a new value was added, false if the value was already
181
- * existing.
182
- */
183
- bool addChecked(uint32_t x) {
184
- return api::roaring_bitmap_add_checked(&roaring, x);
185
- }
186
-
187
- /**
188
- * Add all values from x (included) to y (excluded)
189
- */
190
- void addRange(const uint64_t x, const uint64_t y) {
191
- return api::roaring_bitmap_add_range(&roaring, x, y);
192
- }
193
-
194
- /**
195
- * Add value n_args from pointer vals
196
- */
197
- void addMany(size_t n_args, const uint32_t *vals) {
198
- api::roaring_bitmap_add_many(&roaring, n_args, vals);
199
- }
200
-
201
- /**
202
- * Remove value x
203
- */
204
- void remove(uint32_t x) { api::roaring_bitmap_remove(&roaring, x); }
205
-
206
- /**
207
- * Remove value x
208
- * Returns true if a new value was removed, false if the value was not
209
- * existing.
210
- */
211
- bool removeChecked(uint32_t x) {
212
- return api::roaring_bitmap_remove_checked(&roaring, x);
213
- }
214
-
215
- /**
216
- * Return the largest value (if not empty)
217
- */
218
- uint32_t maximum() const { return api::roaring_bitmap_maximum(&roaring); }
219
-
220
- /**
221
- * Return the smallest value (if not empty)
222
- */
223
- uint32_t minimum() const { return api::roaring_bitmap_minimum(&roaring); }
224
-
225
- /**
226
- * Check if value x is present
227
- */
228
- bool contains(uint32_t x) const {
229
- return api::roaring_bitmap_contains(&roaring, x);
230
- }
231
-
232
- /**
233
- * Check if all values from x (included) to y (excluded) are present
234
- */
235
- bool containsRange(const uint64_t x, const uint64_t y) const {
236
- return api::roaring_bitmap_contains_range(&roaring, x, y);
237
- }
238
-
239
- /**
240
- * Destructor. By contract, calling roaring_bitmap_clear() is enough to
241
- * release all auxiliary memory used by the structure.
242
- */
243
- ~Roaring() {
244
- if (!(roaring.high_low_container.flags & ROARING_FLAG_FROZEN)) {
245
- api::roaring_bitmap_clear(&roaring);
246
- } else {
247
- // The roaring member variable copies the `roaring_bitmap_t` and
248
- // nested `roaring_array_t` structures by value and is freed in the
249
- // constructor, however the underlying memory arena used for the
250
- // container data is not freed with it. Here we derive the arena
251
- // pointer from the second arena allocation in
252
- // `roaring_bitmap_frozen_view` and free it as well.
253
- roaring_bitmap_free(
254
- (roaring_bitmap_t *)((char *)
255
- roaring.high_low_container.containers -
256
- sizeof(roaring_bitmap_t)));
257
- }
258
- }
259
-
260
- /**
261
- * Copies the content of the provided bitmap, and
262
- * discard the current content.
263
- */
264
- Roaring &operator=(const Roaring &r) {
265
- if (!api::roaring_bitmap_overwrite(&roaring, &r.roaring)) {
266
- ROARING_TERMINATE("failed memory alloc in assignment");
267
- }
268
- api::roaring_bitmap_set_copy_on_write(
269
- &roaring,
270
- api::roaring_bitmap_get_copy_on_write(&r.roaring));
271
- return *this;
272
- }
273
-
274
- /**
275
- * Moves the content of the provided bitmap, and
276
- * discard the current content.
277
- */
278
- Roaring &operator=(Roaring &&r) noexcept {
279
- api::roaring_bitmap_clear(&roaring); // free this class's allocations
280
-
281
- // !!! See notes in the Move Constructor regarding roaring_bitmap_move()
282
- //
283
- roaring = r.roaring;
284
- api::roaring_bitmap_init_cleared(&r.roaring);
285
-
286
- return *this;
287
- }
288
-
289
- /**
290
- * Compute the intersection between the current bitmap and the provided
291
- * bitmap, writing the result in the current bitmap. The provided bitmap
292
- * is not modified.
293
- */
294
- Roaring &operator&=(const Roaring &r) {
295
- api::roaring_bitmap_and_inplace(&roaring, &r.roaring);
296
- return *this;
297
- }
298
-
299
- /**
300
- * Compute the difference between the current bitmap and the provided
301
- * bitmap, writing the result in the current bitmap. The provided bitmap
302
- * is not modified.
303
- */
304
- Roaring &operator-=(const Roaring &r) {
305
- api::roaring_bitmap_andnot_inplace(&roaring, &r.roaring);
306
- return *this;
307
- }
308
-
309
- /**
310
- * Compute the union between the current bitmap and the provided bitmap,
311
- * writing the result in the current bitmap. The provided bitmap is not
312
- * modified.
313
- *
314
- * See also the fastunion function to aggregate many bitmaps more quickly.
315
- */
316
- Roaring &operator|=(const Roaring &r) {
317
- api::roaring_bitmap_or_inplace(&roaring, &r.roaring);
318
- return *this;
319
- }
320
-
321
- /**
322
- * Compute the symmetric union between the current bitmap and the provided
323
- * bitmap, writing the result in the current bitmap. The provided bitmap
324
- * is not modified.
325
- */
326
- Roaring &operator^=(const Roaring &r) {
327
- api::roaring_bitmap_xor_inplace(&roaring, &r.roaring);
328
- return *this;
329
- }
330
-
331
- /**
332
- * Exchange the content of this bitmap with another.
333
- */
334
- void swap(Roaring &r) { std::swap(r.roaring, roaring); }
335
-
336
- /**
337
- * Get the cardinality of the bitmap (number of elements).
338
- */
339
- uint64_t cardinality() const {
340
- return api::roaring_bitmap_get_cardinality(&roaring);
341
- }
342
-
343
- /**
344
- * Returns true if the bitmap is empty (cardinality is zero).
345
- */
346
- bool isEmpty() const { return api::roaring_bitmap_is_empty(&roaring); }
347
-
348
- /**
349
- * Returns true if the bitmap is subset of the other.
350
- */
351
- bool isSubset(const Roaring &r) const {
352
- return api::roaring_bitmap_is_subset(&roaring, &r.roaring);
353
- }
354
-
355
- /**
356
- * Returns true if the bitmap is strict subset of the other.
357
- */
358
- bool isStrictSubset(const Roaring &r) const {
359
- return api::roaring_bitmap_is_strict_subset(&roaring, &r.roaring);
360
- }
361
-
362
- /**
363
- * Convert the bitmap to an array. Write the output to "ans", caller is
364
- * responsible to ensure that there is enough memory allocated
365
- * (e.g., ans = new uint32[mybitmap.cardinality()];)
366
- */
367
- void toUint32Array(uint32_t *ans) const {
368
- api::roaring_bitmap_to_uint32_array(&roaring, ans);
369
- }
370
- /**
371
- * To int array with pagination
372
- */
373
- void rangeUint32Array(uint32_t *ans, size_t offset, size_t limit) const {
374
- api::roaring_bitmap_range_uint32_array(&roaring, offset, limit, ans);
375
- }
376
-
377
- /**
378
- * Return true if the two bitmaps contain the same elements.
379
- */
380
- bool operator==(const Roaring &r) const {
381
- return api::roaring_bitmap_equals(&roaring, &r.roaring);
382
- }
383
-
384
- /**
385
- * Compute the negation of the roaring bitmap within a specified interval.
386
- * Areas outside the range are passed through unchanged.
387
- */
388
- void flip(uint64_t range_start, uint64_t range_end) {
389
- api::roaring_bitmap_flip_inplace(&roaring, range_start, range_end);
390
- }
391
-
392
- /**
393
- * Remove run-length encoding even when it is more space efficient.
394
- * Return whether a change was applied.
395
- */
396
- bool removeRunCompression() {
397
- return api::roaring_bitmap_remove_run_compression(&roaring);
398
- }
399
-
400
- /**
401
- * Convert array and bitmap containers to run containers when it is more
402
- * efficient; also convert from run containers when more space efficient.
403
- * Returns true if the result has at least one run container. Additional
404
- * savings might be possible by calling shrinkToFit().
405
- */
406
- bool runOptimize() { return api::roaring_bitmap_run_optimize(&roaring); }
407
-
408
- /**
409
- * If needed, reallocate memory to shrink the memory usage. Returns
410
- * the number of bytes saved.
411
- */
412
- size_t shrinkToFit() { return api::roaring_bitmap_shrink_to_fit(&roaring); }
413
-
414
- /**
415
- * Iterate over the bitmap elements. The function iterator is called once
416
- * for all the values with ptr (can be NULL) as the second parameter of
417
- * each call.
418
- *
419
- * roaring_iterator is simply a pointer to a function that returns bool
420
- * (true means that the iteration should continue while false means that it
421
- * should stop), and takes (uint32_t,void*) as inputs.
422
- */
423
- void iterate(api::roaring_iterator iterator, void *ptr) const {
424
- api::roaring_iterate(&roaring, iterator, ptr);
425
- }
426
-
427
- /**
428
- * Selects the value at index rnk in the bitmap, where the smallest value
429
- * is at index 0.
430
- *
431
- * If the size of the roaring bitmap is strictly greater than rank, then
432
- * this function returns true and sets element to the element of given rank.
433
- * Otherwise, it returns false.
434
- */
435
- bool select(uint32_t rnk, uint32_t *element) const {
436
- return api::roaring_bitmap_select(&roaring, rnk, element);
437
- }
438
-
439
- /**
440
- * Computes the size of the intersection between two bitmaps.
441
- */
442
- uint64_t and_cardinality(const Roaring &r) const {
443
- return api::roaring_bitmap_and_cardinality(&roaring, &r.roaring);
444
- }
445
-
446
- /**
447
- * Check whether the two bitmaps intersect.
448
- */
449
- bool intersect(const Roaring &r) const {
450
- return api::roaring_bitmap_intersect(&roaring, &r.roaring);
451
- }
452
-
453
- /**
454
- * Computes the Jaccard index between two bitmaps. (Also known as the
455
- * Tanimoto distance,
456
- * or the Jaccard similarity coefficient)
457
- *
458
- * The Jaccard index is undefined if both bitmaps are empty.
459
- */
460
- double jaccard_index(const Roaring &r) const {
461
- return api::roaring_bitmap_jaccard_index(&roaring, &r.roaring);
462
- }
463
-
464
- /**
465
- * Computes the size of the union between two bitmaps.
466
- */
467
- uint64_t or_cardinality(const Roaring &r) const {
468
- return api::roaring_bitmap_or_cardinality(&roaring, &r.roaring);
469
- }
470
-
471
- /**
472
- * Computes the size of the difference (andnot) between two bitmaps.
473
- */
474
- uint64_t andnot_cardinality(const Roaring &r) const {
475
- return api::roaring_bitmap_andnot_cardinality(&roaring, &r.roaring);
476
- }
477
-
478
- /**
479
- * Computes the size of the symmetric difference (andnot) between two
480
- * bitmaps.
481
- */
482
- uint64_t xor_cardinality(const Roaring &r) const {
483
- return api::roaring_bitmap_xor_cardinality(&roaring, &r.roaring);
484
- }
485
-
486
- /**
487
- * Returns the number of integers that are smaller or equal to x.
488
- * Thus the rank of the smallest element is one. If
489
- * x is smaller than the smallest element, this function will return 0.
490
- * The rank and select functions differ in convention: this function returns
491
- * 1 when ranking the smallest value, but the select function returns the
492
- * smallest value when using index 0.
493
- */
494
- uint64_t rank(uint32_t x) const {
495
- return api::roaring_bitmap_rank(&roaring, x);
496
- }
497
-
498
- /**
499
- * Write a bitmap to a char buffer. This is meant to be compatible with
500
- * the Java and Go versions. Returns how many bytes were written which
501
- * should be getSizeInBytes().
502
- *
503
- * Setting the portable flag to false enable a custom format that
504
- * can save space compared to the portable format (e.g., for very
505
- * sparse bitmaps).
506
- *
507
- * Boost users can serialize bitmaps in this manner:
508
- *
509
- * BOOST_SERIALIZATION_SPLIT_FREE(Roaring)
510
- * namespace boost {
511
- * namespace serialization {
512
- *
513
- * template <class Archive>
514
- * void save(Archive& ar, const Roaring& bitmask,
515
- * const unsigned int version) {
516
- * std::size_t expected_size_in_bytes = bitmask.getSizeInBytes();
517
- * std::vector<char> buffer(expected_size_in_bytes);
518
- * std::size_t size_in_bytes = bitmask.write(buffer.data());
519
- *
520
- * ar& size_in_bytes;
521
- * ar& boost::serialization::make_binary_object(buffer.data(),
522
- * size_in_bytes);
523
- * }
524
- * template <class Archive>
525
- * void load(Archive& ar, Roaring& bitmask,
526
- * const unsigned int version) {
527
- * std::size_t size_in_bytes = 0;
528
- * ar& size_in_bytes;
529
- * std::vector<char> buffer(size_in_bytes);
530
- * ar& boost::serialization::make_binary_object(buffer.data(),
531
- * size_in_bytes);
532
- * bitmask = Roaring::readSafe(buffer.data(), size_in_bytes);
533
- * }
534
- * } // namespace serialization
535
- * } // namespace boost
536
- */
537
- size_t write(char *buf, bool portable = true) const {
538
- if (portable)
539
- return api::roaring_bitmap_portable_serialize(&roaring, buf);
540
- else
541
- return api::roaring_bitmap_serialize(&roaring, buf);
542
- }
543
-
544
- /**
545
- * Read a bitmap from a serialized version. This is meant to be compatible
546
- * with the Java and Go versions.
547
- *
548
- * Setting the portable flag to false enable a custom format that
549
- * can save space compared to the portable format (e.g., for very
550
- * sparse bitmaps).
551
- *
552
- * This function is unsafe in the sense that if you provide bad data,
553
- * many, many bytes could be read. See also readSafe.
554
- */
555
- static Roaring read(const char *buf, bool portable = true) {
556
- roaring_bitmap_t * r = portable
557
- ? api::roaring_bitmap_portable_deserialize(buf)
558
- : api::roaring_bitmap_deserialize(buf);
559
- if (r == NULL) {
560
- ROARING_TERMINATE("failed alloc while reading");
561
- }
562
- return Roaring(r);
563
- }
564
-
565
- /**
566
- * Read a bitmap from a serialized version, reading no more than maxbytes
567
- * bytes. This is meant to be compatible with the Java and Go versions.
568
- *
569
- */
570
- static Roaring readSafe(const char *buf, size_t maxbytes) {
571
- roaring_bitmap_t * r =
572
- api::roaring_bitmap_portable_deserialize_safe(buf,maxbytes);
573
- if (r == NULL) {
574
- ROARING_TERMINATE("failed alloc while reading");
575
- }
576
- return Roaring(r);
577
- }
578
-
579
- /**
580
- * How many bytes are required to serialize this bitmap (meant to be
581
- * compatible with Java and Go versions)
582
- *
583
- * Setting the portable flag to false enable a custom format that
584
- * can save space compared to the portable format (e.g., for very
585
- * sparse bitmaps).
586
- */
587
- size_t getSizeInBytes(bool portable = true) const {
588
- if (portable)
589
- return api::roaring_bitmap_portable_size_in_bytes(&roaring);
590
- else
591
- return api::roaring_bitmap_size_in_bytes(&roaring);
592
- }
593
-
594
- static const Roaring frozenView(const char *buf, size_t length) {
595
- const roaring_bitmap_t *s =
596
- api::roaring_bitmap_frozen_view(buf, length);
597
- if (s == NULL) {
598
- ROARING_TERMINATE("failed to read frozen bitmap");
599
- }
600
- Roaring r;
601
- r.roaring = *s;
602
- return r;
603
- }
604
-
605
- void writeFrozen(char *buf) const {
606
- roaring_bitmap_frozen_serialize(&roaring, buf);
607
- }
608
-
609
- size_t getFrozenSizeInBytes() const {
610
- return roaring_bitmap_frozen_size_in_bytes(&roaring);
611
- }
612
-
613
- /**
614
- * Computes the intersection between two bitmaps and returns new bitmap.
615
- * The current bitmap and the provided bitmap are unchanged.
616
- */
617
- Roaring operator&(const Roaring &o) const {
618
- roaring_bitmap_t *r = api::roaring_bitmap_and(&roaring, &o.roaring);
619
- if (r == NULL) {
620
- ROARING_TERMINATE("failed materalization in and");
621
- }
622
- return Roaring(r);
623
- }
624
-
625
- /**
626
- * Computes the difference between two bitmaps and returns new bitmap.
627
- * The current bitmap and the provided bitmap are unchanged.
628
- */
629
- Roaring operator-(const Roaring &o) const {
630
- roaring_bitmap_t *r = api::roaring_bitmap_andnot(&roaring, &o.roaring);
631
- if (r == NULL) {
632
- ROARING_TERMINATE("failed materalization in andnot");
633
- }
634
- return Roaring(r);
635
- }
636
-
637
- /**
638
- * Computes the union between two bitmaps and returns new bitmap.
639
- * The current bitmap and the provided bitmap are unchanged.
640
- */
641
- Roaring operator|(const Roaring &o) const {
642
- roaring_bitmap_t *r = api::roaring_bitmap_or(&roaring, &o.roaring);
643
- if (r == NULL) {
644
- ROARING_TERMINATE("failed materalization in or");
645
- }
646
- return Roaring(r);
647
- }
648
-
649
- /**
650
- * Computes the symmetric union between two bitmaps and returns new bitmap.
651
- * The current bitmap and the provided bitmap are unchanged.
652
- */
653
- Roaring operator^(const Roaring &o) const {
654
- roaring_bitmap_t *r = api::roaring_bitmap_xor(&roaring, &o.roaring);
655
- if (r == NULL) {
656
- ROARING_TERMINATE("failed materalization in xor");
657
- }
658
- return Roaring(r);
659
- }
660
-
661
- /**
662
- * Whether or not we apply copy and write.
663
- */
664
- void setCopyOnWrite(bool val) {
665
- api::roaring_bitmap_set_copy_on_write(&roaring, val);
666
- }
667
-
668
- /**
669
- * Print the content of the bitmap
670
- */
671
- void printf() const { api::roaring_bitmap_printf(&roaring); }
672
-
673
- /**
674
- * Print the content of the bitmap into a string
675
- */
676
- std::string toString() const {
677
- struct iter_data {
678
- std::string str{}; // The empty constructor silences warnings from pedantic static analyzers.
679
- char first_char = '{';
680
- } outer_iter_data;
681
- if (!isEmpty()) {
682
- iterate(
683
- [](uint32_t value, void *inner_iter_data) -> bool {
684
- ((iter_data *)inner_iter_data)->str +=
685
- ((iter_data *)inner_iter_data)->first_char;
686
- ((iter_data *)inner_iter_data)->str +=
687
- std::to_string(value);
688
- ((iter_data *)inner_iter_data)->first_char = ',';
689
- return true;
690
- },
691
- (void *)&outer_iter_data);
692
- } else
693
- outer_iter_data.str = '{';
694
- outer_iter_data.str += '}';
695
- return outer_iter_data.str;
696
- }
697
-
698
- /**
699
- * Whether or not copy and write is active.
700
- */
701
- bool getCopyOnWrite() const {
702
- return api::roaring_bitmap_get_copy_on_write(&roaring);
703
- }
704
-
705
- /**
706
- * Computes the logical or (union) between "n" bitmaps (referenced by a
707
- * pointer).
708
- */
709
- static Roaring fastunion(size_t n, const Roaring **inputs) {
710
- const roaring_bitmap_t **x =
711
- (const roaring_bitmap_t **)roaring_malloc(n * sizeof(roaring_bitmap_t *));
712
- if (x == NULL) {
713
- ROARING_TERMINATE("failed memory alloc in fastunion");
714
- }
715
- for (size_t k = 0; k < n; ++k) x[k] = &inputs[k]->roaring;
716
-
717
- roaring_bitmap_t *c_ans = api::roaring_bitmap_or_many(n, x);
718
- if (c_ans == NULL) {
719
- roaring_free(x);
720
- ROARING_TERMINATE("failed memory alloc in fastunion");
721
- }
722
- Roaring ans(c_ans);
723
- roaring_free(x);
724
- return ans;
725
- }
726
-
727
- typedef RoaringSetBitForwardIterator const_iterator;
728
-
729
- /**
730
- * Returns an iterator that can be used to access the position of the set
731
- * bits. The running time complexity of a full scan is proportional to the
732
- * number of set bits: be aware that if you have long strings of 1s, this
733
- * can be very inefficient.
734
- *
735
- * It can be much faster to use the toArray method if you want to retrieve
736
- * the set bits.
737
- */
738
- const_iterator begin() const;
739
-
740
- /**
741
- * A bogus iterator that can be used together with begin()
742
- * for constructions such as for (auto i = b.begin(); * i!=b.end(); ++i) {}
743
- */
744
- const_iterator &end() const;
745
-
746
- roaring_bitmap_t roaring;
747
- };
748
-
749
- /**
750
- * Used to go through the set bits. Not optimally fast, but convenient.
751
- */
752
- class RoaringSetBitForwardIterator final {
753
- public:
754
- typedef std::forward_iterator_tag iterator_category;
755
- typedef uint32_t *pointer;
756
- typedef uint32_t &reference_type;
757
- typedef uint32_t value_type;
758
- typedef int32_t difference_type;
759
- typedef RoaringSetBitForwardIterator type_of_iterator;
760
-
761
- /**
762
- * Provides the location of the set bit.
763
- */
764
- value_type operator*() const { return i.current_value; }
765
-
766
- bool operator<(const type_of_iterator &o) const {
767
- if (!i.has_value) return false;
768
- if (!o.i.has_value) return true;
769
- return i.current_value < *o;
770
- }
771
-
772
- bool operator<=(const type_of_iterator &o) const {
773
- if (!o.i.has_value) return true;
774
- if (!i.has_value) return false;
775
- return i.current_value <= *o;
776
- }
777
-
778
- bool operator>(const type_of_iterator &o) const {
779
- if (!o.i.has_value) return false;
780
- if (!i.has_value) return true;
781
- return i.current_value > *o;
782
- }
783
-
784
- bool operator>=(const type_of_iterator &o) const {
785
- if (!i.has_value) return true;
786
- if (!o.i.has_value) return false;
787
- return i.current_value >= *o;
788
- }
789
-
790
- /**
791
- * Move the iterator to the first value >= val.
792
- */
793
- void equalorlarger(uint32_t val) {
794
- api::roaring_move_uint32_iterator_equalorlarger(&i,val);
795
- }
796
-
797
- type_of_iterator &operator++() { // ++i, must returned inc. value
798
- api::roaring_advance_uint32_iterator(&i);
799
- return *this;
800
- }
801
-
802
- type_of_iterator operator++(int) { // i++, must return orig. value
803
- RoaringSetBitForwardIterator orig(*this);
804
- api::roaring_advance_uint32_iterator(&i);
805
- return orig;
806
- }
807
-
808
- type_of_iterator& operator--() { // prefix --
809
- api::roaring_previous_uint32_iterator(&i);
810
- return *this;
811
- }
812
-
813
- type_of_iterator operator--(int) { // postfix --
814
- RoaringSetBitForwardIterator orig(*this);
815
- api::roaring_previous_uint32_iterator(&i);
816
- return orig;
817
- }
818
-
819
- bool operator==(const RoaringSetBitForwardIterator &o) const {
820
- return i.current_value == *o && i.has_value == o.i.has_value;
821
- }
822
-
823
- bool operator!=(const RoaringSetBitForwardIterator &o) const {
824
- return i.current_value != *o || i.has_value != o.i.has_value;
825
- }
826
-
827
- RoaringSetBitForwardIterator(const Roaring &parent,
828
- bool exhausted = false) {
829
- if (exhausted) {
830
- i.parent = &parent.roaring;
831
- i.container_index = INT32_MAX;
832
- i.has_value = false;
833
- i.current_value = UINT32_MAX;
834
- } else {
835
- api::roaring_init_iterator(&parent.roaring, &i);
836
- }
837
- }
838
-
839
- api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers.
840
- };
841
-
842
- inline RoaringSetBitForwardIterator Roaring::begin() const {
843
- return RoaringSetBitForwardIterator(*this);
844
- }
845
-
846
- inline RoaringSetBitForwardIterator &Roaring::end() const {
847
- static RoaringSetBitForwardIterator e(*this, true);
848
- return e;
849
- }
850
-
851
- } // namespace roaring
852
-
853
- #endif /* INCLUDE_ROARING_HH_ */
854
- /* end file cpp/roaring.hh */
855
- /* begin file cpp/roaring64map.hh */
856
- /*
857
- A C++ header for 64-bit Roaring Bitmaps, implemented by way of a map of many
858
- 32-bit Roaring Bitmaps.
859
- */
860
- #ifndef INCLUDE_ROARING_64_MAP_HH_
861
- #define INCLUDE_ROARING_64_MAP_HH_
862
-
863
- #include <algorithm>
864
- #include <cstdarg> // for va_list handling in bitmapOf()
865
- #include <cstdio> // for std::printf() in the printf() method
866
- #include <cstring> // for std::memcpy()
867
- #include <limits>
868
- #include <map>
869
- #include <new>
870
- #include <numeric>
871
- #include <stdexcept>
872
- #include <string>
873
- #include <utility>
874
-
875
- using roaring::Roaring;
876
-
877
- namespace roaring {
878
-
879
- class Roaring64MapSetBitForwardIterator;
880
- class Roaring64MapSetBitBiDirectionalIterator;
881
-
882
- class Roaring64Map {
883
- typedef api::roaring_bitmap_t roaring_bitmap_t;
884
-
885
- public:
886
- /**
887
- * Create an empty bitmap
888
- */
889
- Roaring64Map() = default;
890
-
891
- /**
892
- * Construct a bitmap from a list of 32-bit integer values.
893
- */
894
- Roaring64Map(size_t n, const uint32_t *data) { addMany(n, data); }
895
-
896
- /**
897
- * Construct a bitmap from a list of 64-bit integer values.
898
- */
899
- Roaring64Map(size_t n, const uint64_t *data) { addMany(n, data); }
900
-
901
- /**
902
- * Construct a 64-bit map from a 32-bit one
903
- */
904
- explicit Roaring64Map(const Roaring &r) { emplaceOrInsert(0, r); }
905
-
906
- /**
907
- * Construct a roaring object from the C struct.
908
- *
909
- * Passing a NULL point is unsafe.
910
- */
911
- explicit Roaring64Map(roaring_bitmap_t *s) {
912
- Roaring r(s);
913
- emplaceOrInsert(0, r);
914
- }
915
-
916
- Roaring64Map(const Roaring64Map& r)
917
- : roarings(r.roarings),
918
- copyOnWrite(r.copyOnWrite) { }
919
-
920
- Roaring64Map(Roaring64Map&& r)
921
- : roarings(r.roarings),
922
- copyOnWrite(r.copyOnWrite) { }
923
-
924
- /**
925
- * Assignment operator.
926
- */
927
- Roaring64Map &operator=(const Roaring64Map &r) {
928
- roarings = r.roarings;
929
- return *this;
930
- }
931
-
932
- /**
933
- * Construct a bitmap from a list of integer values.
934
- */
935
- static Roaring64Map bitmapOf(size_t n...) {
936
- Roaring64Map ans;
937
- va_list vl;
938
- va_start(vl, n);
939
- for (size_t i = 0; i < n; i++) {
940
- ans.add(va_arg(vl, uint64_t));
941
- }
942
- va_end(vl);
943
- return ans;
944
- }
945
-
946
- /**
947
- * Add value x
948
- */
949
- void add(uint32_t x) {
950
- roarings[0].add(x);
951
- roarings[0].setCopyOnWrite(copyOnWrite);
952
- }
953
- void add(uint64_t x) {
954
- roarings[highBytes(x)].add(lowBytes(x));
955
- roarings[highBytes(x)].setCopyOnWrite(copyOnWrite);
956
- }
957
-
958
- /**
959
- * Add value x
960
- * Returns true if a new value was added, false if the value was already existing.
961
- */
962
- bool addChecked(uint32_t x) {
963
- bool result = roarings[0].addChecked(x);
964
- roarings[0].setCopyOnWrite(copyOnWrite);
965
- return result;
966
- }
967
- bool addChecked(uint64_t x) {
968
- bool result = roarings[highBytes(x)].addChecked(lowBytes(x));
969
- roarings[highBytes(x)].setCopyOnWrite(copyOnWrite);
970
- return result;
971
- }
972
-
973
- /**
974
- * Add value n_args from pointer vals
975
- */
976
- void addMany(size_t n_args, const uint32_t *vals) {
977
- for (size_t lcv = 0; lcv < n_args; lcv++) {
978
- roarings[0].add(vals[lcv]);
979
- roarings[0].setCopyOnWrite(copyOnWrite);
980
- }
981
- }
982
- void addMany(size_t n_args, const uint64_t *vals) {
983
- for (size_t lcv = 0; lcv < n_args; lcv++) {
984
- roarings[highBytes(vals[lcv])].add(lowBytes(vals[lcv]));
985
- roarings[highBytes(vals[lcv])].setCopyOnWrite(copyOnWrite);
986
- }
987
- }
988
-
989
- /**
990
- * Remove value x
991
- */
992
- void remove(uint32_t x) { roarings[0].remove(x); }
993
- void remove(uint64_t x) {
994
- auto roaring_iter = roarings.find(highBytes(x));
995
- if (roaring_iter != roarings.cend())
996
- roaring_iter->second.remove(lowBytes(x));
997
- }
998
-
999
- /**
1000
- * Remove value x
1001
- * Returns true if a new value was removed, false if the value was not existing.
1002
- */
1003
- bool removeChecked(uint32_t x) {
1004
- return roarings[0].removeChecked(x);
1005
- }
1006
- bool removeChecked(uint64_t x) {
1007
- auto roaring_iter = roarings.find(highBytes(x));
1008
- if (roaring_iter != roarings.cend())
1009
- return roaring_iter->second.removeChecked(lowBytes(x));
1010
- return false;
1011
- }
1012
-
1013
- /**
1014
- * Clear the bitmap
1015
- */
1016
- void clear() {
1017
- roarings.clear();
1018
- }
1019
-
1020
- /**
1021
- * Return the largest value (if not empty)
1022
- */
1023
- uint64_t maximum() const {
1024
- for (auto roaring_iter = roarings.crbegin();
1025
- roaring_iter != roarings.crend(); ++roaring_iter) {
1026
- if (!roaring_iter->second.isEmpty()) {
1027
- return uniteBytes(roaring_iter->first,
1028
- roaring_iter->second.maximum());
1029
- }
1030
- }
1031
- // we put std::numeric_limits<>::max/min in parenthesis
1032
- // to avoid a clash with the Windows.h header under Windows
1033
- return (std::numeric_limits<uint64_t>::min)();
1034
- }
1035
-
1036
- /**
1037
- * Return the smallest value (if not empty)
1038
- */
1039
- uint64_t minimum() const {
1040
- for (auto roaring_iter = roarings.cbegin();
1041
- roaring_iter != roarings.cend(); ++roaring_iter) {
1042
- if (!roaring_iter->second.isEmpty()) {
1043
- return uniteBytes(roaring_iter->first,
1044
- roaring_iter->second.minimum());
1045
- }
1046
- }
1047
- // we put std::numeric_limits<>::max/min in parenthesis
1048
- // to avoid a clash with the Windows.h header under Windows
1049
- return (std::numeric_limits<uint64_t>::max)();
1050
- }
1051
-
1052
- /**
1053
- * Check if value x is present
1054
- */
1055
- bool contains(uint32_t x) const {
1056
- return roarings.count(0) == 0 ? false : roarings.at(0).contains(x);
1057
- }
1058
- bool contains(uint64_t x) const {
1059
- return roarings.count(highBytes(x)) == 0
1060
- ? false
1061
- : roarings.at(highBytes(x)).contains(lowBytes(x));
1062
- }
1063
-
1064
- /**
1065
- * Compute the intersection between the current bitmap and the provided
1066
- * bitmap, writing the result in the current bitmap. The provided bitmap
1067
- * is not modified.
1068
- */
1069
- Roaring64Map &operator&=(const Roaring64Map &r) {
1070
- for (auto &map_entry : roarings) {
1071
- if (r.roarings.count(map_entry.first) == 1)
1072
- map_entry.second &= r.roarings.at(map_entry.first);
1073
- else
1074
- map_entry.second = Roaring();
1075
- }
1076
- return *this;
1077
- }
1078
-
1079
- /**
1080
- * Compute the difference between the current bitmap and the provided
1081
- * bitmap, writing the result in the current bitmap. The provided bitmap
1082
- * is not modified.
1083
- */
1084
- Roaring64Map &operator-=(const Roaring64Map &r) {
1085
- for (auto &map_entry : roarings) {
1086
- if (r.roarings.count(map_entry.first) == 1)
1087
- map_entry.second -= r.roarings.at(map_entry.first);
1088
- }
1089
- return *this;
1090
- }
1091
-
1092
- /**
1093
- * Compute the union between the current bitmap and the provided bitmap,
1094
- * writing the result in the current bitmap. The provided bitmap is not
1095
- * modified.
1096
- *
1097
- * See also the fastunion function to aggregate many bitmaps more quickly.
1098
- */
1099
- Roaring64Map &operator|=(const Roaring64Map &r) {
1100
- for (const auto &map_entry : r.roarings) {
1101
- if (roarings.count(map_entry.first) == 0) {
1102
- roarings[map_entry.first] = map_entry.second;
1103
- roarings[map_entry.first].setCopyOnWrite(copyOnWrite);
1104
- } else
1105
- roarings[map_entry.first] |= map_entry.second;
1106
- }
1107
- return *this;
1108
- }
1109
-
1110
- /**
1111
- * Compute the symmetric union between the current bitmap and the provided
1112
- * bitmap, writing the result in the current bitmap. The provided bitmap
1113
- * is not modified.
1114
- */
1115
- Roaring64Map &operator^=(const Roaring64Map &r) {
1116
- for (const auto &map_entry : r.roarings) {
1117
- if (roarings.count(map_entry.first) == 0) {
1118
- roarings[map_entry.first] = map_entry.second;
1119
- roarings[map_entry.first].setCopyOnWrite(copyOnWrite);
1120
- } else
1121
- roarings[map_entry.first] ^= map_entry.second;
1122
- }
1123
- return *this;
1124
- }
1125
-
1126
- /**
1127
- * Exchange the content of this bitmap with another.
1128
- */
1129
- void swap(Roaring64Map &r) { roarings.swap(r.roarings); }
1130
-
1131
- /**
1132
- * Get the cardinality of the bitmap (number of elements).
1133
- * Throws std::length_error in the special case where the bitmap is full
1134
- * (cardinality() == 2^64). Check isFull() before calling to avoid
1135
- * exception.
1136
- */
1137
- uint64_t cardinality() const {
1138
- if (isFull()) {
1139
- #if ROARING_EXCEPTIONS
1140
- throw std::length_error("bitmap is full, cardinality is 2^64, "
1141
- "unable to represent in a 64-bit integer");
1142
- #else
1143
- ROARING_TERMINATE("bitmap is full, cardinality is 2^64, "
1144
- "unable to represent in a 64-bit integer");
1145
- #endif
1146
- }
1147
- return std::accumulate(
1148
- roarings.cbegin(), roarings.cend(), (uint64_t)0,
1149
- [](uint64_t previous,
1150
- const std::pair<const uint32_t, Roaring> &map_entry) {
1151
- return previous + map_entry.second.cardinality();
1152
- });
1153
- }
1154
-
1155
- /**
1156
- * Returns true if the bitmap is empty (cardinality is zero).
1157
- */
1158
- bool isEmpty() const {
1159
- return std::all_of(roarings.cbegin(), roarings.cend(),
1160
- [](const std::pair<const uint32_t, Roaring> &map_entry) {
1161
- return map_entry.second.isEmpty();
1162
- });
1163
- }
1164
-
1165
- /**
1166
- * Returns true if the bitmap is full (cardinality is max uint64_t + 1).
1167
- */
1168
- bool isFull() const {
1169
- // only bother to check if map is fully saturated
1170
- //
1171
- // we put std::numeric_limits<>::max/min in parenthesis
1172
- // to avoid a clash with the Windows.h header under Windows
1173
- return roarings.size() ==
1174
- ((uint64_t)(std::numeric_limits<uint32_t>::max)()) + 1
1175
- ? std::all_of(
1176
- roarings.cbegin(), roarings.cend(),
1177
- [](const std::pair<const uint32_t, Roaring> &roaring_map_entry) {
1178
- // roarings within map are saturated if cardinality
1179
- // is uint32_t max + 1
1180
- return roaring_map_entry.second.cardinality() ==
1181
- ((uint64_t)
1182
- (std::numeric_limits<uint32_t>::max)()) +
1183
- 1;
1184
- })
1185
- : false;
1186
- }
1187
-
1188
- /**
1189
- * Returns true if the bitmap is subset of the other.
1190
- */
1191
- bool isSubset(const Roaring64Map &r) const {
1192
- for (const auto &map_entry : roarings) {
1193
- auto roaring_iter = r.roarings.find(map_entry.first);
1194
- if (roaring_iter == r.roarings.cend())
1195
- return false;
1196
- else if (!map_entry.second.isSubset(roaring_iter->second))
1197
- return false;
1198
- }
1199
- return true;
1200
- }
1201
-
1202
- /**
1203
- * Returns true if the bitmap is strict subset of the other.
1204
- * Throws std::length_error in the special case where the bitmap is full
1205
- * (cardinality() == 2^64). Check isFull() before calling to avoid exception.
1206
- */
1207
- bool isStrictSubset(const Roaring64Map &r) const {
1208
- return isSubset(r) && cardinality() != r.cardinality();
1209
- }
1210
-
1211
- /**
1212
- * Convert the bitmap to an array. Write the output to "ans",
1213
- * caller is responsible to ensure that there is enough memory
1214
- * allocated
1215
- * (e.g., ans = new uint32[mybitmap.cardinality()];)
1216
- */
1217
- void toUint64Array(uint64_t *ans) const {
1218
- // Annoyingly, VS 2017 marks std::accumulate() as [[nodiscard]]
1219
- (void)std::accumulate(roarings.cbegin(), roarings.cend(), ans,
1220
- [](uint64_t *previous,
1221
- const std::pair<const uint32_t, Roaring> &map_entry) {
1222
- for (uint32_t low_bits : map_entry.second)
1223
- *previous++ =
1224
- uniteBytes(map_entry.first, low_bits);
1225
- return previous;
1226
- });
1227
- }
1228
-
1229
- /**
1230
- * Return true if the two bitmaps contain the same elements.
1231
- */
1232
- bool operator==(const Roaring64Map &r) const {
1233
- // we cannot use operator == on the map because either side may contain
1234
- // empty Roaring Bitmaps
1235
- auto lhs_iter = roarings.cbegin();
1236
- auto lhs_cend = roarings.cend();
1237
- auto rhs_iter = r.roarings.cbegin();
1238
- auto rhs_cend = r.roarings.cend();
1239
- while (lhs_iter != lhs_cend && rhs_iter != rhs_cend) {
1240
- auto lhs_key = lhs_iter->first, rhs_key = rhs_iter->first;
1241
- const auto &lhs_map = lhs_iter->second, &rhs_map = rhs_iter->second;
1242
- if (lhs_map.isEmpty()) {
1243
- ++lhs_iter;
1244
- continue;
1245
- }
1246
- if (rhs_map.isEmpty()) {
1247
- ++rhs_iter;
1248
- continue;
1249
- }
1250
- if (!(lhs_key == rhs_key)) {
1251
- return false;
1252
- }
1253
- if (!(lhs_map == rhs_map)) {
1254
- return false;
1255
- }
1256
- ++lhs_iter;
1257
- ++rhs_iter;
1258
- }
1259
- while (lhs_iter != lhs_cend) {
1260
- if (!lhs_iter->second.isEmpty()) {
1261
- return false;
1262
- }
1263
- ++lhs_iter;
1264
- }
1265
- while (rhs_iter != rhs_cend) {
1266
- if (!rhs_iter->second.isEmpty()) {
1267
- return false;
1268
- }
1269
- ++rhs_iter;
1270
- }
1271
- return true;
1272
- }
1273
-
1274
- /**
1275
- * Compute the negation of the roaring bitmap within a specified interval.
1276
- * areas outside the range are passed through unchanged.
1277
- */
1278
- void flip(uint64_t range_start, uint64_t range_end) {
1279
- uint32_t start_high = highBytes(range_start);
1280
- uint32_t start_low = lowBytes(range_start);
1281
- uint32_t end_high = highBytes(range_end);
1282
- uint32_t end_low = lowBytes(range_end);
1283
-
1284
- if (start_high == end_high) {
1285
- roarings[start_high].flip(start_low, end_low);
1286
- return;
1287
- }
1288
- // we put std::numeric_limits<>::max/min in parenthesis
1289
- // to avoid a clash with the Windows.h header under Windows
1290
- roarings[start_high].flip(start_low,
1291
- (std::numeric_limits<uint32_t>::max)());
1292
- roarings[start_high++].setCopyOnWrite(copyOnWrite);
1293
-
1294
- for (; start_high <= highBytes(range_end) - 1; ++start_high) {
1295
- roarings[start_high].flip((std::numeric_limits<uint32_t>::min)(),
1296
- (std::numeric_limits<uint32_t>::max)());
1297
- roarings[start_high].setCopyOnWrite(copyOnWrite);
1298
- }
1299
-
1300
- roarings[start_high].flip((std::numeric_limits<uint32_t>::min)(),
1301
- end_low);
1302
- roarings[start_high].setCopyOnWrite(copyOnWrite);
1303
- }
1304
-
1305
- /**
1306
- * Remove run-length encoding even when it is more space efficient
1307
- * return whether a change was applied
1308
- */
1309
- bool removeRunCompression() {
1310
- return std::accumulate(
1311
- roarings.begin(), roarings.end(), true,
1312
- [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
1313
- return map_entry.second.removeRunCompression() && previous;
1314
- });
1315
- }
1316
-
1317
- /**
1318
- * Convert array and bitmap containers to run containers when it is more
1319
- * efficient; also convert from run containers when more space efficient.
1320
- * Returns true if the result has at least one run container.
1321
- * Additional savings might be possible by calling shrinkToFit().
1322
- */
1323
- bool runOptimize() {
1324
- return std::accumulate(
1325
- roarings.begin(), roarings.end(), true,
1326
- [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
1327
- return map_entry.second.runOptimize() && previous;
1328
- });
1329
- }
1330
-
1331
- /**
1332
- * If needed, reallocate memory to shrink the memory usage.
1333
- * Returns the number of bytes saved.
1334
- */
1335
- size_t shrinkToFit() {
1336
- size_t savedBytes = 0;
1337
- auto iter = roarings.begin();
1338
- while (iter != roarings.cend()) {
1339
- if (iter->second.isEmpty()) {
1340
- // empty Roarings are 84 bytes
1341
- savedBytes += 88;
1342
- roarings.erase(iter++);
1343
- } else {
1344
- savedBytes += iter->second.shrinkToFit();
1345
- iter++;
1346
- }
1347
- }
1348
- return savedBytes;
1349
- }
1350
-
1351
- /**
1352
- * Iterate over the bitmap elements in order(start from the smallest one)
1353
- * and call iterator once for every element until the iterator function
1354
- * returns false. To iterate over all values, the iterator function should
1355
- * always return true.
1356
- *
1357
- * The roaring_iterator64 parameter is a pointer to a function that
1358
- * returns bool (true means that the iteration should continue while false
1359
- * means that it should stop), and takes (uint64_t element, void* ptr) as
1360
- * inputs.
1361
- */
1362
- void iterate(api::roaring_iterator64 iterator, void *ptr) const {
1363
- for (const auto &map_entry : roarings) {
1364
- bool should_continue =
1365
- roaring_iterate64(&map_entry.second.roaring, iterator,
1366
- uint64_t(map_entry.first) << 32, ptr);
1367
- if (!should_continue) {
1368
- break;
1369
- }
1370
- }
1371
- }
1372
-
1373
- /**
1374
- * If the size of the roaring bitmap is strictly greater than rank, then
1375
- * this function returns true and set element to the element of given
1376
- * rank. Otherwise, it returns false.
1377
- */
1378
- bool select(uint64_t rnk, uint64_t *element) const {
1379
- for (const auto &map_entry : roarings) {
1380
- uint64_t sub_cardinality = (uint64_t)map_entry.second.cardinality();
1381
- if (rnk < sub_cardinality) {
1382
- *element = ((uint64_t)map_entry.first) << 32;
1383
- // assuming little endian
1384
- return map_entry.second.select((uint32_t)rnk,
1385
- ((uint32_t *)element));
1386
- }
1387
- rnk -= sub_cardinality;
1388
- }
1389
- return false;
1390
- }
1391
-
1392
- /**
1393
- * Returns the number of integers that are smaller or equal to x.
1394
- */
1395
- uint64_t rank(uint64_t x) const {
1396
- uint64_t result = 0;
1397
- auto roaring_destination = roarings.find(highBytes(x));
1398
- if (roaring_destination != roarings.cend()) {
1399
- for (auto roaring_iter = roarings.cbegin();
1400
- roaring_iter != roaring_destination; ++roaring_iter) {
1401
- result += roaring_iter->second.cardinality();
1402
- }
1403
- result += roaring_destination->second.rank(lowBytes(x));
1404
- return result;
1405
- }
1406
- roaring_destination = roarings.lower_bound(highBytes(x));
1407
- for (auto roaring_iter = roarings.cbegin();
1408
- roaring_iter != roaring_destination; ++roaring_iter) {
1409
- result += roaring_iter->second.cardinality();
1410
- }
1411
- return result;
1412
- }
1413
-
1414
- /**
1415
- * Write a bitmap to a char buffer. This is meant to be compatible with
1416
- * the Java and Go versions. Returns how many bytes were written which
1417
- * should be getSizeInBytes().
1418
- *
1419
- * Setting the portable flag to false enables a custom format that
1420
- * can save space compared to the portable format (e.g., for very
1421
- * sparse bitmaps).
1422
- */
1423
- size_t write(char *buf, bool portable = true) const {
1424
- const char *orig = buf;
1425
- // push map size
1426
- uint64_t map_size = roarings.size();
1427
- std::memcpy(buf, &map_size, sizeof(uint64_t));
1428
- buf += sizeof(uint64_t);
1429
- std::for_each(
1430
- roarings.cbegin(), roarings.cend(),
1431
- [&buf, portable](const std::pair<const uint32_t, Roaring> &map_entry) {
1432
- // push map key
1433
- std::memcpy(buf, &map_entry.first, sizeof(uint32_t));
1434
- // ^-- Note: `*((uint32_t*)buf) = map_entry.first;` is undefined
1435
-
1436
- buf += sizeof(uint32_t);
1437
- // push map value Roaring
1438
- buf += map_entry.second.write(buf, portable);
1439
- });
1440
- return buf - orig;
1441
- }
1442
-
1443
- /**
1444
- * Read a bitmap from a serialized version. This is meant to be compatible
1445
- * with the Java and Go versions.
1446
- *
1447
- * Setting the portable flag to false enable a custom format that
1448
- * can save space compared to the portable format (e.g., for very
1449
- * sparse bitmaps).
1450
- *
1451
- * This function is unsafe in the sense that if you provide bad data, many
1452
- * bytes could be read, possibly causing a buffer overflow. See also
1453
- * readSafe.
1454
- */
1455
- static Roaring64Map read(const char *buf, bool portable = true) {
1456
- Roaring64Map result;
1457
- // get map size
1458
- uint64_t map_size;
1459
- std::memcpy(&map_size, buf, sizeof(uint64_t));
1460
- buf += sizeof(uint64_t);
1461
- for (uint64_t lcv = 0; lcv < map_size; lcv++) {
1462
- // get map key
1463
- uint32_t key;
1464
- std::memcpy(&key, buf, sizeof(uint32_t));
1465
- // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined
1466
-
1467
- buf += sizeof(uint32_t);
1468
- // read map value Roaring
1469
- Roaring read_var = Roaring::read(buf, portable);
1470
- // forward buffer past the last Roaring Bitmap
1471
- buf += read_var.getSizeInBytes(portable);
1472
- result.emplaceOrInsert(key, std::move(read_var));
1473
- }
1474
- return result;
1475
- }
1476
-
1477
- /**
1478
- * Read a bitmap from a serialized version, reading no more than maxbytes
1479
- * bytes. This is meant to be compatible with the Java and Go versions.
1480
- *
1481
- * Setting the portable flag to false enable a custom format that can save
1482
- * space compared to the portable format (e.g., for very sparse bitmaps).
1483
- */
1484
- static Roaring64Map readSafe(const char *buf, size_t maxbytes) {
1485
- Roaring64Map result;
1486
- // get map size
1487
- uint64_t map_size;
1488
- std::memcpy(&map_size, buf, sizeof(uint64_t));
1489
- buf += sizeof(uint64_t);
1490
- for (uint64_t lcv = 0; lcv < map_size; lcv++) {
1491
- // get map key
1492
- if(maxbytes < sizeof(uint32_t)) {
1493
- #if ROARING_EXCEPTIONS
1494
- throw std::runtime_error("ran out of bytes");
1495
- #else
1496
- ROARING_TERMINATE("ran out of bytes");
1497
- #endif
1498
- }
1499
- uint32_t key;
1500
- std::memcpy(&key, buf, sizeof(uint32_t));
1501
- // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined
1502
-
1503
- buf += sizeof(uint32_t);
1504
- maxbytes -= sizeof(uint32_t);
1505
- // read map value Roaring
1506
- Roaring read_var = Roaring::readSafe(buf, maxbytes);
1507
- // forward buffer past the last Roaring Bitmap
1508
- size_t tz = read_var.getSizeInBytes(true);
1509
- buf += tz;
1510
- maxbytes -= tz;
1511
- result.emplaceOrInsert(key, std::move(read_var));
1512
- }
1513
- return result;
1514
- }
1515
-
1516
- /**
1517
- * Return the number of bytes required to serialize this bitmap (meant to
1518
- * be compatible with Java and Go versions)
1519
- *
1520
- * Setting the portable flag to false enable a custom format that can save
1521
- * space compared to the portable format (e.g., for very sparse bitmaps).
1522
- */
1523
- size_t getSizeInBytes(bool portable = true) const {
1524
- // start with, respectively, map size and size of keys for each map
1525
- // entry
1526
- return std::accumulate(
1527
- roarings.cbegin(), roarings.cend(),
1528
- sizeof(uint64_t) + roarings.size() * sizeof(uint32_t),
1529
- [=](size_t previous,
1530
- const std::pair<const uint32_t, Roaring> &map_entry) {
1531
- // add in bytes used by each Roaring
1532
- return previous + map_entry.second.getSizeInBytes(portable);
1533
- });
1534
- }
1535
-
1536
- static const Roaring64Map frozenView(const char *buf) {
1537
- // size of bitmap buffer and key
1538
- const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
1539
-
1540
- Roaring64Map result;
1541
-
1542
- // get map size
1543
- uint64_t map_size;
1544
- memcpy(&map_size, buf, sizeof(uint64_t));
1545
- buf += sizeof(uint64_t);
1546
-
1547
- for (uint64_t lcv = 0; lcv < map_size; lcv++) {
1548
- // pad to 32 bytes minus the metadata size
1549
- while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;
1550
-
1551
- // get bitmap size
1552
- size_t len;
1553
- memcpy(&len, buf, sizeof(size_t));
1554
- buf += sizeof(size_t);
1555
-
1556
- // get map key
1557
- uint32_t key;
1558
- memcpy(&key, buf, sizeof(uint32_t));
1559
- buf += sizeof(uint32_t);
1560
-
1561
- // read map value Roaring
1562
- const Roaring read = Roaring::frozenView(buf, len);
1563
- result.emplaceOrInsert(key, read);
1564
-
1565
- // forward buffer past the last Roaring Bitmap
1566
- buf += len;
1567
- }
1568
- return result;
1569
- }
1570
-
1571
- // As with serialized 64-bit bitmaps, 64-bit frozen bitmaps are serialized
1572
- // by concatenating one or more Roaring::write output buffers with the
1573
- // preceeding map key. Unlike standard bitmap serialization, frozen bitmaps
1574
- // must be 32-byte aligned and requires a buffer length to parse. As a
1575
- // result, each concatenated output of Roaring::writeFrozen is preceeded by
1576
- // padding, the buffer size (size_t), and the map key (uint32_t). The
1577
- // padding is used to ensure 32-byte alignment, but since it is followed by
1578
- // the buffer size and map key, it actually pads to `(x - sizeof(size_t) +
1579
- // sizeof(uint32_t)) mod 32` to leave room for the metadata.
1580
- void writeFrozen(char *buf) const {
1581
- // size of bitmap buffer and key
1582
- const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
1583
-
1584
- // push map size
1585
- uint64_t map_size = roarings.size();
1586
- memcpy(buf, &map_size, sizeof(uint64_t));
1587
- buf += sizeof(uint64_t);
1588
-
1589
- for (auto &map_entry : roarings) {
1590
- size_t frozenSizeInBytes = map_entry.second.getFrozenSizeInBytes();
1591
-
1592
- // pad to 32 bytes minus the metadata size
1593
- while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;
1594
-
1595
- // push bitmap size
1596
- memcpy(buf, &frozenSizeInBytes, sizeof(size_t));
1597
- buf += sizeof(size_t);
1598
-
1599
- // push map key
1600
- memcpy(buf, &map_entry.first, sizeof(uint32_t));
1601
- buf += sizeof(uint32_t);
1602
-
1603
- // push map value Roaring
1604
- map_entry.second.writeFrozen(buf);
1605
- buf += map_entry.second.getFrozenSizeInBytes();
1606
- }
1607
- }
1608
-
1609
- size_t getFrozenSizeInBytes() const {
1610
- // size of bitmap size and map key
1611
- const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
1612
- size_t ret = 0;
1613
-
1614
- // map size
1615
- ret += sizeof(uint64_t);
1616
-
1617
- for (auto &map_entry : roarings) {
1618
- // pad to 32 bytes minus the metadata size
1619
- while ((ret + metadata_size) % 32 != 0) ret++;
1620
- ret += metadata_size;
1621
-
1622
- // frozen bitmaps must be 32-byte aligned
1623
- ret += map_entry.second.getFrozenSizeInBytes();
1624
- }
1625
- return ret;
1626
- }
1627
-
1628
- /**
1629
- * Computes the intersection between two bitmaps and returns new bitmap.
1630
- * The current bitmap and the provided bitmap are unchanged.
1631
- */
1632
- Roaring64Map operator&(const Roaring64Map &o) const {
1633
- return Roaring64Map(*this) &= o;
1634
- }
1635
-
1636
- /**
1637
- * Computes the difference between two bitmaps and returns new bitmap.
1638
- * The current bitmap and the provided bitmap are unchanged.
1639
- */
1640
- Roaring64Map operator-(const Roaring64Map &o) const {
1641
- return Roaring64Map(*this) -= o;
1642
- }
1643
-
1644
- /**
1645
- * Computes the union between two bitmaps and returns new bitmap.
1646
- * The current bitmap and the provided bitmap are unchanged.
1647
- */
1648
- Roaring64Map operator|(const Roaring64Map &o) const {
1649
- return Roaring64Map(*this) |= o;
1650
- }
1651
-
1652
- /**
1653
- * Computes the symmetric union between two bitmaps and returns new bitmap.
1654
- * The current bitmap and the provided bitmap are unchanged.
1655
- */
1656
- Roaring64Map operator^(const Roaring64Map &o) const {
1657
- return Roaring64Map(*this) ^= o;
1658
- }
1659
-
1660
- /**
1661
- * Whether or not we apply copy and write.
1662
- */
1663
- void setCopyOnWrite(bool val) {
1664
- if (copyOnWrite == val) return;
1665
- copyOnWrite = val;
1666
- std::for_each(roarings.begin(), roarings.end(),
1667
- [=](std::pair<const uint32_t, Roaring> &map_entry) {
1668
- map_entry.second.setCopyOnWrite(val);
1669
- });
1670
- }
1671
-
1672
- /**
1673
- * Print the content of the bitmap
1674
- */
1675
- void printf() const {
1676
- if (!isEmpty()) {
1677
- auto map_iter = roarings.cbegin();
1678
- while (map_iter->second.isEmpty()) ++map_iter;
1679
- struct iter_data {
1680
- uint32_t high_bits{};
1681
- char first_char{'{'};
1682
- } outer_iter_data;
1683
- outer_iter_data.high_bits = roarings.begin()->first;
1684
- map_iter->second.iterate(
1685
- [](uint32_t low_bits, void *inner_iter_data) -> bool {
1686
- std::printf("%c%llu",
1687
- ((iter_data *)inner_iter_data)->first_char,
1688
- (long long unsigned)uniteBytes(
1689
- ((iter_data *)inner_iter_data)->high_bits,
1690
- low_bits));
1691
- ((iter_data *)inner_iter_data)->first_char = ',';
1692
- return true;
1693
- },
1694
- (void *)&outer_iter_data);
1695
- std::for_each(
1696
- ++map_iter, roarings.cend(),
1697
- [](const std::pair<const uint32_t, Roaring> &map_entry) {
1698
- map_entry.second.iterate(
1699
- [](uint32_t low_bits, void *high_bits) -> bool {
1700
- std::printf(",%llu",
1701
- (long long unsigned)uniteBytes(
1702
- *(uint32_t *)high_bits, low_bits));
1703
- return true;
1704
- },
1705
- (void *)&map_entry.first);
1706
- });
1707
- } else
1708
- std::printf("{");
1709
- std::printf("}\n");
1710
- }
1711
-
1712
- /**
1713
- * Print the content of the bitmap into a string
1714
- */
1715
- std::string toString() const {
1716
- struct iter_data {
1717
- std::string str{}; // The empty constructor silences warnings from pedantic static analyzers.
1718
- uint32_t high_bits{0};
1719
- char first_char{'{'};
1720
- } outer_iter_data;
1721
- if (!isEmpty()) {
1722
- auto map_iter = roarings.cbegin();
1723
- while (map_iter->second.isEmpty()) ++map_iter;
1724
- outer_iter_data.high_bits = roarings.begin()->first;
1725
- map_iter->second.iterate(
1726
- [](uint32_t low_bits, void *inner_iter_data) -> bool {
1727
- ((iter_data *)inner_iter_data)->str +=
1728
- ((iter_data *)inner_iter_data)->first_char;
1729
- ((iter_data *)inner_iter_data)->str += std::to_string(
1730
- uniteBytes(((iter_data *)inner_iter_data)->high_bits,
1731
- low_bits));
1732
- ((iter_data *)inner_iter_data)->first_char = ',';
1733
- return true;
1734
- },
1735
- (void *)&outer_iter_data);
1736
- std::for_each(
1737
- ++map_iter, roarings.cend(),
1738
- [&outer_iter_data](
1739
- const std::pair<const uint32_t, Roaring> &map_entry) {
1740
- outer_iter_data.high_bits = map_entry.first;
1741
- map_entry.second.iterate(
1742
- [](uint32_t low_bits, void *inner_iter_data) -> bool {
1743
- ((iter_data *)inner_iter_data)->str +=
1744
- ((iter_data *)inner_iter_data)->first_char;
1745
- ((iter_data *)inner_iter_data)->str +=
1746
- std::to_string(uniteBytes(
1747
- ((iter_data *)inner_iter_data)->high_bits,
1748
- low_bits));
1749
- return true;
1750
- },
1751
- (void *)&outer_iter_data);
1752
- });
1753
- } else
1754
- outer_iter_data.str = '{';
1755
- outer_iter_data.str += '}';
1756
- return outer_iter_data.str;
1757
- }
1758
-
1759
- /**
1760
- * Whether or not copy and write is active.
1761
- */
1762
- bool getCopyOnWrite() const { return copyOnWrite; }
1763
-
1764
- /**
1765
- * Computes the logical or (union) between "n" bitmaps (referenced by a
1766
- * pointer).
1767
- */
1768
- static Roaring64Map fastunion(size_t n, const Roaring64Map **inputs) {
1769
- Roaring64Map ans;
1770
- // not particularly fast
1771
- for (size_t lcv = 0; lcv < n; ++lcv) {
1772
- ans |= *(inputs[lcv]);
1773
- }
1774
- return ans;
1775
- }
1776
-
1777
- friend class Roaring64MapSetBitForwardIterator;
1778
- friend class Roaring64MapSetBitBiDirectionalIterator;
1779
- typedef Roaring64MapSetBitForwardIterator const_iterator;
1780
- typedef Roaring64MapSetBitBiDirectionalIterator const_bidirectional_iterator;
1781
-
1782
- /**
1783
- * Returns an iterator that can be used to access the position of the set
1784
- * bits. The running time complexity of a full scan is proportional to the
1785
- * number of set bits: be aware that if you have long strings of 1s, this
1786
- * can be very inefficient.
1787
- *
1788
- * It can be much faster to use the toArray method if you want to
1789
- * retrieve the set bits.
1790
- */
1791
- const_iterator begin() const;
1792
-
1793
- /**
1794
- * A bogus iterator that can be used together with begin()
1795
- * for constructions such as: for (auto i = b.begin(); * i!=b.end(); ++i) {}
1796
- */
1797
- const_iterator end() const;
1798
-
1799
- private:
1800
- std::map<uint32_t, Roaring> roarings{}; // The empty constructor silences warnings from pedantic static analyzers.
1801
- bool copyOnWrite{false};
1802
- static uint32_t highBytes(const uint64_t in) { return uint32_t(in >> 32); }
1803
- static uint32_t lowBytes(const uint64_t in) { return uint32_t(in); }
1804
- static uint64_t uniteBytes(const uint32_t highBytes,
1805
- const uint32_t lowBytes) {
1806
- return (uint64_t(highBytes) << 32) | uint64_t(lowBytes);
1807
- }
1808
- // this is needed to tolerate gcc's C++11 libstdc++ lacking emplace
1809
- // prior to version 4.8
1810
- void emplaceOrInsert(const uint32_t key, const Roaring &value) {
1811
- #if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
1812
- roarings.insert(std::make_pair(key, value));
1813
- #else
1814
- roarings.emplace(std::make_pair(key, value));
1815
- #endif
1816
- }
1817
-
1818
- void emplaceOrInsert(const uint32_t key, Roaring &&value) {
1819
- #if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
1820
- roarings.insert(std::make_pair(key, std::move(value)));
1821
- #else
1822
- roarings.emplace(key, value);
1823
- #endif
1824
- }
1825
- };
1826
-
1827
- /**
1828
- * Used to go through the set bits. Not optimally fast, but convenient.
1829
- */
1830
- class Roaring64MapSetBitForwardIterator {
1831
- public:
1832
- typedef std::forward_iterator_tag iterator_category;
1833
- typedef uint64_t *pointer;
1834
- typedef uint64_t &reference_type;
1835
- typedef uint64_t value_type;
1836
- typedef int64_t difference_type;
1837
- typedef Roaring64MapSetBitForwardIterator type_of_iterator;
1838
-
1839
- /**
1840
- * Provides the location of the set bit.
1841
- */
1842
- value_type operator*() const {
1843
- return Roaring64Map::uniteBytes(map_iter->first, i.current_value);
1844
- }
1845
-
1846
- bool operator<(const type_of_iterator &o) const {
1847
- if (map_iter == map_end) return false;
1848
- if (o.map_iter == o.map_end) return true;
1849
- return **this < *o;
1850
- }
1851
-
1852
- bool operator<=(const type_of_iterator &o) const {
1853
- if (o.map_iter == o.map_end) return true;
1854
- if (map_iter == map_end) return false;
1855
- return **this <= *o;
1856
- }
1857
-
1858
- bool operator>(const type_of_iterator &o) const {
1859
- if (o.map_iter == o.map_end) return false;
1860
- if (map_iter == map_end) return true;
1861
- return **this > *o;
1862
- }
1863
-
1864
- bool operator>=(const type_of_iterator &o) const {
1865
- if (map_iter == map_end) return true;
1866
- if (o.map_iter == o.map_end) return false;
1867
- return **this >= *o;
1868
- }
1869
-
1870
- type_of_iterator &operator++() { // ++i, must returned inc. value
1871
- if (i.has_value == true) roaring_advance_uint32_iterator(&i);
1872
- while (!i.has_value) {
1873
- map_iter++;
1874
- if (map_iter == map_end) return *this;
1875
- roaring_init_iterator(&map_iter->second.roaring, &i);
1876
- }
1877
- return *this;
1878
- }
1879
-
1880
- type_of_iterator operator++(int) { // i++, must return orig. value
1881
- Roaring64MapSetBitForwardIterator orig(*this);
1882
- roaring_advance_uint32_iterator(&i);
1883
- while (!i.has_value) {
1884
- map_iter++;
1885
- if (map_iter == map_end) return orig;
1886
- roaring_init_iterator(&map_iter->second.roaring, &i);
1887
- }
1888
- return orig;
1889
- }
1890
-
1891
- bool move(const value_type& x) {
1892
- map_iter = p.lower_bound(Roaring64Map::highBytes(x));
1893
- if (map_iter != p.cend()) {
1894
- roaring_init_iterator(&map_iter->second.roaring, &i);
1895
- if (map_iter->first == Roaring64Map::highBytes(x)) {
1896
- if (roaring_move_uint32_iterator_equalorlarger(&i, Roaring64Map::lowBytes(x)))
1897
- return true;
1898
- map_iter++;
1899
- if (map_iter == map_end) return false;
1900
- roaring_init_iterator(&map_iter->second.roaring, &i);
1901
- }
1902
- return true;
1903
- }
1904
- return false;
1905
- }
1906
-
1907
- bool operator==(const Roaring64MapSetBitForwardIterator &o) const {
1908
- if (map_iter == map_end && o.map_iter == o.map_end) return true;
1909
- if (o.map_iter == o.map_end) return false;
1910
- return **this == *o;
1911
- }
1912
-
1913
- bool operator!=(const Roaring64MapSetBitForwardIterator &o) const {
1914
- if (map_iter == map_end && o.map_iter == o.map_end) return false;
1915
- if (o.map_iter == o.map_end) return true;
1916
- return **this != *o;
1917
- }
1918
-
1919
- Roaring64MapSetBitForwardIterator &operator=(const Roaring64MapSetBitForwardIterator& r) {
1920
- map_iter = r.map_iter;
1921
- map_end = r.map_end;
1922
- i = r.i;
1923
- return *this;
1924
- }
1925
-
1926
- Roaring64MapSetBitForwardIterator(const Roaring64MapSetBitForwardIterator& r)
1927
- : p(r.p),
1928
- map_iter(r.map_iter),
1929
- map_end(r.map_end),
1930
- i(r.i)
1931
- {}
1932
-
1933
- Roaring64MapSetBitForwardIterator(const Roaring64Map &parent,
1934
- bool exhausted = false)
1935
- : p(parent.roarings), map_end(parent.roarings.cend()) {
1936
- if (exhausted || parent.roarings.empty()) {
1937
- map_iter = parent.roarings.cend();
1938
- } else {
1939
- map_iter = parent.roarings.cbegin();
1940
- roaring_init_iterator(&map_iter->second.roaring, &i);
1941
- while (!i.has_value) {
1942
- map_iter++;
1943
- if (map_iter == map_end) return;
1944
- roaring_init_iterator(&map_iter->second.roaring, &i);
1945
- }
1946
- }
1947
- }
1948
-
1949
- protected:
1950
- const std::map<uint32_t, Roaring>& p;
1951
- std::map<uint32_t, Roaring>::const_iterator map_iter{}; // The empty constructor silences warnings from pedantic static analyzers.
1952
- std::map<uint32_t, Roaring>::const_iterator map_end{}; // The empty constructor silences warnings from pedantic static analyzers.
1953
- api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers.
1954
- };
1955
-
1956
- class Roaring64MapSetBitBiDirectionalIterator final :public Roaring64MapSetBitForwardIterator {
1957
- public:
1958
- explicit Roaring64MapSetBitBiDirectionalIterator(const Roaring64Map &parent,
1959
- bool exhausted = false)
1960
- : Roaring64MapSetBitForwardIterator(parent, exhausted), map_begin(parent.roarings.cbegin())
1961
- {}
1962
-
1963
- Roaring64MapSetBitBiDirectionalIterator &operator=(const Roaring64MapSetBitForwardIterator& r) {
1964
- *(Roaring64MapSetBitForwardIterator*)this = r;
1965
- return *this;
1966
- }
1967
-
1968
- Roaring64MapSetBitBiDirectionalIterator& operator--() { // --i, must return dec.value
1969
- if (map_iter == map_end) {
1970
- --map_iter;
1971
- roaring_init_iterator_last(&map_iter->second.roaring, &i);
1972
- if (i.has_value) return *this;
1973
- }
1974
-
1975
- roaring_previous_uint32_iterator(&i);
1976
- while (!i.has_value) {
1977
- if (map_iter == map_begin) return *this;
1978
- map_iter--;
1979
- roaring_init_iterator_last(&map_iter->second.roaring, &i);
1980
- }
1981
- return *this;
1982
- }
1983
-
1984
- Roaring64MapSetBitBiDirectionalIterator operator--(int) { // i--, must return orig. value
1985
- Roaring64MapSetBitBiDirectionalIterator orig(*this);
1986
- if (map_iter == map_end) {
1987
- --map_iter;
1988
- roaring_init_iterator_last(&map_iter->second.roaring, &i);
1989
- return orig;
1990
- }
1991
-
1992
- roaring_previous_uint32_iterator(&i);
1993
- while (!i.has_value) {
1994
- if (map_iter == map_begin) return orig;
1995
- map_iter--;
1996
- roaring_init_iterator_last(&map_iter->second.roaring, &i);
1997
- }
1998
- return orig;
1999
- }
2000
-
2001
- protected:
2002
- std::map<uint32_t, Roaring>::const_iterator map_begin;
2003
- };
2004
-
2005
- inline Roaring64MapSetBitForwardIterator Roaring64Map::begin() const {
2006
- return Roaring64MapSetBitForwardIterator(*this);
2007
- }
2008
-
2009
- inline Roaring64MapSetBitForwardIterator Roaring64Map::end() const {
2010
- return Roaring64MapSetBitForwardIterator(*this, true);
2011
- }
2012
-
2013
- } // namespace roaring
2014
-
2015
- #endif /* INCLUDE_ROARING_64_MAP_HH_ */
2016
- /* end file cpp/roaring64map.hh */