struct block * block_init(uint8_t *data, size_t size, bool needs_free) { struct block *b = my_calloc(1, sizeof(*b)); b->data = data; b->size = size; if (size < sizeof(uint32_t)) { b->size = 0; } else { b->restart_offset = size - (1 + num_restarts(b)) * sizeof(uint32_t); } /* * Check if a 32-bit restart array would leave room for restart offsets * too large for an unsigned 32 bit integer. The writer performs this * same check, and will switch to 64 bit restart offsets if necessary. * We detect this situation here, and do the same. */ if (b->restart_offset > UINT32_MAX) { b->restart_offset = size - (sizeof(uint32_t) + num_restarts(b) * sizeof(uint64_t)); /* * b->restart_offset is the offset of the first byte after * the entries stored in the block. If that offset fits * in a 32 bit unsigned integer field, the block should have * used 32 bit restart offsets. We consider a block where * a 32 bit restart offset array would begin after UINT32_MAX * and a 64 bit restart array would begin before to be malformed. */ if (b->restart_offset <= UINT32_MAX) b->size = 0; } if (b->restart_offset > size - sizeof(uint32_t)) { b->size = 0; } b->needs_free = needs_free; return (b); }
struct block_iter * block_iter_init(struct block *b) { assert(b->size >= 2 * sizeof(uint32_t)); struct block_iter *bi = my_calloc(1, sizeof(*bi)); bi->block = b; bi->data = b->data; bi->restarts = b->restart_offset; bi->num_restarts = num_restarts(b); bi->current = bi->restarts; bi->restart_index = bi->num_restarts; assert(bi->num_restarts > 0); bi->key = ubuf_init(64); return (bi); }
struct block * block_init(uint8_t *data, size_t size, bool needs_free) { struct block *b = my_calloc(1, sizeof(*b)); b->data = data; b->size = size; if (size < sizeof(uint32_t)) { b->size = 0; } else { b->restart_offset = size - (1 + num_restarts(b)) * sizeof(uint32_t); if (b->restart_offset > size - sizeof(uint32_t)) { b->size = 0; } } b->needs_free = needs_free; return (b); }