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
375#define LITE3_KEY_HASH_COMPILE_TIME
376
377#ifndef DOXYGEN_IGNORE
378#ifdef LITE3_KEY_HASH_COMPILE_TIME
379#define LITE3_MOD 4294967296ULL
380
381#define LITE3_P0 33ULL
382#define LITE3_P1 ((LITE3_P0 * LITE3_P0) % LITE3_MOD)
383#define LITE3_P2 ((LITE3_P1 * LITE3_P1) % LITE3_MOD)
384#define LITE3_P3 ((LITE3_P2 * LITE3_P2) % LITE3_MOD)
385#define LITE3_P4 ((LITE3_P3 * LITE3_P3) % LITE3_MOD)
386#define LITE3_P5 ((LITE3_P4 * LITE3_P4) % LITE3_MOD)
387
388#define LITE3_BIT0(k) (((k) >> 0) & 1ULL)
389#define LITE3_BIT1(k) (((k) >> 1) & 1ULL)
390#define LITE3_BIT2(k) (((k) >> 2) & 1ULL)
391#define LITE3_BIT3(k) (((k) >> 3) & 1ULL)
392#define LITE3_BIT4(k) (((k) >> 4) & 1ULL)
393#define LITE3_BIT5(k) (((k) >> 5) & 1ULL)
394
395#define LITE3_POW33(k) \
396 ((((((1ULL \
397 * (LITE3_BIT0(k) ? LITE3_P0 : 1ULL) \
398 ) % LITE3_MOD \
399 * (LITE3_BIT1(k) ? LITE3_P1 : 1ULL) \
400 ) % LITE3_MOD \
401 * (LITE3_BIT2(k) ? LITE3_P2 : 1ULL) \
402 ) % LITE3_MOD \
403 * (LITE3_BIT3(k) ? LITE3_P3 : 1ULL) \
404 ) % LITE3_MOD \
405 * (LITE3_BIT4(k) ? LITE3_P4 : 1ULL) \
406 ) % LITE3_MOD \
407 * (LITE3_BIT5(k) ? LITE3_P5 : 1ULL) \
408 ) % LITE3_MOD
409
410#define LITE3_SUM_1(s, i, p) \
411 ((unsigned long long)(unsigned char)(s)[(i)] * LITE3_POW33((p)))
412
413#define LITE3_SUM_2(s, i, p) \
414 (LITE3_SUM_1(s, (i), (p)) + LITE3_SUM_1(s, (i) + 1, (p) - 1))
415
416#define LITE3_SUM_4(s, i, p) \
417 (LITE3_SUM_2(s, (i), (p)) + LITE3_SUM_2(s, (i) + 2, (p) - 2))
418
419#define LITE3_SUM_8(s, i, p) \
420 (LITE3_SUM_4(s, (i), (p)) + LITE3_SUM_4(s, (i) + 4, (p) - 4))
421
422#define LITE3_SUM_16(s, i, p) \
423 (LITE3_SUM_8(s, (i), (p)) + LITE3_SUM_8(s, (i) + 8, (p) - 8))
424
425#define LITE3_SUM_32(s, i, p) \
426 (LITE3_SUM_16(s, (i), (p)) + LITE3_SUM_16(s, (i) + 16, (p) - 16))
427
428#define LITE3_OFFSET_BIT0(len) \
429 (((len & 2ULL) ? 2ULL : 0ULL) + \
430 ((len & 4ULL) ? 4ULL : 0ULL) + \
431 ((len & 8ULL) ? 8ULL : 0ULL) + \
432 ((len & 16ULL) ? 16ULL : 0ULL) + \
433 ((len & 32ULL) ? 32ULL : 0ULL))
434
435#define LITE3_OFFSET_BIT1(len) \
436 (((len & 4ULL) ? 4ULL : 0ULL) + \
437 ((len & 8ULL) ? 8ULL : 0ULL) + \
438 ((len & 16ULL) ? 16ULL : 0ULL) + \
439 ((len & 32ULL) ? 32ULL : 0ULL))
440
441#define LITE3_OFFSET_BIT2(len) \
442 (((len & 8ULL) ? 8ULL : 0ULL) + \
443 ((len & 16ULL) ? 16ULL : 0ULL) + \
444 ((len & 32ULL) ? 32ULL : 0ULL))
445
446#define LITE3_OFFSET_BIT3(len) \
447 (((len & 16ULL) ? 16ULL : 0ULL) + \
448 ((len & 32ULL) ? 32ULL : 0ULL))
449
450#define LITE3_OFFSET_BIT4(len) \
451 (((len & 32ULL) ? 32ULL : 0ULL))
452
453#define LITE3_OFFSET_BIT5(len) \
454 (0ULL)
455
456#define LITE3_POLY_HASH(s, len) \
457 ((len) & 1ULL ? LITE3_SUM_1(s, LITE3_OFFSET_BIT0((len)), (len) - 1 - LITE3_OFFSET_BIT0((len))) : 0ULL) + \
458 ((len) & 2ULL ? LITE3_SUM_2(s, LITE3_OFFSET_BIT1((len)), (len) - 1 - LITE3_OFFSET_BIT1((len))) : 0ULL) + \
459 ((len) & 4ULL ? LITE3_SUM_4(s, LITE3_OFFSET_BIT2((len)), (len) - 1 - LITE3_OFFSET_BIT2((len))) : 0ULL) + \
460 ((len) & 8ULL ? LITE3_SUM_8(s, LITE3_OFFSET_BIT3((len)), (len) - 1 - LITE3_OFFSET_BIT3((len))) : 0ULL) + \
461 ((len) & 16ULL ? LITE3_SUM_16(s, LITE3_OFFSET_BIT4((len)), (len) - 1 - LITE3_OFFSET_BIT4((len))) : 0ULL) + \
462 ((len) & 32ULL ? LITE3_SUM_32(s, LITE3_OFFSET_BIT5((len)), (len) - 1 - LITE3_OFFSET_BIT5((len))) : 0ULL)
463
464#define LITE3_STRLEN(s) (sizeof(s) - 1)
465
466typedef struct {
467 uint32_t hash;
468 uint32_t size;
469} lite3_key_data;
470
471static inline lite3_key_data lite3_get_key_data(const char *key) {
472 lite3_key_data key_data;
473 const char *key_cursor = key;
474 key_data.hash = LITE3_DJB2_HASH_SEED;
475 while (*key_cursor)
476 key_data.hash = ((key_data.hash << 5) + key_data.hash) + (uint8_t)(*key_cursor++);
477 key_data.size = (uint32_t)(key_cursor - key) + 1;
478 return key_data;
479}
480
481#define LITE3_KEY_DATA(s) ( \
482 __builtin_constant_p(s) ? \
483 ((LITE3_STRLEN(s) < 64) ? \
484 (lite3_key_data){ \
485 .hash = (uint32_t)((LITE3_POLY_HASH(s, LITE3_STRLEN(s)) + LITE3_DJB2_HASH_SEED * LITE3_POW33(LITE3_STRLEN(s))) % LITE3_MOD), \
486 .size = (sizeof(s)), \
487 } \
488 : lite3_get_key_data(s)) \
489 : lite3_get_key_data(__lite3_key__) \
490)
491#else
492#define LITE3_KEY_DATA(s) lite3_get_key_data(__lite3_key__)
493#endif
494#endif // DOXYGEN_IGNORE
496
497
498
522
531typedef struct {
532 uint8_t type;
533 uint8_t val[];
534} lite3_val;
535
536#ifndef DOXYGEN_IGNORE
537#define LITE3_VAL_SIZE sizeof(lite3_val)
538#endif // DOXYGEN_IGNORE
539static_assert(LITE3_VAL_SIZE <= sizeof(size_t), "LITE3_VAL_SIZE must be <= sizeof(size_t)");
540
541#ifndef DOXYGEN_IGNORE
542static const size_t lite3_type_sizes[] = {
543 0, // LITE3_TYPE_NULL
544 1, // LITE3_TYPE_BOOL
545 8, // LITE3_TYPE_I64
546 8, // LITE3_TYPE_F64
547 4, // LITE3_TYPE_BYTES (this value must be <= sizeof(size_t))
548 4, // LITE3_TYPE_STRING (this value must be <= sizeof(size_t))
549 LITE3_NODE_SIZE - LITE3_VAL_SIZE, // LITE3_TYPE_OBJECT (`type` field is contained inside node->gen_type)
550 LITE3_NODE_SIZE - LITE3_VAL_SIZE, // LITE3_TYPE_ARRAY (`type` field is contained inside node->gen_type)
551 0, // LITE3_TYPE_INVALID
552};
553#endif // DOXYGEN_IGNORE
554static_assert((sizeof(lite3_type_sizes) / sizeof(size_t)) == LITE3_TYPE_COUNT, "lite3_type_sizes[] element count != LITE3_TYPE_COUNT");
555static_assert(4 <= sizeof(size_t), "lite3_type_sizes[LITE3_TYPE_BYTES] and lite3_type_sizes[LITE3_TYPE_STRING] must fit inside size_t");
556
572typedef struct {
573 uint32_t gen;
574 uint32_t len;
575 const unsigned char *ptr;
577
578#ifndef DOXYGEN_IGNORE
579#define LITE3_BYTES_LEN_SIZE sizeof(((lite3_bytes *)0)->len)
580#endif // DOXYGEN_IGNORE
581static_assert(LITE3_BYTES_LEN_SIZE <= sizeof(size_t), "lite3_val_bytes() expects LITE3_BYTES_LEN_SIZE to be <= sizeof(size_t)");
582
601typedef struct {
602 uint32_t gen;
603 uint32_t len;
604 const char *ptr;
605} lite3_str;
606
607#ifndef DOXYGEN_IGNORE
608#define LITE3_STR_LEN_SIZE sizeof(((lite3_str *)0)->len)
609#endif // DOXYGEN_IGNORE
610static_assert(LITE3_STR_LEN_SIZE <= sizeof(size_t), "lite3_val_str() expects LITE3_STR_LEN_SIZE to be <= sizeof(size_t)");
611
637#define LITE3_BYTES(buf, val) (const unsigned char *)_lite3_ptr_suppress_nonnull_warning( \
638 (uint32_t)(val).gen == *(uint32_t *)(buf) ? (val).ptr : NULL \
639)
640
666#define LITE3_STR(buf, val) (const char *)_lite3_ptr_suppress_nonnull_warning( \
667 (uint32_t)(val).gen == *(uint32_t *)(buf) ? (val).ptr : NULL \
668)
669
670#ifndef DOXYGEN_IGNORE
671static inline __attribute__((always_inline)) const void *_lite3_ptr_suppress_nonnull_warning(const void *p) { return p; }
672#endif // DOXYGEN_IGNORE
674
675
676
701 unsigned char *buf,
702 size_t *__restrict out_buflen,
703 size_t bufsz
704);
705
719 unsigned char *buf,
720 size_t *__restrict out_buflen,
721 size_t bufsz
722);
724
725
726
757#ifndef DOXYGEN_IGNORE
758static inline int _lite3_verify_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
759{
760 (void)buf;
761 if (LITE3_UNLIKELY(bufsz > LITE3_BUF_SIZE_MAX)) {
762 LITE3_PRINT_ERROR("INVALID ARGUMENT: bufsz > LITE3_BUF_SIZE_MAX\n");
763 errno = EINVAL;
764 return -1;
765 }
766 if (LITE3_UNLIKELY(*inout_buflen > bufsz)) {
767 LITE3_PRINT_ERROR("INVALID ARGUMENT: inout_buflen > bufsz\n");
768 errno = EINVAL;
769 return -1;
770 }
771 if (LITE3_UNLIKELY(LITE3_NODE_SIZE > *inout_buflen || ofs > *inout_buflen - LITE3_NODE_SIZE)) {
772 LITE3_PRINT_ERROR("INVALID ARGUMENT: START OFFSET OUT OF BOUNDS\n");
773 errno = EINVAL;
774 return -1;
775 }
776 return 0;
777}
778
779static inline int _lite3_verify_obj_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
780{
781 int ret;
782 if ((ret = _lite3_verify_set(buf, inout_buflen, ofs, bufsz)) < 0)
783 return ret;
784 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_OBJECT)) {
785 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING OBJECT TYPE\n");
786 errno = EINVAL;
787 return -1;
788 }
789 return ret;
790}
791
792static inline int _lite3_verify_arr_set(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz)
793{
794 int ret;
795 if ((ret = _lite3_verify_set(buf, inout_buflen, ofs, bufsz)) < 0)
796 return ret;
797 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_ARRAY)) {
798 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY TYPE\n");
799 errno = EINVAL;
800 return -1;
801 }
802 return ret;
803}
804
805// Private function
806int 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);
807#endif // DOXYGEN_IGNORE
808
821#define lite3_set_null(buf, inout_buflen, ofs, bufsz, key) ({ \
822 const char *__lite3_key__ = (key); \
823 _lite3_set_null_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key)); \
824})
825#ifndef DOXYGEN_IGNORE
826static 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)
827{
828 int ret;
829 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
830 return ret;
831 lite3_val *val;
832 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
833 return ret;
834 val->type = (uint8_t)LITE3_TYPE_NULL;
835 return ret;
836}
837#endif // DOXYGEN_IGNORE
838
852#define lite3_set_bool(buf, inout_buflen, ofs, bufsz, key, value) ({ \
853 const char *__lite3_key__ = (key); \
854 _lite3_set_bool_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
855})
856#ifndef DOXYGEN_IGNORE
857static 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)
858{
859 int ret;
860 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
861 return ret;
862 lite3_val *val;
863 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
864 return ret;
865 val->type = (uint8_t)LITE3_TYPE_BOOL;
866 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
867 return ret;
868}
869#endif // DOXYGEN_IGNORE
870
884#define lite3_set_i64(buf, inout_buflen, ofs, bufsz, key, value) ({ \
885 const char *__lite3_key__ = (key); \
886 _lite3_set_i64_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
887})
888#ifndef DOXYGEN_IGNORE
889static 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)
890{
891 int ret;
892 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
893 return ret;
894 lite3_val *val;
895 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
896 return ret;
897 val->type = (uint8_t)LITE3_TYPE_I64;
898 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
899 return ret;
900}
901#endif // DOXYGEN_IGNORE
902
916#define lite3_set_f64(buf, inout_buflen, ofs, bufsz, key, value) ({ \
917 const char *__lite3_key__ = (key); \
918 _lite3_set_f64_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), value); \
919})
920#ifndef DOXYGEN_IGNORE
921static 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)
922{
923 int ret;
924 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
925 return ret;
926 lite3_val *val;
927 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
928 return ret;
929 val->type = (uint8_t)LITE3_TYPE_F64;
930 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
931 return ret;
932}
933#endif // DOXYGEN_IGNORE
934
949#define lite3_set_bytes(buf, inout_buflen, ofs, bufsz, key, bytes, bytes_len) ({ \
950 const char *__lite3_key__ = (key); \
951 _lite3_set_bytes_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), bytes, bytes_len); \
952})
953#ifndef DOXYGEN_IGNORE
954static 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)
955{
956 int ret;
957 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
958 return ret;
959 lite3_val *val;
960 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
961 return ret;
962 val->type = (uint8_t)LITE3_TYPE_BYTES;
963 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
964 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
965 return ret;
966}
967#endif // DOXYGEN_IGNORE
968
986#define lite3_set_str(buf, inout_buflen, ofs, bufsz, key, str) ({ \
987 const char *__lite3_key__ = (key); \
988 _lite3_set_str_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), str); \
989})
990#ifndef DOXYGEN_IGNORE
991static 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)
992{
993 int ret;
994 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
995 return ret;
996 lite3_val *val;
997 size_t str_size = strlen(str) + 1;
998 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
999 return ret;
1000 val->type = (uint8_t)LITE3_TYPE_STRING;
1001 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1002 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1003 return ret;
1004}
1005#endif // DOXYGEN_IGNORE
1006
1024#define lite3_set_str_n(buf, inout_buflen, ofs, bufsz, key, str, str_len) ({ \
1025 const char *__lite3_key__ = (key); \
1026 _lite3_set_str_n_impl(buf, inout_buflen, ofs, bufsz, __lite3_key__, LITE3_KEY_DATA(key), str, str_len); \
1027})
1028#ifndef DOXYGEN_IGNORE
1029static 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)
1030{
1031 int ret;
1032 if ((ret = _lite3_verify_obj_set(buf, inout_buflen, ofs, bufsz)) < 0)
1033 return ret;
1034 lite3_val *val;
1035 size_t str_size = str_len + 1;
1036 if ((ret = lite3_set_impl(buf, inout_buflen, ofs, bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1037 return ret;
1038 val->type = (uint8_t)LITE3_TYPE_STRING;
1039 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1040 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1041 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1042 return ret;
1043}
1044#endif // DOXYGEN_IGNORE
1045
1059#define lite3_set_obj(buf, inout_buflen, ofs, bufsz, key, out_ofs) ({ \
1060 unsigned char *__lite3_buf__ = (buf); \
1061 size_t *__lite3_inout_buflen__ = (inout_buflen); \
1062 size_t __lite3_ofs__ = (ofs); \
1063 size_t __lite3_bufsz__ = (bufsz); \
1064 int __lite3_ret__; \
1065 if ((__lite3_ret__ = _lite3_verify_obj_set( \
1066 __lite3_buf__, \
1067 __lite3_inout_buflen__, \
1068 __lite3_ofs__, \
1069 __lite3_bufsz__)) < 0) \
1070 return __lite3_ret__; \
1071 \
1072 const char *__lite3_key__ = (key); \
1073 lite3_set_obj_impl( \
1074 __lite3_buf__, \
1075 __lite3_inout_buflen__, \
1076 __lite3_ofs__, \
1077 __lite3_bufsz__, \
1078 __lite3_key__, \
1079 LITE3_KEY_DATA(key), \
1080 out_ofs); \
1081})
1082#ifndef DOXYGEN_IGNORE
1083// Private function
1084int 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);
1085#endif // DOXYGEN_IGNORE
1086
1100#define lite3_set_arr(buf, inout_buflen, ofs, bufsz, key, out_ofs) ({ \
1101 unsigned char *__lite3_buf__ = (buf); \
1102 size_t *__lite3_inout_buflen__ = (inout_buflen); \
1103 size_t __lite3_ofs__ = (ofs); \
1104 size_t __lite3_bufsz__ = (bufsz); \
1105 int __lite3_ret__; \
1106 if ((__lite3_ret__ = _lite3_verify_obj_set( \
1107 __lite3_buf__, \
1108 __lite3_inout_buflen__, \
1109 __lite3_ofs__, \
1110 __lite3_bufsz__)) < 0) \
1111 return __lite3_ret__; \
1112 \
1113 const char *__lite3_key__ = (key); \
1114 lite3_set_arr_impl( \
1115 __lite3_buf__, \
1116 __lite3_inout_buflen__, \
1117 __lite3_ofs__, \
1118 __lite3_bufsz__, \
1119 __lite3_key__, \
1120 LITE3_KEY_DATA(key), \
1121 out_ofs); \
1122})
1123#ifndef DOXYGEN_IGNORE
1124// Private function
1125int 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);
1126#endif // DOXYGEN_IGNORE
1128
1129
1130
1155#ifndef DOXYGEN_IGNORE
1156static 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)
1157{
1158 int ret;
1159 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1160 return ret;
1161 uint32_t size = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1162 if (LITE3_UNLIKELY(index > size)) {
1163 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1164 errno = EINVAL;
1165 return -1;
1166 }
1167 lite3_key_data key_data = {
1168 .hash = index,
1169 .size = 0,
1170 };
1171 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1172}
1173
1174static 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)
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 lite3_key_data key_data = {
1181 .hash = size,
1182 .size = 0,
1183 };
1184 return lite3_set_impl(buf, inout_buflen, ofs, bufsz, NULL, key_data, val_len, out);
1185}
1186#endif // DOXYGEN_IGNORE
1187
1194static inline int lite3_arr_append_null(
1195 unsigned char *buf,
1196 size_t *__restrict inout_buflen,
1197 size_t ofs,
1198 size_t bufsz)
1199{
1200 lite3_val *val;
1201 int ret;
1202 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
1203 return ret;
1204 val->type = (uint8_t)LITE3_TYPE_NULL;
1205 return ret;
1206}
1207
1214static inline int lite3_arr_append_bool(
1215 unsigned char *buf,
1216 size_t *__restrict inout_buflen,
1217 size_t ofs,
1218 size_t bufsz,
1219 bool value)
1220{
1221 lite3_val *val;
1222 int ret;
1223 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1224 return ret;
1225 val->type = (uint8_t)LITE3_TYPE_BOOL;
1226 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1227 return ret;
1228}
1229
1236static inline int lite3_arr_append_i64(
1237 unsigned char *buf,
1238 size_t *__restrict inout_buflen,
1239 size_t ofs,
1240 size_t bufsz,
1241 int64_t value)
1242{
1243 lite3_val *val;
1244 int ret;
1245 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1246 return ret;
1247 val->type = (uint8_t)LITE3_TYPE_I64;
1248 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1249 return ret;
1250}
1251
1258static inline int lite3_arr_append_f64(
1259 unsigned char *buf,
1260 size_t *__restrict inout_buflen,
1261 size_t ofs,
1262 size_t bufsz,
1263 double value)
1264{
1265 lite3_val *val;
1266 int ret;
1267 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1268 return ret;
1269 val->type = (uint8_t)LITE3_TYPE_F64;
1270 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1271 return ret;
1272}
1273
1280static inline int lite3_arr_append_bytes(
1281 unsigned char *buf,
1282 size_t *__restrict inout_buflen,
1283 size_t ofs,
1284 size_t bufsz,
1285 const unsigned char *__restrict bytes,
1286 size_t bytes_len)
1287{
1288 lite3_val *val;
1289 int ret;
1290 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1291 return ret;
1292 val->type = (uint8_t)LITE3_TYPE_BYTES;
1293 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1294 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1295 return ret;
1296}
1297
1308static inline int lite3_arr_append_str(
1309 unsigned char *buf,
1310 size_t *__restrict inout_buflen,
1311 size_t ofs,
1312 size_t bufsz,
1313 const char *__restrict str)
1314{
1315 lite3_val *val;
1316 size_t str_size = strlen(str) + 1;
1317 int ret;
1318 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1319 return ret;
1320 val->type = (uint8_t)LITE3_TYPE_STRING;
1321 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1322 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1323 return ret;
1324}
1325
1335static inline int lite3_arr_append_str_n(
1336 unsigned char *buf,
1337 size_t *__restrict inout_buflen,
1338 size_t ofs,
1339 size_t bufsz,
1340 const char *__restrict str,
1341 size_t str_len)
1342{
1343 lite3_val *val;
1344 size_t str_size = str_len + 1;
1345 int ret;
1346 if ((ret = _lite3_set_by_append(buf, inout_buflen, ofs, bufsz, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1347 return ret;
1348 val->type = (uint8_t)LITE3_TYPE_STRING;
1349 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1350 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1351 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1352 return ret;
1353}
1354
1361#ifndef DOXYGEN_IGNORE
1362// Private function
1363int lite3_arr_append_obj_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1364#endif // DOXYGEN_IGNORE
1365
1366static inline int lite3_arr_append_obj(
1367 unsigned char *buf,
1368 size_t *__restrict inout_buflen,
1369 size_t ofs,
1370 size_t bufsz,
1371 size_t *__restrict out_ofs)
1372{
1373 int ret;
1374 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1375 return ret;
1376 return lite3_arr_append_obj_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1377}
1378
1379
1386#ifndef DOXYGEN_IGNORE
1387// Private function
1388int lite3_arr_append_arr_impl(unsigned char *buf, size_t *__restrict inout_buflen, size_t ofs, size_t bufsz, size_t *__restrict out_ofs);
1389#endif // DOXYGEN_IGNORE
1390
1391static inline int lite3_arr_append_arr(
1392 unsigned char *buf,
1393 size_t *__restrict inout_buflen,
1394 size_t ofs,
1395 size_t bufsz,
1396 size_t *__restrict out_ofs)
1397{
1398 int ret;
1399 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1400 return ret;
1401 return lite3_arr_append_arr_impl(buf, inout_buflen, ofs, bufsz, out_ofs);
1402}
1403
1405
1406
1407
1444static inline int lite3_arr_set_null(
1445 unsigned char *buf,
1446 size_t *__restrict inout_buflen,
1447 size_t ofs,
1448 size_t bufsz,
1449 uint32_t index)
1450{
1451 lite3_val *val;
1452 int ret;
1453 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
1454 return ret;
1455 val->type = (uint8_t)LITE3_TYPE_NULL;
1456 return ret;
1457}
1458
1465static inline int lite3_arr_set_bool(
1466 unsigned char *buf,
1467 size_t *__restrict inout_buflen,
1468 size_t ofs,
1469 size_t bufsz,
1470 uint32_t index,
1471 bool value)
1472{
1473 lite3_val *val;
1474 int ret;
1475 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1476 return ret;
1477 val->type = (uint8_t)LITE3_TYPE_BOOL;
1478 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1479 return ret;
1480}
1481
1488static inline int lite3_arr_set_i64(
1489 unsigned char *buf,
1490 size_t *__restrict inout_buflen,
1491 size_t ofs,
1492 size_t bufsz,
1493 uint32_t index,
1494 int64_t value)
1495{
1496 lite3_val *val;
1497 int ret;
1498 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1499 return ret;
1500 val->type = (uint8_t)LITE3_TYPE_I64;
1501 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1502 return ret;
1503}
1504
1511static inline int lite3_arr_set_f64(
1512 unsigned char *buf,
1513 size_t *__restrict inout_buflen,
1514 size_t ofs,
1515 size_t bufsz,
1516 uint32_t index,
1517 double value)
1518{
1519 lite3_val *val;
1520 int ret;
1521 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1522 return ret;
1523 val->type = (uint8_t)LITE3_TYPE_F64;
1524 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1525 return ret;
1526}
1527
1534static inline int lite3_arr_set_bytes(
1535 unsigned char *buf,
1536 size_t *__restrict inout_buflen,
1537 size_t ofs,
1538 size_t bufsz,
1539 uint32_t index,
1540 const unsigned char *__restrict bytes,
1541 size_t bytes_len)
1542{
1543 lite3_val *val;
1544 int ret;
1545 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1546 return ret;
1547 val->type = (uint8_t)LITE3_TYPE_BYTES;
1548 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1549 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1550 return ret;
1551}
1552
1563static inline int lite3_arr_set_str(
1564 unsigned char *buf,
1565 size_t *__restrict inout_buflen,
1566 size_t ofs,
1567 size_t bufsz,
1568 uint32_t index,
1569 const char *__restrict str)
1570{
1571 lite3_val *val;
1572 size_t str_size = strlen(str) + 1;
1573 int ret;
1574 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1575 return ret;
1576 val->type = (uint8_t)LITE3_TYPE_STRING;
1577 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1578 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1579 return ret;
1580}
1581
1591static inline int lite3_arr_set_str_n(
1592 unsigned char *buf,
1593 size_t *__restrict inout_buflen,
1594 size_t ofs,
1595 size_t bufsz,
1596 uint32_t index,
1597 const char *__restrict str,
1598 size_t str_len)
1599{
1600 lite3_val *val;
1601 size_t str_size = str_len + 1;
1602 int ret;
1603 if ((ret = _lite3_set_by_index(buf, inout_buflen, ofs, bufsz, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1604 return ret;
1605 val->type = (uint8_t)LITE3_TYPE_STRING;
1606 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1607 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1608 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1609 return ret;
1610}
1611
1618#ifndef DOXYGEN_IGNORE
1619// Private function
1620int 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);
1621#endif // DOXYGEN_IGNORE
1622
1623static inline int lite3_arr_set_obj(
1624 unsigned char *buf,
1625 size_t *__restrict inout_buflen,
1626 size_t ofs,
1627 size_t bufsz,
1628 uint32_t index,
1629 size_t *__restrict out_ofs)
1630{
1631 int ret;
1632 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1633 return ret;
1634 return lite3_arr_set_obj_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1635}
1636
1637
1644#ifndef DOXYGEN_IGNORE
1645// Private function
1646int 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);
1647#endif // DOXYGEN_IGNORE
1648
1649static inline int lite3_arr_set_arr(
1650 unsigned char *buf,
1651 size_t *__restrict inout_buflen,
1652 size_t ofs,
1653 size_t bufsz,
1654 uint32_t index,
1655 size_t *__restrict out_ofs)
1656{
1657 int ret;
1658 if ((ret = _lite3_verify_arr_set(buf, inout_buflen, ofs, bufsz)) < 0)
1659 return ret;
1660 return lite3_arr_set_arr_impl(buf, inout_buflen, ofs, bufsz, index, out_ofs);
1661}
1663
1664
1665
1680#ifndef DOXYGEN_IGNORE
1681static inline int _lite3_verify_get(const unsigned char *buf, size_t buflen, size_t ofs)
1682{
1683 (void)buf;
1684 if (LITE3_UNLIKELY(buflen > LITE3_BUF_SIZE_MAX)) {
1685 LITE3_PRINT_ERROR("INVALID ARGUMENT: buflen > LITE3_BUF_SIZE_MAX\n");
1686 errno = EINVAL;
1687 return -1;
1688 }
1689 if (LITE3_UNLIKELY(LITE3_NODE_SIZE > buflen || ofs > buflen - LITE3_NODE_SIZE)) {
1690 LITE3_PRINT_ERROR("INVALID ARGUMENT: START OFFSET OUT OF BOUNDS\n");
1691 errno = EINVAL;
1692 return -1;
1693 }
1694 return 0;
1695}
1696
1697static inline int _lite3_verify_obj_get(const unsigned char *buf, size_t buflen, size_t ofs)
1698{
1699 if (_lite3_verify_get(buf, buflen, ofs) < 0)
1700 return -1;
1701 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_OBJECT)) {
1702 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING OBJECT TYPE\n");
1703 errno = EINVAL;
1704 return -1;
1705 }
1706 return 0;
1707}
1708
1709static inline int _lite3_verify_arr_get(const unsigned char *buf, size_t buflen, size_t ofs)
1710{
1711 if (_lite3_verify_get(buf, buflen, ofs) < 0)
1712 return -1;
1713 if (LITE3_UNLIKELY(*(buf + ofs) != LITE3_TYPE_ARRAY)) {
1714 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY TYPE\n");
1715 errno = EINVAL;
1716 return -1;
1717 }
1718 return 0;
1719}
1720
1721// Private function
1722int 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);
1723
1724static inline int _lite3_get_by_index(const unsigned char *buf, size_t buflen, size_t ofs, uint32_t index, lite3_val **out)
1725{
1726 int ret;
1727 if ((ret = _lite3_verify_arr_get(buf, buflen, ofs)) < 0)
1728 return ret;
1729 uint32_t size = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1730 if (LITE3_UNLIKELY(index >= size)) {
1731 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
1732 errno = EINVAL;
1733 return -1;
1734 }
1735 lite3_key_data key_data = {
1736 .hash = index,
1737 .size = 0,
1738 };
1739 return lite3_get_impl(buf, buflen, ofs, NULL, key_data, out);
1740}
1741#endif // DOXYGEN_IGNORE
1742
1754#define lite3_get_type(buf, buflen, ofs, key) ({ \
1755 const char *__lite3_key__ = (key); \
1756 _lite3_get_type_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1757})
1758#ifndef DOXYGEN_IGNORE
1759static 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)
1760{
1761 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1762 return LITE3_TYPE_INVALID;
1763 lite3_val *val;
1764 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1765 return LITE3_TYPE_INVALID;
1766 enum lite3_type type = (enum lite3_type)val->type;
1767 return type;
1768}
1769#endif // DOXYGEN_IGNORE
1770
1786#define lite3_get_type_size(buf, buflen, ofs, key, out) ({ \
1787 const char *__lite3_key__ = (key); \
1788 _lite3_get_type_size_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1789})
1790#ifndef DOXYGEN_IGNORE
1791static 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)
1792{
1793 int ret;
1794 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
1795 return ret;
1796 lite3_val *val;
1797 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
1798 return ret;
1799 if (val->type == LITE3_TYPE_STRING || val->type == LITE3_TYPE_BYTES) {
1800 *out = 0;
1801 memcpy(out, &val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
1802 return ret;
1803 }
1804 *out = lite3_type_sizes[val->type];
1805 return ret;
1806}
1807#endif // DOXYGEN_IGNORE
1808
1820#define lite3_exists(buf, buflen, ofs, key) ({ \
1821 const char *__lite3_key__ = (key); \
1822 _lite3_exists_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1823})
1824#ifndef DOXYGEN_IGNORE
1825static inline bool _lite3_exists_impl(const unsigned char *buf, size_t buflen, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1826{
1827 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1828 return false;
1829 lite3_val *val;
1830 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1831 return false;
1832 return true;
1833}
1834#endif // DOXYGEN_IGNORE
1835
1844static inline int lite3_count(
1845 unsigned char *buf,
1846 size_t buflen,
1847 size_t ofs,
1848 uint32_t *out)
1849{
1850 int ret;
1851 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
1852 return ret;
1853 enum lite3_type type = (enum lite3_type)(*(buf + ofs));
1854 if (LITE3_UNLIKELY(!(type == LITE3_TYPE_OBJECT || type == LITE3_TYPE_ARRAY))) {
1855 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY OR OBJECT TYPE\n");
1856 errno = EINVAL;
1857 return -1;
1858 }
1859 *out = (*(uint32_t *)(buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1860 return ret;
1861}
1862
1874#define lite3_is_null(buf, buflen, ofs, key) ({ \
1875 const char *__lite3_key__ = (key); \
1876 _lite3_is_null_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1877})
1878#ifndef DOXYGEN_IGNORE
1879static 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)
1880{
1881 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1882 return false;
1883 lite3_val *val;
1884 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1885 return false;
1886 return val->type == LITE3_TYPE_NULL;
1887}
1888#endif // DOXYGEN_IGNORE
1889
1901#define lite3_is_bool(buf, buflen, ofs, key) ({ \
1902 const char *__lite3_key__ = (key); \
1903 _lite3_is_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1904})
1905#ifndef DOXYGEN_IGNORE
1906static 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)
1907{
1908 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1909 return false;
1910 lite3_val *val;
1911 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1912 return false;
1913 return val->type == LITE3_TYPE_BOOL;
1914}
1915#endif // DOXYGEN_IGNORE
1916
1928#define lite3_is_i64(buf, buflen, ofs, key) ({ \
1929 const char *__lite3_key__ = (key); \
1930 _lite3_is_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1931})
1932#ifndef DOXYGEN_IGNORE
1933static 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)
1934{
1935 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1936 return false;
1937 lite3_val *val;
1938 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1939 return false;
1940 return val->type == LITE3_TYPE_I64;
1941}
1942#endif // DOXYGEN_IGNORE
1943
1955#define lite3_is_f64(buf, buflen, ofs, key) ({ \
1956 const char *__lite3_key__ = (key); \
1957 _lite3_is_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1958})
1959#ifndef DOXYGEN_IGNORE
1960static 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)
1961{
1962 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1963 return false;
1964 lite3_val *val;
1965 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1966 return false;
1967 return val->type == LITE3_TYPE_F64;
1968}
1969#endif // DOXYGEN_IGNORE
1970
1982#define lite3_is_bytes(buf, buflen, ofs, key) ({ \
1983 const char *__lite3_key__ = (key); \
1984 _lite3_is_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1985})
1986#ifndef DOXYGEN_IGNORE
1987static 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)
1988{
1989 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
1990 return false;
1991 lite3_val *val;
1992 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
1993 return false;
1994 return val->type == LITE3_TYPE_BYTES;
1995}
1996#endif // DOXYGEN_IGNORE
1997
2009#define lite3_is_str(buf, buflen, ofs, key) ({ \
2010 const char *__lite3_key__ = (key); \
2011 _lite3_is_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2012})
2013#ifndef DOXYGEN_IGNORE
2014static 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)
2015{
2016 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
2017 return false;
2018 lite3_val *val;
2019 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2020 return false;
2021 return val->type == LITE3_TYPE_STRING;
2022}
2023#endif // DOXYGEN_IGNORE
2024
2036#define lite3_is_obj(buf, buflen, ofs, key) ({ \
2037 const char *__lite3_key__ = (key); \
2038 _lite3_is_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2039})
2040#ifndef DOXYGEN_IGNORE
2041static 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)
2042{
2043 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
2044 return false;
2045 lite3_val *val;
2046 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2047 return false;
2048 return val->type == LITE3_TYPE_OBJECT;
2049}
2050#endif // DOXYGEN_IGNORE
2051
2063#define lite3_is_arr(buf, buflen, ofs, key) ({ \
2064 const char *__lite3_key__ = (key); \
2065 _lite3_is_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
2066})
2067#ifndef DOXYGEN_IGNORE
2068static 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)
2069{
2070 if (_lite3_verify_obj_get(buf, buflen, ofs) < 0)
2071 return false;
2072 lite3_val *val;
2073 if (lite3_get_impl(buf, buflen, ofs, key, key_data, &val) < 0)
2074 return false;
2075 return val->type == LITE3_TYPE_ARRAY;
2076}
2077#endif // DOXYGEN_IGNORE
2079
2080
2081
2116#define lite3_get(buf, buflen, ofs, key, out) ({ \
2117 const unsigned char *__lite3_buf__ = (buf); \
2118 size_t __lite3_buflen__ = (buflen); \
2119 size_t __lite3_ofs__ = (ofs); \
2120 int __lite3_ret__; \
2121 if ((__lite3_ret__ = _lite3_verify_get(__lite3_buf__, __lite3_buflen__, __lite3_ofs__) < 0)) \
2122 return __lite3_ret__; \
2123 const char *__lite3_key__ = (key); \
2124 lite3_get_impl(__lite3_buf__, __lite3_buflen__, __lite3_ofs__, __lite3_key__, LITE3_KEY_DATA(key), out); \
2125})
2126
2139#define lite3_get_bool(buf, buflen, ofs, key, out) ({ \
2140 const char *__lite3_key__ = (key); \
2141 _lite3_get_bool_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2142})
2143#ifndef DOXYGEN_IGNORE
2144static 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)
2145{
2146 int ret;
2147 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2148 return ret;
2149 lite3_val *val;
2150 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2151 return ret;
2152 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2153 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2154 errno = EINVAL;
2155 return -1;
2156 }
2157 *out = (bool)(*(val->val));
2158 return ret;
2159}
2160#endif // DOXYGEN_IGNORE
2161
2174#define lite3_get_i64(buf, buflen, ofs, key, out) ({ \
2175 const char *__lite3_key__ = (key); \
2176 _lite3_get_i64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2177})
2178#ifndef DOXYGEN_IGNORE
2179static 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)
2180{
2181 int ret;
2182 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2183 return ret;
2184 lite3_val *val;
2185 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2186 return ret;
2187 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2188 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2189 errno = EINVAL;
2190 return -1;
2191 }
2192 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2193 return ret;
2194}
2195#endif // DOXYGEN_IGNORE
2196
2209#define lite3_get_f64(buf, buflen, ofs, key, out) ({ \
2210 const char *__lite3_key__ = (key); \
2211 _lite3_get_f64_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2212})
2213#ifndef DOXYGEN_IGNORE
2214static 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)
2215{
2216 int ret;
2217 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2218 return ret;
2219 lite3_val *val;
2220 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2221 return ret;
2222 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2223 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2224 errno = EINVAL;
2225 return -1;
2226 }
2227 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2228 return ret;
2229}
2230#endif // DOXYGEN_IGNORE
2231
2244#define lite3_get_bytes(buf, buflen, ofs, key, out) ({ \
2245 const char *__lite3_key__ = (key); \
2246 _lite3_get_bytes_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2247})
2248#ifndef DOXYGEN_IGNORE
2249static 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)
2250{
2251 int ret;
2252 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2253 return ret;
2254 lite3_val *val;
2255 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2256 return ret;
2257 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2258 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2259 errno = EINVAL;
2260 return -1;
2261 }
2262 *out = (lite3_bytes){
2263 .gen = *(uint32_t *)buf,
2264 .len = 0,
2265 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2266 };
2267 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2268 return ret;
2269}
2270#endif // DOXYGEN_IGNORE
2271
2284#define lite3_get_str(buf, buflen, ofs, key, out) ({ \
2285 const char *__lite3_key__ = (key); \
2286 _lite3_get_str_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2287})
2288#ifndef DOXYGEN_IGNORE
2289static 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)
2290{
2291 int ret;
2292 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2293 return ret;
2294 lite3_val *val;
2295 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2296 return ret;
2297 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2298 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2299 errno = EINVAL;
2300 return -1;
2301 }
2302 *out = (lite3_str){
2303 .gen = *(uint32_t *)buf,
2304 .len = 0,
2305 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2306 };
2307 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2308 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2309 return ret;
2310}
2311#endif // DOXYGEN_IGNORE
2312
2325#define lite3_get_obj(buf, buflen, ofs, key, out) ({ \
2326 const char *__lite3_key__ = (key); \
2327 _lite3_get_obj_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2328})
2329#ifndef DOXYGEN_IGNORE
2330static 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)
2331{
2332 int ret;
2333 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2334 return ret;
2335 lite3_val *val;
2336 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2337 return ret;
2338 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2339 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2340 errno = EINVAL;
2341 return -1;
2342 }
2343 *out_ofs = (size_t)((uint8_t *)val - buf);
2344 return ret;
2345}
2346#endif // DOXYGEN_IGNORE
2347
2360#define lite3_get_arr(buf, buflen, ofs, key, out) ({ \
2361 const char *__lite3_key__ = (key); \
2362 _lite3_get_arr_impl(buf, buflen, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
2363})
2364#ifndef DOXYGEN_IGNORE
2365static 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)
2366{
2367 int ret;
2368 if ((ret = _lite3_verify_obj_get(buf, buflen, ofs)) < 0)
2369 return ret;
2370 lite3_val *val;
2371 if ((ret = lite3_get_impl(buf, buflen, ofs, key, key_data, &val)) < 0)
2372 return ret;
2373 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2374 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2375 errno = EINVAL;
2376 return -1;
2377 }
2378 *out_ofs = (size_t)((uint8_t *)val - buf);
2379 return ret;
2380}
2381#endif // DOXYGEN_IGNORE
2383
2384
2385
2410static inline int lite3_arr_get_bool(
2411 const unsigned char *buf,
2412 size_t buflen,
2413 size_t ofs,
2414 uint32_t index,
2415 bool *out)
2416{
2417 lite3_val *val;
2418 int ret;
2419 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2420 return ret;
2421 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
2422 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
2423 errno = EINVAL;
2424 return -1;
2425 }
2426 *out = (bool)(*(val->val));
2427 return ret;
2428}
2429
2436static inline int lite3_arr_get_i64(
2437 const unsigned char *buf,
2438 size_t buflen,
2439 size_t ofs,
2440 uint32_t index,
2441 int64_t *out)
2442{
2443 lite3_val *val;
2444 int ret;
2445 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2446 return ret;
2447 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
2448 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
2449 errno = EINVAL;
2450 return -1;
2451 }
2452 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
2453 return ret;
2454}
2455
2462static inline int lite3_arr_get_f64(
2463 const unsigned char *buf,
2464 size_t buflen,
2465 size_t ofs,
2466 uint32_t index,
2467 double *out)
2468{
2469 lite3_val *val;
2470 int ret;
2471 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2472 return ret;
2473 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
2474 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
2475 errno = EINVAL;
2476 return -1;
2477 }
2478 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
2479 return ret;
2480}
2481
2488static inline int lite3_arr_get_bytes(
2489 const unsigned char *buf,
2490 size_t buflen,
2491 size_t ofs,
2492 uint32_t index,
2493 lite3_bytes *out)
2494{
2495 lite3_val *val;
2496 int ret;
2497 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2498 return ret;
2499 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
2500 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
2501 errno = EINVAL;
2502 return -1;
2503 }
2504 *out = (lite3_bytes){
2505 .gen = *(uint32_t *)buf,
2506 .len = 0,
2507 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
2508 };
2509 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2510 return ret;
2511}
2512
2519static inline int lite3_arr_get_str(
2520 const unsigned char *buf,
2521 size_t buflen,
2522 size_t ofs,
2523 uint32_t index,
2524 lite3_str *out)
2525{
2526 lite3_val *val;
2527 int ret;
2528 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2529 return ret;
2530 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
2531 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
2532 errno = EINVAL;
2533 return -1;
2534 }
2535 *out = (lite3_str){
2536 .gen = *(uint32_t *)buf,
2537 .len = 0,
2538 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
2539 };
2540 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
2541 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2542 return ret;
2543}
2544
2551static inline int lite3_arr_get_obj(
2552 const unsigned char *buf,
2553 size_t buflen,
2554 size_t ofs,
2555 uint32_t index,
2556 size_t *__restrict out_ofs)
2557{
2558 lite3_val *val;
2559 int ret;
2560 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2561 return ret;
2562 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
2563 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
2564 errno = EINVAL;
2565 return -1;
2566 }
2567 *out_ofs = (size_t)((uint8_t *)val - buf);
2568 return ret;
2569}
2570
2577static inline int lite3_arr_get_arr(
2578 const unsigned char *buf,
2579 size_t buflen,
2580 size_t ofs,
2581 uint32_t index,
2582 size_t *__restrict out_ofs)
2583{
2584 lite3_val *val;
2585 int ret;
2586 if ((ret = _lite3_get_by_index(buf, buflen, ofs, index, &val)) < 0)
2587 return ret;
2588 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2589 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2590 errno = EINVAL;
2591 return -1;
2592 }
2593 *out_ofs = (size_t)((uint8_t *)val - buf);
2594 return ret;
2595}
2597
2598
2599
2616#define LITE3_ITER_ITEM 1
2618#define LITE3_ITER_DONE 0
2619
2626typedef struct {
2627 uint32_t gen;
2628 uint32_t node_ofs[LITE3_TREE_HEIGHT_MAX + 1];
2629 uint8_t depth;
2630 uint8_t node_i[LITE3_TREE_HEIGHT_MAX + 1];
2631} lite3_iter;
2632
2633#ifndef DOXYGEN_IGNORE
2634// Private function
2635int lite3_iter_create_impl(const unsigned char *buf, size_t buflen, size_t ofs, lite3_iter *out);
2636#endif // DOXYGEN_IGNORE
2637
2644static inline int lite3_iter_create(
2645 const unsigned char *buf,
2646 size_t buflen,
2647 size_t ofs,
2648 lite3_iter *out)
2649{
2650 int ret;
2651 if ((ret = _lite3_verify_get(buf, buflen, ofs)) < 0)
2652 return ret;
2653 return lite3_iter_create_impl(buf, buflen, ofs, out);
2654}
2655
2672int lite3_iter_next(
2673 const unsigned char *buf,
2674 size_t buflen,
2675 lite3_iter *iter,
2676 lite3_str *out_key,
2677 size_t *out_val_ofs
2678);
2680
2681
2682
2694static inline enum lite3_type lite3_val_type(lite3_val *val)
2695{
2696 enum lite3_type type = (enum lite3_type)val->type;
2697 return type < LITE3_TYPE_INVALID ? type : LITE3_TYPE_INVALID;
2698}
2699
2709static inline size_t lite3_val_type_size(lite3_val *val)
2710{
2711 enum lite3_type type = (enum lite3_type)val->type;
2712 if (type == LITE3_TYPE_STRING || type == LITE3_TYPE_BYTES) {
2713 size_t tmp = 0;
2714 memcpy(&tmp, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
2715 return tmp;
2716 }
2717 return lite3_type_sizes[val->type];
2718}
2719
2720static inline bool lite3_val_is_null(lite3_val *val) { return val->type == LITE3_TYPE_NULL; }
2721static inline bool lite3_val_is_bool(lite3_val *val) { return val->type == LITE3_TYPE_BOOL; }
2722static inline bool lite3_val_is_i64(lite3_val *val) { return val->type == LITE3_TYPE_I64; }
2723static inline bool lite3_val_is_f64(lite3_val *val) { return val->type == LITE3_TYPE_F64; }
2724static inline bool lite3_val_is_bytes(lite3_val *val) { return val->type == LITE3_TYPE_BYTES; }
2725static inline bool lite3_val_is_str(lite3_val *val) { return val->type == LITE3_TYPE_STRING; }
2726static inline bool lite3_val_is_obj(lite3_val *val) { return val->type == LITE3_TYPE_OBJECT; }
2727static inline bool lite3_val_is_arr(lite3_val *val) { return val->type == LITE3_TYPE_ARRAY; }
2728
2729static inline bool lite3_val_bool(lite3_val *val)
2730{
2731 return *(bool *)(val->val);
2732}
2733
2734static inline int64_t lite3_val_i64(lite3_val *val)
2735{
2736 int64_t tmp;
2737 memcpy(&tmp, val->val, sizeof(tmp));
2738 return tmp;
2739}
2740
2741static inline double lite3_val_f64(lite3_val *val)
2742{
2743 double tmp;
2744 memcpy(&tmp, val->val, sizeof(tmp));
2745 return tmp;
2746}
2747
2748static inline const char *lite3_val_str(lite3_val *val)
2749{
2750 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2751}
2752
2757static inline const char *lite3_val_str_n(lite3_val *val, size_t *out_len)
2758{
2759 *out_len = 0;
2760 memcpy(out_len, val->val, LITE3_STR_LEN_SIZE);
2761 *out_len -= 1; // Lite³ stores string size including NULL-terminator. Correction required for public API.
2762 return (const char *)val->val + LITE3_STR_LEN_SIZE;
2763}
2764
2765static inline const unsigned char *lite3_val_bytes(lite3_val *val, size_t *out_len)
2766{
2767 *out_len = 0;
2768 memcpy(out_len, val->val, LITE3_BYTES_LEN_SIZE);
2769 return (const unsigned char *)val->val + LITE3_BYTES_LEN_SIZE;
2770}
2772
2773
2774
2811#define LITE3_JSON
2812
2813#if defined(DOXYGEN_ONLY) && !defined(LITE3_JSON)
2814#define LITE3_JSON
2815#endif // DOXYGEN_ONLY
2816
2817#ifdef LITE3_JSON
2818#include <stdio.h>
2819
2828#define LITE3_JSON_NESTING_DEPTH_MAX 32
2829
2842 unsigned char *buf,
2843 size_t *__restrict out_buflen,
2844 size_t bufsz,
2845 const char *__restrict json_str,
2846 size_t json_len
2847);
2848
2861 unsigned char *buf,
2862 size_t *__restrict out_buflen,
2863 size_t bufsz,
2864 const char *__restrict path
2865);
2866
2879 unsigned char *buf,
2880 size_t *__restrict out_buflen,
2881 size_t bufsz,
2882 FILE *fp
2883);
2884
2899 const unsigned char *buf,
2900 size_t buflen,
2901 size_t ofs
2902);
2903
2918 const unsigned char *buf,
2919 size_t buflen,
2920 size_t ofs,
2921 size_t *__restrict out_len
2922);
2923
2940 const unsigned char *buf,
2941 size_t buflen,
2942 size_t ofs,
2943 size_t *__restrict out_len
2944);
2945
2957 const unsigned char *buf,
2958 size_t buflen,
2959 size_t ofs,
2960 char *__restrict json_buf,
2961 size_t json_bufsz
2962);
2963
2977 const unsigned char *buf,
2978 size_t buflen,
2979 size_t ofs,
2980 char *__restrict json_buf,
2981 size_t json_bufsz
2982);
2983#else
2984static 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)
2985{
2986 (void)buf; (void)out_buflen; (void)bufsz; (void)json_str; (void)json_len;
2987 return -1;
2988}
2989
2990static inline int lite3_json_dec_file(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, const char *__restrict path)
2991{
2992 (void)buf; (void)out_buflen; (void)bufsz; (void)path;
2993 return -1;
2994}
2995
2996static inline int lite3_json_dec_fp(unsigned char *buf, size_t *__restrict out_buflen, size_t bufsz, FILE *fp)
2997{
2998 (void)buf; (void)out_buflen; (void)bufsz; (void)fp;
2999 return -1;
3000}
3001
3002static inline int lite3_json_print(const unsigned char *buf, size_t buflen, size_t ofs)
3003{
3004 (void)buf; (void)buflen; (void)ofs;
3005 return 0;
3006}
3007
3008static inline char *lite3_json_enc(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3009{
3010 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3011 return NULL;
3012}
3013
3014static inline char *lite3_json_enc_pretty(const unsigned char *buf, size_t buflen, size_t ofs, size_t *out_len)
3015{
3016 (void)buf; (void)buflen; (void)ofs; (void)out_len;
3017 return NULL;
3018}
3019
3020static 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)
3021{
3022 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3023 return -1;
3024}
3025
3026static 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)
3027{
3028 (void)buf; (void)buflen; (void)ofs; (void)json_buf; (void)json_bufsz;
3029 return -1;
3030}
3031#endif
3033
3034#ifdef __cplusplus
3035}
3036#endif
3037
3038#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:1258
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:1214
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:1335
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:1194
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:1391
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:1236
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:1280
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:1366
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:1308
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:2551
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:2436
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:2410
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:2462
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:2519
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:2488
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:2577
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:1444
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:1623
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:1591
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:1488
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:1563
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:1465
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:1534
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:1649
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:1511
#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:333
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:2644
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:510
@ LITE3_TYPE_ARRAY
maps to 'array' type in JSON
Definition lite3.h:518
@ LITE3_TYPE_INVALID
any type value equal or greater than this is considered invalid
Definition lite3.h:519
@ LITE3_TYPE_STRING
maps to 'string' type in JSON
Definition lite3.h:516
@ LITE3_TYPE_BOOL
maps to 'boolean' type in JSON; underlying datatype: bool
Definition lite3.h:512
@ LITE3_TYPE_BYTES
coverted to base64 string in JSON
Definition lite3.h:515
@ LITE3_TYPE_F64
maps to 'number' type in JSON; underlying datatype: double
Definition lite3.h:514
@ LITE3_TYPE_OBJECT
maps to 'object' type in JSON
Definition lite3.h:517
@ LITE3_TYPE_I64
maps to 'number' type in JSON; underlying datatype: int64_t
Definition lite3.h:513
@ LITE3_TYPE_NULL
maps to 'null' type in JSON
Definition lite3.h:511
@ LITE3_TYPE_COUNT
not an actual type, only used for counting
Definition lite3.h:520
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:1844
static size_t lite3_val_type_size(lite3_val *val)
Returns the size of the value type.
Definition lite3.h:2709
static const char * lite3_val_str_n(lite3_val *val, size_t *out_len)
Definition lite3.h:2757
static enum lite3_type lite3_val_type(lite3_val *val)
Returns the value type of *val
Definition lite3.h:2694
Struct holding a reference to a bytes value inside a Lite³ buffer.
Definition lite3.h:572
uint32_t gen
generation of the Lite³ buffer when this struct was returned
Definition lite3.h:573
uint32_t len
byte array length (bytes)
Definition lite3.h:574
const unsigned char * ptr
byte array pointer to bytes inside Lite³ buffer
Definition lite3.h:575
Struct containing iterator state.
Definition lite3.h:2626
Struct holding a reference to a string inside a Lite³ buffer.
Definition lite3.h:601
uint32_t len
char array length (characters, exclusive of NULL-terminator)
Definition lite3.h:603
const char * ptr
char array pointer to string inside Lite³ buffer
Definition lite3.h:604
uint32_t gen
generation of the Lite³ buffer when this struct was returned
Definition lite3.h:602
Struct representing a value inside a Lite³ buffer.
Definition lite3.h:531