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
299#define LITE3_NODE_ALIGNMENT 4
300// #define LITE3_NODE_ALIGNMENT 8
301// #define LITE3_NODE_ALIGNMENT 16
302// #define LITE3_NODE_ALIGNMENT 32
303// #define LITE3_NODE_ALIGNMENT 64
304
305#ifndef DOXYGEN_IGNORE
306#define LITE3_NODE_ALIGNMENT_MASK ((uintptr_t)(LITE3_NODE_ALIGNMENT - 1))
307#endif // DOXYGEN_IGNORE
308
320// #define LITE3_NODE_SIZE 48 // key_count: 0-3 LITE3_NODE_SIZE: 48 (0.75 cache lines)
321#define LITE3_NODE_SIZE 96 // key_count: 0-7 LITE3_NODE_SIZE: 96 (1.5 cache lines)
322// #define LITE3_NODE_SIZE 192 // key_count: 0-15 LITE3_NODE_SIZE: 192 (3 cache lines)
323// #define LITE3_NODE_SIZE 384 // key_count: 0-31 LITE3_NODE_SIZE: 384 (6 cache lines)
324// #define LITE3_NODE_SIZE 768 // key_count: 0-63 LITE3_NODE_SIZE: 768 (12 cache lines)
325
335// #define LITE3_TREE_HEIGHT_MAX 14 // key_count: 0-3 LITE3_NODE_SIZE: 48 (0.75 cache lines)
336#define LITE3_TREE_HEIGHT_MAX 9 // key_count: 0-7 LITE3_NODE_SIZE: 96 (1.5 cache lines)
337// #define LITE3_TREE_HEIGHT_MAX 7 // key_count: 0-15 LITE3_NODE_SIZE: 192 (3 cache lines)
338// #define LITE3_TREE_HEIGHT_MAX 5 // key_count: 0-31 LITE3_NODE_SIZE: 384 (6 cache lines)
339// #define LITE3_TREE_HEIGHT_MAX 4 // key_count: 0-63 LITE3_NODE_SIZE: 768 (12 cache lines)
340
349// #define LITE3_NODE_SIZE_KC_OFFSET 16 // key_count: 0-3 LITE3_NODE_SIZE: 48 (0.75 cache lines)
350#define LITE3_NODE_SIZE_KC_OFFSET 32 // key_count: 0-7 LITE3_NODE_SIZE: 96 (1.5 cache lines)
351// #define LITE3_NODE_SIZE_KC_OFFSET 64 // key_count: 0-15 LITE3_NODE_SIZE: 192 (3 cache lines)
352// #define LITE3_NODE_SIZE_KC_OFFSET 128 // key_count: 0-31 LITE3_NODE_SIZE: 384 (6 cache lines)
353// #define LITE3_NODE_SIZE_KC_OFFSET 256 // key_count: 0-63 LITE3_NODE_SIZE: 768 (12 cache lines)
354
355#ifndef DOXYGEN_IGNORE
356#define LITE3_NODE_SIZE_SHIFT 6
357#define LITE3_NODE_SIZE_MASK ((u32)~((1 << 6) - 1)) // 26 MSB
358
359#define LITE3_DJB2_HASH_SEED ((uint32_t)5381)
360#endif // DOXYGEN_IGNORE
361
369#ifndef LITE3_HASH_PROBE_MAX
370#define LITE3_HASH_PROBE_MAX 128U
371#endif
372
373#if LITE3_HASH_PROBE_MAX < 2
374 #error "LITE3_HASH_PROBE_MAX must be >= 2"
375#endif
376
377#define LITE3_VERIFY_KEY_OK 0
378#define LITE3_VERIFY_KEY_HASH_COLLISION 1
379
393#define LITE3_KEY_HASH_COMPILE_TIME
394
395#ifndef DOXYGEN_IGNORE
396#ifdef LITE3_KEY_HASH_COMPILE_TIME
397#define LITE3_MOD 4294967296ULL
398
399#define LITE3_P0 33ULL
400#define LITE3_P1 ((LITE3_P0 * LITE3_P0) % LITE3_MOD)
401#define LITE3_P2 ((LITE3_P1 * LITE3_P1) % LITE3_MOD)
402#define LITE3_P3 ((LITE3_P2 * LITE3_P2) % LITE3_MOD)
403#define LITE3_P4 ((LITE3_P3 * LITE3_P3) % LITE3_MOD)
404#define LITE3_P5 ((LITE3_P4 * LITE3_P4) % LITE3_MOD)
405
406#define LITE3_BIT0(k) (((k) >> 0) & 1ULL)
407#define LITE3_BIT1(k) (((k) >> 1) & 1ULL)
408#define LITE3_BIT2(k) (((k) >> 2) & 1ULL)
409#define LITE3_BIT3(k) (((k) >> 3) & 1ULL)
410#define LITE3_BIT4(k) (((k) >> 4) & 1ULL)
411#define LITE3_BIT5(k) (((k) >> 5) & 1ULL)
412
413#define LITE3_POW33(k) \
414 ((((((1ULL \
415 * (LITE3_BIT0(k) ? LITE3_P0 : 1ULL) \
416 ) % LITE3_MOD \
417 * (LITE3_BIT1(k) ? LITE3_P1 : 1ULL) \
418 ) % LITE3_MOD \
419 * (LITE3_BIT2(k) ? LITE3_P2 : 1ULL) \
420 ) % LITE3_MOD \
421 * (LITE3_BIT3(k) ? LITE3_P3 : 1ULL) \
422 ) % LITE3_MOD \
423 * (LITE3_BIT4(k) ? LITE3_P4 : 1ULL) \
424 ) % LITE3_MOD \
425 * (LITE3_BIT5(k) ? LITE3_P5 : 1ULL) \
426 ) % LITE3_MOD
427
428#define LITE3_SUM_1(s, i, p) \
429 ((unsigned long long)(unsigned char)(s)[(i)] * LITE3_POW33((p)))
430
431#define LITE3_SUM_2(s, i, p) \
432 (LITE3_SUM_1(s, (i), (p)) + LITE3_SUM_1(s, (i) + 1, (p) - 1))
433
434#define LITE3_SUM_4(s, i, p) \
435 (LITE3_SUM_2(s, (i), (p)) + LITE3_SUM_2(s, (i) + 2, (p) - 2))
436
437#define LITE3_SUM_8(s, i, p) \
438 (LITE3_SUM_4(s, (i), (p)) + LITE3_SUM_4(s, (i) + 4, (p) - 4))
439
440#define LITE3_SUM_16(s, i, p) \
441 (LITE3_SUM_8(s, (i), (p)) + LITE3_SUM_8(s, (i) + 8, (p) - 8))
442
443#define LITE3_SUM_32(s, i, p) \
444 (LITE3_SUM_16(s, (i), (p)) + LITE3_SUM_16(s, (i) + 16, (p) - 16))
445
446#define LITE3_OFFSET_BIT0(len) \
447 (((len & 2ULL) ? 2ULL : 0ULL) + \
448 ((len & 4ULL) ? 4ULL : 0ULL) + \
449 ((len & 8ULL) ? 8ULL : 0ULL) + \
450 ((len & 16ULL) ? 16ULL : 0ULL) + \
451 ((len & 32ULL) ? 32ULL : 0ULL))
452
453#define LITE3_OFFSET_BIT1(len) \
454 (((len & 4ULL) ? 4ULL : 0ULL) + \
455 ((len & 8ULL) ? 8ULL : 0ULL) + \
456 ((len & 16ULL) ? 16ULL : 0ULL) + \
457 ((len & 32ULL) ? 32ULL : 0ULL))
458
459#define LITE3_OFFSET_BIT2(len) \
460 (((len & 8ULL) ? 8ULL : 0ULL) + \
461 ((len & 16ULL) ? 16ULL : 0ULL) + \
462 ((len & 32ULL) ? 32ULL : 0ULL))
463
464#define LITE3_OFFSET_BIT3(len) \
465 (((len & 16ULL) ? 16ULL : 0ULL) + \
466 ((len & 32ULL) ? 32ULL : 0ULL))
467
468#define LITE3_OFFSET_BIT4(len) \
469 (((len & 32ULL) ? 32ULL : 0ULL))
470
471#define LITE3_OFFSET_BIT5(len) \
472 (0ULL)
473
474#define LITE3_POLY_HASH(s, len) \
475 ((len) & 1ULL ? LITE3_SUM_1(s, LITE3_OFFSET_BIT0((len)), (len) - 1 - LITE3_OFFSET_BIT0((len))) : 0ULL) + \
476 ((len) & 2ULL ? LITE3_SUM_2(s, LITE3_OFFSET_BIT1((len)), (len) - 1 - LITE3_OFFSET_BIT1((len))) : 0ULL) + \
477 ((len) & 4ULL ? LITE3_SUM_4(s, LITE3_OFFSET_BIT2((len)), (len) - 1 - LITE3_OFFSET_BIT2((len))) : 0ULL) + \
478 ((len) & 8ULL ? LITE3_SUM_8(s, LITE3_OFFSET_BIT3((len)), (len) - 1 - LITE3_OFFSET_BIT3((len))) : 0ULL) + \
479 ((len) & 16ULL ? LITE3_SUM_16(s, LITE3_OFFSET_BIT4((len)), (len) - 1 - LITE3_OFFSET_BIT4((len))) : 0ULL) + \
480 ((len) & 32ULL ? LITE3_SUM_32(s, LITE3_OFFSET_BIT5((len)), (len) - 1 - LITE3_OFFSET_BIT5((len))) : 0ULL)
481
482#define LITE3_STRLEN(s) (sizeof(s) - 1)
483
484typedef struct {
485 uint32_t hash;
486 uint32_t size;
487} lite3_key_data;
488
489static inline lite3_key_data lite3_get_key_data(const char *key) {
490 lite3_key_data key_data;
491 const char *key_cursor = key;
492 key_data.hash = LITE3_DJB2_HASH_SEED;
493 while (*key_cursor)
494 key_data.hash = ((key_data.hash << 5) + key_data.hash) + (uint8_t)(*key_cursor++);
495 key_data.size = (uint32_t)(key_cursor - key) + 1;
496 return key_data;
497}
498
499#define LITE3_KEY_DATA(s) ( \
500 __builtin_constant_p(s) ? \
501 ((LITE3_STRLEN(s) < 64) ? \
502 (lite3_key_data){ \
503 .hash = (uint32_t)((LITE3_POLY_HASH(s, LITE3_STRLEN(s)) + LITE3_DJB2_HASH_SEED * LITE3_POW33(LITE3_STRLEN(s))) % LITE3_MOD), \
504 .size = (sizeof(s)), \
505 } \
506 : lite3_get_key_data(s)) \
507 : lite3_get_key_data(__lite3_key__) \
508)
509#else
510#define LITE3_KEY_DATA(s) lite3_get_key_data(__lite3_key__)
511#endif
512#endif // DOXYGEN_IGNORE
514
515
516
540
549typedef struct {
550 uint8_t type;
551 uint8_t val[];
552} lite3_val;
553
554#ifndef DOXYGEN_IGNORE
555#define LITE3_VAL_SIZE sizeof(lite3_val)
556#endif // DOXYGEN_IGNORE
557static_assert(LITE3_VAL_SIZE <= sizeof(size_t), "LITE3_VAL_SIZE must be <= sizeof(size_t)");
558
559#ifndef DOXYGEN_IGNORE
560static const size_t lite3_type_sizes[] = {
561 0, // LITE3_TYPE_NULL
562 1, // LITE3_TYPE_BOOL
563 8, // LITE3_TYPE_I64
564 8, // LITE3_TYPE_F64
565 4, // LITE3_TYPE_BYTES (this value must be <= sizeof(size_t))
566 4, // LITE3_TYPE_STRING (this value must be <= sizeof(size_t))
567 LITE3_NODE_SIZE - LITE3_VAL_SIZE, // LITE3_TYPE_OBJECT (`type` field is contained inside node->gen_type)
568 LITE3_NODE_SIZE - LITE3_VAL_SIZE, // LITE3_TYPE_ARRAY (`type` field is contained inside node->gen_type)
569 0, // LITE3_TYPE_INVALID
570};
571#endif // DOXYGEN_IGNORE
572static_assert((sizeof(lite3_type_sizes) / sizeof(size_t)) == LITE3_TYPE_COUNT, "lite3_type_sizes[] element count != LITE3_TYPE_COUNT");
573static_assert(4 <= sizeof(size_t), "lite3_type_sizes[LITE3_TYPE_BYTES] and lite3_type_sizes[LITE3_TYPE_STRING] must fit inside size_t");
574
590typedef struct {
591 uint32_t gen;
592 uint32_t len;
593 const unsigned char *ptr;
595
596#ifndef DOXYGEN_IGNORE
597#define LITE3_BYTES_LEN_SIZE sizeof(((lite3_bytes *)0)->len)
598#endif // DOXYGEN_IGNORE
599static_assert(LITE3_BYTES_LEN_SIZE <= sizeof(size_t), "lite3_val_bytes() expects LITE3_BYTES_LEN_SIZE to be <= sizeof(size_t)");
600
619typedef struct {
620 uint32_t gen;
621 uint32_t len;
622 const char *ptr;
623} lite3_str;
624
625#ifndef DOXYGEN_IGNORE
626#define LITE3_STR_LEN_SIZE sizeof(((lite3_str *)0)->len)
627#endif // DOXYGEN_IGNORE
628static_assert(LITE3_STR_LEN_SIZE <= sizeof(size_t), "lite3_val_str() expects LITE3_STR_LEN_SIZE to be <= sizeof(size_t)");
629
655#define LITE3_BYTES(buf, val) (const unsigned char *)_lite3_ptr_suppress_nonnull_warning( \
656 (uint32_t)(val).gen == *(uint32_t *)(buf) ? (val).ptr : NULL \
657)
658
684#define LITE3_STR(buf, val) (const char *)_lite3_ptr_suppress_nonnull_warning( \
685 (uint32_t)(val).gen == *(uint32_t *)(buf) ? (val).ptr : NULL \
686)
687
688#ifndef DOXYGEN_IGNORE
689static inline __attribute__((always_inline)) const void *_lite3_ptr_suppress_nonnull_warning(const void *p) { return p; }
690#endif // DOXYGEN_IGNORE
692
693
694
719 unsigned char *buf,
720 size_t *__restrict out_buflen,
721 size_t bufsz
722);
723
737 unsigned char *buf,
738 size_t *__restrict out_buflen,
739 size_t bufsz
740);
742
743
744
775#ifndef DOXYGEN_IGNORE
776static inline int _lite3_verify_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
777{
778 (void)buf;
779 if (LITE3_UNLIKELY(bufsz > LITE3_BUF_SIZE_MAX)) {
780 LITE3_PRINT_ERROR("INVALID ARGUMENT: bufsz > LITE3_BUF_SIZE_MAX\n");
781 errno = EINVAL;
782 return -1;
783 }
784 if (LITE3_UNLIKELY(*inout_buflen > bufsz)) {
785 LITE3_PRINT_ERROR("INVALID ARGUMENT: inout_buflen > bufsz\n");
786 errno = EINVAL;
787 return -1;
788 }
789 if (LITE3_UNLIKELY(LITE3_NODE_SIZE > *inout_buflen || ofs > *inout_buflen - LITE3_NODE_SIZE)) {
790 LITE3_PRINT_ERROR("INVALID ARGUMENT: START OFFSET OUT OF BOUNDS\n");
791 errno = EINVAL;
792 return -1;
793 }
794 return 0;
795}
796
797static inline int _lite3_verify_obj_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
798{
799 int ret;
800 if ((ret = _lite3_verify_set(buf, inout_buflen, ofs, bufsz)) < 0)
801 return ret;
802 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_OBJECT)) {
803 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING OBJECT TYPE\n");
804 errno = EINVAL;
805 return -1;
806 }
807 return ret;
808}
809
810static inline int _lite3_verify_arr_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
811{
812 int ret;
813 if ((ret = _lite3_verify_set(buf, inout_buflen, ofs, bufsz)) < 0)
814 return ret;
815 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_ARRAY)) {
816 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY TYPE\n");
817 errno = EINVAL;
818 return -1;
819 }
820 return ret;
821}
822
823// Private function
824int 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);
825#endif // DOXYGEN_IGNORE
826
839#define lite3_set_null(buf, inout_buflen, ofs, bufsz, key) ({ \
840 const char *__lite3_key__ = (key); \
841 _lite3_set_null_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key)); \
842})
843#ifndef DOXYGEN_IGNORE
844static 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)
845{
846 int ret;
847 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
848 return ret;
849 lite3_val *val;
850 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
851 return ret;
852 val->type = (uint8_t)LITE3_TYPE_NULL;
853 return ret;
854}
855#endif // DOXYGEN_IGNORE
856
870#define lite3_set_bool(buf, inout_buflen, ofs, bufsz, key, value) ({ \
871 const char *__lite3_key__ = (key); \
872 _lite3_set_bool_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
873})
874#ifndef DOXYGEN_IGNORE
875static 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)
876{
877 int ret;
878 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
879 return ret;
880 lite3_val *val;
881 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
882 return ret;
883 val->type = (uint8_t)LITE3_TYPE_BOOL;
884 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
885 return ret;
886}
887#endif // DOXYGEN_IGNORE
888
902#define lite3_set_i64(buf, inout_buflen, ofs, bufsz, key, value) ({ \
903 const char *__lite3_key__ = (key); \
904 _lite3_set_i64_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
905})
906#ifndef DOXYGEN_IGNORE
907static 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)
908{
909 int ret;
910 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
911 return ret;
912 lite3_val *val;
913 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
914 return ret;
915 val->type = (uint8_t)LITE3_TYPE_I64;
916 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
917 return ret;
918}
919#endif // DOXYGEN_IGNORE
920
934#define lite3_set_f64(buf, inout_buflen, ofs, bufsz, key, value) ({ \
935 const char *__lite3_key__ = (key); \
936 _lite3_set_f64_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
937})
938#ifndef DOXYGEN_IGNORE
939static 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)
940{
941 int ret;
942 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
943 return ret;
944 lite3_val *val;
945 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
946 return ret;
947 val->type = (uint8_t)LITE3_TYPE_F64;
948 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
949 return ret;
950}
951#endif // DOXYGEN_IGNORE
952
967#define lite3_set_bytes(buf, inout_buflen, ofs, bufsz, key, bytes, bytes_len) ({ \
968 const char *__lite3_key__ = (key); \
969 _lite3_set_bytes_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), bytes, bytes_len); \
970})
971#ifndef DOXYGEN_IGNORE
972static 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)
973{
974 int ret;
975 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
976 return ret;
977 lite3_val *val;
978 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
979 return ret;
980 val->type = (uint8_t)LITE3_TYPE_BYTES;
981 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
982 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
983 return ret;
984}
985#endif // DOXYGEN_IGNORE
986
1004#define lite3_set_str(buf, inout_buflen, ofs, bufsz, key, str) ({ \
1005 const char *__lite3_key__ = (key); \
1006 _lite3_set_str_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), str); \
1007})
1008#ifndef DOXYGEN_IGNORE
1009static 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)
1010{
1011 int ret;
1012 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
1013 return ret;
1014 lite3_val *val;
1015 size_t str_size = strlen(str) + 1;
1016 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1017 return ret;
1018 val->type = (uint8_t)LITE3_TYPE_STRING;
1019 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1020 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1021 return ret;
1022}
1023#endif // DOXYGEN_IGNORE
1024
1042#define lite3_set_str_n(buf, inout_buflen, ofs, bufsz, key, str, str_len) ({ \
1043 const char *__lite3_key__ = (key); \
1044 _lite3_set_str_n_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), str, str_len); \
1045})
1046#ifndef DOXYGEN_IGNORE
1047static 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)
1048{
1049 int ret;
1050 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
1051 return ret;
1052 lite3_val *val;
1053 size_t str_size = str_len + 1;
1054 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1055 return ret;
1056 val->type = (uint8_t)LITE3_TYPE_STRING;
1057 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1058 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1059 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1060 return ret;
1061}
1062#endif // DOXYGEN_IGNORE
1063
1077#define lite3_set_obj(buf, inout_buflen, ofs, bufsz, key, out_ofs) ({ \
1078 unsigned char *__lite3_buf__ = (buf); \
1079 size_t *__lite3_inout_buflen__ = (inout_buflen); \
1080 size_t __lite3_ofs__ = (ofs); \
1081 size_t __lite3_bufsz__ = (bufsz); \
1082 int __lite3_ret__; \
1083 if ((__lite3_ret__ = _lite3_verify_obj_set( \
1084 __lite3_buf__, \
1085 __lite3_inout_buflen__, \
1086 __lite3_ofs__, \
1087 __lite3_bufsz__)) < 0) \
1088 return __lite3_ret__; \
1089 \
1090 const char *__lite3_key__ = (key); \
1091 lite3_set_obj_impl( \
1092 __lite3_buf__, \
1093 __lite3_inout_buflen__, \
1094 __lite3_ofs__, \
1095 __lite3_bufsz__, \
1096 __lite3_key__, \
1097 LITE3_KEY_DATA(key), \
1098 out_ofs); \
1099})
1100#ifndef DOXYGEN_IGNORE
1101// Private function
1102int 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);
1103#endif // DOXYGEN_IGNORE
1104
1118#define lite3_set_arr(buf, inout_buflen, ofs, bufsz, key, out_ofs) ({ \
1119 unsigned char *__lite3_buf__ = (buf); \
1120 size_t *__lite3_inout_buflen__ = (inout_buflen); \
1121 size_t __lite3_ofs__ = (ofs); \
1122 size_t __lite3_bufsz__ = (bufsz); \
1123 int __lite3_ret__; \
1124 if ((__lite3_ret__ = _lite3_verify_obj_set( \
1125 __lite3_buf__, \
1126 __lite3_inout_buflen__, \
1127 __lite3_ofs__, \
1128 __lite3_bufsz__)) < 0) \
1129 return __lite3_ret__; \
1130 \
1131 const char *__lite3_key__ = (key); \
1132 lite3_set_arr_impl( \
1133 __lite3_buf__, \
1134 __lite3_inout_buflen__, \
1135 __lite3_ofs__, \
1136 __lite3_bufsz__, \
1137 __lite3_key__, \
1138 LITE3_KEY_DATA(key), \
1139 out_ofs); \
1140})
1141#ifndef DOXYGEN_IGNORE
1142// Private function
1143int 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);
1144#endif // DOXYGEN_IGNORE
1146
1147
1148
1173#ifndef DOXYGEN_IGNORE
1174static 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)
1175{
1176 int ret;
1177 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1178 return ret;
1179 uint32_t size = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1180 if (LITE3_UNLIKELY(index > size)) {
1181 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1182 errno = EINVAL;
1183 return -1;
1184 }
1185 lite3_key_data key_data = {
1186 .hash = index,
1187 .size = 0,
1188 };
1189 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1190}
1191
1192static 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)
1193{
1194 int ret;
1195 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1196 return ret;
1197 uint32_t size = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1198 lite3_key_data key_data = {
1199 .hash = size,
1200 .size = 0,
1201 };
1202 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1203}
1204#endif // DOXYGEN_IGNORE
1205
1212static inline int lite3_arr_append_null(
1213 unsigned char *buf,
1214 size_t *__restrict inout_buflen,
1215 size_t ofs,
1216 size_t bufsz)
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_NULL], &val)) < 0)
1221 return ret;
1222 val->type = (uint8_t)LITE3_TYPE_NULL;
1223 return ret;
1224}
1225
1232static inline int lite3_arr_append_bool(
1233 unsigned char *buf,
1234 size_t *__restrict inout_buflen,
1235 size_t ofs,
1236 size_t bufsz,
1237 bool value)
1238{
1239 lite3_val *val;
1240 int ret;
1241 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1242 return ret;
1243 val->type = (uint8_t)LITE3_TYPE_BOOL;
1244 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1245 return ret;
1246}
1247
1254static inline int lite3_arr_append_i64(
1255 unsigned char *buf,
1256 size_t *__restrict inout_buflen,
1257 size_t ofs,
1258 size_t bufsz,
1259 int64_t value)
1260{
1261 lite3_val *val;
1262 int ret;
1263 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1264 return ret;
1265 val->type = (uint8_t)LITE3_TYPE_I64;
1266 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1267 return ret;
1268}
1269
1276static inline int lite3_arr_append_f64(
1277 unsigned char *buf,
1278 size_t *__restrict inout_buflen,
1279 size_t ofs,
1280 size_t bufsz,
1281 double value)
1282{
1283 lite3_val *val;
1284 int ret;
1285 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1286 return ret;
1287 val->type = (uint8_t)LITE3_TYPE_F64;
1288 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1289 return ret;
1290}
1291
1298static inline int lite3_arr_append_bytes(
1299 unsigned char *buf,
1300 size_t *__restrict inout_buflen,
1301 size_t ofs,
1302 size_t bufsz,
1303 const unsigned char *__restrict bytes,
1304 size_t bytes_len)
1305{
1306 lite3_val *val;
1307 int ret;
1308 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1309 return ret;
1310 val->type = (uint8_t)LITE3_TYPE_BYTES;
1311 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1312 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1313 return ret;
1314}
1315
1326static inline int lite3_arr_append_str(
1327 unsigned char *buf,
1328 size_t *__restrict inout_buflen,
1329 size_t ofs,
1330 size_t bufsz,
1331 const char *__restrict str)
1332{
1333 lite3_val *val;
1334 size_t str_size = strlen(str) + 1;
1335 int ret;
1336 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1337 return ret;
1338 val->type = (uint8_t)LITE3_TYPE_STRING;
1339 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1340 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1341 return ret;
1342}
1343
1353static inline int lite3_arr_append_str_n(
1354 unsigned char *buf,
1355 size_t *__restrict inout_buflen,
1356 size_t ofs,
1357 size_t bufsz,
1358 const char *__restrict str,
1359 size_t str_len)
1360{
1361 lite3_val *val;
1362 size_t str_size = str_len + 1;
1363 int ret;
1364 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1365 return ret;
1366 val->type = (uint8_t)LITE3_TYPE_STRING;
1367 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1368 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1369 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1370 return ret;
1371}
1372
1379#ifndef DOXYGEN_IGNORE
1380// Private function
1381int lite3_arr_append_obj_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1382#endif // DOXYGEN_IGNORE
1383
1384static inline int lite3_arr_append_obj(
1385 unsigned char *buf,
1386 size_t *__restrict inout_buflen,
1387 size_t ofs,
1388 size_t bufsz,
1389 size_t *__restrict out_ofs)
1390{
1391 int ret;
1392 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1393 return ret;
1394 return lite3_arr_append_obj_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1395}
1396
1397
1404#ifndef DOXYGEN_IGNORE
1405// Private function
1406int lite3_arr_append_arr_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1407#endif // DOXYGEN_IGNORE
1408
1409static inline int lite3_arr_append_arr(
1410 unsigned char *buf,
1411 size_t *__restrict inout_buflen,
1412 size_t ofs,
1413 size_t bufsz,
1414 size_t *__restrict out_ofs)
1415{
1416 int ret;
1417 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1418 return ret;
1419 return lite3_arr_append_arr_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1420}
1421
1423
1424
1425
1462static inline int lite3_arr_set_null(
1463 unsigned char *buf,
1464 size_t *__restrict inout_buflen,
1465 size_t ofs,
1466 size_t bufsz,
1467 uint32_t index)
1468{
1469 lite3_val *val;
1470 int ret;
1471 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
1472 return ret;
1473 val->type = (uint8_t)LITE3_TYPE_NULL;
1474 return ret;
1475}
1476
1483static inline int lite3_arr_set_bool(
1484 unsigned char *buf,
1485 size_t *__restrict inout_buflen,
1486 size_t ofs,
1487 size_t bufsz,
1488 uint32_t index,
1489 bool value)
1490{
1491 lite3_val *val;
1492 int ret;
1493 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1494 return ret;
1495 val->type = (uint8_t)LITE3_TYPE_BOOL;
1496 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1497 return ret;
1498}
1499
1506static inline int lite3_arr_set_i64(
1507 unsigned char *buf,
1508 size_t *__restrict inout_buflen,
1509 size_t ofs,
1510 size_t bufsz,
1511 uint32_t index,
1512 int64_t value)
1513{
1514 lite3_val *val;
1515 int ret;
1516 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1517 return ret;
1518 val->type = (uint8_t)LITE3_TYPE_I64;
1519 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1520 return ret;
1521}
1522
1529static inline int lite3_arr_set_f64(
1530 unsigned char *buf,
1531 size_t *__restrict inout_buflen,
1532 size_t ofs,
1533 size_t bufsz,
1534 uint32_t index,
1535 double value)
1536{
1537 lite3_val *val;
1538 int ret;
1539 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1540 return ret;
1541 val->type = (uint8_t)LITE3_TYPE_F64;
1542 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1543 return ret;
1544}
1545
1552static inline int lite3_arr_set_bytes(
1553 unsigned char *buf,
1554 size_t *__restrict inout_buflen,
1555 size_t ofs,
1556 size_t bufsz,
1557 uint32_t index,
1558 const unsigned char *__restrict bytes,
1559 size_t bytes_len)
1560{
1561 lite3_val *val;
1562 int ret;
1563 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1564 return ret;
1565 val->type = (uint8_t)LITE3_TYPE_BYTES;
1566 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1567 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1568 return ret;
1569}
1570
1581static inline int lite3_arr_set_str(
1582 unsigned char *buf,
1583 size_t *__restrict inout_buflen,
1584 size_t ofs,
1585 size_t bufsz,
1586 uint32_t index,
1587 const char *__restrict str)
1588{
1589 lite3_val *val;
1590 size_t str_size = strlen(str) + 1;
1591 int ret;
1592 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1593 return ret;
1594 val->type = (uint8_t)LITE3_TYPE_STRING;
1595 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1596 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1597 return ret;
1598}
1599
1609static inline int lite3_arr_set_str_n(
1610 unsigned char *buf,
1611 size_t *__restrict inout_buflen,
1612 size_t ofs,
1613 size_t bufsz,
1614 uint32_t index,
1615 const char *__restrict str,
1616 size_t str_len)
1617{
1618 lite3_val *val;
1619 size_t str_size = str_len + 1;
1620 int ret;
1621 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1622 return ret;
1623 val->type = (uint8_t)LITE3_TYPE_STRING;
1624 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1625 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1626 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1627 return ret;
1628}
1629
1636#ifndef DOXYGEN_IGNORE
1637// Private function
1638int 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);
1639#endif // DOXYGEN_IGNORE
1640
1641static inline int lite3_arr_set_obj(
1642 unsigned char *buf,
1643 size_t *__restrict inout_buflen,
1644 size_t ofs,
1645 size_t bufsz,
1646 uint32_t index,
1647 size_t *__restrict out_ofs)
1648{
1649 int ret;
1650 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1651 return ret;
1652 return lite3_arr_set_obj_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1653}
1654
1655
1662#ifndef DOXYGEN_IGNORE
1663// Private function
1664int 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);
1665#endif // DOXYGEN_IGNORE
1666
1667static inline int lite3_arr_set_arr(
1668 unsigned char *buf,
1669 size_t *__restrict inout_buflen,
1670 size_t ofs,
1671 size_t bufsz,
1672 uint32_t index,
1673 size_t *__restrict out_ofs)
1674{
1675 int ret;
1676 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1677 return ret;
1678 return lite3_arr_set_arr_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1679}
1681
1682
1683
1698#ifndef DOXYGEN_IGNORE
1699static inline int _lite3_verify_get(const unsigned char *buf, size_t buflen, size_t ofs)
1700{
1701 (void)buf;
1702 if (LITE3_UNLIKELY(buflen > LITE3_BUF_SIZE_MAX)) {
1703 LITE3_PRINT_ERROR("INVALID ARGUMENT: buflen > LITE3_BUF_SIZE_MAX\n");
1704 errno = EINVAL;
1705 return -1;
1706 }
1707 if (LITE3_UNLIKELY(LITE3_NODE_SIZE > buflen || ofs > buflen - LITE3_NODE_SIZE)) {
1708 LITE3_PRINT_ERROR("INVALID ARGUMENT: START OFFSET OUT OF BOUNDS\n");
1709 errno = EINVAL;
1710 return -1;
1711 }
1712 return 0;
1713}
1714
1715static inline int _lite3_verify_obj_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_OBJECT)) {
1720 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING OBJECT TYPE\n");
1721 errno = EINVAL;
1722 return -1;
1723 }
1724 return 0;
1725}
1726
1727static inline int _lite3_verify_arr_get(const unsigned char *buf, size_t buflen, size_t ofs)
1728{
1729 if (_lite3_verify_get(buf, buflen, ofs) < 0)
1730 return -1;
1731 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_ARRAY)) {
1732 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY TYPE\n");
1733 errno = EINVAL;
1734 return -1;
1735 }
1736 return 0;
1737}
1738
1739// Private function
1740int 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);
1741
1742static inline int _lite3_get_by_index(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, lite3_val **out)
1743{
1744 int ret;
1745 if ((ret = _lite3_verify_arr_get(buf, buflen, ofs)) < 0)
1746 return ret;
1747 uint32_t size = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1748 if (LITE3_UNLIKELY(index >= size)) {
1749 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1750 errno = EINVAL;
1751 return -1;
1752 }
1753 lite3_key_data key_data = {
1754 .hash = index,
1755 .size = 0,
1756 };
1757 return lite3_get_impl(buf, buflen, ofs, NULL, key_data, out);
1758}
1759#endif // DOXYGEN_IGNORE
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) < 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 enum lite3_type type = (enum lite3_type)val->type;
1785 return type;
1786}
1787#endif // DOXYGEN_IGNORE
1788
1804#define lite3_get_type_size(buf, buflen, ofs, key, out) ({ \
1805 const char *__lite3_key__ = (key); \
1806 _lite3_get_type_size_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1807})
1808#ifndef DOXYGEN_IGNORE
1809static 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)
1810{
1811 int ret;
1812 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
1813 return ret;
1814 lite3_val *val;
1815 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
1816 return ret;
1817 if (val->type == LITE3_TYPE_STRING || val->type == LITE3_TYPE_BYTES) {
1818 *out = 0;
1819 memcpy(out, &val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
1820 return ret;
1821 }
1822 *out = lite3_type_sizes[val->type];
1823 return ret;
1824}
1825#endif // DOXYGEN_IGNORE
1826
1838#define lite3_exists(buf, buflen, ofs, key) ({ \
1839 const char *__lite3_key__ = (key); \
1840 _lite3_exists_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1841})
1842#ifndef DOXYGEN_IGNORE
1843static inline bool _lite3_exists_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1844{
1845 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1846 return false;
1847 lite3_val *val;
1848 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1849 return false;
1850 return true;
1851}
1852#endif // DOXYGEN_IGNORE
1853
1862static inline int lite3_count(
1863 unsigned char *buf,
1864 size_t buflen,
1865 size_t ofs,
1866 uint32_t *out)
1867{
1868 int ret;
1869 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
1870 return ret;
1871 enum lite3_type type = (enum lite3_type)(*(buf + ofs));
1872 if (LITE3_UNLIKELY(!(type == LITE3_TYPE_OBJECT || type == LITE3_TYPE_ARRAY))) {
1873 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY OR OBJECT TYPE\n");
1874 errno = EINVAL;
1875 return -1;
1876 }
1877 *out = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1878 return ret;
1879}
1880
1892#define lite3_is_null(buf, buflen, ofs, key) ({ \
1893 const char *__lite3_key__ = (key); \
1894 _lite3_is_null_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1895})
1896#ifndef DOXYGEN_IGNORE
1897static 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)
1898{
1899 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1900 return false;
1901 lite3_val *val;
1902 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1903 return false;
1904 return val->type == LITE3_TYPE_NULL;
1905}
1906#endif // DOXYGEN_IGNORE
1907
1919#define lite3_is_bool(buf, buflen, ofs, key) ({ \
1920 const char *__lite3_key__ = (key); \
1921 _lite3_is_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1922})
1923#ifndef DOXYGEN_IGNORE
1924static 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)
1925{
1926 if (_lite3_verify_obj_get(buf, buflen, ofs) < 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_BOOL;
1932}
1933#endif // DOXYGEN_IGNORE
1934
1946#define lite3_is_i64(buf, buflen, ofs, key) ({ \
1947 const char *__lite3_key__ = (key); \
1948 _lite3_is_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1949})
1950#ifndef DOXYGEN_IGNORE
1951static 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)
1952{
1953 if (_lite3_verify_obj_get(buf, buflen, ofs) < 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_I64;
1959}
1960#endif // DOXYGEN_IGNORE
1961
1973#define lite3_is_f64(buf, buflen, ofs, key) ({ \
1974 const char *__lite3_key__ = (key); \
1975 _lite3_is_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1976})
1977#ifndef DOXYGEN_IGNORE
1978static 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)
1979{
1980 if (_lite3_verify_obj_get(buf, buflen, ofs) < 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_F64;
1986}
1987#endif // DOXYGEN_IGNORE
1988
2000#define lite3_is_bytes(buf, buflen, ofs, key) ({ \
2001 const char *__lite3_key__ = (key); \
2002 _lite3_is_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2003})
2004#ifndef DOXYGEN_IGNORE
2005static 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)
2006{
2007 if (_lite3_verify_obj_get(buf, buflen, ofs) < 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_BYTES;
2013}
2014#endif // DOXYGEN_IGNORE
2015
2027#define lite3_is_str(buf, buflen, ofs, key) ({ \
2028 const char *__lite3_key__ = (key); \
2029 _lite3_is_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2030})
2031#ifndef DOXYGEN_IGNORE
2032static 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)
2033{
2034 if (_lite3_verify_obj_get(buf, buflen, ofs) < 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_STRING;
2040}
2041#endif // DOXYGEN_IGNORE
2042
2054#define lite3_is_obj(buf, buflen, ofs, key) ({ \
2055 const char *__lite3_key__ = (key); \
2056 _lite3_is_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2057})
2058#ifndef DOXYGEN_IGNORE
2059static 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)
2060{
2061 if (_lite3_verify_obj_get(buf, buflen, ofs) < 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_OBJECT;
2067}
2068#endif // DOXYGEN_IGNORE
2069
2081#define lite3_is_arr(buf, buflen, ofs, key) ({ \
2082 const char *__lite3_key__ = (key); \
2083 _lite3_is_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2084})
2085#ifndef DOXYGEN_IGNORE
2086static 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)
2087{
2088 if (_lite3_verify_obj_get(buf, buflen, ofs) < 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_ARRAY;
2094}
2095#endif // DOXYGEN_IGNORE
2097
2098
2099
2134#define lite3_get(buf, buflen, ofs, key, out) ({ \
2135 const unsigned char *__lite3_buf__ = (buf); \
2136 size_t __lite3_buflen__ = (buflen); \
2137 size_t __lite3_ofs__ = (ofs); \
2138 int __lite3_ret__; \
2139 if ((__lite3_ret__ = _lite3_verify_get(__lite3_buf__, __lite3_buflen__, __lite3_ofs__) < 0)) \
2140 return __lite3_ret__; \
2141 const char *__lite3_key__ = (key); \
2142 lite3_get_impl(__lite3_buf__, __lite3_buflen__, __lite3_ofs__, __lite3_key__, LITE3_KEY_DATA(key), out); \
2143})
2144
2157#define lite3_get_bool(buf, buflen, ofs, key, out) ({ \
2158 const char *__lite3_key__ = (key); \
2159 _lite3_get_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2160})
2161#ifndef DOXYGEN_IGNORE
2162static 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)
2163{
2164 int ret;
2165 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2166 return ret;
2167 lite3_val *val;
2168 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2169 return ret;
2170 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2171 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2172 errno = EINVAL;
2173 return -1;
2174 }
2175 *out = (bool)(*(val->val));
2176 return ret;
2177}
2178#endif // DOXYGEN_IGNORE
2179
2192#define lite3_get_i64(buf, buflen, ofs, key, out) ({ \
2193 const char *__lite3_key__ = (key); \
2194 _lite3_get_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2195})
2196#ifndef DOXYGEN_IGNORE
2197static 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)
2198{
2199 int ret;
2200 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2201 return ret;
2202 lite3_val *val;
2203 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2204 return ret;
2205 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2206 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2207 errno = EINVAL;
2208 return -1;
2209 }
2210 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2211 return ret;
2212}
2213#endif // DOXYGEN_IGNORE
2214
2227#define lite3_get_f64(buf, buflen, ofs, key, out) ({ \
2228 const char *__lite3_key__ = (key); \
2229 _lite3_get_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2230})
2231#ifndef DOXYGEN_IGNORE
2232static 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)
2233{
2234 int ret;
2235 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2236 return ret;
2237 lite3_val *val;
2238 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2239 return ret;
2240 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2241 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2242 errno = EINVAL;
2243 return -1;
2244 }
2245 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2246 return ret;
2247}
2248#endif // DOXYGEN_IGNORE
2249
2262#define lite3_get_bytes(buf, buflen, ofs, key, out) ({ \
2263 const char *__lite3_key__ = (key); \
2264 _lite3_get_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2265})
2266#ifndef DOXYGEN_IGNORE
2267static 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)
2268{
2269 int ret;
2270 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2271 return ret;
2272 lite3_val *val;
2273 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2274 return ret;
2275 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2276 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2277 errno = EINVAL;
2278 return -1;
2279 }
2280 *out = (lite3_bytes){
2281 .gen = *(uint32_t *)buf,
2282 .len = 0,
2283 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2284 };
2285 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2286 return ret;
2287}
2288#endif // DOXYGEN_IGNORE
2289
2302#define lite3_get_str(buf, buflen, ofs, key, out) ({ \
2303 const char *__lite3_key__ = (key); \
2304 _lite3_get_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2305})
2306#ifndef DOXYGEN_IGNORE
2307static 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)
2308{
2309 int ret;
2310 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2311 return ret;
2312 lite3_val *val;
2313 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2314 return ret;
2315 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2316 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2317 errno = EINVAL;
2318 return -1;
2319 }
2320 *out = (lite3_str){
2321 .gen = *(uint32_t *)buf,
2322 .len = 0,
2323 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2324 };
2325 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2326 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2327 return ret;
2328}
2329#endif // DOXYGEN_IGNORE
2330
2343#define lite3_get_obj(buf, buflen, ofs, key, out) ({ \
2344 const char *__lite3_key__ = (key); \
2345 _lite3_get_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2346})
2347#ifndef DOXYGEN_IGNORE
2348static 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)
2349{
2350 int ret;
2351 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2352 return ret;
2353 lite3_val *val;
2354 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2355 return ret;
2356 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2357 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2358 errno = EINVAL;
2359 return -1;
2360 }
2361 *out_ofs = (size_t)((uint8_t *)val - buf);
2362 return ret;
2363}
2364#endif // DOXYGEN_IGNORE
2365
2378#define lite3_get_arr(buf, buflen, ofs, key, out) ({ \
2379 const char *__lite3_key__ = (key); \
2380 _lite3_get_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2381})
2382#ifndef DOXYGEN_IGNORE
2383static 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)
2384{
2385 int ret;
2386 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2387 return ret;
2388 lite3_val *val;
2389 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2390 return ret;
2391 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2392 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2393 errno = EINVAL;
2394 return -1;
2395 }
2396 *out_ofs = (size_t)((uint8_t *)val - buf);
2397 return ret;
2398}
2399#endif // DOXYGEN_IGNORE
2401
2402
2403
2428static inline int lite3_arr_get_bool(
2429 const unsigned char *buf,
2430 size_t buflen,
2431 size_t ofs,
2432 uint32_t index,
2433 bool *out)
2434{
2435 lite3_val *val;
2436 int ret;
2437 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2438 return ret;
2439 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2440 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2441 errno = EINVAL;
2442 return -1;
2443 }
2444 *out = (bool)(*(val->val));
2445 return ret;
2446}
2447
2454static inline int lite3_arr_get_i64(
2455 const unsigned char *buf,
2456 size_t buflen,
2457 size_t ofs,
2458 uint32_t index,
2459 int64_t *out)
2460{
2461 lite3_val *val;
2462 int ret;
2463 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2464 return ret;
2465 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2466 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2467 errno = EINVAL;
2468 return -1;
2469 }
2470 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2471 return ret;
2472}
2473
2480static inline int lite3_arr_get_f64(
2481 const unsigned char *buf,
2482 size_t buflen,
2483 size_t ofs,
2484 uint32_t index,
2485 double *out)
2486{
2487 lite3_val *val;
2488 int ret;
2489 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2490 return ret;
2491 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2492 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2493 errno = EINVAL;
2494 return -1;
2495 }
2496 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2497 return ret;
2498}
2499
2506static inline int lite3_arr_get_bytes(
2507 const unsigned char *buf,
2508 size_t buflen,
2509 size_t ofs,
2510 uint32_t index,
2511 lite3_bytes *out)
2512{
2513 lite3_val *val;
2514 int ret;
2515 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2516 return ret;
2517 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2518 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2519 errno = EINVAL;
2520 return -1;
2521 }
2522 *out = (lite3_bytes){
2523 .gen = *(uint32_t *)buf,
2524 .len = 0,
2525 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2526 };
2527 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2528 return ret;
2529}
2530
2537static inline int lite3_arr_get_str(
2538 const unsigned char *buf,
2539 size_t buflen,
2540 size_t ofs,
2541 uint32_t index,
2542 lite3_str *out)
2543{
2544 lite3_val *val;
2545 int ret;
2546 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2547 return ret;
2548 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2549 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2550 errno = EINVAL;
2551 return -1;
2552 }
2553 *out = (lite3_str){
2554 .gen = *(uint32_t *)buf,
2555 .len = 0,
2556 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2557 };
2558 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2559 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2560 return ret;
2561}
2562
2569static inline int lite3_arr_get_obj(
2570 const unsigned char *buf,
2571 size_t buflen,
2572 size_t ofs,
2573 uint32_t index,
2574 size_t *__restrict out_ofs)
2575{
2576 lite3_val *val;
2577 int ret;
2578 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2579 return ret;
2580 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2581 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2582 errno = EINVAL;
2583 return -1;
2584 }
2585 *out_ofs = (size_t)((uint8_t *)val - buf);
2586 return ret;
2587}
2588
2595static inline int lite3_arr_get_arr(
2596 const unsigned char *buf,
2597 size_t buflen,
2598 size_t ofs,
2599 uint32_t index,
2600 size_t *__restrict out_ofs)
2601{
2602 lite3_val *val;
2603 int ret;
2604 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2605 return ret;
2606 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2607 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2608 errno = EINVAL;
2609 return -1;
2610 }
2611 *out_ofs = (size_t)((uint8_t *)val - buf);
2612 return ret;
2613}
2615
2616
2617
2634#define LITE3_ITER_ITEM 1
2636#define LITE3_ITER_DONE 0
2637
2644typedef struct {
2645 uint32_t gen;
2646 uint32_t node_ofs[LITE3_TREE_HEIGHT_MAX + 1];
2647 uint8_t depth;
2648 uint8_t node_i[LITE3_TREE_HEIGHT_MAX + 1];
2649} lite3_iter;
2650
2651#ifndef DOXYGEN_IGNORE
2652// Private function
2653int lite3_iter_create_impl(const unsigned char *buf, size_t buflen, size_t ofs, lite3_iter *out);
2654#endif // DOXYGEN_IGNORE
2655
2662static inline int lite3_iter_create(
2663 const unsigned char *buf,
2664 size_t buflen,
2665 size_t ofs,
2666 lite3_iter *out)
2667{
2668 int ret;
2669 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
2670 return ret;
2671 return lite3_iter_create_impl(buf, buflen, ofs, out);
2672}
2673
2690int lite3_iter_next(
2691 const unsigned char *buf,
2692 size_t buflen,
2693 lite3_iter *iter,
2694 lite3_str *out_key,
2695 size_t *out_val_ofs
2696);
2698
2699
2700
2712static inline enum lite3_type lite3_val_type(lite3_val *val)
2713{
2714 enum lite3_type type = (enum lite3_type)val->type;
2715 return type < LITE3_TYPE_INVALID ? type : LITE3_TYPE_INVALID;
2716}
2717
2727static inline size_t lite3_val_type_size(lite3_val *val)
2728{
2729 enum lite3_type type = (enum lite3_type)val->type;
2730 if (type == LITE3_TYPE_STRING || type == LITE3_TYPE_BYTES) {
2731 size_t tmp = 0;
2732 memcpy(&tmp, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2733 return tmp;
2734 }
2735 return lite3_type_sizes[val->type];
2736}
2737
2738static inline bool lite3_val_is_null(lite3_val *val) { return val->type == LITE3_TYPE_NULL; }
2739static inline bool lite3_val_is_bool(lite3_val *val) { return val->type == LITE3_TYPE_BOOL; }
2740static inline bool lite3_val_is_i64(lite3_val *val) { return val->type == LITE3_TYPE_I64; }
2741static inline bool lite3_val_is_f64(lite3_val *val) { return val->type == LITE3_TYPE_F64; }
2742static inline bool lite3_val_is_bytes(lite3_val *val) { return val->type == LITE3_TYPE_BYTES; }
2743static inline bool lite3_val_is_str(lite3_val *val) { return val->type == LITE3_TYPE_STRING; }
2744static inline bool lite3_val_is_obj(lite3_val *val) { return val->type == LITE3_TYPE_OBJECT; }
2745static inline bool lite3_val_is_arr(lite3_val *val) { return val->type == LITE3_TYPE_ARRAY; }
2746
2747static inline bool lite3_val_bool(lite3_val *val)
2748{
2749 return *(bool *)(val->val);
2750}
2751
2752static inline int64_t lite3_val_i64(lite3_val *val)
2753{
2754 int64_t tmp;
2755 memcpy(&tmp, val->val, sizeof(tmp));
2756 return tmp;
2757}
2758
2759static inline double lite3_val_f64(lite3_val *val)
2760{
2761 double tmp;
2762 memcpy(&tmp, val->val, sizeof(tmp));
2763 return tmp;
2764}
2765
2766static inline const char *lite3_val_str(lite3_val *val)
2767{
2768 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2769}
2770
2775static inline const char *lite3_val_str_n(lite3_val *val, size_t *out_len)
2776{
2777 *out_len = 0;
2778 memcpy(out_len, val->val, LITE3_STR_LEN_SIZE);
2779 *out_len -= 1; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2780 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2781}
2782
2783static inline const unsigned char *lite3_val_bytes(lite3_val *val, size_t *out_len)
2784{
2785 *out_len = 0;
2786 memcpy(out_len, val->val, LITE3_BYTES_LEN_SIZE);
2787 return (const unsigned char *)val->val + LITE3_BYTES_LEN_SIZE;
2788}
2790
2791
2792
2829#define LITE3_JSON
2830
2831#if defined(DOXYGEN_ONLY) && !defined(LITE3_JSON)
2832#define LITE3_JSON
2833#endif // DOXYGEN_ONLY
2834
2835#ifdef LITE3_JSON
2836#include <stdio.h>
2837
2846#define LITE3_JSON_NESTING_DEPTH_MAX 32
2847
2860 unsigned char *buf,
2861 size_t *__restrict out_buflen,
2862 size_t bufsz,
2863 const char *__restrict json_str,
2864 size_t json_len
2865);
2866
2879 unsigned char *buf,
2880 size_t *__restrict out_buflen,
2881 size_t bufsz,
2882 const char *__restrict path
2883);
2884
2897 unsigned char *buf,
2898 size_t *__restrict out_buflen,
2899 size_t bufsz,
2900 FILE *fp
2901);
2902
2917 const unsigned char *buf,
2918 size_t buflen,
2919 size_t ofs
2920);
2921
2936 const unsigned char *buf,
2937 size_t buflen,
2938 size_t ofs,
2939 size_t *__restrict out_len
2940);
2941
2958 const unsigned char *buf,
2959 size_t buflen,
2960 size_t ofs,
2961 size_t *__restrict out_len
2962);
2963
2975 const unsigned char *buf,
2976 size_t buflen,
2977 size_t ofs,
2978 char *__restrict json_buf,
2979 size_t json_bufsz
2980);
2981
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#else
3002static 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)
3003{
3004 (void)buf; (void)out_buflen; (void)bufsz; (void)json_str; (void)json_len;
3005 return -1;
3006}
3007
3008static inline int lite3_json_dec_file(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, const char *__restrict path)
3009{
3010 (void)buf; (void)out_buflen; (void)bufsz; (void)path;
3011 return -1;
3012}
3013
3014static inline int lite3_json_dec_fp(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, FILE *fp)
3015{
3016 (void)buf; (void)out_buflen; (void)bufsz; (void)fp;
3017 return -1;
3018}
3019
3020static inline int lite3_json_print(const unsigned char *buf, size_t buflen, size_t ofs)
3021{
3022 (void)buf; (void)buflen; (void)ofs;
3023 return 0;
3024}
3025
3026static inline char *lite3_json_enc(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3027{
3028 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3029 return NULL;
3030}
3031
3032static inline char *lite3_json_enc_pretty(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3033{
3034 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3035 return NULL;
3036}
3037
3038static 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)
3039{
3040 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3041 return -1;
3042}
3043
3044static 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)
3045{
3046 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3047 return -1;
3048}
3049#endif
3051
3052#ifdef __cplusplus
3053}
3054#endif
3055
3056#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:1276
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:1232
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:1353
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:1212
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:1409
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:1254
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:1298
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:1384
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:1326
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:2569
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:2454
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:2428
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:2480
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:2537
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:2506
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:2595
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:1462
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:1641
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:1609
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:1506
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:1581
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:1483
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:1552
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:1667
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:1529
#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:336
#define LITE3_NODE_SIZE
B-tree node size setting.
Definition lite3.h:321
#define LITE3_NODE_SIZE_KC_OFFSET
Offset of the size_kc field inside struct node.
Definition lite3.h:350
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:2662
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:528
@ LITE3_TYPE_ARRAY
maps to 'array' type in JSON
Definition lite3.h:536
@ LITE3_TYPE_INVALID
any type value equal or greater than this is considered invalid
Definition lite3.h:537
@ LITE3_TYPE_STRING
maps to 'string' type in JSON
Definition lite3.h:534
@ LITE3_TYPE_BOOL
maps to 'boolean' type in JSON; underlying datatype: bool
Definition lite3.h:530
@ LITE3_TYPE_BYTES
coverted to base64 string in JSON
Definition lite3.h:533
@ LITE3_TYPE_F64
maps to 'number' type in JSON; underlying datatype: double
Definition lite3.h:532
@ LITE3_TYPE_OBJECT
maps to 'object' type in JSON
Definition lite3.h:535
@ LITE3_TYPE_I64
maps to 'number' type in JSON; underlying datatype: int64_t
Definition lite3.h:531
@ LITE3_TYPE_NULL
maps to 'null' type in JSON
Definition lite3.h:529
@ LITE3_TYPE_COUNT
not an actual type, only used for counting
Definition lite3.h:538
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:1862
static size_t lite3_val_type_size(lite3_val *val)
Returns the size of the value type.
Definition lite3.h:2727
static const char * lite3_val_str_n(lite3_val *val, size_t *out_len)
Definition lite3.h:2775
static enum lite3_type lite3_val_type(lite3_val *val)
Returns the value type of *val
Definition lite3.h:2712
Struct holding a reference to a bytes value inside a Lite³ buffer.
Definition lite3.h:590
uint32_t gen
generation of the Lite³ buffer when this struct was returned
Definition lite3.h:591
uint32_t len
byte array length (bytes)
Definition lite3.h:592
const unsigned char * ptr
byte array pointer to bytes inside Lite³ buffer
Definition lite3.h:593
Struct containing iterator state.
Definition lite3.h:2644
Struct holding a reference to a string inside a Lite³ buffer.
Definition lite3.h:619
uint32_t len
char array length (characters, exclusive of NULL-terminator)
Definition lite3.h:621
const char * ptr
char array pointer to string inside Lite³ buffer
Definition lite3.h:622
uint32_t gen
generation of the Lite³ buffer when this struct was returned
Definition lite3.h:620
Struct representing a value inside a Lite³ buffer.
Definition lite3.h:549