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 ((u32)~((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 = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1159 if (LITE3_UNLIKELY(index > size)) {
1160 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1161 errno = EINVAL;
1162 return -1;
1163 }
1164 lite3_key_data key_data = {
1165 .hash = index,
1166 .size = 0,
1167 };
1168 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1169}
1170
1171static 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)
1172{
1173 int ret;
1174 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1175 return ret;
1176 uint32_t size = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1177 lite3_key_data key_data = {
1178 .hash = size,
1179 .size = 0,
1180 };
1181 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1182}
1183#endif // DOXYGEN_IGNORE
1184
1191static inline int lite3_arr_append_null(
1192 unsigned char *buf,
1193 size_t *__restrict inout_buflen,
1194 size_t ofs,
1195 size_t bufsz)
1196{
1197 lite3_val *val;
1198 int ret;
1199 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
1200 return ret;
1201 val->type = (uint8_t)LITE3_TYPE_NULL;
1202 return ret;
1203}
1204
1211static inline int lite3_arr_append_bool(
1212 unsigned char *buf,
1213 size_t *__restrict inout_buflen,
1214 size_t ofs,
1215 size_t bufsz,
1216 bool value)
1217{
1218 lite3_val *val;
1219 int ret;
1220 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1221 return ret;
1222 val->type = (uint8_t)LITE3_TYPE_BOOL;
1223 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1224 return ret;
1225}
1226
1233static inline int lite3_arr_append_i64(
1234 unsigned char *buf,
1235 size_t *__restrict inout_buflen,
1236 size_t ofs,
1237 size_t bufsz,
1238 int64_t value)
1239{
1240 lite3_val *val;
1241 int ret;
1242 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1243 return ret;
1244 val->type = (uint8_t)LITE3_TYPE_I64;
1245 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1246 return ret;
1247}
1248
1255static inline int lite3_arr_append_f64(
1256 unsigned char *buf,
1257 size_t *__restrict inout_buflen,
1258 size_t ofs,
1259 size_t bufsz,
1260 double value)
1261{
1262 lite3_val *val;
1263 int ret;
1264 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1265 return ret;
1266 val->type = (uint8_t)LITE3_TYPE_F64;
1267 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1268 return ret;
1269}
1270
1277static inline int lite3_arr_append_bytes(
1278 unsigned char *buf,
1279 size_t *__restrict inout_buflen,
1280 size_t ofs,
1281 size_t bufsz,
1282 const unsigned char *__restrict bytes,
1283 size_t bytes_len)
1284{
1285 lite3_val *val;
1286 int ret;
1287 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1288 return ret;
1289 val->type = (uint8_t)LITE3_TYPE_BYTES;
1290 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1291 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1292 return ret;
1293}
1294
1305static inline int lite3_arr_append_str(
1306 unsigned char *buf,
1307 size_t *__restrict inout_buflen,
1308 size_t ofs,
1309 size_t bufsz,
1310 const char *__restrict str)
1311{
1312 lite3_val *val;
1313 size_t str_size = strlen(str) + 1;
1314 int ret;
1315 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1316 return ret;
1317 val->type = (uint8_t)LITE3_TYPE_STRING;
1318 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1319 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1320 return ret;
1321}
1322
1332static inline int lite3_arr_append_str_n(
1333 unsigned char *buf,
1334 size_t *__restrict inout_buflen,
1335 size_t ofs,
1336 size_t bufsz,
1337 const char *__restrict str,
1338 size_t str_len)
1339{
1340 lite3_val *val;
1341 size_t str_size = str_len + 1;
1342 int ret;
1343 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1344 return ret;
1345 val->type = (uint8_t)LITE3_TYPE_STRING;
1346 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1347 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1348 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1349 return ret;
1350}
1351
1358#ifndef DOXYGEN_IGNORE
1359// Private function
1360int lite3_arr_append_obj_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1361#endif // DOXYGEN_IGNORE
1362
1363static inline int lite3_arr_append_obj(
1364 unsigned char *buf,
1365 size_t *__restrict inout_buflen,
1366 size_t ofs,
1367 size_t bufsz,
1368 size_t *__restrict out_ofs)
1369{
1370 int ret;
1371 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1372 return ret;
1373 return lite3_arr_append_obj_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1374}
1375
1376
1383#ifndef DOXYGEN_IGNORE
1384// Private function
1385int lite3_arr_append_arr_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1386#endif // DOXYGEN_IGNORE
1387
1388static inline int lite3_arr_append_arr(
1389 unsigned char *buf,
1390 size_t *__restrict inout_buflen,
1391 size_t ofs,
1392 size_t bufsz,
1393 size_t *__restrict out_ofs)
1394{
1395 int ret;
1396 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1397 return ret;
1398 return lite3_arr_append_arr_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1399}
1400
1402
1403
1404
1441static inline int lite3_arr_set_null(
1442 unsigned char *buf,
1443 size_t *__restrict inout_buflen,
1444 size_t ofs,
1445 size_t bufsz,
1446 uint32_t index)
1447{
1448 lite3_val *val;
1449 int ret;
1450 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
1451 return ret;
1452 val->type = (uint8_t)LITE3_TYPE_NULL;
1453 return ret;
1454}
1455
1462static inline int lite3_arr_set_bool(
1463 unsigned char *buf,
1464 size_t *__restrict inout_buflen,
1465 size_t ofs,
1466 size_t bufsz,
1467 uint32_t index,
1468 bool value)
1469{
1470 lite3_val *val;
1471 int ret;
1472 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1473 return ret;
1474 val->type = (uint8_t)LITE3_TYPE_BOOL;
1475 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1476 return ret;
1477}
1478
1485static inline int lite3_arr_set_i64(
1486 unsigned char *buf,
1487 size_t *__restrict inout_buflen,
1488 size_t ofs,
1489 size_t bufsz,
1490 uint32_t index,
1491 int64_t value)
1492{
1493 lite3_val *val;
1494 int ret;
1495 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1496 return ret;
1497 val->type = (uint8_t)LITE3_TYPE_I64;
1498 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1499 return ret;
1500}
1501
1508static inline int lite3_arr_set_f64(
1509 unsigned char *buf,
1510 size_t *__restrict inout_buflen,
1511 size_t ofs,
1512 size_t bufsz,
1513 uint32_t index,
1514 double value)
1515{
1516 lite3_val *val;
1517 int ret;
1518 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1519 return ret;
1520 val->type = (uint8_t)LITE3_TYPE_F64;
1521 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1522 return ret;
1523}
1524
1531static inline int lite3_arr_set_bytes(
1532 unsigned char *buf,
1533 size_t *__restrict inout_buflen,
1534 size_t ofs,
1535 size_t bufsz,
1536 uint32_t index,
1537 const unsigned char *__restrict bytes,
1538 size_t bytes_len)
1539{
1540 lite3_val *val;
1541 int ret;
1542 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1543 return ret;
1544 val->type = (uint8_t)LITE3_TYPE_BYTES;
1545 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1546 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1547 return ret;
1548}
1549
1560static inline int lite3_arr_set_str(
1561 unsigned char *buf,
1562 size_t *__restrict inout_buflen,
1563 size_t ofs,
1564 size_t bufsz,
1565 uint32_t index,
1566 const char *__restrict str)
1567{
1568 lite3_val *val;
1569 size_t str_size = strlen(str) + 1;
1570 int ret;
1571 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1572 return ret;
1573 val->type = (uint8_t)LITE3_TYPE_STRING;
1574 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1575 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1576 return ret;
1577}
1578
1588static inline int lite3_arr_set_str_n(
1589 unsigned char *buf,
1590 size_t *__restrict inout_buflen,
1591 size_t ofs,
1592 size_t bufsz,
1593 uint32_t index,
1594 const char *__restrict str,
1595 size_t str_len)
1596{
1597 lite3_val *val;
1598 size_t str_size = str_len + 1;
1599 int ret;
1600 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1601 return ret;
1602 val->type = (uint8_t)LITE3_TYPE_STRING;
1603 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1604 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1605 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1606 return ret;
1607}
1608
1615#ifndef DOXYGEN_IGNORE
1616// Private function
1617int 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);
1618#endif // DOXYGEN_IGNORE
1619
1620static inline int lite3_arr_set_obj(
1621 unsigned char *buf,
1622 size_t *__restrict inout_buflen,
1623 size_t ofs,
1624 size_t bufsz,
1625 uint32_t index,
1626 size_t *__restrict out_ofs)
1627{
1628 int ret;
1629 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1630 return ret;
1631 return lite3_arr_set_obj_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1632}
1633
1634
1641#ifndef DOXYGEN_IGNORE
1642// Private function
1643int 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);
1644#endif // DOXYGEN_IGNORE
1645
1646static inline int lite3_arr_set_arr(
1647 unsigned char *buf,
1648 size_t *__restrict inout_buflen,
1649 size_t ofs,
1650 size_t bufsz,
1651 uint32_t index,
1652 size_t *__restrict out_ofs)
1653{
1654 int ret;
1655 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1656 return ret;
1657 return lite3_arr_set_arr_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1658}
1660
1661
1662
1677#ifndef DOXYGEN_IGNORE
1678static inline int _lite3_verify_get(const unsigned char *buf, size_t buflen, size_t ofs)
1679{
1680 (void)buf;
1681 if (LITE3_UNLIKELY(buflen > LITE3_BUF_SIZE_MAX)) {
1682 LITE3_PRINT_ERROR("INVALID ARGUMENT: buflen > LITE3_BUF_SIZE_MAX\n");
1683 errno = EINVAL;
1684 return -1;
1685 }
1686 if (LITE3_UNLIKELY(LITE3_NODE_SIZE > buflen || ofs > buflen - LITE3_NODE_SIZE)) {
1687 LITE3_PRINT_ERROR("INVALID ARGUMENT: START OFFSET OUT OF BOUNDS\n");
1688 errno = EINVAL;
1689 return -1;
1690 }
1691 return 0;
1692}
1693
1694static inline int _lite3_verify_obj_get(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key)
1695{
1696 if (_lite3_verify_get(buf, buflen, ofs) < 0)
1697 return -1;
1698 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_OBJECT)) {
1699 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING OBJECT TYPE\n");
1700 errno = EINVAL;
1701 return -1;
1702 }
1703 if (LITE3_UNLIKELY(!key)) {
1704 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING NON-NULL KEY\n");
1705 errno = EINVAL;
1706 return -1;
1707 }
1708 return 0;
1709}
1710
1711static inline int _lite3_verify_arr_get(const unsigned char *buf, size_t buflen, size_t ofs)
1712{
1713 if (_lite3_verify_get(buf, buflen, ofs) < 0)
1714 return -1;
1715 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_ARRAY)) {
1716 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY TYPE\n");
1717 errno = EINVAL;
1718 return -1;
1719 }
1720 return 0;
1721}
1722
1723// Private function
1724int 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);
1725
1726static inline int _lite3_get_by_index(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, lite3_val **out)
1727{
1728 int ret;
1729 if ((ret = _lite3_verify_arr_get(buf, buflen, ofs)) < 0)
1730 return ret;
1731 uint32_t size = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1732 if (LITE3_UNLIKELY(index >= size)) {
1733 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1734 errno = EINVAL;
1735 return -1;
1736 }
1737 lite3_key_data key_data = {
1738 .hash = index,
1739 .size = 0,
1740 };
1741 return lite3_get_impl(buf, buflen, ofs, NULL, key_data, out);
1742}
1743#endif // DOXYGEN_IGNORE
1744
1754static inline enum lite3_type lite3_get_root_type(const unsigned char *buf, size_t buflen)
1755{
1756 if (_lite3_verify_get(buf, buflen, 0) < 0)
1757 return LITE3_TYPE_INVALID;
1758 return (enum lite3_type)(*buf);
1759}
1760
1772#define lite3_get_type(buf, buflen, ofs, key) ({ \
1773 const char *__lite3_key__ = (key); \
1774 _lite3_get_type_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1775})
1776#ifndef DOXYGEN_IGNORE
1777static 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)
1778{
1779 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1780 return LITE3_TYPE_INVALID;
1781 lite3_val *val;
1782 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1783 return LITE3_TYPE_INVALID;
1784 return (enum lite3_type)val->type;
1785}
1786#endif // DOXYGEN_IGNORE
1787
1799static inline enum lite3_type lite3_arr_get_type(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index)
1800{
1801 if (_lite3_verify_arr_get(buf, buflen, ofs) < 0)
1802 return LITE3_TYPE_INVALID;
1803 lite3_val *val;
1804 if (_lite3_get_by_index(buf, buflen, ofs, index, &val) < 0)
1805 return LITE3_TYPE_INVALID;
1806 return (enum lite3_type)val->type;
1807}
1808
1824#define lite3_get_type_size(buf, buflen, ofs, key, out) ({ \
1825 const char *__lite3_key__ = (key); \
1826 _lite3_get_type_size_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1827})
1828#ifndef DOXYGEN_IGNORE
1829static 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)
1830{
1831 int ret;
1832 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
1833 return ret;
1834 lite3_val *val;
1835 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
1836 return ret;
1837 if (val->type == LITE3_TYPE_STRING || val->type == LITE3_TYPE_BYTES) {
1838 *out = 0;
1839 memcpy(out, &val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
1840 return ret;
1841 }
1842 *out = lite3_type_sizes[val->type];
1843 return ret;
1844}
1845#endif // DOXYGEN_IGNORE
1846
1858#define lite3_exists(buf, buflen, ofs, key) ({ \
1859 const char *__lite3_key__ = (key); \
1860 _lite3_exists_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1861})
1862#ifndef DOXYGEN_IGNORE
1863static inline bool _lite3_exists_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1864{
1865 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1866 return false;
1867 lite3_val *val;
1868 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1869 return false;
1870 return true;
1871}
1872#endif // DOXYGEN_IGNORE
1873
1882static inline int lite3_count(
1883 unsigned char *buf,
1884 size_t buflen,
1885 size_t ofs,
1886 uint32_t *out)
1887{
1888 int ret;
1889 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
1890 return ret;
1891 enum lite3_type type = (enum lite3_type)(*(buf + ofs));
1892 if (LITE3_UNLIKELY(!(type == LITE3_TYPE_OBJECT || type == LITE3_TYPE_ARRAY))) {
1893 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY OR OBJECT TYPE\n");
1894 errno = EINVAL;
1895 return -1;
1896 }
1897 *out = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1898 return ret;
1899}
1900
1912#define lite3_is_null(buf, buflen, ofs, key) ({ \
1913 const char *__lite3_key__ = (key); \
1914 _lite3_is_null_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1915})
1916#ifndef DOXYGEN_IGNORE
1917static 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)
1918{
1919 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1920 return false;
1921 lite3_val *val;
1922 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1923 return false;
1924 return val->type == LITE3_TYPE_NULL;
1925}
1926#endif // DOXYGEN_IGNORE
1927
1939#define lite3_is_bool(buf, buflen, ofs, key) ({ \
1940 const char *__lite3_key__ = (key); \
1941 _lite3_is_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1942})
1943#ifndef DOXYGEN_IGNORE
1944static 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)
1945{
1946 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1947 return false;
1948 lite3_val *val;
1949 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1950 return false;
1951 return val->type == LITE3_TYPE_BOOL;
1952}
1953#endif // DOXYGEN_IGNORE
1954
1966#define lite3_is_i64(buf, buflen, ofs, key) ({ \
1967 const char *__lite3_key__ = (key); \
1968 _lite3_is_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1969})
1970#ifndef DOXYGEN_IGNORE
1971static 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)
1972{
1973 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
1974 return false;
1975 lite3_val *val;
1976 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1977 return false;
1978 return val->type == LITE3_TYPE_I64;
1979}
1980#endif // DOXYGEN_IGNORE
1981
1993#define lite3_is_f64(buf, buflen, ofs, key) ({ \
1994 const char *__lite3_key__ = (key); \
1995 _lite3_is_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1996})
1997#ifndef DOXYGEN_IGNORE
1998static 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)
1999{
2000 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2001 return false;
2002 lite3_val *val;
2003 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2004 return false;
2005 return val->type == LITE3_TYPE_F64;
2006}
2007#endif // DOXYGEN_IGNORE
2008
2020#define lite3_is_bytes(buf, buflen, ofs, key) ({ \
2021 const char *__lite3_key__ = (key); \
2022 _lite3_is_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2023})
2024#ifndef DOXYGEN_IGNORE
2025static 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)
2026{
2027 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2028 return false;
2029 lite3_val *val;
2030 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2031 return false;
2032 return val->type == LITE3_TYPE_BYTES;
2033}
2034#endif // DOXYGEN_IGNORE
2035
2047#define lite3_is_str(buf, buflen, ofs, key) ({ \
2048 const char *__lite3_key__ = (key); \
2049 _lite3_is_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2050})
2051#ifndef DOXYGEN_IGNORE
2052static 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)
2053{
2054 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2055 return false;
2056 lite3_val *val;
2057 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2058 return false;
2059 return val->type == LITE3_TYPE_STRING;
2060}
2061#endif // DOXYGEN_IGNORE
2062
2074#define lite3_is_obj(buf, buflen, ofs, key) ({ \
2075 const char *__lite3_key__ = (key); \
2076 _lite3_is_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2077})
2078#ifndef DOXYGEN_IGNORE
2079static 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)
2080{
2081 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2082 return false;
2083 lite3_val *val;
2084 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2085 return false;
2086 return val->type == LITE3_TYPE_OBJECT;
2087}
2088#endif // DOXYGEN_IGNORE
2089
2101#define lite3_is_arr(buf, buflen, ofs, key) ({ \
2102 const char *__lite3_key__ = (key); \
2103 _lite3_is_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2104})
2105#ifndef DOXYGEN_IGNORE
2106static 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)
2107{
2108 if (_lite3_verify_obj_get(buf, buflen, ofs, key) < 0)
2109 return false;
2110 lite3_val *val;
2111 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2112 return false;
2113 return val->type == LITE3_TYPE_ARRAY;
2114}
2115#endif // DOXYGEN_IGNORE
2117
2118
2119
2154#define lite3_get(buf, buflen, ofs, key, out) ({ \
2155 const unsigned char *__lite3_buf__ = (buf); \
2156 size_t __lite3_buflen__ = (buflen); \
2157 size_t __lite3_ofs__ = (ofs); \
2158 int __lite3_ret__; \
2159 if ((__lite3_ret__ = _lite3_verify_get(__lite3_buf__, __lite3_buflen__, __lite3_ofs__) < 0)) \
2160 return __lite3_ret__; \
2161 const char *__lite3_key__ = (key); \
2162 lite3_get_impl(__lite3_buf__, __lite3_buflen__, __lite3_ofs__, __lite3_key__, LITE3_KEY_DATA(key), out); \
2163})
2164
2177#define lite3_get_bool(buf, buflen, ofs, key, out) ({ \
2178 const char *__lite3_key__ = (key); \
2179 _lite3_get_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2180})
2181#ifndef DOXYGEN_IGNORE
2182static 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)
2183{
2184 int ret;
2185 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2186 return ret;
2187 lite3_val *val;
2188 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2189 return ret;
2190 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2191 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2192 errno = EINVAL;
2193 return -1;
2194 }
2195 *out = (bool)(*(val->val));
2196 return ret;
2197}
2198#endif // DOXYGEN_IGNORE
2199
2212#define lite3_get_i64(buf, buflen, ofs, key, out) ({ \
2213 const char *__lite3_key__ = (key); \
2214 _lite3_get_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2215})
2216#ifndef DOXYGEN_IGNORE
2217static 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)
2218{
2219 int ret;
2220 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2221 return ret;
2222 lite3_val *val;
2223 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2224 return ret;
2225 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2226 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2227 errno = EINVAL;
2228 return -1;
2229 }
2230 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2231 return ret;
2232}
2233#endif // DOXYGEN_IGNORE
2234
2247#define lite3_get_f64(buf, buflen, ofs, key, out) ({ \
2248 const char *__lite3_key__ = (key); \
2249 _lite3_get_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2250})
2251#ifndef DOXYGEN_IGNORE
2252static 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)
2253{
2254 int ret;
2255 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2256 return ret;
2257 lite3_val *val;
2258 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2259 return ret;
2260 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2261 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2262 errno = EINVAL;
2263 return -1;
2264 }
2265 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2266 return ret;
2267}
2268#endif // DOXYGEN_IGNORE
2269
2282#define lite3_get_bytes(buf, buflen, ofs, key, out) ({ \
2283 const char *__lite3_key__ = (key); \
2284 _lite3_get_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2285})
2286#ifndef DOXYGEN_IGNORE
2287static 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)
2288{
2289 int ret;
2290 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2291 return ret;
2292 lite3_val *val;
2293 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2294 return ret;
2295 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2296 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2297 errno = EINVAL;
2298 return -1;
2299 }
2300 *out = (lite3_bytes){
2301 .gen = *(uint32_t *)buf,
2302 .len = 0,
2303 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2304 };
2305 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2306 return ret;
2307}
2308#endif // DOXYGEN_IGNORE
2309
2322#define lite3_get_str(buf, buflen, ofs, key, out) ({ \
2323 const char *__lite3_key__ = (key); \
2324 _lite3_get_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2325})
2326#ifndef DOXYGEN_IGNORE
2327static 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)
2328{
2329 int ret;
2330 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2331 return ret;
2332 lite3_val *val;
2333 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2334 return ret;
2335 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2336 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2337 errno = EINVAL;
2338 return -1;
2339 }
2340 *out = (lite3_str){
2341 .gen = *(uint32_t *)buf,
2342 .len = 0,
2343 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2344 };
2345 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2346 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2347 return ret;
2348}
2349#endif // DOXYGEN_IGNORE
2350
2363#define lite3_get_obj(buf, buflen, ofs, key, out) ({ \
2364 const char *__lite3_key__ = (key); \
2365 _lite3_get_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2366})
2367#ifndef DOXYGEN_IGNORE
2368static 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)
2369{
2370 int ret;
2371 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2372 return ret;
2373 lite3_val *val;
2374 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2375 return ret;
2376 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2377 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2378 errno = EINVAL;
2379 return -1;
2380 }
2381 *out_ofs = (size_t)((uint8_t *)val - buf);
2382 return ret;
2383}
2384#endif // DOXYGEN_IGNORE
2385
2398#define lite3_get_arr(buf, buflen, ofs, key, out) ({ \
2399 const char *__lite3_key__ = (key); \
2400 _lite3_get_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2401})
2402#ifndef DOXYGEN_IGNORE
2403static 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)
2404{
2405 int ret;
2406 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs, key)) < 0)
2407 return ret;
2408 lite3_val *val;
2409 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2410 return ret;
2411 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2412 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2413 errno = EINVAL;
2414 return -1;
2415 }
2416 *out_ofs = (size_t)((uint8_t *)val - buf);
2417 return ret;
2418}
2419#endif // DOXYGEN_IGNORE
2421
2422
2423
2448static inline int lite3_arr_get_bool(
2449 const unsigned char *buf,
2450 size_t buflen,
2451 size_t ofs,
2452 uint32_t index,
2453 bool *out)
2454{
2455 lite3_val *val;
2456 int ret;
2457 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2458 return ret;
2459 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2460 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2461 errno = EINVAL;
2462 return -1;
2463 }
2464 *out = (bool)(*(val->val));
2465 return ret;
2466}
2467
2474static inline int lite3_arr_get_i64(
2475 const unsigned char *buf,
2476 size_t buflen,
2477 size_t ofs,
2478 uint32_t index,
2479 int64_t *out)
2480{
2481 lite3_val *val;
2482 int ret;
2483 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2484 return ret;
2485 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2486 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2487 errno = EINVAL;
2488 return -1;
2489 }
2490 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2491 return ret;
2492}
2493
2500static inline int lite3_arr_get_f64(
2501 const unsigned char *buf,
2502 size_t buflen,
2503 size_t ofs,
2504 uint32_t index,
2505 double *out)
2506{
2507 lite3_val *val;
2508 int ret;
2509 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2510 return ret;
2511 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2512 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2513 errno = EINVAL;
2514 return -1;
2515 }
2516 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2517 return ret;
2518}
2519
2526static inline int lite3_arr_get_bytes(
2527 const unsigned char *buf,
2528 size_t buflen,
2529 size_t ofs,
2530 uint32_t index,
2531 lite3_bytes *out)
2532{
2533 lite3_val *val;
2534 int ret;
2535 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2536 return ret;
2537 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2538 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2539 errno = EINVAL;
2540 return -1;
2541 }
2542 *out = (lite3_bytes){
2543 .gen = *(uint32_t *)buf,
2544 .len = 0,
2545 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2546 };
2547 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2548 return ret;
2549}
2550
2557static inline int lite3_arr_get_str(
2558 const unsigned char *buf,
2559 size_t buflen,
2560 size_t ofs,
2561 uint32_t index,
2562 lite3_str *out)
2563{
2564 lite3_val *val;
2565 int ret;
2566 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2567 return ret;
2568 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2569 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2570 errno = EINVAL;
2571 return -1;
2572 }
2573 *out = (lite3_str){
2574 .gen = *(uint32_t *)buf,
2575 .len = 0,
2576 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2577 };
2578 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2579 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2580 return ret;
2581}
2582
2589static inline int lite3_arr_get_obj(
2590 const unsigned char *buf,
2591 size_t buflen,
2592 size_t ofs,
2593 uint32_t index,
2594 size_t *__restrict out_ofs)
2595{
2596 lite3_val *val;
2597 int ret;
2598 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2599 return ret;
2600 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2601 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2602 errno = EINVAL;
2603 return -1;
2604 }
2605 *out_ofs = (size_t)((uint8_t *)val - buf);
2606 return ret;
2607}
2608
2615static inline int lite3_arr_get_arr(
2616 const unsigned char *buf,
2617 size_t buflen,
2618 size_t ofs,
2619 uint32_t index,
2620 size_t *__restrict out_ofs)
2621{
2622 lite3_val *val;
2623 int ret;
2624 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2625 return ret;
2626 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2627 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2628 errno = EINVAL;
2629 return -1;
2630 }
2631 *out_ofs = (size_t)((uint8_t *)val - buf);
2632 return ret;
2633}
2635
2636
2637
2654#define LITE3_ITER_ITEM 1
2656#define LITE3_ITER_DONE 0
2657
2664typedef struct {
2665 uint32_t gen;
2666 uint32_t node_ofs[LITE3_TREE_HEIGHT_MAX + 1];
2667 uint8_t depth;
2668 uint8_t node_i[LITE3_TREE_HEIGHT_MAX + 1];
2669} lite3_iter;
2670
2671#ifndef DOXYGEN_IGNORE
2672// Private function
2673int lite3_iter_create_impl(const unsigned char *buf, size_t buflen, size_t ofs, lite3_iter *out);
2674#endif // DOXYGEN_IGNORE
2675
2682static inline int lite3_iter_create(
2683 const unsigned char *buf,
2684 size_t buflen,
2685 size_t ofs,
2686 lite3_iter *out)
2687{
2688 int ret;
2689 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
2690 return ret;
2691 return lite3_iter_create_impl(buf, buflen, ofs, out);
2692}
2693
2710int lite3_iter_next(
2711 const unsigned char *buf,
2712 size_t buflen,
2713 lite3_iter *iter,
2714 lite3_str *out_key,
2715 size_t *out_val_ofs
2716);
2718
2719
2720
2732static inline enum lite3_type lite3_val_type(lite3_val *val)
2733{
2734 enum lite3_type type = (enum lite3_type)val->type;
2735 return type < LITE3_TYPE_INVALID ? type : LITE3_TYPE_INVALID;
2736}
2737
2747static inline size_t lite3_val_type_size(lite3_val *val)
2748{
2749 enum lite3_type type = (enum lite3_type)val->type;
2750 if (type == LITE3_TYPE_STRING || type == LITE3_TYPE_BYTES) {
2751 size_t tmp = 0;
2752 memcpy(&tmp, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2753 return tmp;
2754 }
2755 return lite3_type_sizes[val->type];
2756}
2757
2758static inline bool lite3_val_is_null(lite3_val *val) { return val->type == LITE3_TYPE_NULL; }
2759static inline bool lite3_val_is_bool(lite3_val *val) { return val->type == LITE3_TYPE_BOOL; }
2760static inline bool lite3_val_is_i64(lite3_val *val) { return val->type == LITE3_TYPE_I64; }
2761static inline bool lite3_val_is_f64(lite3_val *val) { return val->type == LITE3_TYPE_F64; }
2762static inline bool lite3_val_is_bytes(lite3_val *val) { return val->type == LITE3_TYPE_BYTES; }
2763static inline bool lite3_val_is_str(lite3_val *val) { return val->type == LITE3_TYPE_STRING; }
2764static inline bool lite3_val_is_obj(lite3_val *val) { return val->type == LITE3_TYPE_OBJECT; }
2765static inline bool lite3_val_is_arr(lite3_val *val) { return val->type == LITE3_TYPE_ARRAY; }
2766
2767static inline bool lite3_val_bool(lite3_val *val)
2768{
2769 return *(bool *)(val->val);
2770}
2771
2772static inline int64_t lite3_val_i64(lite3_val *val)
2773{
2774 int64_t tmp;
2775 memcpy(&tmp, val->val, sizeof(tmp));
2776 return tmp;
2777}
2778
2779static inline double lite3_val_f64(lite3_val *val)
2780{
2781 double tmp;
2782 memcpy(&tmp, val->val, sizeof(tmp));
2783 return tmp;
2784}
2785
2786static inline const char *lite3_val_str(lite3_val *val)
2787{
2788 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2789}
2790
2795static inline const char *lite3_val_str_n(lite3_val *val, size_t *out_len)
2796{
2797 *out_len = 0;
2798 memcpy(out_len, val->val, LITE3_STR_LEN_SIZE);
2799 *out_len -= 1; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2800 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2801}
2802
2803static inline const unsigned char *lite3_val_bytes(lite3_val *val, size_t *out_len)
2804{
2805 *out_len = 0;
2806 memcpy(out_len, val->val, LITE3_BYTES_LEN_SIZE);
2807 return (const unsigned char *)val->val + LITE3_BYTES_LEN_SIZE;
2808}
2810
2811
2812
2849#define LITE3_JSON
2850
2851#if defined(DOXYGEN_ONLY) && !defined(LITE3_JSON)
2852#define LITE3_JSON
2853#endif // DOXYGEN_ONLY
2854
2855#ifdef LITE3_JSON
2856#include <stdio.h>
2857
2866#define LITE3_JSON_NESTING_DEPTH_MAX 32
2867
2880 unsigned char *buf,
2881 size_t *__restrict out_buflen,
2882 size_t bufsz,
2883 const char *__restrict json_str,
2884 size_t json_len
2885);
2886
2899 unsigned char *buf,
2900 size_t *__restrict out_buflen,
2901 size_t bufsz,
2902 const char *__restrict path
2903);
2904
2917 unsigned char *buf,
2918 size_t *__restrict out_buflen,
2919 size_t bufsz,
2920 FILE *fp
2921);
2922
2937 const unsigned char *buf,
2938 size_t buflen,
2939 size_t ofs
2940);
2941
2956 const unsigned char *buf,
2957 size_t buflen,
2958 size_t ofs,
2959 size_t *__restrict out_len
2960);
2961
2978 const unsigned char *buf,
2979 size_t buflen,
2980 size_t ofs,
2981 size_t *__restrict out_len
2982);
2983
2995 const unsigned char *buf,
2996 size_t buflen,
2997 size_t ofs,
2998 char *__restrict json_buf,
2999 size_t json_bufsz
3000);
3001
3015 const unsigned char *buf,
3016 size_t buflen,
3017 size_t ofs,
3018 char *__restrict json_buf,
3019 size_t json_bufsz
3020);
3021#else
3022static 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)
3023{
3024 (void)buf; (void)out_buflen; (void)bufsz; (void)json_str; (void)json_len;
3025 return -1;
3026}
3027
3028static inline int lite3_json_dec_file(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, const char *__restrict path)
3029{
3030 (void)buf; (void)out_buflen; (void)bufsz; (void)path;
3031 return -1;
3032}
3033
3034static inline int lite3_json_dec_fp(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, FILE *fp)
3035{
3036 (void)buf; (void)out_buflen; (void)bufsz; (void)fp;
3037 return -1;
3038}
3039
3040static inline int lite3_json_print(const unsigned char *buf, size_t buflen, size_t ofs)
3041{
3042 (void)buf; (void)buflen; (void)ofs;
3043 return 0;
3044}
3045
3046static inline char *lite3_json_enc(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3047{
3048 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3049 return NULL;
3050}
3051
3052static inline char *lite3_json_enc_pretty(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3053{
3054 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3055 return NULL;
3056}
3057
3058static 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)
3059{
3060 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3061 return -1;
3062}
3063
3064static 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)
3065{
3066 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3067 return -1;
3068}
3069#endif
3071
3072#ifdef __cplusplus
3073}
3074#endif
3075
3076#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:1255
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:1211
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:1332
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:1191
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:1388
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:1233
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:1277
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:1363
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:1305
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:2589
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:2474
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:2448
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:2500
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:2557
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:2526
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:2615
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:1441
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:1620
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:1588
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:1485
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:1560
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:1462
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:1531
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:1646
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:1508
#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:369
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:2682
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:1754
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:1882
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:1799
static size_t lite3_val_type_size(lite3_val *val)
Returns the size of the value type.
Definition lite3.h:2747
static const char * lite3_val_str_n(lite3_val *val, size_t *out_len)
Definition lite3.h:2795
static enum lite3_type lite3_val_type(lite3_val *val)
Returns the value type of *val
Definition lite3.h:2732
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:2664
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