Lite³
A JSON-Compatible Zero-Copy Serialization Format
Loading...
Searching...
No Matches
lite3.h
Go to the documentation of this file.
1/*
2 Lite³: A JSON-Compatible Zero-Copy Serialization Format
3
4 Copyright © 2025 Elias de Jong <elias@fastserial.com>
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23
24 __ __________________ ____
25 _ ___ ___/ /___(_)_/ /_______|_ /
26 _ _____/ / __/ /_ __/ _ \_/_ <
27 ___ __/ /___/ / / /_ / __/____/
28 /_____/_/ \__/ \___/
29*/
30
39#ifndef LITE3_H
40#define LITE3_H
41
42#include <stdint.h>
43#include <stddef.h>
44#include <stdbool.h>
45#include <assert.h>
46#include <string.h>
47#include <errno.h>
48
49
50
51#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
52 defined(__BIG_ENDIAN__) || \
53 defined(__ARMEB__) || \
54 defined(__THUMBEB__) || \
55 defined(__AARCH64EB__) || \
56 defined(__or1k__) || defined(__OR1K__)
57 #error "Byte order must be little-endian"
58#endif
59
60static_assert(sizeof(double) == 8, "Double must be 8 bytes");
61
62#ifndef DOXYGEN_IGNORE
63#define LITE3_LIKELY(expr) __builtin_expect(!!(expr), 1)
64#define LITE3_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
65#endif // DOXYGEN_IGNORE
66
67
68
69#ifdef __cplusplus
70extern "C" {
71#endif
72
137#ifndef DOXYGEN_IGNORE
138#define LITE3_ZERO_MEM_8 0x00
139#define LITE3_ZERO_MEM_32 0x00000000
140#endif // DOXYGEN_IGNORE
141
152#define LITE3_ZERO_MEM_DELETED
153
154#if defined(DOXYGEN_ONLY) && !defined(LITE3_ZERO_MEM_DELETED)
155#define LITE3_ZERO_MEM_DELETED
156#endif // DOXYGEN_ONLY
157
169#define LITE3_ZERO_MEM_EXTRA
170
171#if defined(DOXYGEN_ONLY) && !defined(LITE3_ZERO_MEM_EXTRA)
172#define LITE3_ZERO_MEM_EXTRA
173#endif // DOXYGEN_ONLY
174
184#define LITE3_PREFETCHING
185
186#if defined(DOXYGEN_ONLY) && !defined(LITE3_PREFETCHING)
187#define LITE3_PREFETCHING
188#endif // DOXYGEN_ONLY
189
197// #define LITE3_ERROR_MESSAGES
198
199#if defined(DOXYGEN_ONLY) && !defined(LITE3_ERROR_MESSAGES)
200#define LITE3_ERROR_MESSAGES
201#endif // DOXYGEN_ONLY
202
203#ifndef DOXYGEN_IGNORE
204#ifdef LITE3_ERROR_MESSAGES
205 #include <stdio.h>
206 #define LITE3_PRINT_ERROR(format, ...) printf(format, ##__VA_ARGS__)
207#else
208 #define LITE3_PRINT_ERROR(format, ...) /* nothing */
209#endif
210#endif // DOXYGEN_IGNORE
211
222// #define LITE3_DEBUG
223
224#if defined(DOXYGEN_ONLY) && !defined(LITE3_DEBUG)
225#define LITE3_DEBUG
226#endif // DOXYGEN_ONLY
227
228#ifndef DOXYGEN_IGNORE
229#ifdef LITE3_DEBUG
230 #include <stdio.h>
231
232 #ifndef LITE3_ZERO_MEM_DELETED
233 #define LITE3_ZERO_MEM_DELETED
234 #endif
235
236 #ifndef LITE3_ZERO_MEM_EXTRA
237 #define LITE3_ZERO_MEM_EXTRA
238 #endif
239 // In `LITE3_DEBUG` mode, bytes are replaced with underscores (`0x5F`) for better readability.
240 #undef LITE3_ZERO_MEM_8
241 #undef LITE3_ZERO_MEM_32
242 #define LITE3_ZERO_MEM_8 0x5F
243 #define LITE3_ZERO_MEM_32 0x5F5F5F5F
244
245 #define LITE3_PRINT_DEBUG(format, ...) printf(format, ##__VA_ARGS__)
246 void lite3_print(const unsigned char *buf, size_t buflen); // View the internal structure of a Lite³ buffer
247#else
248 #define LITE3_PRINT_DEBUG(format, ...) /* nothing */
249 static inline void lite3_print(const unsigned char *buf, size_t buflen) { (void)buf; (void)buflen; }
250#endif
251#endif // DOXYGEN_IGNORE
252
259#define LITE3_BUF_SIZE_MAX UINT32_MAX
260
275#define LITE3_NODE_ALIGNMENT 4
276
277#ifndef DOXYGEN_IGNORE
278#define LITE3_NODE_ALIGNMENT_MASK ((uintptr_t)(LITE3_NODE_ALIGNMENT - 1))
279#endif // DOXYGEN_IGNORE
280
292// #define LITE3_NODE_SIZE 48 // key_count: 0-3 LITE3_NODE_SIZE: 48 (0.75 cache lines)
293#define LITE3_NODE_SIZE 96 // key_count: 0-7 LITE3_NODE_SIZE: 96 (1.5 cache lines)
294// #define LITE3_NODE_SIZE 192 // key_count: 0-15 LITE3_NODE_SIZE: 192 (3 cache lines)
295// #define LITE3_NODE_SIZE 384 // key_count: 0-31 LITE3_NODE_SIZE: 384 (6 cache lines)
296// #define LITE3_NODE_SIZE 768 // key_count: 0-63 LITE3_NODE_SIZE: 768 (12 cache lines)
297
307// #define LITE3_TREE_HEIGHT_MAX 14 // key_count: 0-3 LITE3_NODE_SIZE: 48 (0.75 cache lines)
308#define LITE3_TREE_HEIGHT_MAX 9 // key_count: 0-7 LITE3_NODE_SIZE: 96 (1.5 cache lines)
309// #define LITE3_TREE_HEIGHT_MAX 7 // key_count: 0-15 LITE3_NODE_SIZE: 192 (3 cache lines)
310// #define LITE3_TREE_HEIGHT_MAX 5 // key_count: 0-31 LITE3_NODE_SIZE: 384 (6 cache lines)
311// #define LITE3_TREE_HEIGHT_MAX 4 // key_count: 0-63 LITE3_NODE_SIZE: 768 (12 cache lines)
312
321// #define LITE3_NODE_SIZE_KC_OFFSET 16 // key_count: 0-3 LITE3_NODE_SIZE: 48 (0.75 cache lines)
322#define LITE3_NODE_SIZE_KC_OFFSET 32 // key_count: 0-7 LITE3_NODE_SIZE: 96 (1.5 cache lines)
323// #define LITE3_NODE_SIZE_KC_OFFSET 64 // key_count: 0-15 LITE3_NODE_SIZE: 192 (3 cache lines)
324// #define LITE3_NODE_SIZE_KC_OFFSET 128 // key_count: 0-31 LITE3_NODE_SIZE: 384 (6 cache lines)
325// #define LITE3_NODE_SIZE_KC_OFFSET 256 // key_count: 0-63 LITE3_NODE_SIZE: 768 (12 cache lines)
326
327#ifndef DOXYGEN_IGNORE
328#define LITE3_NODE_SIZE_SHIFT 6
329#define LITE3_NODE_SIZE_MASK ((uint32_t)~((1 << 6) - 1)) // 26 MSB
330
331#define LITE3_DJB2_HASH_SEED ((uint32_t)5381)
332#endif // DOXYGEN_IGNORE
333
341#ifndef LITE3_HASH_PROBE_MAX
342#define LITE3_HASH_PROBE_MAX 128U
343#endif
344
345#if LITE3_HASH_PROBE_MAX < 2
346 #error "LITE3_HASH_PROBE_MAX must be >= 2"
347#endif
348
349#define LITE3_VERIFY_KEY_OK 0
350#define LITE3_VERIFY_KEY_HASH_COLLISION 1
351
365#define LITE3_KEY_HASH_COMPILE_TIME
366
367#ifndef DOXYGEN_IGNORE
368#ifdef LITE3_KEY_HASH_COMPILE_TIME
369#define LITE3_MOD 4294967296ULL
370
371#define LITE3_P0 33ULL
372#define LITE3_P1 ((LITE3_P0 * LITE3_P0) % LITE3_MOD)
373#define LITE3_P2 ((LITE3_P1 * LITE3_P1) % LITE3_MOD)
374#define LITE3_P3 ((LITE3_P2 * LITE3_P2) % LITE3_MOD)
375#define LITE3_P4 ((LITE3_P3 * LITE3_P3) % LITE3_MOD)
376#define LITE3_P5 ((LITE3_P4 * LITE3_P4) % LITE3_MOD)
377
378#define LITE3_BIT0(k) (((k) >> 0) & 1ULL)
379#define LITE3_BIT1(k) (((k) >> 1) & 1ULL)
380#define LITE3_BIT2(k) (((k) >> 2) & 1ULL)
381#define LITE3_BIT3(k) (((k) >> 3) & 1ULL)
382#define LITE3_BIT4(k) (((k) >> 4) & 1ULL)
383#define LITE3_BIT5(k) (((k) >> 5) & 1ULL)
384
385#define LITE3_POW33(k) \
386 ((((((1ULL \
387 * (LITE3_BIT0(k) ? LITE3_P0 : 1ULL) \
388 ) % LITE3_MOD \
389 * (LITE3_BIT1(k) ? LITE3_P1 : 1ULL) \
390 ) % LITE3_MOD \
391 * (LITE3_BIT2(k) ? LITE3_P2 : 1ULL) \
392 ) % LITE3_MOD \
393 * (LITE3_BIT3(k) ? LITE3_P3 : 1ULL) \
394 ) % LITE3_MOD \
395 * (LITE3_BIT4(k) ? LITE3_P4 : 1ULL) \
396 ) % LITE3_MOD \
397 * (LITE3_BIT5(k) ? LITE3_P5 : 1ULL) \
398 ) % LITE3_MOD
399
400#define LITE3_SUM_1(s, i, p) \
401 ((unsigned long long)(unsigned char)(s)[(i)] * LITE3_POW33((p)))
402
403#define LITE3_SUM_2(s, i, p) \
404 (LITE3_SUM_1(s, (i), (p)) + LITE3_SUM_1(s, (i) + 1, (p) - 1))
405
406#define LITE3_SUM_4(s, i, p) \
407 (LITE3_SUM_2(s, (i), (p)) + LITE3_SUM_2(s, (i) + 2, (p) - 2))
408
409#define LITE3_SUM_8(s, i, p) \
410 (LITE3_SUM_4(s, (i), (p)) + LITE3_SUM_4(s, (i) + 4, (p) - 4))
411
412#define LITE3_SUM_16(s, i, p) \
413 (LITE3_SUM_8(s, (i), (p)) + LITE3_SUM_8(s, (i) + 8, (p) - 8))
414
415#define LITE3_SUM_32(s, i, p) \
416 (LITE3_SUM_16(s, (i), (p)) + LITE3_SUM_16(s, (i) + 16, (p) - 16))
417
418#define LITE3_OFFSET_BIT0(len) \
419 (((len & 2ULL) ? 2ULL : 0ULL) + \
420 ((len & 4ULL) ? 4ULL : 0ULL) + \
421 ((len & 8ULL) ? 8ULL : 0ULL) + \
422 ((len & 16ULL) ? 16ULL : 0ULL) + \
423 ((len & 32ULL) ? 32ULL : 0ULL))
424
425#define LITE3_OFFSET_BIT1(len) \
426 (((len & 4ULL) ? 4ULL : 0ULL) + \
427 ((len & 8ULL) ? 8ULL : 0ULL) + \
428 ((len & 16ULL) ? 16ULL : 0ULL) + \
429 ((len & 32ULL) ? 32ULL : 0ULL))
430
431#define LITE3_OFFSET_BIT2(len) \
432 (((len & 8ULL) ? 8ULL : 0ULL) + \
433 ((len & 16ULL) ? 16ULL : 0ULL) + \
434 ((len & 32ULL) ? 32ULL : 0ULL))
435
436#define LITE3_OFFSET_BIT3(len) \
437 (((len & 16ULL) ? 16ULL : 0ULL) + \
438 ((len & 32ULL) ? 32ULL : 0ULL))
439
440#define LITE3_OFFSET_BIT4(len) \
441 (((len & 32ULL) ? 32ULL : 0ULL))
442
443#define LITE3_OFFSET_BIT5(len) \
444 (0ULL)
445
446#define LITE3_POLY_HASH(s, len) \
447 ((len) & 1ULL ? LITE3_SUM_1(s, LITE3_OFFSET_BIT0((len)), (len) - 1 - LITE3_OFFSET_BIT0((len))) : 0ULL) + \
448 ((len) & 2ULL ? LITE3_SUM_2(s, LITE3_OFFSET_BIT1((len)), (len) - 1 - LITE3_OFFSET_BIT1((len))) : 0ULL) + \
449 ((len) & 4ULL ? LITE3_SUM_4(s, LITE3_OFFSET_BIT2((len)), (len) - 1 - LITE3_OFFSET_BIT2((len))) : 0ULL) + \
450 ((len) & 8ULL ? LITE3_SUM_8(s, LITE3_OFFSET_BIT3((len)), (len) - 1 - LITE3_OFFSET_BIT3((len))) : 0ULL) + \
451 ((len) & 16ULL ? LITE3_SUM_16(s, LITE3_OFFSET_BIT4((len)), (len) - 1 - LITE3_OFFSET_BIT4((len))) : 0ULL) + \
452 ((len) & 32ULL ? LITE3_SUM_32(s, LITE3_OFFSET_BIT5((len)), (len) - 1 - LITE3_OFFSET_BIT5((len))) : 0ULL)
453
454#define LITE3_STRLEN(s) (sizeof(s) - 1)
455
456typedef struct {
457 uint32_t hash;
458 uint32_t size;
459} lite3_key_data;
460
461static inline lite3_key_data lite3_get_key_data(const char *key) {
462 lite3_key_data key_data;
463 const char *key_cursor = key;
464 key_data.hash = LITE3_DJB2_HASH_SEED;
465 while (*key_cursor)
466 key_data.hash = ((key_data.hash << 5) + key_data.hash) + (uint8_t)(*key_cursor++);
467 key_data.size = (uint32_t)(key_cursor - key) + 1;
468 return key_data;
469}
470
471#define LITE3_KEY_DATA(s) ( \
472 __builtin_constant_p(s) ? \
473 ((LITE3_STRLEN(s) < 64) ? \
474 (lite3_key_data){ \
475 .hash = (uint32_t)((LITE3_POLY_HASH(s, LITE3_STRLEN(s)) + LITE3_DJB2_HASH_SEED * LITE3_POW33(LITE3_STRLEN(s))) % LITE3_MOD), \
476 .size = (sizeof(s)), \
477 } \
478 : lite3_get_key_data(s)) \
479 : lite3_get_key_data(__lite3_key__) \
480)
481#else
482#define LITE3_KEY_DATA(s) lite3_get_key_data(__lite3_key__)
483#endif
484#endif // DOXYGEN_IGNORE
486
487
488
512
521typedef struct {
522 uint8_t type;
523 uint8_t val[];
524} lite3_val;
525
526#ifndef DOXYGEN_IGNORE
527#define LITE3_VAL_SIZE sizeof(lite3_val)
528#endif // DOXYGEN_IGNORE
529static_assert(LITE3_VAL_SIZE <= sizeof(size_t), "LITE3_VAL_SIZE must be <= sizeof(size_t)");
530
531#ifndef DOXYGEN_IGNORE
532static const size_t lite3_type_sizes[] = {
533 0, // LITE3_TYPE_NULL
534 1, // LITE3_TYPE_BOOL
535 8, // LITE3_TYPE_I64
536 8, // LITE3_TYPE_F64
537 4, // LITE3_TYPE_BYTES (this value must be <= sizeof(size_t))
538 4, // LITE3_TYPE_STRING (this value must be <= sizeof(size_t))
539 LITE3_NODE_SIZE - LITE3_VAL_SIZE, // LITE3_TYPE_OBJECT (`type` field is contained inside node->gen_type)
540 LITE3_NODE_SIZE - LITE3_VAL_SIZE, // LITE3_TYPE_ARRAY (`type` field is contained inside node->gen_type)
541 0, // LITE3_TYPE_INVALID
542};
543#endif // DOXYGEN_IGNORE
544static_assert((sizeof(lite3_type_sizes) / sizeof(size_t)) == LITE3_TYPE_COUNT, "lite3_type_sizes[] element count != LITE3_TYPE_COUNT");
545static_assert(4 <= sizeof(size_t), "lite3_type_sizes[LITE3_TYPE_BYTES] and lite3_type_sizes[LITE3_TYPE_STRING] must fit inside size_t");
546
562typedef struct {
563 uint32_t gen;
564 uint32_t len;
565 const unsigned char *ptr;
567
568#ifndef DOXYGEN_IGNORE
569#define LITE3_BYTES_LEN_SIZE sizeof(((lite3_bytes *)0)->len)
570#endif // DOXYGEN_IGNORE
571static_assert(LITE3_BYTES_LEN_SIZE <= sizeof(size_t), "lite3_val_bytes() expects LITE3_BYTES_LEN_SIZE to be <= sizeof(size_t)");
572
591typedef struct {
592 uint32_t gen;
593 uint32_t len;
594 const char *ptr;
595} lite3_str;
596
597#ifndef DOXYGEN_IGNORE
598#define LITE3_STR_LEN_SIZE sizeof(((lite3_str *)0)->len)
599#endif // DOXYGEN_IGNORE
600static_assert(LITE3_STR_LEN_SIZE <= sizeof(size_t), "lite3_val_str() expects LITE3_STR_LEN_SIZE to be <= sizeof(size_t)");
601
627#define LITE3_BYTES(buf, val) (const unsigned char *)_lite3_ptr_suppress_nonnull_warning( \
628 (uint32_t)(val).gen == *(uint32_t *)(buf) ? (val).ptr : NULL \
629)
630
656#define LITE3_STR(buf, val) (const char *)_lite3_ptr_suppress_nonnull_warning( \
657 (uint32_t)(val).gen == *(uint32_t *)(buf) ? (val).ptr : NULL \
658)
659
660#ifndef DOXYGEN_IGNORE
661static inline __attribute__((always_inline)) const void *_lite3_ptr_suppress_nonnull_warning(const void *p) { return p; }
662#endif // DOXYGEN_IGNORE
664
665
666
691 unsigned char *buf,
692 size_t *__restrict out_buflen,
693 size_t bufsz
694);
695
709 unsigned char *buf,
710 size_t *__restrict out_buflen,
711 size_t bufsz
712);
714
715
716
747#ifndef DOXYGEN_IGNORE
748static inline int _lite3_verify_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
749{
750 (void)buf;
751 if (LITE3_UNLIKELY(bufsz > LITE3_BUF_SIZE_MAX)) {
752 LITE3_PRINT_ERROR("INVALID ARGUMENT: bufsz > LITE3_BUF_SIZE_MAX\n");
753 errno = EINVAL;
754 return -1;
755 }
756 if (LITE3_UNLIKELY(*inout_buflen > bufsz)) {
757 LITE3_PRINT_ERROR("INVALID ARGUMENT: inout_buflen > bufsz\n");
758 errno = EINVAL;
759 return -1;
760 }
761 if (LITE3_UNLIKELY(LITE3_NODE_SIZE > *inout_buflen || ofs > *inout_buflen - LITE3_NODE_SIZE)) {
762 LITE3_PRINT_ERROR("INVALID ARGUMENT: START OFFSET OUT OF BOUNDS\n");
763 errno = EINVAL;
764 return -1;
765 }
766 return 0;
767}
768
769static inline int _lite3_verify_obj_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key)
770{
771 int ret;
772 if ((ret = _lite3_verify_set(buf, inout_buflen, ofs, bufsz)) < 0)
773 return ret;
774 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_OBJECT)) {
775 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING OBJECT TYPE\n");
776 errno = EINVAL;
777 return -1;
778 }
779 if (LITE3_UNLIKELY(!key)) {
780 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING NON-NULL KEY\n");
781 errno = EINVAL;
782 return -1;
783 }
784 return ret;
785}
786
787static inline int _lite3_verify_arr_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
788{
789 int ret;
790 if ((ret = _lite3_verify_set(buf, inout_buflen, ofs, bufsz)) < 0)
791 return ret;
792 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_ARRAY)) {
793 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY TYPE\n");
794 errno = EINVAL;
795 return -1;
796 }
797 return ret;
798}
799
800// Private function
801int lite3_set_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 val_len, lite3_val **out);
802#endif // DOXYGEN_IGNORE
803
816#define lite3_set_null(buf, inout_buflen, ofs, bufsz, key) ({ \
817 const char *__lite3_key__ = (key); \
818 _lite3_set_null_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key)); \
819})
820#ifndef DOXYGEN_IGNORE
821static inline int _lite3_set_null_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key, lite3_key_data key_data)
822{
823 int ret;
824 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz, key)) < 0)
825 return ret;
826 lite3_val *val;
827 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
828 return ret;
829 val->type = (uint8_t)LITE3_TYPE_NULL;
830 return ret;
831}
832#endif // DOXYGEN_IGNORE
833
847#define lite3_set_bool(buf, inout_buflen, ofs, bufsz, key, value) ({ \
848 const char *__lite3_key__ = (key); \
849 _lite3_set_bool_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
850})
851#ifndef DOXYGEN_IGNORE
852static inline int _lite3_set_bool_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key, lite3_key_data key_data, bool value)
853{
854 int ret;
855 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz, key)) < 0)
856 return ret;
857 lite3_val *val;
858 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
859 return ret;
860 val->type = (uint8_t)LITE3_TYPE_BOOL;
861 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
862 return ret;
863}
864#endif // DOXYGEN_IGNORE
865
879#define lite3_set_i64(buf, inout_buflen, ofs, bufsz, key, value) ({ \
880 const char *__lite3_key__ = (key); \
881 _lite3_set_i64_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
882})
883#ifndef DOXYGEN_IGNORE
884static inline int _lite3_set_i64_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key, lite3_key_data key_data, int64_t value)
885{
886 int ret;
887 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz, key)) < 0)
888 return ret;
889 lite3_val *val;
890 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
891 return ret;
892 val->type = (uint8_t)LITE3_TYPE_I64;
893 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
894 return ret;
895}
896#endif // DOXYGEN_IGNORE
897
911#define lite3_set_f64(buf, inout_buflen, ofs, bufsz, key, value) ({ \
912 const char *__lite3_key__ = (key); \
913 _lite3_set_f64_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
914})
915#ifndef DOXYGEN_IGNORE
916static inline int _lite3_set_f64_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key, lite3_key_data key_data, double value)
917{
918 int ret;
919 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz, key)) < 0)
920 return ret;
921 lite3_val *val;
922 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
923 return ret;
924 val->type = (uint8_t)LITE3_TYPE_F64;
925 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
926 return ret;
927}
928#endif // DOXYGEN_IGNORE
929
944#define lite3_set_bytes(buf, inout_buflen, ofs, bufsz, key, bytes, bytes_len) ({ \
945 const char *__lite3_key__ = (key); \
946 _lite3_set_bytes_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), bytes, bytes_len); \
947})
948#ifndef DOXYGEN_IGNORE
949static inline int _lite3_set_bytes_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key, lite3_key_data key_data, const unsigned char *__restrict bytes, size_t bytes_len)
950{
951 int ret;
952 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz, key)) < 0)
953 return ret;
954 lite3_val *val;
955 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
956 return ret;
957 val->type = (uint8_t)LITE3_TYPE_BYTES;
958 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
959 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
960 return ret;
961}
962#endif // DOXYGEN_IGNORE
963
981#define lite3_set_str(buf, inout_buflen, ofs, bufsz, key, str) ({ \
982 const char *__lite3_key__ = (key); \
983 _lite3_set_str_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), str); \
984})
985#ifndef DOXYGEN_IGNORE
986static inline int _lite3_set_str_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key, lite3_key_data key_data, const char *__restrict str)
987{
988 int ret;
989 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz, key)) < 0)
990 return ret;
991 lite3_val *val;
992 size_t str_size = strlen(str) + 1;
993 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
994 return ret;
995 val->type = (uint8_t)LITE3_TYPE_STRING;
996 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
997 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
998 return ret;
999}
1000#endif // DOXYGEN_IGNORE
1001
1019#define lite3_set_str_n(buf, inout_buflen, ofs, bufsz, key, str, str_len) ({ \
1020 const char *__lite3_key__ = (key); \
1021 _lite3_set_str_n_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), str, str_len); \
1022})
1023#ifndef DOXYGEN_IGNORE
1024static inline int _lite3_set_str_n_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict key, lite3_key_data key_data, const char *__restrict str, size_t str_len)
1025{
1026 int ret;
1027 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz, key)) < 0)
1028 return ret;
1029 lite3_val *val;
1030 size_t str_size = str_len + 1;
1031 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1032 return ret;
1033 val->type = (uint8_t)LITE3_TYPE_STRING;
1034 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1035 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1036 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1037 return ret;
1038}
1039#endif // DOXYGEN_IGNORE
1040
1054#define lite3_set_obj(buf, inout_buflen, ofs, bufsz, key, out_ofs) ({ \
1055 unsigned char *__lite3_buf__ = (buf); \
1056 size_t *__lite3_inout_buflen__ = (inout_buflen); \
1057 size_t __lite3_ofs__ = (ofs); \
1058 size_t __lite3_bufsz__ = (bufsz); \
1059 const char *__lite3_key__ = (key); \
1060 int __lite3_ret__; \
1061 if ((__lite3_ret__ = _lite3_verify_obj_set( \
1062 __lite3_buf__, \
1063 __lite3_inout_buflen__, \
1064 __lite3_ofs__, \
1065 __lite3_bufsz__, \
1066 __lite3_key__)) < 0) \
1067 return __lite3_ret__; \
1068 \
1069 lite3_set_obj_impl( \
1070 __lite3_buf__, \
1071 __lite3_inout_buflen__, \
1072 __lite3_ofs__, \
1073 __lite3_bufsz__, \
1074 __lite3_key__, \
1075 LITE3_KEY_DATA(key), \
1076 out_ofs); \
1077})
1078#ifndef DOXYGEN_IGNORE
1079// Private function
1080int 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);
1081#endif // DOXYGEN_IGNORE
1082
1096#define lite3_set_arr(buf, inout_buflen, ofs, bufsz, key, out_ofs) ({ \
1097 unsigned char *__lite3_buf__ = (buf); \
1098 size_t *__lite3_inout_buflen__ = (inout_buflen); \
1099 size_t __lite3_ofs__ = (ofs); \
1100 size_t __lite3_bufsz__ = (bufsz); \
1101 const char *__lite3_key__ = (key); \
1102 int __lite3_ret__; \
1103 if ((__lite3_ret__ = _lite3_verify_obj_set( \
1104 __lite3_buf__, \
1105 __lite3_inout_buflen__, \
1106 __lite3_ofs__, \
1107 __lite3_bufsz__, \
1108 __lite3_key__)) < 0) \
1109 return __lite3_ret__; \
1110 \
1111 lite3_set_arr_impl( \
1112 __lite3_buf__, \
1113 __lite3_inout_buflen__, \
1114 __lite3_ofs__, \
1115 __lite3_bufsz__, \
1116 __lite3_key__, \
1117 LITE3_KEY_DATA(key), \
1118 out_ofs); \
1119})
1120#ifndef DOXYGEN_IGNORE
1121// Private function
1122int 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);
1123#endif // DOXYGEN_IGNORE
1125
1126
1127
1152#ifndef DOXYGEN_IGNORE
1153static inline int _lite3_set_by_index(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, size_t val_len, lite3_val **out)
1154{
1155 int ret;
1156 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1157 return ret;
1158 uint32_t size;
1159 memcpy(&size, buf + ofs + LITE3_NODE_SIZE_KC_OFFSET, sizeof(size));
1160 size >>= LITE3_NODE_SIZE_SHIFT;
1161 if (LITE3_UNLIKELY(index > size)) {
1162 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1163 errno = EINVAL;
1164 return -1;
1165 }
1166 lite3_key_data key_data = {
1167 .hash = index,
1168 .size = 0,
1169 };
1170 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1171}
1172
1173static inline int _lite3_set_by_append(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t val_len, lite3_val **out)
1174{
1175 int ret;
1176 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1177 return ret;
1178 uint32_t size;
1179 memcpy(&size, buf + ofs + LITE3_NODE_SIZE_KC_OFFSET, sizeof(size));
1180 size >>= LITE3_NODE_SIZE_SHIFT;
1181 lite3_key_data key_data = {
1182 .hash = size,
1183 .size = 0,
1184 };
1185 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1186}
1187#endif // DOXYGEN_IGNORE
1188
1195static inline int lite3_arr_append_null(
1196 unsigned char *buf,
1197 size_t *__restrict inout_buflen,
1198 size_t ofs,
1199 size_t bufsz)
1200{
1201 lite3_val *val;
1202 int ret;
1203 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
1204 return ret;
1205 val->type = (uint8_t)LITE3_TYPE_NULL;
1206 return ret;
1207}
1208
1215static inline int lite3_arr_append_bool(
1216 unsigned char *buf,
1217 size_t *__restrict inout_buflen,
1218 size_t ofs,
1219 size_t bufsz,
1220 bool value)
1221{
1222 lite3_val *val;
1223 int ret;
1224 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1225 return ret;
1226 val->type = (uint8_t)LITE3_TYPE_BOOL;
1227 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1228 return ret;
1229}
1230
1237static inline int lite3_arr_append_i64(
1238 unsigned char *buf,
1239 size_t *__restrict inout_buflen,
1240 size_t ofs,
1241 size_t bufsz,
1242 int64_t value)
1243{
1244 lite3_val *val;
1245 int ret;
1246 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1247 return ret;
1248 val->type = (uint8_t)LITE3_TYPE_I64;
1249 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1250 return ret;
1251}
1252
1259static inline int lite3_arr_append_f64(
1260 unsigned char *buf,
1261 size_t *__restrict inout_buflen,
1262 size_t ofs,
1263 size_t bufsz,
1264 double value)
1265{
1266 lite3_val *val;
1267 int ret;
1268 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1269 return ret;
1270 val->type = (uint8_t)LITE3_TYPE_F64;
1271 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1272 return ret;
1273}
1274
1281static inline int lite3_arr_append_bytes(
1282 unsigned char *buf,
1283 size_t *__restrict inout_buflen,
1284 size_t ofs,
1285 size_t bufsz,
1286 const unsigned char *__restrict bytes,
1287 size_t bytes_len)
1288{
1289 lite3_val *val;
1290 int ret;
1291 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1292 return ret;
1293 val->type = (uint8_t)LITE3_TYPE_BYTES;
1294 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1295 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1296 return ret;
1297}
1298
1309static inline int lite3_arr_append_str(
1310 unsigned char *buf,
1311 size_t *__restrict inout_buflen,
1312 size_t ofs,
1313 size_t bufsz,
1314 const char *__restrict str)
1315{
1316 lite3_val *val;
1317 size_t str_size = strlen(str) + 1;
1318 int ret;
1319 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1320 return ret;
1321 val->type = (uint8_t)LITE3_TYPE_STRING;
1322 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1323 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1324 return ret;
1325}
1326
1336static inline int lite3_arr_append_str_n(
1337 unsigned char *buf,
1338 size_t *__restrict inout_buflen,
1339 size_t ofs,
1340 size_t bufsz,
1341 const char *__restrict str,
1342 size_t str_len)
1343{
1344 lite3_val *val;
1345 size_t str_size = str_len + 1;
1346 int ret;
1347 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1348 return ret;
1349 val->type = (uint8_t)LITE3_TYPE_STRING;
1350 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1351 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1352 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1353 return ret;
1354}
1355
1362#ifndef DOXYGEN_IGNORE
1363// Private function
1364int lite3_arr_append_obj_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1365#endif // DOXYGEN_IGNORE
1366
1367static inline int lite3_arr_append_obj(
1368 unsigned char *buf,
1369 size_t *__restrict inout_buflen,
1370 size_t ofs,
1371 size_t bufsz,
1372 size_t *__restrict out_ofs)
1373{
1374 int ret;
1375 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1376 return ret;
1377 return lite3_arr_append_obj_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1378}
1379
1380
1387#ifndef DOXYGEN_IGNORE
1388// Private function
1389int lite3_arr_append_arr_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1390#endif // DOXYGEN_IGNORE
1391
1392static inline int lite3_arr_append_arr(
1393 unsigned char *buf,
1394 size_t *__restrict inout_buflen,
1395 size_t ofs,
1396 size_t bufsz,
1397 size_t *__restrict out_ofs)
1398{
1399 int ret;
1400 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1401 return ret;
1402 return lite3_arr_append_arr_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1403}
1404
1406
1407
1408
1445static inline int lite3_arr_set_null(
1446 unsigned char *buf,
1447 size_t *__restrict inout_buflen,
1448 size_t ofs,
1449 size_t bufsz,
1450 uint32_t index)
1451{
1452 lite3_val *val;
1453 int ret;
1454 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
1455 return ret;
1456 val->type = (uint8_t)LITE3_TYPE_NULL;
1457 return ret;
1458}
1459
1466static inline int lite3_arr_set_bool(
1467 unsigned char *buf,
1468 size_t *__restrict inout_buflen,
1469 size_t ofs,
1470 size_t bufsz,
1471 uint32_t index,
1472 bool value)
1473{
1474 lite3_val *val;
1475 int ret;
1476 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1477 return ret;
1478 val->type = (uint8_t)LITE3_TYPE_BOOL;
1479 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1480 return ret;
1481}
1482
1489static inline int lite3_arr_set_i64(
1490 unsigned char *buf,
1491 size_t *__restrict inout_buflen,
1492 size_t ofs,
1493 size_t bufsz,
1494 uint32_t index,
1495 int64_t value)
1496{
1497 lite3_val *val;
1498 int ret;
1499 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1500 return ret;
1501 val->type = (uint8_t)LITE3_TYPE_I64;
1502 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1503 return ret;
1504}
1505
1512static inline int lite3_arr_set_f64(
1513 unsigned char *buf,
1514 size_t *__restrict inout_buflen,
1515 size_t ofs,
1516 size_t bufsz,
1517 uint32_t index,
1518 double value)
1519{
1520 lite3_val *val;
1521 int ret;
1522 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1523 return ret;
1524 val->type = (uint8_t)LITE3_TYPE_F64;
1525 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1526 return ret;
1527}
1528
1535static inline int lite3_arr_set_bytes(
1536 unsigned char *buf,
1537 size_t *__restrict inout_buflen,
1538 size_t ofs,
1539 size_t bufsz,
1540 uint32_t index,
1541 const unsigned char *__restrict bytes,
1542 size_t bytes_len)
1543{
1544 lite3_val *val;
1545 int ret;
1546 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1547 return ret;
1548 val->type = (uint8_t)LITE3_TYPE_BYTES;
1549 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1550 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1551 return ret;
1552}
1553
1564static inline int lite3_arr_set_str(
1565 unsigned char *buf,
1566 size_t *__restrict inout_buflen,
1567 size_t ofs,
1568 size_t bufsz,
1569 uint32_t index,
1570 const char *__restrict str)
1571{
1572 lite3_val *val;
1573 size_t str_size = strlen(str) + 1;
1574 int ret;
1575 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1576 return ret;
1577 val->type = (uint8_t)LITE3_TYPE_STRING;
1578 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1579 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1580 return ret;
1581}
1582
1592static inline int lite3_arr_set_str_n(
1593 unsigned char *buf,
1594 size_t *__restrict inout_buflen,
1595 size_t ofs,
1596 size_t bufsz,
1597 uint32_t index,
1598 const char *__restrict str,
1599 size_t str_len)
1600{
1601 lite3_val *val;
1602 size_t str_size = str_len + 1;
1603 int ret;
1604 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1605 return ret;
1606 val->type = (uint8_t)LITE3_TYPE_STRING;
1607 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1608 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1609 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1610 return ret;
1611}
1612
1619#ifndef DOXYGEN_IGNORE
1620// Private function
1621int 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);
1622#endif // DOXYGEN_IGNORE
1623
1624static inline int lite3_arr_set_obj(
1625 unsigned char *buf,
1626 size_t *__restrict inout_buflen,
1627 size_t ofs,
1628 size_t bufsz,
1629 uint32_t index,
1630 size_t *__restrict out_ofs)
1631{
1632 int ret;
1633 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1634 return ret;
1635 return lite3_arr_set_obj_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1636}
1637
1638
1645#ifndef DOXYGEN_IGNORE
1646// Private function
1647int 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);
1648#endif // DOXYGEN_IGNORE
1649
1650static inline int lite3_arr_set_arr(
1651 unsigned char *buf,
1652 size_t *__restrict inout_buflen,
1653 size_t ofs,
1654 size_t bufsz,
1655 uint32_t index,
1656 size_t *__restrict out_ofs)
1657{
1658 int ret;
1659 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1660 return ret;
1661 return lite3_arr_set_arr_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1662}
1664
1665
1666
1681#ifndef DOXYGEN_IGNORE
1682static inline int _lite3_verify_get(const unsigned char *buf, size_t buflen, size_t ofs)
1683{
1684 (void)buf;
1685 if (LITE3_UNLIKELY(buflen > LITE3_BUF_SIZE_MAX)) {
1686 LITE3_PRINT_ERROR("INVALID ARGUMENT: buflen > LITE3_BUF_SIZE_MAX\n");
1687 errno = EINVAL;
1688 return -1;
1689 }
1690 if (LITE3_UNLIKELY(LITE3_NODE_SIZE > buflen || ofs > buflen - LITE3_NODE_SIZE)) {
1691 LITE3_PRINT_ERROR("INVALID ARGUMENT: START OFFSET OUT OF BOUNDS\n");
1692 errno = EINVAL;
1693 return -1;
1694 }
1695 return 0;
1696}
1697
1698static inline int _lite3_verify_obj_get(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key)
1699{
1700 if (_lite3_verify_get(buf, buflen, ofs) < 0)
1701 return -1;
1702 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_OBJECT)) {
1703 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING OBJECT TYPE\n");
1704 errno = EINVAL;
1705 return -1;
1706 }
1707 if (LITE3_UNLIKELY(!key)) {
1708 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING NON-NULL KEY\n");
1709 errno = EINVAL;
1710 return -1;
1711 }
1712 return 0;
1713}
1714
1715static inline int _lite3_verify_arr_get(const unsigned char *buf, size_t buflen, size_t ofs)
1716{
1717 if (_lite3_verify_get(buf, buflen, ofs) < 0)
1718 return -1;
1719 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_ARRAY)) {
1720 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY TYPE\n");
1721 errno = EINVAL;
1722 return -1;
1723 }
1724 return 0;
1725}
1726
1727// Private function
1728int lite3_get_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, lite3_val **out);
1729
1730static inline int _lite3_get_by_index(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, lite3_val **out)
1731{
1732 int ret;
1733 if ((ret = _lite3_verify_arr_get(buf, buflen, ofs)) < 0)
1734 return ret;
1735 uint32_t size;
1736 memcpy(&size, buf + ofs + LITE3_NODE_SIZE_KC_OFFSET, sizeof(size));
1737 size >>= LITE3_NODE_SIZE_SHIFT;
1738 if (LITE3_UNLIKELY(index >= size)) {
1739 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1740 errno = EINVAL;
1741 return -1;
1742 }
1743 lite3_key_data key_data = {
1744 .hash = index,
1745 .size = 0,
1746 };
1747 return lite3_get_impl(buf, buflen, ofs, NULL, key_data, out);
1748}
1749#endif // DOXYGEN_IGNORE
1750
1760static inline enum lite3_type lite3_get_root_type(const unsigned char *buf, size_t buflen)
1761{
1762 if (_lite3_verify_get(buf, buflen, 0) < 0)
1763 return LITE3_TYPE_INVALID;
1764 return (enum lite3_type)(*buf);
1765}
1766
1778#define lite3_get_type(buf, buflen, ofs, key) ({ \
1779 const char *__lite3_key__ = (key); \
1780 _lite3_get_type_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1781})
1782#ifndef DOXYGEN_IGNORE
1783static inline enum lite3_type _lite3_get_type_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1784{
1785 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1786 return LITE3_TYPE_INVALID;
1787 lite3_val *val;
1788 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1789 return LITE3_TYPE_INVALID;
1790 return (enum lite3_type)val->type;
1791}
1792#endif // DOXYGEN_IGNORE
1793
1805static inline enum lite3_type lite3_arr_get_type(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index)
1806{
1807 if (_lite3_verify_arr_get(buf, buflen, ofs) < 0)
1808 return LITE3_TYPE_INVALID;
1809 lite3_val *val;
1810 if (_lite3_get_by_index(buf, buflen, ofs, index, &val) < 0)
1811 return LITE3_TYPE_INVALID;
1812 return (enum lite3_type)val->type;
1813}
1814
1830#define lite3_get_type_size(buf, buflen, ofs, key, out) ({ \
1831 const char *__lite3_key__ = (key); \
1832 _lite3_get_type_size_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1833})
1834#ifndef DOXYGEN_IGNORE
1835static inline int _lite3_get_type_size_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, size_t *__restrict out)
1836{
1837 int ret;
1838 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
1839 return ret;
1840 lite3_val *val;
1841 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
1842 return ret;
1843 if (val->type == LITE3_TYPE_STRING || val->type == LITE3_TYPE_BYTES) {
1844 *out = 0;
1845 memcpy(out, &val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
1846 return ret;
1847 }
1848 *out = lite3_type_sizes[val->type];
1849 return ret;
1850}
1851#endif // DOXYGEN_IGNORE
1852
1864#define lite3_exists(buf, buflen, ofs, key) ({ \
1865 const char *__lite3_key__ = (key); \
1866 _lite3_exists_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1867})
1868#ifndef DOXYGEN_IGNORE
1869static inline bool _lite3_exists_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1870{
1871 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1872 return false;
1873 lite3_val *val;
1874 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1875 return false;
1876 return true;
1877}
1878#endif // DOXYGEN_IGNORE
1879
1888static inline int lite3_count(
1889 unsigned char *buf,
1890 size_t buflen,
1891 size_t ofs,
1892 uint32_t *out)
1893{
1894 int ret;
1895 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
1896 return ret;
1897 enum lite3_type type = (enum lite3_type)(*(buf + ofs));
1898 if (LITE3_UNLIKELY(!(type == LITE3_TYPE_OBJECT || type == LITE3_TYPE_ARRAY))) {
1899 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY OR OBJECT TYPE\n");
1900 errno = EINVAL;
1901 return -1;
1902 }
1903 memcpy(out, buf + ofs + LITE3_NODE_SIZE_KC_OFFSET, sizeof(*out));
1904 *out >>= LITE3_NODE_SIZE_SHIFT;
1905 return ret;
1906}
1907
1919#define lite3_is_null(buf, buflen, ofs, key) ({ \
1920 const char *__lite3_key__ = (key); \
1921 _lite3_is_null_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1922})
1923#ifndef DOXYGEN_IGNORE
1924static inline bool _lite3_is_null_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1925{
1926 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1927 return false;
1928 lite3_val *val;
1929 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1930 return false;
1931 return val->type == LITE3_TYPE_NULL;
1932}
1933#endif // DOXYGEN_IGNORE
1934
1946#define lite3_is_bool(buf, buflen, ofs, key) ({ \
1947 const char *__lite3_key__ = (key); \
1948 _lite3_is_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1949})
1950#ifndef DOXYGEN_IGNORE
1951static inline bool _lite3_is_bool_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1952{
1953 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1954 return false;
1955 lite3_val *val;
1956 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1957 return false;
1958 return val->type == LITE3_TYPE_BOOL;
1959}
1960#endif // DOXYGEN_IGNORE
1961
1973#define lite3_is_i64(buf, buflen, ofs, key) ({ \
1974 const char *__lite3_key__ = (key); \
1975 _lite3_is_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1976})
1977#ifndef DOXYGEN_IGNORE
1978static inline bool _lite3_is_i64_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1979{
1980 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1981 return false;
1982 lite3_val *val;
1983 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1984 return false;
1985 return val->type == LITE3_TYPE_I64;
1986}
1987#endif // DOXYGEN_IGNORE
1988
2000#define lite3_is_f64(buf, buflen, ofs, key) ({ \
2001 const char *__lite3_key__ = (key); \
2002 _lite3_is_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2003})
2004#ifndef DOXYGEN_IGNORE
2005static inline bool _lite3_is_f64_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
2006{
2007 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2008 return false;
2009 lite3_val *val;
2010 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2011 return false;
2012 return val->type == LITE3_TYPE_F64;
2013}
2014#endif // DOXYGEN_IGNORE
2015
2027#define lite3_is_bytes(buf, buflen, ofs, key) ({ \
2028 const char *__lite3_key__ = (key); \
2029 _lite3_is_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2030})
2031#ifndef DOXYGEN_IGNORE
2032static inline bool _lite3_is_bytes_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
2033{
2034 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2035 return false;
2036 lite3_val *val;
2037 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2038 return false;
2039 return val->type == LITE3_TYPE_BYTES;
2040}
2041#endif // DOXYGEN_IGNORE
2042
2054#define lite3_is_str(buf, buflen, ofs, key) ({ \
2055 const char *__lite3_key__ = (key); \
2056 _lite3_is_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2057})
2058#ifndef DOXYGEN_IGNORE
2059static inline bool _lite3_is_str_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
2060{
2061 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2062 return false;
2063 lite3_val *val;
2064 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2065 return false;
2066 return val->type == LITE3_TYPE_STRING;
2067}
2068#endif // DOXYGEN_IGNORE
2069
2081#define lite3_is_obj(buf, buflen, ofs, key) ({ \
2082 const char *__lite3_key__ = (key); \
2083 _lite3_is_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2084})
2085#ifndef DOXYGEN_IGNORE
2086static inline bool _lite3_is_obj_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
2087{
2088 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2089 return false;
2090 lite3_val *val;
2091 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2092 return false;
2093 return val->type == LITE3_TYPE_OBJECT;
2094}
2095#endif // DOXYGEN_IGNORE
2096
2108#define lite3_is_arr(buf, buflen, ofs, key) ({ \
2109 const char *__lite3_key__ = (key); \
2110 _lite3_is_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2111})
2112#ifndef DOXYGEN_IGNORE
2113static inline bool _lite3_is_arr_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
2114{
2115 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2116 return false;
2117 lite3_val *val;
2118 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2119 return false;
2120 return val->type == LITE3_TYPE_ARRAY;
2121}
2122#endif // DOXYGEN_IGNORE
2124
2125
2126
2161#define lite3_get(buf, buflen, ofs, key, out) ({ \
2162 const unsigned char *__lite3_buf__ = (buf); \
2163 size_t __lite3_buflen__ = (buflen); \
2164 size_t __lite3_ofs__ = (ofs); \
2165 int __lite3_ret__; \
2166 if ((__lite3_ret__ = _lite3_verify_get(__lite3_buf__, __lite3_buflen__, __lite3_ofs__) < 0)) \
2167 return __lite3_ret__; \
2168 const char *__lite3_key__ = (key); \
2169 lite3_get_impl(__lite3_buf__, __lite3_buflen__, __lite3_ofs__, __lite3_key__, LITE3_KEY_DATA(key), out); \
2170})
2171
2184#define lite3_get_bool(buf, buflen, ofs, key, out) ({ \
2185 const char *__lite3_key__ = (key); \
2186 _lite3_get_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2187})
2188#ifndef DOXYGEN_IGNORE
2189static inline int _lite3_get_bool_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, bool *out)
2190{
2191 int ret;
2192 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2193 return ret;
2194 lite3_val *val;
2195 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2196 return ret;
2197 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2198 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2199 errno = EINVAL;
2200 return -1;
2201 }
2202 *out = (bool)(*(val->val));
2203 return ret;
2204}
2205#endif // DOXYGEN_IGNORE
2206
2219#define lite3_get_i64(buf, buflen, ofs, key, out) ({ \
2220 const char *__lite3_key__ = (key); \
2221 _lite3_get_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2222})
2223#ifndef DOXYGEN_IGNORE
2224static inline int _lite3_get_i64_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, int64_t *out)
2225{
2226 int ret;
2227 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2228 return ret;
2229 lite3_val *val;
2230 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2231 return ret;
2232 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2233 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2234 errno = EINVAL;
2235 return -1;
2236 }
2237 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2238 return ret;
2239}
2240#endif // DOXYGEN_IGNORE
2241
2254#define lite3_get_f64(buf, buflen, ofs, key, out) ({ \
2255 const char *__lite3_key__ = (key); \
2256 _lite3_get_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2257})
2258#ifndef DOXYGEN_IGNORE
2259static inline int _lite3_get_f64_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, double *out)
2260{
2261 int ret;
2262 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2263 return ret;
2264 lite3_val *val;
2265 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2266 return ret;
2267 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2268 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2269 errno = EINVAL;
2270 return -1;
2271 }
2272 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2273 return ret;
2274}
2275#endif // DOXYGEN_IGNORE
2276
2289#define lite3_get_bytes(buf, buflen, ofs, key, out) ({ \
2290 const char *__lite3_key__ = (key); \
2291 _lite3_get_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2292})
2293#ifndef DOXYGEN_IGNORE
2294static inline int _lite3_get_bytes_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, lite3_bytes *out)
2295{
2296 int ret;
2297 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2298 return ret;
2299 lite3_val *val;
2300 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2301 return ret;
2302 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2303 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2304 errno = EINVAL;
2305 return -1;
2306 }
2307 *out = (lite3_bytes){
2308 .gen = *(uint32_t *)buf,
2309 .len = 0,
2310 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2311 };
2312 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2313 return ret;
2314}
2315#endif // DOXYGEN_IGNORE
2316
2329#define lite3_get_str(buf, buflen, ofs, key, out) ({ \
2330 const char *__lite3_key__ = (key); \
2331 _lite3_get_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2332})
2333#ifndef DOXYGEN_IGNORE
2334static inline int _lite3_get_str_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, lite3_str *out)
2335{
2336 int ret;
2337 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2338 return ret;
2339 lite3_val *val;
2340 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2341 return ret;
2342 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2343 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2344 errno = EINVAL;
2345 return -1;
2346 }
2347 *out = (lite3_str){
2348 .gen = *(uint32_t *)buf,
2349 .len = 0,
2350 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2351 };
2352 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2353 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2354 return ret;
2355}
2356#endif // DOXYGEN_IGNORE
2357
2370#define lite3_get_obj(buf, buflen, ofs, key, out) ({ \
2371 const char *__lite3_key__ = (key); \
2372 _lite3_get_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2373})
2374#ifndef DOXYGEN_IGNORE
2375static inline int _lite3_get_obj_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, size_t *__restrict out_ofs)
2376{
2377 int ret;
2378 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2379 return ret;
2380 lite3_val *val;
2381 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2382 return ret;
2383 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2384 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2385 errno = EINVAL;
2386 return -1;
2387 }
2388 *out_ofs = (size_t)((uint8_t *)val - buf);
2389 return ret;
2390}
2391#endif // DOXYGEN_IGNORE
2392
2405#define lite3_get_arr(buf, buflen, ofs, key, out) ({ \
2406 const char *__lite3_key__ = (key); \
2407 _lite3_get_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2408})
2409#ifndef DOXYGEN_IGNORE
2410static inline int _lite3_get_arr_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data, size_t *__restrict out_ofs)
2411{
2412 int ret;
2413 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2414 return ret;
2415 lite3_val *val;
2416 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2417 return ret;
2418 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2419 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2420 errno = EINVAL;
2421 return -1;
2422 }
2423 *out_ofs = (size_t)((uint8_t *)val - buf);
2424 return ret;
2425}
2426#endif // DOXYGEN_IGNORE
2428
2429
2430
2455static inline int lite3_arr_get_bool(
2456 const unsigned char *buf,
2457 size_t buflen,
2458 size_t ofs,
2459 uint32_t index,
2460 bool *out)
2461{
2462 lite3_val *val;
2463 int ret;
2464 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2465 return ret;
2466 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2467 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2468 errno = EINVAL;
2469 return -1;
2470 }
2471 *out = (bool)(*(val->val));
2472 return ret;
2473}
2474
2481static inline int lite3_arr_get_i64(
2482 const unsigned char *buf,
2483 size_t buflen,
2484 size_t ofs,
2485 uint32_t index,
2486 int64_t *out)
2487{
2488 lite3_val *val;
2489 int ret;
2490 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2491 return ret;
2492 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2493 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2494 errno = EINVAL;
2495 return -1;
2496 }
2497 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2498 return ret;
2499}
2500
2507static inline int lite3_arr_get_f64(
2508 const unsigned char *buf,
2509 size_t buflen,
2510 size_t ofs,
2511 uint32_t index,
2512 double *out)
2513{
2514 lite3_val *val;
2515 int ret;
2516 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2517 return ret;
2518 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2519 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2520 errno = EINVAL;
2521 return -1;
2522 }
2523 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2524 return ret;
2525}
2526
2533static inline int lite3_arr_get_bytes(
2534 const unsigned char *buf,
2535 size_t buflen,
2536 size_t ofs,
2537 uint32_t index,
2538 lite3_bytes *out)
2539{
2540 lite3_val *val;
2541 int ret;
2542 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2543 return ret;
2544 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2545 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2546 errno = EINVAL;
2547 return -1;
2548 }
2549 *out = (lite3_bytes){
2550 .gen = *(uint32_t *)buf,
2551 .len = 0,
2552 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2553 };
2554 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2555 return ret;
2556}
2557
2564static inline int lite3_arr_get_str(
2565 const unsigned char *buf,
2566 size_t buflen,
2567 size_t ofs,
2568 uint32_t index,
2569 lite3_str *out)
2570{
2571 lite3_val *val;
2572 int ret;
2573 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2574 return ret;
2575 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2576 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2577 errno = EINVAL;
2578 return -1;
2579 }
2580 *out = (lite3_str){
2581 .gen = *(uint32_t *)buf,
2582 .len = 0,
2583 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2584 };
2585 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2586 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2587 return ret;
2588}
2589
2596static inline int lite3_arr_get_obj(
2597 const unsigned char *buf,
2598 size_t buflen,
2599 size_t ofs,
2600 uint32_t index,
2601 size_t *__restrict out_ofs)
2602{
2603 lite3_val *val;
2604 int ret;
2605 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2606 return ret;
2607 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2608 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2609 errno = EINVAL;
2610 return -1;
2611 }
2612 *out_ofs = (size_t)((uint8_t *)val - buf);
2613 return ret;
2614}
2615
2622static inline int lite3_arr_get_arr(
2623 const unsigned char *buf,
2624 size_t buflen,
2625 size_t ofs,
2626 uint32_t index,
2627 size_t *__restrict out_ofs)
2628{
2629 lite3_val *val;
2630 int ret;
2631 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2632 return ret;
2633 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2634 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2635 errno = EINVAL;
2636 return -1;
2637 }
2638 *out_ofs = (size_t)((uint8_t *)val - buf);
2639 return ret;
2640}
2642
2643
2644
2661#define LITE3_ITER_ITEM 1
2663#define LITE3_ITER_DONE 0
2664
2671typedef struct {
2672 uint32_t gen;
2673 uint32_t node_ofs[LITE3_TREE_HEIGHT_MAX + 1];
2674 uint8_t depth;
2675 uint8_t node_i[LITE3_TREE_HEIGHT_MAX + 1];
2676} lite3_iter;
2677
2678#ifndef DOXYGEN_IGNORE
2679// Private function
2680int lite3_iter_create_impl(const unsigned char *buf, size_t buflen, size_t ofs, lite3_iter *out);
2681#endif // DOXYGEN_IGNORE
2682
2689static inline int lite3_iter_create(
2690 const unsigned char *buf,
2691 size_t buflen,
2692 size_t ofs,
2693 lite3_iter *out)
2694{
2695 int ret;
2696 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
2697 return ret;
2698 return lite3_iter_create_impl(buf, buflen, ofs, out);
2699}
2700
2717int lite3_iter_next(
2718 const unsigned char *buf,
2719 size_t buflen,
2720 lite3_iter *iter,
2721 lite3_str *out_key,
2722 size_t *out_val_ofs
2723);
2725
2726
2727
2739static inline enum lite3_type lite3_val_type(lite3_val *val)
2740{
2741 enum lite3_type type = (enum lite3_type)val->type;
2742 return type < LITE3_TYPE_INVALID ? type : LITE3_TYPE_INVALID;
2743}
2744
2754static inline size_t lite3_val_type_size(lite3_val *val)
2755{
2756 enum lite3_type type = (enum lite3_type)val->type;
2757 if (type == LITE3_TYPE_STRING || type == LITE3_TYPE_BYTES) {
2758 size_t tmp = 0;
2759 memcpy(&tmp, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2760 return tmp;
2761 }
2762 return lite3_type_sizes[val->type];
2763}
2764
2765static inline bool lite3_val_is_null(lite3_val *val) { return val->type == LITE3_TYPE_NULL; }
2766static inline bool lite3_val_is_bool(lite3_val *val) { return val->type == LITE3_TYPE_BOOL; }
2767static inline bool lite3_val_is_i64(lite3_val *val) { return val->type == LITE3_TYPE_I64; }
2768static inline bool lite3_val_is_f64(lite3_val *val) { return val->type == LITE3_TYPE_F64; }
2769static inline bool lite3_val_is_bytes(lite3_val *val) { return val->type == LITE3_TYPE_BYTES; }
2770static inline bool lite3_val_is_str(lite3_val *val) { return val->type == LITE3_TYPE_STRING; }
2771static inline bool lite3_val_is_obj(lite3_val *val) { return val->type == LITE3_TYPE_OBJECT; }
2772static inline bool lite3_val_is_arr(lite3_val *val) { return val->type == LITE3_TYPE_ARRAY; }
2773
2774static inline bool lite3_val_bool(lite3_val *val)
2775{
2776 return *(bool *)(val->val);
2777}
2778
2779static inline int64_t lite3_val_i64(lite3_val *val)
2780{
2781 int64_t tmp;
2782 memcpy(&tmp, val->val, sizeof(tmp));
2783 return tmp;
2784}
2785
2786static inline double lite3_val_f64(lite3_val *val)
2787{
2788 double tmp;
2789 memcpy(&tmp, val->val, sizeof(tmp));
2790 return tmp;
2791}
2792
2793static inline const char *lite3_val_str(lite3_val *val)
2794{
2795 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2796}
2797
2802static inline const char *lite3_val_str_n(lite3_val *val, size_t *out_len)
2803{
2804 *out_len = 0;
2805 memcpy(out_len, val->val, LITE3_STR_LEN_SIZE);
2806 *out_len -= 1; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2807 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2808}
2809
2810static inline const unsigned char *lite3_val_bytes(lite3_val *val, size_t *out_len)
2811{
2812 *out_len = 0;
2813 memcpy(out_len, val->val, LITE3_BYTES_LEN_SIZE);
2814 return (const unsigned char *)val->val + LITE3_BYTES_LEN_SIZE;
2815}
2817
2818
2819
2856#define LITE3_JSON
2857
2858#if defined(DOXYGEN_ONLY) && !defined(LITE3_JSON)
2859#define LITE3_JSON
2860#endif // DOXYGEN_ONLY
2861
2862#ifdef LITE3_JSON
2863#include <stdio.h>
2864
2873#define LITE3_JSON_NESTING_DEPTH_MAX 32
2874
2887 unsigned char *buf,
2888 size_t *__restrict out_buflen,
2889 size_t bufsz,
2890 const char *__restrict json_str,
2891 size_t json_len
2892);
2893
2906 unsigned char *buf,
2907 size_t *__restrict out_buflen,
2908 size_t bufsz,
2909 const char *__restrict path
2910);
2911
2924 unsigned char *buf,
2925 size_t *__restrict out_buflen,
2926 size_t bufsz,
2927 FILE *fp
2928);
2929
2944 const unsigned char *buf,
2945 size_t buflen,
2946 size_t ofs
2947);
2948
2963 const unsigned char *buf,
2964 size_t buflen,
2965 size_t ofs,
2966 size_t *__restrict out_len
2967);
2968
2985 const unsigned char *buf,
2986 size_t buflen,
2987 size_t ofs,
2988 size_t *__restrict out_len
2989);
2990
3002 const unsigned char *buf,
3003 size_t buflen,
3004 size_t ofs,
3005 char *__restrict json_buf,
3006 size_t json_bufsz
3007);
3008
3022 const unsigned char *buf,
3023 size_t buflen,
3024 size_t ofs,
3025 char *__restrict json_buf,
3026 size_t json_bufsz
3027);
3028#else
3029static inline int lite3_json_dec(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, const char *__restrict json_str, size_t json_len)
3030{
3031 (void)buf; (void)out_buflen; (void)bufsz; (void)json_str; (void)json_len;
3032 return -1;
3033}
3034
3035static inline int lite3_json_dec_file(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, const char *__restrict path)
3036{
3037 (void)buf; (void)out_buflen; (void)bufsz; (void)path;
3038 return -1;
3039}
3040
3041static inline int lite3_json_dec_fp(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, FILE *fp)
3042{
3043 (void)buf; (void)out_buflen; (void)bufsz; (void)fp;
3044 return -1;
3045}
3046
3047static inline int lite3_json_print(const unsigned char *buf, size_t buflen, size_t ofs)
3048{
3049 (void)buf; (void)buflen; (void)ofs;
3050 return 0;
3051}
3052
3053static inline char *lite3_json_enc(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3054{
3055 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3056 return NULL;
3057}
3058
3059static inline char *lite3_json_enc_pretty(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3060{
3061 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3062 return NULL;
3063}
3064
3065static inline int64_t lite3_json_enc_buf(const unsigned char *buf, size_t buflen, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
3066{
3067 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3068 return -1;
3069}
3070
3071static inline int64_t lite3_json_enc_pretty_buf(const unsigned char *buf, size_t buflen, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
3072{
3073 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3074 return -1;
3075}
3076#endif
3078
3079#ifdef __cplusplus
3080}
3081#endif
3082
3083#endif // LITE3_H
static int lite3_arr_append_f64(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, double value)
Append floating point to array.
Definition lite3.h:1259
static int lite3_arr_append_bool(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, bool value)
Append boolean to array.
Definition lite3.h:1215
static int lite3_arr_append_str_n(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict str, size_t str_len)
Append string to array by length.
Definition lite3.h:1336
static int lite3_arr_append_null(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
Append null to array.
Definition lite3.h:1195
static int lite3_arr_append_arr(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs)
Append array to array.
Definition lite3.h:1392
static int lite3_arr_append_i64(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, int64_t value)
Append integer to array.
Definition lite3.h:1237
static int lite3_arr_append_bytes(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const unsigned char *__restrict bytes, size_t bytes_len)
Append bytes to array.
Definition lite3.h:1281
static int lite3_arr_append_obj(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs)
Append object to array.
Definition lite3.h:1367
static int lite3_arr_append_str(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, const char *__restrict str)
Append string to array.
Definition lite3.h:1309
static int lite3_arr_get_obj(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, size_t *__restrict out_ofs)
Get object by index.
Definition lite3.h:2596
static int lite3_arr_get_i64(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, int64_t *out)
Get integer value by index.
Definition lite3.h:2481
static int lite3_arr_get_bool(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, bool *out)
Get boolean value by index.
Definition lite3.h:2455
static int lite3_arr_get_f64(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, double *out)
Get floating point value by index.
Definition lite3.h:2507
static int lite3_arr_get_str(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, lite3_str *out)
Get string value by index.
Definition lite3.h:2564
static int lite3_arr_get_bytes(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, lite3_bytes *out)
Get bytes value by index.
Definition lite3.h:2533
static int lite3_arr_get_arr(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, size_t *__restrict out_ofs)
Get array by index.
Definition lite3.h:2622
static int lite3_arr_set_null(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index)
Set null in array.
Definition lite3.h:1445
static int lite3_arr_set_obj(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, size_t *__restrict out_ofs)
Set object in array.
Definition lite3.h:1624
static int lite3_arr_set_str_n(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, const char *__restrict str, size_t str_len)
Set string in array by length.
Definition lite3.h:1592
static int lite3_arr_set_i64(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, int64_t value)
Set integer in array.
Definition lite3.h:1489
static int lite3_arr_set_str(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, const char *__restrict str)
Set string in array.
Definition lite3.h:1564
static int lite3_arr_set_bool(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, bool value)
Set boolean in array.
Definition lite3.h:1466
static int lite3_arr_set_bytes(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, const unsigned char *__restrict bytes, size_t bytes_len)
Set bytes in array.
Definition lite3.h:1535
static int lite3_arr_set_arr(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, size_t *__restrict out_ofs)
Set array in array.
Definition lite3.h:1650
static int lite3_arr_set_f64(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, uint32_t index, double value)
Set float in array.
Definition lite3.h:1512
#define LITE3_BUF_SIZE_MAX
Maximum Lite³ buffer size.
Definition lite3.h:259
#define LITE3_TREE_HEIGHT_MAX
Maximum B-tree height.
Definition lite3.h:308
#define LITE3_NODE_SIZE
B-tree node size setting.
Definition lite3.h:293
#define LITE3_NODE_SIZE_KC_OFFSET
Offset of the size_kc field inside struct node.
Definition lite3.h:322
int lite3_init_arr(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz)
Initialize a Lite³ buffer as an array.
int lite3_init_obj(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz)
Initialize a Lite³ buffer as an object.
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.
Definition lite3.c:373
static int lite3_iter_create(const unsigned char *buf, size_t buflen, size_t ofs, lite3_iter *out)
Create a lite3 iterator for the given object or array.
Definition lite3.h:2689
int lite3_json_dec_file(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, const char *__restrict path)
Convert JSON from file path to Lite³
int64_t lite3_json_enc_pretty_buf(const unsigned char *buf, size_t buflen, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
Convert Lite³ to prettified JSON and write to output buffer.
char * lite3_json_enc_pretty(const unsigned char *buf, size_t buflen, size_t ofs, size_t *__restrict out_len)
Convert Lite³ to JSON prettified string.
int lite3_json_print(const unsigned char *buf, size_t buflen, size_t ofs)
Print Lite³ buffer as JSON to stdout
int lite3_json_dec(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, const char *__restrict json_str, size_t json_len)
Convert JSON string to Lite³
int lite3_json_dec_fp(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, FILE *fp)
Convert JSON from file pointer to Lite³
int64_t lite3_json_enc_buf(const unsigned char *buf, size_t buflen, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
Convert Lite³ to JSON and write to output buffer.
char * lite3_json_enc(const unsigned char *buf, size_t buflen, size_t ofs, size_t *__restrict out_len)
Convert Lite³ to JSON string.
lite3_type
enum containing all Lite³ types
Definition lite3.h:500
@ LITE3_TYPE_ARRAY
maps to 'array' type in JSON
Definition lite3.h:508
@ LITE3_TYPE_INVALID
any type value equal or greater than this is considered invalid
Definition lite3.h:509
@ LITE3_TYPE_STRING
maps to 'string' type in JSON
Definition lite3.h:506
@ LITE3_TYPE_BOOL
maps to 'boolean' type in JSON; underlying datatype: bool
Definition lite3.h:502
@ LITE3_TYPE_BYTES
coverted to base64 string in JSON
Definition lite3.h:505
@ LITE3_TYPE_F64
maps to 'number' type in JSON; underlying datatype: double
Definition lite3.h:504
@ LITE3_TYPE_OBJECT
maps to 'object' type in JSON
Definition lite3.h:507
@ LITE3_TYPE_I64
maps to 'number' type in JSON; underlying datatype: int64_t
Definition lite3.h:503
@ LITE3_TYPE_NULL
maps to 'null' type in JSON
Definition lite3.h:501
@ LITE3_TYPE_COUNT
not an actual type, only used for counting
Definition lite3.h:510
static enum lite3_type lite3_get_root_type(const unsigned char *buf, size_t buflen)
Get the root type of a Lite³ buffer.
Definition lite3.h:1760
static int lite3_count(unsigned char *buf, size_t buflen, size_t ofs, uint32_t *out)
Write back the number of object entries or array elements.
Definition lite3.h:1888
static enum lite3_type lite3_arr_get_type(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index)
Find value by index and return value type.
Definition lite3.h:1805
static size_t lite3_val_type_size(lite3_val *val)
Returns the size of the value type.
Definition lite3.h:2754
static const char * lite3_val_str_n(lite3_val *val, size_t *out_len)
Definition lite3.h:2802
static enum lite3_type lite3_val_type(lite3_val *val)
Returns the value type of *val
Definition lite3.h:2739
Struct holding a reference to a bytes value inside a Lite³ buffer.
Definition lite3.h:562
uint32_t gen
generation of the Lite³ buffer when this struct was returned
Definition lite3.h:563
uint32_t len
byte array length (bytes)
Definition lite3.h:564
const unsigned char * ptr
byte array pointer to bytes inside Lite³ buffer
Definition lite3.h:565
Struct containing iterator state.
Definition lite3.h:2671
Struct holding a reference to a string inside a Lite³ buffer.
Definition lite3.h:591
uint32_t len
char array length (characters, exclusive of NULL-terminator)
Definition lite3.h:593
const char * ptr
char array pointer to string inside Lite³ buffer
Definition lite3.h:594
uint32_t gen
generation of the Lite³ buffer when this struct was returned
Definition lite3.h:592
Struct representing a value inside a Lite³ buffer.
Definition lite3.h:521