84static_assert(
sizeof(
struct node) ==
LITE3_NODE_SIZE,
"sizeof(struct node) must equal LITE3_NODE_SIZE");
85static_assert(offsetof(
struct node, gen_type) == 0,
"Runtime type checks and LITE3_BYTES() & LITE3_STR() macros expect to read (struct node).gen_type field at offset 0");
86static_assert(
sizeof(((
struct node *)0)->gen_type) ==
sizeof(uint32_t),
"LITE3_BYTES() & LITE3_STR() macros expect to read (struct node).gen_type as uint32_t");
87static_assert(offsetof(
struct node, size_kc) ==
LITE3_NODE_SIZE_KC_OFFSET,
"Offset of (struct node).size_kc must equal LITE3_NODE_SIZE_KC_OFFSET");
88static_assert(
sizeof(((
struct node *)0)->size_kc) ==
sizeof(uint32_t),
"Node size checks expect to read (struct node).size_kc as uint32_t");
89static_assert(
sizeof(((
struct node *)0)->gen_type) ==
sizeof(((
lite3_iter *)0)->gen),
"Iterator expects to read (struct node).gen_type as uint32_t");
91#define LITE3_NODE_TYPE_SHIFT 0
92#define LITE3_NODE_TYPE_MASK ((u32)((1 << 8) - 1))
94#define LITE3_NODE_GEN_SHIFT 8
95#define LITE3_NODE_GEN_MASK ((u32)~((1 << 8) - 1))
97#define LITE3_NODE_KEY_COUNT_MAX ((int)(sizeof(((struct node *)0)->hashes) / sizeof(u32)))
98#define LITE3_NODE_KEY_COUNT_MIN ((int)(LITE3_NODE_KEY_COUNT_MAX / 2))
100#define LITE3_NODE_KEY_COUNT_SHIFT 0
102#define LITE3_NODE_KEY_COUNT_MASK ((u32)((1 << 3) - 1))
109#define LITE3_KEY_TAG_SIZE_MIN 1
110#define LITE3_KEY_TAG_SIZE_MAX 4
111#define LITE3_KEY_TAG_SIZE_MASK ((1 << 2) - 1)
112#define LITE3_KEY_TAG_SIZE_SHIFT 0
114#define LITE3_KEY_TAG_KEY_SIZE_MASK (~((1 << 2) - 1))
115#define LITE3_KEY_TAG_KEY_SIZE_SHIFT 2
124static inline int _verify_key(
127 const char *restrict key,
130 size_t *restrict inout_ofs,
131 size_t *restrict out_key_tag_size)
133 if (LITE3_UNLIKELY(LITE3_KEY_TAG_SIZE_MAX > buflen || *inout_ofs > buflen - LITE3_KEY_TAG_SIZE_MAX)) {
134 LITE3_PRINT_ERROR(
"KEY ENTRY OUT OF BOUNDS\n");
138 size_t _key_tag_size = (size_t)((*((u8 *)(buf + *inout_ofs)) & LITE3_KEY_TAG_SIZE_MASK) + 1);
140 if (key_tag_size != _key_tag_size) {
141 LITE3_PRINT_ERROR(
"KEY TAG SIZE DOES NOT MATCH\n");
146 size_t _key_size = 0;
147 memcpy(&_key_size, buf + *inout_ofs, _key_tag_size);
148 _key_size >>= LITE3_KEY_TAG_KEY_SIZE_SHIFT;
149 *inout_ofs += _key_tag_size;
151 if (LITE3_UNLIKELY(_key_size > buflen || *inout_ofs > buflen - _key_size)) {
152 LITE3_PRINT_ERROR(
"KEY ENTRY OUT OF BOUNDS\n");
158 (
const char *)(buf + *inout_ofs),
160 (key_size < _key_size) ? key_size : _key_size
162 if (LITE3_UNLIKELY(cmp != 0)) {
163 LITE3_PRINT_ERROR(
"HASH COLLISION\n");
168 *inout_ofs += _key_size;
169 if (out_key_tag_size)
170 *out_key_tag_size = _key_tag_size;
181static inline int _verify_val(
184 size_t *restrict inout_ofs)
186 if (LITE3_UNLIKELY(LITE3_VAL_SIZE > buflen || *inout_ofs > buflen - LITE3_VAL_SIZE)) {
187 LITE3_PRINT_ERROR(
"VALUE OUT OF BOUNDS\n");
194 LITE3_PRINT_ERROR(
"VALUE TYPE INVALID\n");
198 size_t _val_entry_size = LITE3_VAL_SIZE + lite3_type_sizes[type];
200 if (LITE3_UNLIKELY(_val_entry_size > buflen || *inout_ofs > buflen - _val_entry_size)) {
201 LITE3_PRINT_ERROR(
"VALUE OUT OF BOUNDS\n");
206 size_t byte_count = 0;
207 memcpy(&byte_count, buf + *inout_ofs + LITE3_VAL_SIZE, lite3_type_sizes[
LITE3_TYPE_BYTES]);
208 _val_entry_size += byte_count;
209 if (LITE3_UNLIKELY(_val_entry_size > buflen || *inout_ofs > buflen - _val_entry_size)) {
210 LITE3_PRINT_ERROR(
"VALUE OUT OF BOUNDS\n");
215 *inout_ofs += _val_entry_size;
220 const unsigned char *buf,
223 const char *restrict key,
224 lite3_key_data key_data,
229 LITE3_PRINT_DEBUG(
"GET\tkey: %s\n", key);
231 LITE3_PRINT_DEBUG(
"GET\tindex: %u\n", key_data.hash);
233 LITE3_PRINT_DEBUG(
"GET INVALID: EXEPCTING ARRAY OR OBJECT TYPE\n");
237 size_t key_tag_size = (size_t)((!!(key_data.size >> (16 - LITE3_KEY_TAG_KEY_SIZE_SHIFT)) << 1)
238 + !!(key_data.size >> (8 - LITE3_KEY_TAG_KEY_SIZE_SHIFT))
242 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
248 key_count =
node->size_kc & LITE3_NODE_KEY_COUNT_MASK;
250 while (i < key_count && node->hashes[i] < key_data.hash)
252 if (i < key_count && node->hashes[i] == key_data.hash) {
253 size_t target_ofs =
node->kv_ofs[i];
254 if (key && _verify_key(buf, buflen, key, (
size_t)key_data.size, key_tag_size, &target_ofs, NULL) < 0)
256 size_t val_start_ofs = target_ofs;
257 if (_verify_val(buf, buflen, &target_ofs) < 0)
259 *out = (
lite3_val *)(buf + val_start_ofs);
262 if (
node->child_ofs[0]) {
263 size_t next_node_ofs = (size_t)
node->child_ofs[i];
265 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
268 LITE3_PRINT_ERROR(
"NODE WALK OFFSET OUT OF BOUNDS\n");
273 LITE3_PRINT_ERROR(
"NODE WALKS EXCEEDED LITE3_TREE_HEIGHT_MAX\n");
278 LITE3_PRINT_ERROR(
"KEY NOT FOUND\n");
285int lite3_iter_create_impl(
const unsigned char *buf,
size_t buflen,
size_t ofs,
lite3_iter *out)
287 LITE3_PRINT_DEBUG(
"CREATE ITER\n");
290 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
294 LITE3_PRINT_ERROR(
"INVALID ARGUMENT: EXPECTING ARRAY OR OBJECT TYPE\n");
298 out->gen = ((
struct node *)buf)->gen_type;
300 out->node_ofs[0] = (u32)ofs;
303 while (
node->child_ofs[0]) {
304 u32 next_node_ofs =
node->child_ofs[0];
307 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
310 LITE3_PRINT_ERROR(
"NODE WALKS EXCEEDED LITE3_TREE_HEIGHT_MAX\n");
314 if (LITE3_UNLIKELY((
size_t)next_node_ofs > buflen -
LITE3_NODE_SIZE)) {
315 LITE3_PRINT_ERROR(
"NODE WALK OFFSET OUT OF BOUNDS\n");
319 out->node_ofs[out->depth] = next_node_ofs;
320 out->node_i[out->depth] = 0;
322 #ifdef LITE3_PREFETCHING
323 __builtin_prefetch(buf +
node->kv_ofs[0], 0, 0);
324 __builtin_prefetch(buf +
node->kv_ofs[0] + 64, 0, 0);
325 __builtin_prefetch(buf +
node->kv_ofs[1], 0, 0);
326 __builtin_prefetch(buf +
node->kv_ofs[1] + 64, 0, 0);
327 __builtin_prefetch(buf +
node->kv_ofs[2], 0, 0);
328 __builtin_prefetch(buf +
node->kv_ofs[2] + 64, 0, 0);
335 if (LITE3_UNLIKELY(iter->gen != ((
struct node *)buf)->gen_type)) {
336 LITE3_PRINT_ERROR(
"ITERATOR INVALID: iter->gen != node->gen_type (BUFFER MUTATION INVALIDATES ITERATORS)\n");
342 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
346 LITE3_PRINT_ERROR(
"INVALID ARGUMENT: EXPECTING ARRAY ORlite3_iter_nex OBJECT TYPE\n");
350 if (iter->depth == 0 && (iter->node_i[iter->depth] == (
node->size_kc & LITE3_NODE_KEY_COUNT_MASK))) {
353 size_t target_ofs =
node->kv_ofs[iter->node_i[iter->depth]];
358 size_t key_start_ofs = target_ofs;
359 if ((ret = _verify_key(buf, buflen, NULL, 0, 0, &target_ofs, &key_tag_size)) < 0)
361 out_key->
gen = iter->gen;
363 memcpy(&out_key->
len, buf + key_start_ofs, key_tag_size);
365 out_key->
ptr = (
const char *)(buf + key_start_ofs + key_tag_size);
368 size_t val_start_ofs = target_ofs;
369 if ((ret = _verify_val(buf, buflen, &target_ofs)) < 0)
371 *out_val_ofs = val_start_ofs;
374 ++iter->node_i[iter->depth];
376 while (
node->child_ofs[iter->node_i[iter->depth]]) {
377 u32 next_node_ofs =
node->child_ofs[iter->node_i[iter->depth]];
380 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
383 LITE3_PRINT_ERROR(
"NODE WALKS EXCEEDED LITE3_TREE_HEIGHT_MAX\n");
387 if (LITE3_UNLIKELY((
size_t)next_node_ofs > buflen -
LITE3_NODE_SIZE)) {
388 LITE3_PRINT_ERROR(
"NODE WALK OFFSET OUT OF BOUNDS\n");
392 iter->node_ofs[iter->depth] = next_node_ofs;
393 iter->node_i[iter->depth] = 0;
395 while (iter->depth > 0 && (iter->node_i[iter->depth] == (
node->size_kc & LITE3_NODE_KEY_COUNT_MASK))) {
398 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
399 #ifdef LITE3_PREFETCHING
400 __builtin_prefetch(buf +
node->child_ofs[(iter->node_i[iter->depth] + 1) & LITE3_NODE_KEY_COUNT_MASK], 0, 2);
401 __builtin_prefetch(buf +
node->child_ofs[(iter->node_i[iter->depth] + 1) & LITE3_NODE_KEY_COUNT_MASK] + 64, 0, 2);
402 __builtin_prefetch(buf +
node->child_ofs[(iter->node_i[iter->depth] + 2) & LITE3_NODE_KEY_COUNT_MASK], 0, 2);
403 __builtin_prefetch(buf +
node->child_ofs[(iter->node_i[iter->depth] + 2) & LITE3_NODE_KEY_COUNT_MASK] + 64, 0, 2);
406 #ifdef LITE3_PREFETCHING
407 __builtin_prefetch(buf +
node->kv_ofs[iter->node_i[iter->depth]], 0, 0);
408 __builtin_prefetch(buf +
node->kv_ofs[iter->node_i[iter->depth]] + 64, 0, 0);
409 __builtin_prefetch(buf +
node->kv_ofs[iter->node_i[iter->depth] + 1], 0, 0);
410 __builtin_prefetch(buf +
node->kv_ofs[iter->node_i[iter->depth] + 1] + 64, 0, 0);
411 __builtin_prefetch(buf +
node->kv_ofs[iter->node_i[iter->depth] + 2], 0, 0);
412 __builtin_prefetch(buf +
node->kv_ofs[iter->node_i[iter->depth] + 2] + 64, 0, 0);
418static inline void _lite3_init_impl(
unsigned char *buf,
size_t ofs,
enum lite3_type type)
420 LITE3_PRINT_DEBUG(
"INITIALIZE %s\n", type ==
LITE3_TYPE_OBJECT ?
"OBJECT" :
"ARRAY");
423 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
424 node->gen_type = type & LITE3_NODE_TYPE_MASK;
425 node->size_kc = 0x00;
426 #ifdef LITE3_ZERO_MEM_EXTRA
427 memset(
node->hashes, LITE3_ZERO_MEM_8,
sizeof(((
struct node *)0)->hashes));
428 memset(
node->kv_ofs, LITE3_ZERO_MEM_8,
sizeof(((
struct node *)0)->kv_ofs));
430 memset(
node->child_ofs, 0x00,
sizeof(((
struct node *)0)->child_ofs));
433int lite3_init_obj(
unsigned char *buf,
size_t *restrict out_buflen,
size_t bufsz)
436 LITE3_PRINT_ERROR(
"INVALID ARGUMENT: bufsz < LITE3_NODE_SIZE\n");
445int lite3_init_arr(
unsigned char *buf,
size_t *restrict out_buflen,
size_t bufsz)
448 LITE3_PRINT_ERROR(
"INVALID ARGUMENT: bufsz < LITE3_NODE_SIZE\n");
470 size_t *restrict inout_buflen,
473 const char *restrict key,
474 lite3_key_data key_data,
480 LITE3_PRINT_DEBUG(
"SET\tkey: %s\n", key);
482 LITE3_PRINT_DEBUG(
"SET\tindex: %u\n", key_data.hash);
484 LITE3_PRINT_DEBUG(
"SET INVALID: EXEPCTING ARRAY OR OBJECT TYPE\n");
487 size_t key_tag_size = (size_t)((!!(key_data.size >> (16 - LITE3_KEY_TAG_KEY_SIZE_SHIFT)) << 1)
488 + !!(key_data.size >> (8 - LITE3_KEY_TAG_KEY_SIZE_SHIFT))
490 size_t entry_size = key_tag_size + (size_t)key_data.size + LITE3_VAL_SIZE + val_len;
492 struct node *restrict parent = NULL;
494 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
496 u32 gen =
node->gen_type >> LITE3_NODE_GEN_SHIFT;
498 node->gen_type = (
node->gen_type & ~LITE3_NODE_GEN_MASK) | (gen << LITE3_NODE_GEN_SHIFT);
504 if ((
node->size_kc & LITE3_NODE_KEY_COUNT_MASK) == LITE3_NODE_KEY_COUNT_MAX) {
506 size_t buflen_aligned = (*inout_buflen + LITE3_NODE_ALIGNMENT_MASK) & ~(
size_t)LITE3_NODE_ALIGNMENT_MASK;
509 if (LITE3_UNLIKELY(new_node_size > bufsz || buflen_aligned > bufsz - new_node_size)) {
510 LITE3_PRINT_ERROR(
"NO BUFFER SPACE FOR NODE SPLIT\n");
514 *inout_buflen = buflen_aligned;
517 LITE3_PRINT_DEBUG(
"NEW ROOT\n");
520 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
522 assert(((uintptr_t)parent & LITE3_NODE_ALIGNMENT_MASK) == 0);
523 #ifdef LITE3_ZERO_MEM_EXTRA
524 memset(parent->hashes, LITE3_ZERO_MEM_8,
sizeof(((
struct node *)0)->hashes));
525 memset(parent->kv_ofs, LITE3_ZERO_MEM_8,
sizeof(((
struct node *)0)->kv_ofs));
526 memset(parent->child_ofs, 0x00,
sizeof(((
struct node *)0)->child_ofs));
528 parent->size_kc &= ~LITE3_NODE_KEY_COUNT_MASK;
529 parent->child_ofs[0] = (u32)*inout_buflen;
534 LITE3_PRINT_DEBUG(
"SPLIT NODE\n");
535 for (
int j = key_count; j > i; j--) {
536 parent->hashes[j] = parent->hashes[j - 1];
537 parent->kv_ofs[j] = parent->kv_ofs[j - 1];
538 parent->child_ofs[j + 1] = parent->child_ofs[j];
540 parent->hashes[i] =
node->hashes[LITE3_NODE_KEY_COUNT_MIN];
541 parent->kv_ofs[i] =
node->kv_ofs[LITE3_NODE_KEY_COUNT_MIN];
542 parent->child_ofs[i + 1] = (u32)*inout_buflen;
543 parent->size_kc = (parent->size_kc & ~LITE3_NODE_KEY_COUNT_MASK)
544 | ((parent->size_kc + 1) & LITE3_NODE_KEY_COUNT_MASK);
545 #ifdef LITE3_ZERO_MEM_EXTRA
546 node->hashes[LITE3_NODE_KEY_COUNT_MIN] = LITE3_ZERO_MEM_32;
547 node->kv_ofs[LITE3_NODE_KEY_COUNT_MIN] = LITE3_ZERO_MEM_32;
550 assert(((uintptr_t)sibling & LITE3_NODE_ALIGNMENT_MASK) == 0);
551 #ifdef LITE3_ZERO_MEM_EXTRA
552 memset(sibling->hashes, LITE3_ZERO_MEM_8,
sizeof(((
struct node *)0)->hashes));
553 memset(sibling->kv_ofs, LITE3_ZERO_MEM_8,
sizeof(((
struct node *)0)->kv_ofs));
555 sibling->gen_type = ((
struct node *)(buf + ofs))->gen_type & LITE3_NODE_TYPE_MASK;
556 sibling->size_kc = LITE3_NODE_KEY_COUNT_MIN & LITE3_NODE_KEY_COUNT_MASK;
557 node->size_kc = LITE3_NODE_KEY_COUNT_MIN & LITE3_NODE_KEY_COUNT_MASK;
558 memset(sibling->child_ofs, 0x00,
sizeof(((
struct node *)0)->child_ofs));
559 sibling->child_ofs[0] =
node->child_ofs[LITE3_NODE_KEY_COUNT_MIN + 1];
560 node->child_ofs[LITE3_NODE_KEY_COUNT_MIN + 1] = 0x00;
561 for (
int j = 0; j < LITE3_NODE_KEY_COUNT_MIN; j++) {
562 sibling->hashes[j] =
node->hashes[j + LITE3_NODE_KEY_COUNT_MIN + 1];
563 sibling->kv_ofs[j] =
node->kv_ofs[j + LITE3_NODE_KEY_COUNT_MIN + 1];
564 sibling->child_ofs[j + 1] =
node->child_ofs[j + LITE3_NODE_KEY_COUNT_MIN + 2];
565 #ifdef LITE3_ZERO_MEM_EXTRA
566 node->hashes[j + LITE3_NODE_KEY_COUNT_MIN + 1] = LITE3_ZERO_MEM_32;
567 node->kv_ofs[j + LITE3_NODE_KEY_COUNT_MIN + 1] = LITE3_ZERO_MEM_32;
568 node->child_ofs[j + LITE3_NODE_KEY_COUNT_MIN + 2] = 0x00000000;
571 if (key_data.hash > parent->hashes[i]) {
573 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
578 key_count =
node->size_kc & LITE3_NODE_KEY_COUNT_MASK;
580 while (i < key_count && node->hashes[i] < key_data.hash)
582 if (i < key_count && node->hashes[i] == key_data.hash) {
583 size_t target_ofs =
node->kv_ofs[i];
584 size_t key_start_ofs = target_ofs;
585 if (key && _verify_key(buf, *inout_buflen, key, (
size_t)key_data.size, key_tag_size, &target_ofs, NULL) < 0)
587 size_t val_start_ofs = target_ofs;
588 if (_verify_val(buf, *inout_buflen, &target_ofs) < 0)
590 if (val_len >= target_ofs - val_start_ofs) {
591 size_t alignment_mask = val_len == lite3_type_sizes[
LITE3_TYPE_OBJECT] ? (size_t)LITE3_NODE_ALIGNMENT_MASK : 0;
592 size_t unaligned_val_ofs = *inout_buflen + key_tag_size + (size_t)key_data.size;
593 size_t alignment_padding = ((unaligned_val_ofs + alignment_mask) & ~alignment_mask) - unaligned_val_ofs;
594 entry_size += alignment_padding;
595 if (LITE3_UNLIKELY(entry_size > bufsz || *inout_buflen > bufsz - entry_size)) {
596 LITE3_PRINT_ERROR(
"NO BUFFER SPACE FOR ENTRY INSERTION\n");
600 #ifdef LITE3_ZERO_MEM_DELETED
601 memset(buf +
node->kv_ofs[i], LITE3_ZERO_MEM_8, target_ofs - key_start_ofs);
604 *inout_buflen += alignment_padding;
605 node->kv_ofs[i] = (u32)*inout_buflen;
609 #ifdef LITE3_ZERO_MEM_DELETED
610 memset(buf + val_start_ofs, LITE3_ZERO_MEM_8, target_ofs - val_start_ofs);
612 *out = (
lite3_val *)(buf + val_start_ofs);
616 if (
node->child_ofs[0]) {
617 size_t next_node_ofs = (size_t)
node->child_ofs[i];
620 assert(((uintptr_t)parent & LITE3_NODE_ALIGNMENT_MASK) == 0);
622 assert(((uintptr_t)
node & LITE3_NODE_ALIGNMENT_MASK) == 0);
625 LITE3_PRINT_ERROR(
"NODE WALK OFFSET OUT OF BOUNDS\n");
630 LITE3_PRINT_ERROR(
"NODE WALKS EXCEEDED LITE3_TREE_HEIGHT_MAX\n");
635 size_t alignment_mask = val_len == lite3_type_sizes[
LITE3_TYPE_OBJECT] ? (size_t)LITE3_NODE_ALIGNMENT_MASK : 0;
636 size_t unaligned_val_ofs = *inout_buflen + key_tag_size + (size_t)key_data.size;
637 size_t alignment_padding = ((unaligned_val_ofs + alignment_mask) & ~alignment_mask) - unaligned_val_ofs;
638 entry_size += alignment_padding;
639 if (LITE3_UNLIKELY(entry_size > bufsz || *inout_buflen > bufsz - entry_size)) {
640 LITE3_PRINT_ERROR(
"NO BUFFER SPACE FOR ENTRY INSERTION\n");
644 for (
int j = key_count; j > i; j--) {
645 node->hashes[j] =
node->hashes[j - 1];
646 node->kv_ofs[j] =
node->kv_ofs[j - 1];
648 node->hashes[i] = key_data.hash;
649 node->size_kc = (
node->size_kc & ~LITE3_NODE_KEY_COUNT_MASK)
650 | ((
node->size_kc + 1) & LITE3_NODE_KEY_COUNT_MASK);
651 *inout_buflen += alignment_padding;
652 node->kv_ofs[i] = (u32)*inout_buflen;
655 u32 size =
node->size_kc >> LITE3_NODE_SIZE_SHIFT;
657 node->size_kc = (
node->size_kc & ~LITE3_NODE_SIZE_MASK) | (size << LITE3_NODE_SIZE_SHIFT);
662 size_t key_size_tmp = (key_data.size << LITE3_KEY_TAG_KEY_SIZE_SHIFT) | (key_tag_size - 1);
663 memcpy(buf + *inout_buflen, &key_size_tmp, key_tag_size);
664 *inout_buflen += key_tag_size;
665 memcpy(buf + *inout_buflen, key, (
size_t)key_data.size);
666 *inout_buflen += (size_t)key_data.size;
667 *out = (
lite3_val *)(buf + *inout_buflen);
668 *inout_buflen += LITE3_VAL_SIZE + val_len;
672int lite3_set_obj_impl(
unsigned char *buf,
size_t *restrict inout_buflen,
size_t ofs,
size_t bufsz,
const char *restrict key, lite3_key_data key_data,
size_t *restrict out_ofs)
676 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[
LITE3_TYPE_OBJECT], &val)) < 0)
678 size_t init_ofs = (size_t)((u8 *)val - buf);
685int lite3_set_arr_impl(
unsigned char *buf,
size_t *restrict inout_buflen,
size_t ofs,
size_t bufsz,
const char *restrict key, lite3_key_data key_data,
size_t *restrict out_ofs)
689 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[
LITE3_TYPE_ARRAY], &val)) < 0)
691 size_t init_ofs = (size_t)((u8 *)val - buf);
698int lite3_arr_append_obj_impl(
unsigned char *buf,
size_t *restrict inout_buflen,
size_t ofs,
size_t bufsz,
size_t *restrict out_ofs)
700 u32 size = ((
struct node *)(buf + ofs))->size_kc >> LITE3_NODE_SIZE_SHIFT;
701 lite3_key_data key_data = {
707 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, lite3_type_sizes[
LITE3_TYPE_OBJECT], &val)) < 0)
709 size_t init_ofs = (size_t)((u8 *)val - buf);
716int lite3_arr_append_arr_impl(
unsigned char *buf,
size_t *restrict inout_buflen,
size_t ofs,
size_t bufsz,
size_t *restrict out_ofs)
718 u32 size = ((
struct node *)(buf + ofs))->size_kc >> LITE3_NODE_SIZE_SHIFT;
719 lite3_key_data key_data = {
725 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, lite3_type_sizes[
LITE3_TYPE_ARRAY], &val)) < 0)
727 size_t init_ofs = (size_t)((u8 *)val - buf);
734int lite3_arr_set_obj_impl(
unsigned char *buf,
size_t *restrict inout_buflen,
size_t ofs,
size_t bufsz, uint32_t index,
size_t *restrict out_ofs)
736 u32 size = ((
struct node *)(buf + ofs))->size_kc >> LITE3_NODE_SIZE_SHIFT;
737 if (LITE3_UNLIKELY(index > size)) {
738 LITE3_PRINT_ERROR(
"INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
742 lite3_key_data key_data = {
748 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, lite3_type_sizes[
LITE3_TYPE_OBJECT], &val)) < 0)
750 size_t init_ofs = (size_t)((u8 *)val - buf);
757int lite3_arr_set_arr_impl(
unsigned char *buf,
size_t *restrict inout_buflen,
size_t ofs,
size_t bufsz, uint32_t index,
size_t *restrict out_ofs)
759 u32 size = ((
struct node *)(buf + ofs))->size_kc >> LITE3_NODE_SIZE_SHIFT;
760 if (LITE3_UNLIKELY(index > size)) {
761 LITE3_PRINT_ERROR(
"INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
765 lite3_key_data key_data = {
771 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, lite3_type_sizes[
LITE3_TYPE_ARRAY], &val)) < 0)
773 size_t init_ofs = (size_t)((u8 *)val - buf);
#define LITE3_TREE_HEIGHT_MAX
Maximum B-tree height.
#define LITE3_NODE_ALIGNMENT
B-tree node alignment configuration.
#define LITE3_NODE_SIZE
B-tree node size setting.
#define LITE3_NODE_SIZE_KC_OFFSET
Offset of the size_kc field inside struct node.
#define LITE3_ITER_ITEM
Return value of lite3_iter_next(); iterator produced an item, continue;.
#define LITE3_ITER_DONE
Return value of lite3_iter_next(); iterator finished; stop.
int lite3_iter_next(const unsigned char *buf, size_t buflen, lite3_iter *iter, lite3_str *out_key, size_t *out_val_ofs)
Get the next item from a lite3 iterator.
lite3_type
enum containing all Lite³ types
@ LITE3_TYPE_ARRAY
maps to 'array' type in JSON
@ LITE3_TYPE_INVALID
any type value equal or greater than this is considered invalid
@ LITE3_TYPE_STRING
maps to 'string' type in JSON
@ LITE3_TYPE_BYTES
coverted to base64 string in JSON
@ LITE3_TYPE_OBJECT
maps to 'object' type in JSON
Struct containing iterator state.
Struct holding a reference to a string inside a Lite³ buffer.
uint32_t len
char array length (characters, exclusive of NULL-terminator)
const char * ptr
char array pointer to string inside Lite³ buffer
uint32_t gen
generation of the Lite³ buffer when this struct was returned
Struct representing a value inside a Lite³ buffer.