Packages
rocksdb
2.6.1
3.1.1
3.1.0
3.0.0
2.6.2
2.6.1
retired
2.6.0
retired
2.5.0
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
1.9.0
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.1
1.1.0
1.0.0
0.26.2
0.26.1
0.26.0
0.25.0
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.0
0.21.0
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
RocksDB for Erlang
Retired package: Release invalid - Build broken, use 2.6.2
Current section
Files
Jump to
Current section
Files
deps/CRoaring/src/roaring_array.c
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <roaring/containers/bitset.h>
#include <roaring/containers/containers.h>
#include <roaring/memory.h>
#include <roaring/roaring_array.h>
#ifdef __cplusplus
extern "C" {
namespace roaring {
namespace internal {
#endif
// Convention: [0,ra->size) all elements are initialized
// [ra->size, ra->allocation_size) is junk and contains nothing needing freeing
extern inline int32_t ra_get_size(const roaring_array_t *ra);
extern inline int32_t ra_get_index(const roaring_array_t *ra, uint16_t x);
extern inline container_t *ra_get_container_at_index(const roaring_array_t *ra,
uint16_t i,
uint8_t *typecode);
extern inline void ra_unshare_container_at_index(roaring_array_t *ra,
uint16_t i);
extern inline void ra_replace_key_and_container_at_index(roaring_array_t *ra,
int32_t i,
uint16_t key,
container_t *c,
uint8_t typecode);
extern inline void ra_set_container_at_index(const roaring_array_t *ra,
int32_t i, container_t *c,
uint8_t typecode);
static bool realloc_array(roaring_array_t *ra, int32_t new_capacity) {
//
// Note: not implemented using C's realloc(), because the memory layout is
// Struct-of-Arrays vs. Array-of-Structs:
// https://github.com/RoaringBitmap/CRoaring/issues/256
if (new_capacity == 0) {
roaring_free(ra->containers);
ra->containers = NULL;
ra->keys = NULL;
ra->typecodes = NULL;
ra->allocation_size = 0;
return true;
}
const size_t memoryneeded =
new_capacity *
(sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t));
void *bigalloc = roaring_malloc(memoryneeded);
if (!bigalloc) return false;
void *oldbigalloc = ra->containers;
container_t **newcontainers = (container_t **)bigalloc;
uint16_t *newkeys = (uint16_t *)(newcontainers + new_capacity);
uint8_t *newtypecodes = (uint8_t *)(newkeys + new_capacity);
assert((char *)(newtypecodes + new_capacity) ==
(char *)bigalloc + memoryneeded);
if (ra->size > 0) {
memcpy(newcontainers, ra->containers, sizeof(container_t *) * ra->size);
memcpy(newkeys, ra->keys, sizeof(uint16_t) * ra->size);
memcpy(newtypecodes, ra->typecodes, sizeof(uint8_t) * ra->size);
}
ra->containers = newcontainers;
ra->keys = newkeys;
ra->typecodes = newtypecodes;
ra->allocation_size = new_capacity;
roaring_free(oldbigalloc);
return true;
}
bool ra_init_with_capacity(roaring_array_t *new_ra, uint32_t cap) {
if (!new_ra) return false;
ra_init(new_ra);
// Containers hold 64Ki elements, so 64Ki containers is enough to hold
// `0x10000 * 0x10000` (all 2^32) elements
if (cap > 0x10000) {
cap = 0x10000;
}
if (cap > 0) {
void *bigalloc = roaring_malloc(
cap * (sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t)));
if (bigalloc == NULL) return false;
new_ra->containers = (container_t **)bigalloc;
new_ra->keys = (uint16_t *)(new_ra->containers + cap);
new_ra->typecodes = (uint8_t *)(new_ra->keys + cap);
// Narrowing is safe because of above check
new_ra->allocation_size = (int32_t)cap;
}
return true;
}
int ra_shrink_to_fit(roaring_array_t *ra) {
int savings = (ra->allocation_size - ra->size) *
(sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t));
if (!realloc_array(ra, ra->size)) {
return 0;
}
ra->allocation_size = ra->size;
return savings;
}
void ra_init(roaring_array_t *new_ra) {
if (!new_ra) {
return;
}
new_ra->keys = NULL;
new_ra->containers = NULL;
new_ra->typecodes = NULL;
new_ra->allocation_size = 0;
new_ra->size = 0;
new_ra->flags = 0;
}
bool ra_overwrite(const roaring_array_t *source, roaring_array_t *dest,
bool copy_on_write) {
ra_clear_containers(dest); // we are going to overwrite them
if (source->size == 0) { // Note: can't call memcpy(NULL), even w/size
dest->size = 0; // <--- This is important.
return true; // output was just cleared, so they match
}
if (dest->allocation_size < source->size) {
if (!realloc_array(dest, source->size)) {
return false;
}
}
dest->size = source->size;
memcpy(dest->keys, source->keys, dest->size * sizeof(uint16_t));
// we go through the containers, turning them into shared containers...
if (copy_on_write) {
for (int32_t i = 0; i < dest->size; ++i) {
source->containers[i] = get_copy_of_container(
source->containers[i], &source->typecodes[i], copy_on_write);
}
// we do a shallow copy to the other bitmap
memcpy(dest->containers, source->containers,
dest->size * sizeof(container_t *));
memcpy(dest->typecodes, source->typecodes,
dest->size * sizeof(uint8_t));
} else {
memcpy(dest->typecodes, source->typecodes,
dest->size * sizeof(uint8_t));
for (int32_t i = 0; i < dest->size; i++) {
dest->containers[i] =
container_clone(source->containers[i], source->typecodes[i]);
if (dest->containers[i] == NULL) {
for (int32_t j = 0; j < i; j++) {
container_free(dest->containers[j], dest->typecodes[j]);
}
ra_clear_without_containers(dest);
return false;
}
}
}
return true;
}
void ra_clear_containers(roaring_array_t *ra) {
for (int32_t i = 0; i < ra->size; ++i) {
container_free(ra->containers[i], ra->typecodes[i]);
}
}
void ra_reset(roaring_array_t *ra) {
ra_clear_containers(ra);
ra->size = 0;
ra_shrink_to_fit(ra);
}
void ra_clear_without_containers(roaring_array_t *ra) {
roaring_free(
ra->containers); // keys and typecodes are allocated with containers
ra->size = 0;
ra->allocation_size = 0;
ra->containers = NULL;
ra->keys = NULL;
ra->typecodes = NULL;
}
void ra_clear(roaring_array_t *ra) {
ra_clear_containers(ra);
ra_clear_without_containers(ra);
}
bool extend_array(roaring_array_t *ra, int32_t k) {
int32_t desired_size = ra->size + k;
const int32_t max_containers = 65536;
assert(desired_size <= max_containers);
if (desired_size > ra->allocation_size) {
int32_t new_capacity =
(ra->size < 1024) ? 2 * desired_size : 5 * desired_size / 4;
if (new_capacity > max_containers) {
new_capacity = max_containers;
}
return realloc_array(ra, new_capacity);
}
return true;
}
void ra_append(roaring_array_t *ra, uint16_t key, container_t *c,
uint8_t typecode) {
extend_array(ra, 1);
const int32_t pos = ra->size;
ra->keys[pos] = key;
ra->containers[pos] = c;
ra->typecodes[pos] = typecode;
ra->size++;
}
void ra_append_copy(roaring_array_t *ra, const roaring_array_t *sa,
uint16_t index, bool copy_on_write) {
extend_array(ra, 1);
const int32_t pos = ra->size;
// old contents is junk that does not need freeing
ra->keys[pos] = sa->keys[index];
// the shared container will be in two bitmaps
if (copy_on_write) {
sa->containers[index] = get_copy_of_container(
sa->containers[index], &sa->typecodes[index], copy_on_write);
ra->containers[pos] = sa->containers[index];
ra->typecodes[pos] = sa->typecodes[index];
} else {
ra->containers[pos] =
container_clone(sa->containers[index], sa->typecodes[index]);
ra->typecodes[pos] = sa->typecodes[index];
}
ra->size++;
}
void ra_append_copies_until(roaring_array_t *ra, const roaring_array_t *sa,
uint16_t stopping_key, bool copy_on_write) {
for (int32_t i = 0; i < sa->size; ++i) {
if (sa->keys[i] >= stopping_key) break;
ra_append_copy(ra, sa, (uint16_t)i, copy_on_write);
}
}
void ra_append_copy_range(roaring_array_t *ra, const roaring_array_t *sa,
int32_t start_index, int32_t end_index,
bool copy_on_write) {
extend_array(ra, end_index - start_index);
for (int32_t i = start_index; i < end_index; ++i) {
const int32_t pos = ra->size;
ra->keys[pos] = sa->keys[i];
if (copy_on_write) {
sa->containers[i] = get_copy_of_container(
sa->containers[i], &sa->typecodes[i], copy_on_write);
ra->containers[pos] = sa->containers[i];
ra->typecodes[pos] = sa->typecodes[i];
} else {
ra->containers[pos] =
container_clone(sa->containers[i], sa->typecodes[i]);
ra->typecodes[pos] = sa->typecodes[i];
}
ra->size++;
}
}
void ra_append_copies_after(roaring_array_t *ra, const roaring_array_t *sa,
uint16_t before_start, bool copy_on_write) {
int start_location = ra_get_index(sa, before_start);
if (start_location >= 0)
++start_location;
else
start_location = -start_location - 1;
ra_append_copy_range(ra, sa, start_location, sa->size, copy_on_write);
}
void ra_append_move_range(roaring_array_t *ra, roaring_array_t *sa,
int32_t start_index, int32_t end_index) {
extend_array(ra, end_index - start_index);
for (int32_t i = start_index; i < end_index; ++i) {
const int32_t pos = ra->size;
ra->keys[pos] = sa->keys[i];
ra->containers[pos] = sa->containers[i];
ra->typecodes[pos] = sa->typecodes[i];
ra->size++;
}
}
void ra_append_range(roaring_array_t *ra, roaring_array_t *sa,
int32_t start_index, int32_t end_index,
bool copy_on_write) {
extend_array(ra, end_index - start_index);
for (int32_t i = start_index; i < end_index; ++i) {
const int32_t pos = ra->size;
ra->keys[pos] = sa->keys[i];
if (copy_on_write) {
sa->containers[i] = get_copy_of_container(
sa->containers[i], &sa->typecodes[i], copy_on_write);
ra->containers[pos] = sa->containers[i];
ra->typecodes[pos] = sa->typecodes[i];
} else {
ra->containers[pos] =
container_clone(sa->containers[i], sa->typecodes[i]);
ra->typecodes[pos] = sa->typecodes[i];
}
ra->size++;
}
}
container_t *ra_get_container(roaring_array_t *ra, uint16_t x,
uint8_t *typecode) {
int i = binarySearch(ra->keys, (int32_t)ra->size, x);
if (i < 0) return NULL;
*typecode = ra->typecodes[i];
return ra->containers[i];
}
extern inline container_t *ra_get_container_at_index(const roaring_array_t *ra,
uint16_t i,
uint8_t *typecode);
extern inline uint16_t ra_get_key_at_index(const roaring_array_t *ra,
uint16_t i);
extern inline int32_t ra_get_index(const roaring_array_t *ra, uint16_t x);
extern inline int32_t ra_advance_until(const roaring_array_t *ra, uint16_t x,
int32_t pos);
// everything skipped over is freed
int32_t ra_advance_until_freeing(roaring_array_t *ra, uint16_t x, int32_t pos) {
while (pos < ra->size && ra->keys[pos] < x) {
container_free(ra->containers[pos], ra->typecodes[pos]);
++pos;
}
return pos;
}
void ra_insert_new_key_value_at(roaring_array_t *ra, int32_t i, uint16_t key,
container_t *c, uint8_t typecode) {
extend_array(ra, 1);
// May be an optimization opportunity with DIY memmove
memmove(&(ra->keys[i + 1]), &(ra->keys[i]),
sizeof(uint16_t) * (ra->size - i));
memmove(&(ra->containers[i + 1]), &(ra->containers[i]),
sizeof(container_t *) * (ra->size - i));
memmove(&(ra->typecodes[i + 1]), &(ra->typecodes[i]),
sizeof(uint8_t) * (ra->size - i));
ra->keys[i] = key;
ra->containers[i] = c;
ra->typecodes[i] = typecode;
ra->size++;
}
// note: Java routine set things to 0, enabling GC.
// Java called it "resize" but it was always used to downsize.
// Allowing upsize would break the conventions about
// valid containers below ra->size.
void ra_downsize(roaring_array_t *ra, int32_t new_length) {
assert(new_length <= ra->size);
ra->size = new_length;
}
void ra_remove_at_index(roaring_array_t *ra, int32_t i) {
memmove(&(ra->containers[i]), &(ra->containers[i + 1]),
sizeof(container_t *) * (ra->size - i - 1));
memmove(&(ra->keys[i]), &(ra->keys[i + 1]),
sizeof(uint16_t) * (ra->size - i - 1));
memmove(&(ra->typecodes[i]), &(ra->typecodes[i + 1]),
sizeof(uint8_t) * (ra->size - i - 1));
ra->size--;
}
void ra_remove_at_index_and_free(roaring_array_t *ra, int32_t i) {
container_free(ra->containers[i], ra->typecodes[i]);
ra_remove_at_index(ra, i);
}
// used in inplace andNot only, to slide left the containers from
// the mutated RoaringBitmap that are after the largest container of
// the argument RoaringBitmap. In use it should be followed by a call to
// downsize.
//
void ra_copy_range(roaring_array_t *ra, uint32_t begin, uint32_t end,
uint32_t new_begin) {
assert(begin <= end);
assert(new_begin < begin);
const int range = end - begin;
// We ensure to previously have freed overwritten containers
// that are not copied elsewhere
memmove(&(ra->containers[new_begin]), &(ra->containers[begin]),
sizeof(container_t *) * range);
memmove(&(ra->keys[new_begin]), &(ra->keys[begin]),
sizeof(uint16_t) * range);
memmove(&(ra->typecodes[new_begin]), &(ra->typecodes[begin]),
sizeof(uint8_t) * range);
}
void ra_shift_tail(roaring_array_t *ra, int32_t count, int32_t distance) {
if (distance > 0) {
extend_array(ra, distance);
}
int32_t srcpos = ra->size - count;
int32_t dstpos = srcpos + distance;
memmove(&(ra->keys[dstpos]), &(ra->keys[srcpos]), sizeof(uint16_t) * count);
memmove(&(ra->containers[dstpos]), &(ra->containers[srcpos]),
sizeof(container_t *) * count);
memmove(&(ra->typecodes[dstpos]), &(ra->typecodes[srcpos]),
sizeof(uint8_t) * count);
ra->size += distance;
}
void ra_to_uint32_array(const roaring_array_t *ra, uint32_t *ans) {
size_t ctr = 0;
for (int32_t i = 0; i < ra->size; ++i) {
int num_added = container_to_uint32_array(
ans + ctr, ra->containers[i], ra->typecodes[i],
((uint32_t)ra->keys[i]) << 16);
ctr += num_added;
}
}
bool ra_has_run_container(const roaring_array_t *ra) {
for (int32_t k = 0; k < ra->size; ++k) {
if (get_container_type(ra->containers[k], ra->typecodes[k]) ==
RUN_CONTAINER_TYPE)
return true;
}
return false;
}
uint32_t ra_portable_header_size(const roaring_array_t *ra) {
if (ra_has_run_container(ra)) {
if (ra->size <
NO_OFFSET_THRESHOLD) { // for small bitmaps, we omit the offsets
return 4 + (ra->size + 7) / 8 + 4 * ra->size;
}
return 4 + (ra->size + 7) / 8 +
8 * ra->size; // - 4 because we pack the size with the cookie
} else {
return 4 + 4 + 8 * ra->size;
}
}
size_t ra_portable_size_in_bytes(const roaring_array_t *ra) {
size_t count = ra_portable_header_size(ra);
for (int32_t k = 0; k < ra->size; ++k) {
count += container_size_in_bytes(ra->containers[k], ra->typecodes[k]);
}
return count;
}
// This function is endian-sensitive.
size_t ra_portable_serialize(const roaring_array_t *ra, char *buf) {
char *initbuf = buf;
uint32_t startOffset = 0;
bool hasrun = ra_has_run_container(ra);
if (hasrun) {
uint32_t cookie = SERIAL_COOKIE | ((uint32_t)(ra->size - 1) << 16);
memcpy(buf, &cookie, sizeof(cookie));
buf += sizeof(cookie);
uint32_t s = (ra->size + 7) / 8;
memset(buf, 0, s);
for (int32_t i = 0; i < ra->size; ++i) {
if (get_container_type(ra->containers[i], ra->typecodes[i]) ==
RUN_CONTAINER_TYPE) {
buf[i / 8] |= 1 << (i % 8);
}
}
buf += s;
if (ra->size < NO_OFFSET_THRESHOLD) {
startOffset = 4 + 4 * ra->size + s;
} else {
startOffset = 4 + 8 * ra->size + s;
}
} else { // backwards compatibility
uint32_t cookie = SERIAL_COOKIE_NO_RUNCONTAINER;
memcpy(buf, &cookie, sizeof(cookie));
buf += sizeof(cookie);
memcpy(buf, &ra->size, sizeof(ra->size));
buf += sizeof(ra->size);
startOffset = 4 + 4 + 4 * ra->size + 4 * ra->size;
}
for (int32_t k = 0; k < ra->size; ++k) {
memcpy(buf, &ra->keys[k], sizeof(ra->keys[k]));
buf += sizeof(ra->keys[k]);
// get_cardinality returns a value in [1,1<<16], subtracting one
// we get [0,1<<16 - 1] which fits in 16 bits
uint16_t card = (uint16_t)(container_get_cardinality(ra->containers[k],
ra->typecodes[k]) -
1);
memcpy(buf, &card, sizeof(card));
buf += sizeof(card);
}
if ((!hasrun) || (ra->size >= NO_OFFSET_THRESHOLD)) {
// writing the containers offsets
for (int32_t k = 0; k < ra->size; k++) {
memcpy(buf, &startOffset, sizeof(startOffset));
buf += sizeof(startOffset);
startOffset =
startOffset +
container_size_in_bytes(ra->containers[k], ra->typecodes[k]);
}
}
for (int32_t k = 0; k < ra->size; ++k) {
buf += container_write(ra->containers[k], ra->typecodes[k], buf);
}
return buf - initbuf;
}
// Quickly checks whether there is a serialized bitmap at the pointer,
// not exceeding size "maxbytes" in bytes. This function does not allocate
// memory dynamically.
//
// This function returns 0 if and only if no valid bitmap is found.
// Otherwise, it returns how many bytes are occupied.
//
size_t ra_portable_deserialize_size(const char *buf, const size_t maxbytes) {
size_t bytestotal = sizeof(int32_t); // for cookie
if (bytestotal > maxbytes) return 0;
uint32_t cookie;
memcpy(&cookie, buf, sizeof(int32_t));
buf += sizeof(uint32_t);
if ((cookie & 0xFFFF) != SERIAL_COOKIE &&
cookie != SERIAL_COOKIE_NO_RUNCONTAINER) {
return 0;
}
int32_t size;
if ((cookie & 0xFFFF) == SERIAL_COOKIE)
size = (cookie >> 16) + 1;
else {
bytestotal += sizeof(int32_t);
if (bytestotal > maxbytes) return 0;
memcpy(&size, buf, sizeof(int32_t));
buf += sizeof(uint32_t);
}
if (size > (1 << 16) || size < 0) {
return 0;
}
char *bitmapOfRunContainers = NULL;
bool hasrun = (cookie & 0xFFFF) == SERIAL_COOKIE;
if (hasrun) {
int32_t s = (size + 7) / 8;
bytestotal += s;
if (bytestotal > maxbytes) return 0;
bitmapOfRunContainers = (char *)buf;
buf += s;
}
bytestotal += size * 2 * sizeof(uint16_t);
if (bytestotal > maxbytes) return 0;
const char *keyscards = buf;
buf += size * 2 * sizeof(uint16_t);
if ((!hasrun) || (size >= NO_OFFSET_THRESHOLD)) {
// skipping the offsets
bytestotal += size * 4;
if (bytestotal > maxbytes) return 0;
buf += size * 4;
}
// Reading the containers
for (int32_t k = 0; k < size; ++k) {
uint16_t tmp;
memcpy(&tmp, keyscards + 4 * k + 2, sizeof(tmp));
uint32_t thiscard = tmp + 1;
bool isbitmap = (thiscard > DEFAULT_MAX_SIZE);
bool isrun = false;
if (hasrun) {
if ((bitmapOfRunContainers[k / 8] & (1 << (k % 8))) != 0) {
isbitmap = false;
isrun = true;
}
}
if (isbitmap) {
size_t containersize =
BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
bytestotal += containersize;
if (bytestotal > maxbytes) return 0;
buf += containersize;
} else if (isrun) {
bytestotal += sizeof(uint16_t);
if (bytestotal > maxbytes) return 0;
uint16_t n_runs;
memcpy(&n_runs, buf, sizeof(uint16_t));
buf += sizeof(uint16_t);
size_t containersize = n_runs * sizeof(rle16_t);
bytestotal += containersize;
if (bytestotal > maxbytes) return 0;
buf += containersize;
} else {
size_t containersize = thiscard * sizeof(uint16_t);
bytestotal += containersize;
if (bytestotal > maxbytes) return 0;
buf += containersize;
}
}
return bytestotal;
}
// This function populates answer from the content of buf (reading up to
// maxbytes bytes). The function returns false if a properly serialized bitmap
// cannot be found. If it returns true, readbytes is populated by how many bytes
// were read, we have that *readbytes <= maxbytes.
//
// This function is endian-sensitive.
bool ra_portable_deserialize(roaring_array_t *answer, const char *buf,
const size_t maxbytes, size_t *readbytes) {
*readbytes = sizeof(int32_t); // for cookie
if (*readbytes > maxbytes) {
// Ran out of bytes while reading first 4 bytes.
return false;
}
uint32_t cookie;
memcpy(&cookie, buf, sizeof(int32_t));
buf += sizeof(uint32_t);
if ((cookie & 0xFFFF) != SERIAL_COOKIE &&
cookie != SERIAL_COOKIE_NO_RUNCONTAINER) {
// "I failed to find one of the right cookies.
return false;
}
int32_t size;
if ((cookie & 0xFFFF) == SERIAL_COOKIE)
size = (cookie >> 16) + 1;
else {
*readbytes += sizeof(int32_t);
if (*readbytes > maxbytes) {
// Ran out of bytes while reading second part of the cookie.
return false;
}
memcpy(&size, buf, sizeof(int32_t));
buf += sizeof(uint32_t);
}
if (size < 0) {
// You cannot have a negative number of containers, the data must be
// corrupted.
return false;
}
if (size > (1 << 16)) {
// You cannot have so many containers, the data must be corrupted.
return false;
}
const char *bitmapOfRunContainers = NULL;
bool hasrun = (cookie & 0xFFFF) == SERIAL_COOKIE;
if (hasrun) {
int32_t s = (size + 7) / 8;
*readbytes += s;
if (*readbytes > maxbytes) { // data is corrupted?
// Ran out of bytes while reading run bitmap.
return false;
}
bitmapOfRunContainers = buf;
buf += s;
}
const char *keyscards = buf;
*readbytes += size * 2 * sizeof(uint16_t);
if (*readbytes > maxbytes) {
// Ran out of bytes while reading key-cardinality array.
return false;
}
buf += size * 2 * sizeof(uint16_t);
bool is_ok = ra_init_with_capacity(answer, size);
if (!is_ok) {
// Failed to allocate memory for roaring array. Bailing out.
return false;
}
for (int32_t k = 0; k < size; ++k) {
uint16_t tmp;
memcpy(&tmp, keyscards + 4 * k, sizeof(tmp));
answer->keys[k] = tmp;
}
if ((!hasrun) || (size >= NO_OFFSET_THRESHOLD)) {
*readbytes += size * 4;
if (*readbytes > maxbytes) { // data is corrupted?
// Ran out of bytes while reading offsets.
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
// skipping the offsets
buf += size * 4;
}
// Reading the containers
for (int32_t k = 0; k < size; ++k) {
uint16_t tmp;
memcpy(&tmp, keyscards + 4 * k + 2, sizeof(tmp));
uint32_t thiscard = tmp + 1;
bool isbitmap = (thiscard > DEFAULT_MAX_SIZE);
bool isrun = false;
if (hasrun) {
if ((bitmapOfRunContainers[k / 8] & (1 << (k % 8))) != 0) {
isbitmap = false;
isrun = true;
}
}
if (isbitmap) {
// we check that the read is allowed
size_t containersize =
BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
*readbytes += containersize;
if (*readbytes > maxbytes) {
// Running out of bytes while reading a bitset container.
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
// it is now safe to read
bitset_container_t *c = bitset_container_create();
if (c == NULL) { // memory allocation failure
// Failed to allocate memory for a bitset container.
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
answer->size++;
buf += bitset_container_read(thiscard, c, buf);
answer->containers[k] = c;
answer->typecodes[k] = BITSET_CONTAINER_TYPE;
} else if (isrun) {
// we check that the read is allowed
*readbytes += sizeof(uint16_t);
if (*readbytes > maxbytes) {
// Running out of bytes while reading a run container (header).
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
uint16_t n_runs;
memcpy(&n_runs, buf, sizeof(uint16_t));
size_t containersize = n_runs * sizeof(rle16_t);
*readbytes += containersize;
if (*readbytes > maxbytes) { // data is corrupted?
// Running out of bytes while reading a run container.
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
// it is now safe to read
run_container_t *c = run_container_create();
if (c == NULL) { // memory allocation failure
// Failed to allocate memory for a run container.
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
answer->size++;
buf += run_container_read(thiscard, c, buf);
answer->containers[k] = c;
answer->typecodes[k] = RUN_CONTAINER_TYPE;
} else {
// we check that the read is allowed
size_t containersize = thiscard * sizeof(uint16_t);
*readbytes += containersize;
if (*readbytes > maxbytes) { // data is corrupted?
// Running out of bytes while reading an array container.
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
// it is now safe to read
array_container_t *c =
array_container_create_given_capacity(thiscard);
if (c == NULL) { // memory allocation failure
// Failed to allocate memory for an array container.
ra_clear(answer); // we need to clear the containers already
// allocated, and the roaring array
return false;
}
answer->size++;
buf += array_container_read(thiscard, c, buf);
answer->containers[k] = c;
answer->typecodes[k] = ARRAY_CONTAINER_TYPE;
}
}
return true;
}
#ifdef __cplusplus
}
}
} // extern "C" { namespace roaring { namespace internal {
#endif