Lite³
A JSON-Compatible Zero-Copy Serialization Format
Loading...
Searching...
No Matches
lite3_context_api.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_CONTEXT_API_H
40#define LITE3_CONTEXT_API_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#include "lite3.h"
50
51
52
53#ifdef __cplusplus
54extern "C" {
55#endif
56
130#define LITE3_CONTEXT_BUF_SIZE_MIN 1024
131static_assert(LITE3_CONTEXT_BUF_SIZE_MIN > (size_t)LITE3_NODE_ALIGNMENT_MASK, "LITE3_CONTEXT_BUF_SIZE_MIN must be greater than LITE3_NODE_ALIGNMENT_MASK");
132
140typedef struct lite3_ctx {
141 uint8_t __attribute__((aligned(LITE3_NODE_ALIGNMENT))) *buf;
142 size_t buflen;
143 size_t bufsz;
144 void *underlying_buf;
146
147
148
173
183 const unsigned char *buf,
184 size_t buflen
185);
186
201 unsigned char *buf,
202 size_t buflen,
203 size_t bufsz
204);
205
217
230 lite3_ctx *ctx,
231 const unsigned char *buf,
232 size_t buflen
233);
234
244
245#ifndef DOXYGEN_IGNORE
246// Private function
247int lite3_ctx_grow_impl(lite3_ctx *ctx);
248#endif // DOXYGEN_IGNORE
250
251
252
273static inline int lite3_ctx_init_obj(lite3_ctx *ctx)
274{
275 return lite3_init_obj(ctx->buf, &ctx->buflen, ctx->bufsz);
276}
277
287static inline int lite3_ctx_init_arr(lite3_ctx *ctx)
288{
289 return lite3_init_arr(ctx->buf, &ctx->buflen, ctx->bufsz);
290}
292
293
294
330#define lite3_ctx_set_null(ctx, ofs, key) ({ \
331 const char *__lite3_key__ = (key); \
332 lite3_ctx_set_null_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
333})
334#ifndef DOXYGEN_IGNORE
335static inline int lite3_ctx_set_null_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
336{
337 int ret;
338 if ((ret = _lite3_verify_obj_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
339 return ret;
340 lite3_val *val;
341 errno = 0;
342 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0) {
343 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
344 continue;
345 } else {
346 return ret;
347 }
348 }
349 val->type = (uint8_t)LITE3_TYPE_NULL;
350 return ret;
351}
352#endif // DOXYGEN_IGNORE
353
365#define lite3_ctx_set_bool(ctx, ofs, key, value) ({ \
366 const char *__lite3_key__ = (key); \
367 _lite3_ctx_set_bool_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), value); \
368})
369#ifndef DOXYGEN_IGNORE
370static inline int _lite3_ctx_set_bool_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, bool value)
371{
372 int ret;
373 if ((ret = _lite3_verify_obj_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
374 return ret;
375 lite3_val *val;
376 errno = 0;
377 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0) {
378 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
379 continue;
380 } else {
381 return ret;
382 }
383 }
384 val->type = (uint8_t)LITE3_TYPE_BOOL;
385 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
386 return ret;
387}
388#endif // DOXYGEN_IGNORE
389
401#define lite3_ctx_set_i64(ctx, ofs, key, value) ({ \
402 const char *__lite3_key__ = (key); \
403 _lite3_ctx_set_i64_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), value); \
404})
405#ifndef DOXYGEN_IGNORE
406static inline int _lite3_ctx_set_i64_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, int64_t value)
407{
408 int ret;
409 if ((ret = _lite3_verify_obj_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
410 return ret;
411 lite3_val *val;
412 errno = 0;
413 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0) {
414 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
415 continue;
416 } else {
417 return ret;
418 }
419 }
420 val->type = (uint8_t)LITE3_TYPE_I64;
421 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
422 return ret;
423}
424#endif // DOXYGEN_IGNORE
425
437#define lite3_ctx_set_f64(ctx, ofs, key, value) ({ \
438 const char *__lite3_key__ = (key); \
439 _lite3_ctx_set_f64_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), value); \
440})
441#ifndef DOXYGEN_IGNORE
442static inline int _lite3_ctx_set_f64_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, double value)
443{
444 int ret;
445 if ((ret = _lite3_verify_obj_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
446 return ret;
447 lite3_val *val;
448 errno = 0;
449 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0) {
450 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
451 continue;
452 } else {
453 return ret;
454 }
455 }
456 val->type = (uint8_t)LITE3_TYPE_F64;
457 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
458 return ret;
459}
460#endif // DOXYGEN_IGNORE
461
474#define lite3_ctx_set_bytes(ctx, ofs, key, bytes, bytes_len) ({ \
475 const char *__lite3_key__ = (key); \
476 _lite3_ctx_set_bytes_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), bytes, bytes_len); \
477})
478#ifndef DOXYGEN_IGNORE
479static inline int _lite3_ctx_set_bytes_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, const unsigned char *__restrict bytes, size_t bytes_len)
480{
481 int ret;
482 if ((ret = _lite3_verify_obj_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
483 return ret;
484 lite3_val *val;
485 errno = 0;
486 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0) {
487 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
488 continue;
489 } else {
490 return ret;
491 }
492 }
493 val->type = (uint8_t)LITE3_TYPE_BYTES;
494 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
495 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
496 return ret;
497}
498#endif // DOXYGEN_IGNORE
499
515#define lite3_ctx_set_str(ctx, ofs, key, str) ({ \
516 const char *__lite3_key__ = (key); \
517 _lite3_ctx_set_str_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), str); \
518})
519#ifndef DOXYGEN_IGNORE
520static inline int _lite3_ctx_set_str_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, const char *__restrict str)
521{
522 int ret;
523 if ((ret = _lite3_verify_obj_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
524 return ret;
525 lite3_val *val;
526 size_t str_size = strlen(str) + 1;
527 errno = 0;
528 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0) {
529 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
530 continue;
531 } else {
532 return ret;
533 }
534 }
535 val->type = (uint8_t)LITE3_TYPE_STRING;
536 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
537 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
538 return ret;
539}
540#endif // DOXYGEN_IGNORE
541
557#define lite3_ctx_set_str_n(ctx, ofs, key, str, str_len) ({ \
558 const char *__lite3_key__ = (key); \
559 _lite3_ctx_set_str_n_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), str, str_len); \
560})
561#ifndef DOXYGEN_IGNORE
562static inline int _lite3_ctx_set_str_n_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, const char *__restrict str, size_t str_len)
563{
564 int ret;
565 if ((ret = _lite3_verify_obj_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
566 return ret;
567 lite3_val *val;
568 size_t str_size = str_len + 1;
569 errno = 0;
570 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, key, key_data, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0) {
571 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
572 continue;
573 } else {
574 return ret;
575 }
576 }
577 val->type = (uint8_t)LITE3_TYPE_STRING;
578 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
579 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
580 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
581 return ret;
582}
583#endif // DOXYGEN_IGNORE
584
596#define lite3_ctx_set_obj(ctx, ofs, key, out_ofs) ({ \
597 lite3_ctx *__lite3_ctx__ = (ctx); \
598 size_t __lite3_ofs__ = (ofs); \
599 int __lite3_ret__; \
600 if ((__lite3_ret__ = _lite3_verify_obj_set( \
601 __lite3_ctx__->buf, \
602 &__lite3_ctx__->buflen, \
603 __lite3_ofs__, \
604 __lite3_ctx__->bufsz)) < 0) \
605 return __lite3_ret__; \
606 \
607 const char *__lite3_key__ = (key); \
608 errno = 0; \
609 while ((__lite3_ret__ = lite3_set_obj_impl( \
610 __lite3_ctx__->buf, \
611 &__lite3_ctx__->buflen, \
612 __lite3_ofs__, \
613 __lite3_ctx__->bufsz, \
614 __lite3_key__, \
615 LITE3_KEY_DATA(key), \
616 out_ofs)) < 0) { \
617 if (errno == ENOBUFS && (lite3_ctx_grow_impl(__lite3_ctx__) == 0)) { \
618 continue; \
619 } else { \
620 return __lite3_ret__; \
621 } \
622 } \
623 __lite3_ret__; \
624})
625
637#define lite3_ctx_set_arr(ctx, ofs, key, out_ofs) ({ \
638 lite3_ctx *__lite3_ctx__ = (ctx); \
639 size_t __lite3_ofs__ = (ofs); \
640 int __lite3_ret__; \
641 if ((__lite3_ret__ = _lite3_verify_obj_set( \
642 __lite3_ctx__->buf, \
643 &__lite3_ctx__->buflen, \
644 __lite3_ofs__, \
645 __lite3_ctx__->bufsz)) < 0) \
646 return __lite3_ret__; \
647 \
648 const char *__lite3_key__ = (key); \
649 errno = 0; \
650 while ((__lite3_ret__ = lite3_set_arr_impl( \
651 __lite3_ctx__->buf, \
652 &__lite3_ctx__->buflen, \
653 __lite3_ofs__, \
654 __lite3_ctx__->bufsz, \
655 __lite3_key__, \
656 LITE3_KEY_DATA(key), \
657 out_ofs)) < 0) { \
658 if (errno == ENOBUFS && (lite3_ctx_grow_impl(__lite3_ctx__) == 0)) { \
659 continue; \
660 } else { \
661 return __lite3_ret__; \
662 } \
663 } \
664 __lite3_ret__; \
665})
667
668
669
689#ifndef DOXYGEN_IGNORE
690static inline int _lite3_ctx_set_by_index(lite3_ctx *ctx, size_t ofs, uint32_t index, size_t val_len, lite3_val **out)
691{
692 int ret;
693 if ((ret = _lite3_verify_arr_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
694 return ret;
695 uint32_t size = (*(uint32_t *)(ctx->buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
696 if (LITE3_UNLIKELY(index > size)) {
697 LITE3_PRINT_ERROR("INVALID ARGUMENT: ARRAY INDEX %u OUT OF BOUNDS (size == %u)\n", index, size);
698 errno = EINVAL;
699 return -1;
700 }
701 lite3_key_data key_data = {
702 .hash = index,
703 .size = 0,
704 };
705 errno = 0;
706 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, NULL, key_data, val_len, out)) < 0) {
707 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
708 continue;
709 } else {
710 return ret;
711 }
712 }
713 return ret;
714}
715
716static inline int _lite3_ctx_set_by_append(lite3_ctx *ctx, size_t ofs, size_t val_len, lite3_val **out)
717{
718 int ret;
719 if ((ret = _lite3_verify_arr_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
720 return ret;
721 uint32_t size = (*(uint32_t *)(ctx->buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
722 lite3_key_data key_data = {
723 .hash = size,
724 .size = 0,
725 };
726 errno = 0;
727 while ((ret = lite3_set_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, NULL, key_data, val_len, out)) < 0) {
728 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
729 continue;
730 } else {
731 return ret;
732 }
733 }
734 return ret;
735}
736#endif // DOXYGEN_IGNORE
737
745 lite3_ctx *ctx,
746 size_t ofs)
747{
748 lite3_val *val;
749 int ret;
750 if ((ret = _lite3_ctx_set_by_append(ctx, ofs, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
751 return ret;
752 val->type = (uint8_t)LITE3_TYPE_NULL;
753 return ret;
754}
755
763 lite3_ctx *ctx,
764 size_t ofs,
765 bool value)
766{
767 lite3_val *val;
768 int ret;
769 if ((ret = _lite3_ctx_set_by_append(ctx, ofs, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
770 return ret;
771 val->type = (uint8_t)LITE3_TYPE_BOOL;
772 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
773 return ret;
774}
775
782static inline int lite3_ctx_arr_append_i64(
783 lite3_ctx *ctx,
784 size_t ofs,
785 int64_t value)
786{
787 lite3_val *val;
788 int ret;
789 if ((ret = _lite3_ctx_set_by_append(ctx, ofs, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
790 return ret;
791 val->type = (uint8_t)LITE3_TYPE_I64;
792 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
793 return ret;
794}
795
802static inline int lite3_ctx_arr_append_f64(
803 lite3_ctx *ctx,
804 size_t ofs,
805 double value)
806{
807 lite3_val *val;
808 int ret;
809 if ((ret = _lite3_ctx_set_by_append(ctx, ofs, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
810 return ret;
811 val->type = (uint8_t)LITE3_TYPE_F64;
812 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
813 return ret;
814}
815
823 lite3_ctx *ctx,
824 size_t ofs,
825 const unsigned char *__restrict bytes,
826 size_t bytes_len)
827{
828 lite3_val *val;
829 int ret;
830 if ((ret = _lite3_ctx_set_by_append(ctx, ofs, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
831 return ret;
832 val->type = (uint8_t)LITE3_TYPE_BYTES;
833 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
834 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
835 return ret;
836}
837
848static inline int lite3_ctx_arr_append_str(
849 lite3_ctx *ctx,
850 size_t ofs,
851 const char *__restrict str)
852{
853 lite3_val *val;
854 size_t str_size = strlen(str) + 1;
855 int ret;
856 if ((ret = _lite3_ctx_set_by_append(ctx, ofs, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
857 return ret;
858 val->type = (uint8_t)LITE3_TYPE_STRING;
859 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
860 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
861 return ret;
862}
863
874 lite3_ctx *ctx,
875 size_t ofs,
876 const char *__restrict str,
877 size_t str_len)
878{
879 lite3_val *val;
880 size_t str_size = str_len + 1;
881 int ret;
882 if ((ret = _lite3_ctx_set_by_append(ctx, ofs, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
883 return ret;
884 val->type = (uint8_t)LITE3_TYPE_STRING;
885 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
886 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
887 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
888 return ret;
889}
890
897static inline int lite3_ctx_arr_append_obj(
898 lite3_ctx *ctx,
899 size_t ofs,
900 size_t *__restrict out_ofs)
901{
902 int ret;
903 if ((ret = _lite3_verify_arr_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
904 return ret;
905 errno = 0;
906 while ((ret = lite3_arr_append_obj_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, out_ofs)) < 0) {
907 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
908 continue;
909 } else {
910 return ret;
911 }
912 }
913 return ret;
914}
915
922static inline int lite3_ctx_arr_append_arr(
923 lite3_ctx *ctx,
924 size_t ofs,
925 size_t *__restrict out_ofs)
926{
927 int ret;
928 if ((ret = _lite3_verify_arr_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
929 return ret;
930 errno = 0;
931 while ((ret = lite3_arr_append_arr_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, out_ofs)) < 0) {
932 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
933 continue;
934 } else {
935 return ret;
936 }
937 }
938 return ret;
939}
941
942
974static inline int lite3_ctx_arr_set_null(
975 lite3_ctx *ctx,
976 size_t ofs,
977 uint32_t index)
978{
979 lite3_val *val;
980 int ret;
981 if ((ret = _lite3_ctx_set_by_index(ctx, ofs, index, lite3_type_sizes[LITE3_TYPE_NULL], &val)) < 0)
982 return ret;
983 val->type = (uint8_t)LITE3_TYPE_NULL;
984 return ret;
985}
986
993static inline int lite3_ctx_arr_set_bool(
994 lite3_ctx *ctx,
995 size_t ofs,
996 uint32_t index,
997 bool value)
998{
999 lite3_val *val;
1000 int ret;
1001 if ((ret = _lite3_ctx_set_by_index(ctx, ofs, index, lite3_type_sizes[LITE3_TYPE_BOOL], &val)) < 0)
1002 return ret;
1003 val->type = (uint8_t)LITE3_TYPE_BOOL;
1004 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_BOOL]);
1005 return ret;
1006}
1007
1014static inline int lite3_ctx_arr_set_i64(
1015 lite3_ctx *ctx,
1016 size_t ofs,
1017 uint32_t index,
1018 int64_t value)
1019{
1020 lite3_val *val;
1021 int ret;
1022 if ((ret = _lite3_ctx_set_by_index(ctx, ofs, index, lite3_type_sizes[LITE3_TYPE_I64], &val)) < 0)
1023 return ret;
1024 val->type = (uint8_t)LITE3_TYPE_I64;
1025 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_I64]);
1026 return ret;
1027}
1028
1035static inline int lite3_ctx_arr_set_f64(
1036 lite3_ctx *ctx,
1037 size_t ofs,
1038 uint32_t index,
1039 double value)
1040{
1041 lite3_val *val;
1042 int ret;
1043 if ((ret = _lite3_ctx_set_by_index(ctx, ofs, index, lite3_type_sizes[LITE3_TYPE_F64], &val)) < 0)
1044 return ret;
1045 val->type = (uint8_t)LITE3_TYPE_F64;
1046 memcpy(val->val, &value, lite3_type_sizes[LITE3_TYPE_F64]);
1047 return ret;
1048}
1049
1056static inline int lite3_ctx_arr_set_bytes(
1057 lite3_ctx *ctx,
1058 size_t ofs,
1059 uint32_t index,
1060 const unsigned char *__restrict bytes,
1061 size_t bytes_len)
1062{
1063 lite3_val *val;
1064 int ret;
1065 if ((ret = _lite3_ctx_set_by_index(ctx, ofs, index, lite3_type_sizes[LITE3_TYPE_BYTES] + bytes_len, &val)) < 0)
1066 return ret;
1067 val->type = (uint8_t)LITE3_TYPE_BYTES;
1068 memcpy(val->val, &bytes_len, lite3_type_sizes[LITE3_TYPE_BYTES]);
1069 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_BYTES], bytes, bytes_len);
1070 return ret;
1071}
1072
1083static inline int lite3_ctx_arr_set_str(
1084 lite3_ctx *ctx,
1085 size_t ofs,
1086 uint32_t index,
1087 const char *__restrict str)
1088{
1089 lite3_val *val;
1090 size_t str_size = strlen(str) + 1;
1091 int ret;
1092 if ((ret = _lite3_ctx_set_by_index(ctx, ofs, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1093 return ret;
1094 val->type = (uint8_t)LITE3_TYPE_STRING;
1095 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1096 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_size);
1097 return ret;
1098}
1099
1109static inline int lite3_ctx_arr_set_str_n(
1110 lite3_ctx *ctx,
1111 size_t ofs,
1112 uint32_t index,
1113 const char *__restrict str,
1114 size_t str_len)
1115{
1116 lite3_val *val;
1117 size_t str_size = str_len + 1;
1118 int ret;
1119 if ((ret = _lite3_ctx_set_by_index(ctx, ofs, index, lite3_type_sizes[LITE3_TYPE_STRING] + str_size, &val)) < 0)
1120 return ret;
1121 val->type = (uint8_t)LITE3_TYPE_STRING;
1122 memcpy(val->val, &str_size, lite3_type_sizes[LITE3_TYPE_STRING]);
1123 memcpy(val->val + lite3_type_sizes[LITE3_TYPE_STRING], str, str_len);
1124 *(val->val + lite3_type_sizes[LITE3_TYPE_STRING] + str_len) = 0x00; // Insert NULL-terminator
1125 return ret;
1126}
1127
1134static inline int lite3_ctx_arr_set_obj(
1135 lite3_ctx *ctx,
1136 size_t ofs,
1137 uint32_t index,
1138 size_t *__restrict out_ofs)
1139{
1140 int ret;
1141 if ((ret = _lite3_verify_arr_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
1142 return ret;
1143 errno = 0;
1144 while ((ret = lite3_arr_set_obj_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, index, out_ofs)) < 0) {
1145 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
1146 continue;
1147 } else {
1148 return ret;
1149 }
1150 }
1151 return ret;
1152}
1153
1160static inline int lite3_ctx_arr_set_arr(
1161 lite3_ctx *ctx,
1162 size_t ofs,
1163 uint32_t index,
1164 size_t *__restrict out_ofs)
1165{
1166 int ret;
1167 if ((ret = _lite3_verify_arr_set(ctx->buf, &ctx->buflen, ofs, ctx->bufsz)) < 0)
1168 return ret;
1169 errno = 0;
1170 while ((ret = lite3_arr_set_arr_impl(ctx->buf, &ctx->buflen, ofs, ctx->bufsz, index, out_ofs)) < 0) {
1171 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
1172 continue;
1173 } else {
1174 return ret;
1175 }
1176 }
1177 return ret;
1178}
1180
1181
1199#ifdef LITE3_DEBUG
1200static inline void lite3_ctx_print(lite3_ctx *ctx) { lite3_print(ctx->buf, ctx->buflen); }
1201#else
1202static inline void lite3_ctx_print(lite3_ctx *ctx) { (void)ctx; }
1203#endif
1204
1215#define lite3_ctx_get_type(ctx, ofs, key) ({ \
1216 const char *__lite3_key__ = (key); \
1217 _lite3_ctx_get_type_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1218})
1219#ifndef DOXYGEN_IGNORE
1220static inline enum lite3_type _lite3_ctx_get_type_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1221{
1222 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1223 return LITE3_TYPE_INVALID;
1224 lite3_val *val;
1225 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1226 return LITE3_TYPE_INVALID;
1227 enum lite3_type type = (enum lite3_type)val->type;
1228 return type;
1229}
1230#endif // DOXYGEN_IGNORE
1231
1246#define lite3_ctx_get_type_size(ctx, ofs, key, out) ({ \
1247 const char *__lite3_key__ = (key); \
1248 _lite3_ctx_get_type_size_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1249})
1250#ifndef DOXYGEN_IGNORE
1251static inline int _lite3_ctx_get_type_size_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, size_t *__restrict out)
1252{
1253 int ret;
1254 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1255 return ret;
1256 lite3_val *val;
1257 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1258 return ret;
1259 if (val->type == LITE3_TYPE_STRING || val->type == LITE3_TYPE_BYTES) {
1260 *out = 0;
1261 memcpy(out, &val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
1262 return ret;
1263 }
1264 *out = lite3_type_sizes[val->type];
1265 return ret;
1266}
1267#endif // DOXYGEN_IGNORE
1268
1279#define lite3_ctx_exists(ctx, ofs, key) ({ \
1280 const char *__lite3_key__ = (key); \
1281 _lite3_ctx_exists_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1282})
1283#ifndef DOXYGEN_IGNORE
1284static inline bool _lite3_ctx_exists_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1285{
1286 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1287 return false;
1288 lite3_val *val;
1289 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1290 return false;
1291 return true;
1292}
1293#endif // DOXYGEN_IGNORE
1294
1303static inline int lite3_ctx_count(
1304 lite3_ctx *ctx,
1305 size_t ofs,
1306 uint32_t *out)
1307{
1308 int ret;
1309 if ((ret = _lite3_verify_get(ctx->buf, ctx->buflen, ofs)) < 0)
1310 return ret;
1311 enum lite3_type type = (enum lite3_type)(*(ctx->buf + ofs));
1312 if (LITE3_UNLIKELY(!(type == LITE3_TYPE_OBJECT || type == LITE3_TYPE_ARRAY))) {
1313 LITE3_PRINT_ERROR("INVALID ARGUMENT: EXPECTING ARRAY OR OBJECT TYPE\n");
1314 errno = EINVAL;
1315 return -1;
1316 }
1317 *out = (*(uint32_t *)(ctx->buf + ofs + LITE3_NODE_SIZE_KC_OFFSET)) >> LITE3_NODE_SIZE_SHIFT;
1318 return ret;
1319}
1320
1331#define lite3_ctx_is_null(ctx, ofs, key) ({ \
1332 const char *__lite3_key__ = (key); \
1333 _lite3_ctx_is_null_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1334})
1335#ifndef DOXYGEN_IGNORE
1336static inline bool _lite3_ctx_is_null_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1337{
1338 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1339 return false;
1340 lite3_val *val;
1341 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1342 return false;
1343 return val->type == LITE3_TYPE_NULL;
1344}
1345#endif // DOXYGEN_IGNORE
1346
1357#define lite3_ctx_is_bool(ctx, ofs, key) ({ \
1358 const char *__lite3_key__ = (key); \
1359 _lite3_ctx_is_bool_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1360})
1361#ifndef DOXYGEN_IGNORE
1362static inline bool _lite3_ctx_is_bool_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1363{
1364 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1365 return false;
1366 lite3_val *val;
1367 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1368 return false;
1369 return val->type == LITE3_TYPE_BOOL;
1370}
1371#endif // DOXYGEN_IGNORE
1372
1383#define lite3_ctx_is_i64(ctx, ofs, key) ({ \
1384 const char *__lite3_key__ = (key); \
1385 _lite3_ctx_is_i64_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1386})
1387#ifndef DOXYGEN_IGNORE
1388static inline bool _lite3_ctx_is_i64_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1389{
1390 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1391 return false;
1392 lite3_val *val;
1393 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1394 return false;
1395 return val->type == LITE3_TYPE_I64;
1396}
1397#endif // DOXYGEN_IGNORE
1398
1409#define lite3_ctx_is_f64(ctx, ofs, key) ({ \
1410 const char *__lite3_key__ = (key); \
1411 _lite3_ctx_is_f64_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1412})
1413#ifndef DOXYGEN_IGNORE
1414static inline bool _lite3_ctx_is_f64_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1415{
1416 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1417 return false;
1418 lite3_val *val;
1419 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1420 return false;
1421 return val->type == LITE3_TYPE_F64;
1422}
1423#endif // DOXYGEN_IGNORE
1424
1435#define lite3_ctx_is_bytes(ctx, ofs, key) ({ \
1436 const char *__lite3_key__ = (key); \
1437 _lite3_ctx_is_bytes_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1438})
1439#ifndef DOXYGEN_IGNORE
1440static inline bool _lite3_ctx_is_bytes_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1441{
1442 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1443 return false;
1444 lite3_val *val;
1445 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1446 return false;
1447 return val->type == LITE3_TYPE_BYTES;
1448}
1449#endif // DOXYGEN_IGNORE
1450
1461#define lite3_ctx_is_str(ctx, ofs, key) ({ \
1462 const char *__lite3_key__ = (key); \
1463 _lite3_ctx_is_str_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1464})
1465#ifndef DOXYGEN_IGNORE
1466static inline bool _lite3_ctx_is_str_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1467{
1468 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1469 return false;
1470 lite3_val *val;
1471 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1472 return false;
1473 return val->type == LITE3_TYPE_STRING;
1474}
1475#endif // DOXYGEN_IGNORE
1476
1487#define lite3_ctx_is_obj(ctx, ofs, key) ({ \
1488 const char *__lite3_key__ = (key); \
1489 _lite3_ctx_is_obj_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1490})
1491#ifndef DOXYGEN_IGNORE
1492static inline bool _lite3_ctx_is_obj_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1493{
1494 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1495 return false;
1496 lite3_val *val;
1497 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1498 return false;
1499 return val->type == LITE3_TYPE_OBJECT;
1500}
1501#endif // DOXYGEN_IGNORE
1502
1513#define lite3_ctx_is_arr(ctx, ofs, key) ({ \
1514 const char *__lite3_key__ = (key); \
1515 _lite3_ctx_is_arr_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key)); \
1516})
1517#ifndef DOXYGEN_IGNORE
1518static inline bool _lite3_ctx_is_arr_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data)
1519{
1520 if (_lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs) < 0)
1521 return false;
1522 lite3_val *val;
1523 if (lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val) < 0)
1524 return false;
1525 return val->type == LITE3_TYPE_ARRAY;
1526}
1527#endif // DOXYGEN_IGNORE
1529
1530
1531
1563#define lite3_ctx_get(ctx, ofs, key, out) ({ \
1564 lite3_ctx *__lite3_ctx__ = (ctx); \
1565 size_t __lite3_ofs__ = (ofs); \
1566 int __lite3_ret__; \
1567 if ((__lite3_ret__ = _lite3_verify_get(__lite3_ctx__->buf, __lite3_ctx__->buflen, __lite3_ofs__)) < 0) \
1568 return __lite3_ret__; \
1569 const char *__lite3_key__ = (key); \
1570 lite3_get_impl(__lite3_ctx__->buf, __lite3_ctx__->buflen, __lite3_ofs__, __lite3_key__, LITE3_KEY_DATA(key), out); \
1571})
1572
1584#define lite3_ctx_get_bool(ctx, ofs, key, out) ({ \
1585 const char *__lite3_key__ = (key); \
1586 _lite3_ctx_get_bool_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1587})
1588#ifndef DOXYGEN_IGNORE
1589static inline int _lite3_ctx_get_bool_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, bool *out)
1590{
1591 int ret;
1592 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1593 return ret;
1594 lite3_val *val;
1595 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1596 return ret;
1597 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
1598 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
1599 errno = EINVAL;
1600 return -1;
1601 }
1602 *out = (bool)(*(val->val));
1603 return ret;
1604}
1605#endif // DOXYGEN_IGNORE
1606
1618#define lite3_ctx_get_i64(ctx, ofs, key, out) ({ \
1619 const char *__lite3_key__ = (key); \
1620 _lite3_ctx_get_i64_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1621})
1622#ifndef DOXYGEN_IGNORE
1623static inline int _lite3_ctx_get_i64_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, int64_t *out)
1624{
1625 int ret;
1626 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1627 return ret;
1628 lite3_val *val;
1629 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1630 return ret;
1631 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
1632 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
1633 errno = EINVAL;
1634 return -1;
1635 }
1636 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
1637 return ret;
1638}
1639#endif // DOXYGEN_IGNORE
1640
1652#define lite3_ctx_get_f64(ctx, ofs, key, out) ({ \
1653 const char *__lite3_key__ = (key); \
1654 _lite3_ctx_get_f64_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1655})
1656#ifndef DOXYGEN_IGNORE
1657static inline int _lite3_ctx_get_f64_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, double *out)
1658{
1659 int ret;
1660 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1661 return ret;
1662 lite3_val *val;
1663 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1664 return ret;
1665 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
1666 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
1667 errno = EINVAL;
1668 return -1;
1669 }
1670 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
1671 return ret;
1672}
1673#endif // DOXYGEN_IGNORE
1674
1686#define lite3_ctx_get_bytes(ctx, ofs, key, out) ({ \
1687 const char *__lite3_key__ = (key); \
1688 _lite3_ctx_get_bytes_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1689})
1690#ifndef DOXYGEN_IGNORE
1691static inline int _lite3_ctx_get_bytes_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, lite3_bytes *out)
1692{
1693 int ret;
1694 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1695 return ret;
1696 lite3_val *val;
1697 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1698 return ret;
1699 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
1700 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
1701 errno = EINVAL;
1702 return -1;
1703 }
1704 *out = (lite3_bytes){
1705 .gen = *(uint32_t *)(ctx->buf),
1706 .len = 0,
1707 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
1708 };
1709 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
1710 return ret;
1711}
1712#endif // DOXYGEN_IGNORE
1713
1725#define lite3_ctx_get_str(ctx, ofs, key, out) ({ \
1726 const char *__lite3_key__ = (key); \
1727 _lite3_ctx_get_str_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1728})
1729#ifndef DOXYGEN_IGNORE
1730static inline int _lite3_ctx_get_str_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, lite3_str *out)
1731{
1732 int ret;
1733 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1734 return ret;
1735 lite3_val *val;
1736 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1737 return ret;
1738 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
1739 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
1740 errno = EINVAL;
1741 return -1;
1742 }
1743 *out = (lite3_str){
1744 .gen = *(uint32_t *)(ctx->buf),
1745 .len = 0,
1746 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
1747 };
1748 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
1749 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
1750 return ret;
1751}
1752#endif // DOXYGEN_IGNORE
1753
1765#define lite3_ctx_get_obj(ctx, ofs, key, out) ({ \
1766 const char *__lite3_key__ = (key); \
1767 _lite3_ctx_get_obj_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1768})
1769#ifndef DOXYGEN_IGNORE
1770static inline int _lite3_ctx_get_obj_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, size_t *__restrict out_ofs)
1771{
1772 int ret;
1773 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1774 return ret;
1775 lite3_val *val;
1776 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1777 return ret;
1778 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
1779 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
1780 errno = EINVAL;
1781 return -1;
1782 }
1783 *out_ofs = (size_t)((uint8_t *)val - ctx->buf);
1784 return ret;
1785}
1786#endif // DOXYGEN_IGNORE
1787
1799#define lite3_ctx_get_arr(ctx, ofs, key, out) ({ \
1800 const char *__lite3_key__ = (key); \
1801 _lite3_ctx_get_arr_impl(ctx, ofs, __lite3_key__, LITE3_KEY_DATA(key), out); \
1802})
1803#ifndef DOXYGEN_IGNORE
1804static inline int _lite3_ctx_get_arr_impl(lite3_ctx *ctx, size_t ofs, const char *__restrict key, lite3_key_data key_data, size_t *__restrict out_ofs)
1805{
1806 int ret;
1807 if ((ret = _lite3_verify_obj_get(ctx->buf, ctx->buflen, ofs)) < 0)
1808 return ret;
1809 lite3_val *val;
1810 if ((ret = lite3_get_impl(ctx->buf, ctx->buflen, ofs, key, key_data, &val)) < 0)
1811 return ret;
1812 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
1813 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
1814 errno = EINVAL;
1815 return -1;
1816 }
1817 *out_ofs = (size_t)((uint8_t *)val - ctx->buf);
1818 return ret;
1819}
1820#endif // DOXYGEN_IGNORE
1822
1823
1824
1847static inline int lite3_ctx_arr_get_bool(
1848 lite3_ctx *ctx,
1849 size_t ofs,
1850 uint32_t index,
1851 bool *out)
1852{
1853 lite3_val *val;
1854 int ret;
1855 if ((ret = _lite3_get_by_index(ctx->buf, ctx->buflen, ofs, index, &val)) < 0)
1856 return ret;
1857 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BOOL)) {
1858 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BOOL\n");
1859 errno = EINVAL;
1860 return -1;
1861 }
1862 *out = (bool)(*(val->val));
1863 return ret;
1864}
1865
1872static inline int lite3_ctx_arr_get_i64(
1873 lite3_ctx *ctx,
1874 size_t ofs,
1875 uint32_t index,
1876 int64_t *out)
1877{
1878 lite3_val *val;
1879 int ret;
1880 if ((ret = _lite3_get_by_index(ctx->buf, ctx->buflen, ofs, index, &val)) < 0)
1881 return ret;
1882 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_I64)) {
1883 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_I64\n");
1884 errno = EINVAL;
1885 return -1;
1886 }
1887 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_I64]);
1888 return ret;
1889}
1890
1897static inline int lite3_ctx_arr_get_f64(
1898 lite3_ctx *ctx,
1899 size_t ofs,
1900 uint32_t index,
1901 double *out)
1902{
1903 lite3_val *val;
1904 int ret;
1905 if ((ret = _lite3_get_by_index(ctx->buf, ctx->buflen, ofs, index, &val)) < 0)
1906 return ret;
1907 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_F64)) {
1908 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_F64\n");
1909 errno = EINVAL;
1910 return -1;
1911 }
1912 memcpy(out, val->val, lite3_type_sizes[LITE3_TYPE_F64]);
1913 return ret;
1914}
1915
1922static inline int lite3_ctx_arr_get_bytes(
1923 lite3_ctx *ctx,
1924 size_t ofs,
1925 uint32_t index,
1926 lite3_bytes *out)
1927{
1928 lite3_val *val;
1929 int ret;
1930 if ((ret = _lite3_get_by_index(ctx->buf, ctx->buflen, ofs, index, &val)) < 0)
1931 return ret;
1932 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_BYTES)) {
1933 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_BYTES\n");
1934 errno = EINVAL;
1935 return -1;
1936 }
1937 *out = (lite3_bytes){
1938 .gen = *(uint32_t *)(ctx->buf),
1939 .len = 0,
1940 .ptr = val->val + lite3_type_sizes[LITE3_TYPE_BYTES]
1941 };
1942 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_BYTES]);
1943 return ret;
1944}
1945
1952static inline int lite3_ctx_arr_get_str(
1953 lite3_ctx *ctx,
1954 size_t ofs,
1955 uint32_t index,
1956 lite3_str *out)
1957{
1958 lite3_val *val;
1959 int ret;
1960 if ((ret = _lite3_get_by_index(ctx->buf, ctx->buflen, ofs, index, &val)) < 0)
1961 return ret;
1962 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_STRING)) {
1963 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_STRING\n");
1964 errno = EINVAL;
1965 return -1;
1966 }
1967 *out = (lite3_str){
1968 .gen = *(uint32_t *)(ctx->buf),
1969 .len = 0,
1970 .ptr = (char *)(val->val + lite3_type_sizes[LITE3_TYPE_STRING])
1971 };
1972 memcpy(&out->len, val->val, lite3_type_sizes[LITE3_TYPE_STRING]);
1973 --out->len; // Lite³ stores string size including NULL-terminator. Correction required for public API.
1974 return ret;
1975}
1976
1983static inline int lite3_ctx_arr_get_obj(
1984 lite3_ctx *ctx,
1985 size_t ofs,
1986 uint32_t index,
1987 size_t *__restrict out_ofs)
1988{
1989 lite3_val *val;
1990 int ret;
1991 if ((ret = _lite3_get_by_index(ctx->buf, ctx->buflen, ofs, index, &val)) < 0)
1992 return ret;
1993 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_OBJECT)) {
1994 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_OBJECT\n");
1995 errno = EINVAL;
1996 return -1;
1997 }
1998 *out_ofs = (size_t)((uint8_t *)val - (ctx->buf));
1999 return ret;
2000}
2001
2008static inline int lite3_ctx_arr_get_arr(
2009 lite3_ctx *ctx,
2010 size_t ofs,
2011 uint32_t index,
2012 size_t *__restrict out_ofs)
2013{
2014 lite3_val *val;
2015 int ret;
2016 if ((ret = _lite3_get_by_index(ctx->buf, ctx->buflen, ofs, index, &val)) < 0)
2017 return ret;
2018 if (LITE3_UNLIKELY(val->type != LITE3_TYPE_ARRAY)) {
2019 LITE3_PRINT_ERROR("VALUE TYPE != LITE3_TYPE_ARRAY\n");
2020 errno = EINVAL;
2021 return -1;
2022 }
2023 *out_ofs = (size_t)((uint8_t *)val - (ctx->buf));
2024 return ret;
2025}
2027
2028
2029
2042#ifdef DOXYGEN_ONLY
2044#define LITE3_ITER_ITEM 1
2046#define LITE3_ITER_DONE 0
2047#endif
2048
2055static inline int lite3_ctx_iter_create(
2056 lite3_ctx *ctx,
2057 size_t ofs,
2058 lite3_iter *out)
2059{
2060 int ret;
2061 if ((ret = _lite3_verify_get(ctx->buf, ctx->buflen, ofs)) < 0)
2062 return ret;
2063 return lite3_iter_create_impl(ctx->buf, ctx->buflen, ofs, out);
2064}
2065
2082static inline int lite3_ctx_iter_next(
2083 lite3_ctx *ctx,
2084 lite3_iter *iter,
2085 lite3_str *out_key,
2086 size_t *out_val_ofs)
2087{
2088 return lite3_iter_next(ctx->buf, ctx->buflen, iter, out_key, out_val_ofs);
2089}
2091
2092
2123#if defined(DOXYGEN_ONLY) && !defined(LITE3_JSON)
2124#define LITE3_JSON
2125#endif // DOXYGEN_ONLY
2126
2127#ifdef LITE3_JSON
2137static inline int lite3_ctx_json_dec(
2138 lite3_ctx *ctx,
2139 const char *__restrict json_str,
2140 size_t json_len)
2141{
2142 int ret;
2143 errno = 0;
2144 while ((ret = lite3_json_dec(ctx->buf, &ctx->buflen, ctx->bufsz, json_str, json_len)) < 0) {
2145 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
2146 continue;
2147 } else {
2148 return ret;
2149 }
2150 }
2151 return ret;
2152}
2153
2163static inline int lite3_ctx_json_dec_file(
2164 lite3_ctx *ctx,
2165 const char *__restrict path)
2166{
2167 int ret;
2168 errno = 0;
2169 while ((ret = lite3_json_dec_file(ctx->buf, &ctx->buflen, ctx->bufsz, path)) < 0) {
2170 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
2171 continue;
2172 } else {
2173 return ret;
2174 }
2175 }
2176 return ret;
2177}
2178
2188static inline int lite3_ctx_json_dec_fp(
2189 lite3_ctx *ctx,
2190 FILE *fp)
2191{
2192 int ret;
2193 errno = 0;
2194 while ((ret = lite3_json_dec_fp(ctx->buf, &ctx->buflen, ctx->bufsz, fp)) < 0) {
2195 if (errno == ENOBUFS && (lite3_ctx_grow_impl(ctx) == 0)) {
2196 continue;
2197 } else {
2198 return ret;
2199 }
2200 }
2201 return ret;
2202}
2203
2217static inline int lite3_ctx_json_print(
2218 lite3_ctx *ctx,
2219 size_t ofs)
2220{
2221 return lite3_json_print(ctx->buf, ctx->buflen, ofs);
2222}
2223
2237static inline char *lite3_ctx_json_enc(
2238 lite3_ctx *ctx,
2239 size_t ofs,
2240 size_t *__restrict out_len)
2241{
2242 return lite3_json_enc(ctx->buf, ctx->buflen, ofs, out_len);
2243}
2244
2260static inline char *lite3_ctx_json_enc_pretty(
2261 lite3_ctx *ctx,
2262 size_t ofs,
2263 size_t *__restrict out_len)
2264{
2265 return lite3_json_enc_pretty(ctx->buf, ctx->buflen, ofs, out_len);
2266}
2267
2278static inline int64_t lite3_ctx_json_enc_buf(
2279 lite3_ctx *ctx,
2280 size_t ofs,
2281 char *__restrict json_buf,
2282 size_t json_bufsz
2283)
2284{
2285 return lite3_json_enc_buf(ctx->buf, ctx->buflen, ofs, json_buf, json_bufsz);
2286}
2287
2300static inline int64_t lite3_ctx_json_enc_pretty_buf(
2301 lite3_ctx *ctx,
2302 size_t ofs,
2303 char *__restrict json_buf,
2304 size_t json_bufsz)
2305{
2306 return lite3_json_enc_pretty_buf(ctx->buf, ctx->buflen, ofs, json_buf, json_bufsz);
2307}
2308#else
2309static inline int lite3_ctx_json_dec(lite3_ctx *ctx, const char *__restrict json_str, size_t json_len)
2310{
2311 (void)ctx; (void)json_str; (void)json_len;
2312 return -1;
2313}
2314
2315static inline int lite3_ctx_json_dec_file(lite3_ctx *ctx, const char *__restrict path)
2316{
2317 (void)ctx; (void)path;
2318 return -1;
2319}
2320
2321static inline int lite3_ctx_json_dec_fp(lite3_ctx *ctx, FILE *fp)
2322{
2323 (void)ctx; (void)fp;
2324 return -1;
2325}
2326
2327static inline int lite3_ctx_json_print(lite3_ctx *ctx, size_t ofs)
2328{
2329 (void)ctx; (void)ofs;
2330 return 0;
2331}
2332
2333static inline char *lite3_ctx_json_enc(lite3_ctx *ctx, size_t ofs, size_t *out_len)
2334{
2335 (void)ctx; (void)ofs; (void)out_len;
2336 return NULL;
2337}
2338
2339static inline char *lite3_ctx_json_enc_pretty(lite3_ctx *ctx, size_t ofs, size_t *out_len)
2340{
2341 (void)ctx; (void)ofs; (void)out_len;
2342 return NULL;
2343}
2344
2345static inline int64_t lite3_ctx_json_enc_buf(lite3_ctx *ctx, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
2346{
2347 (void)ctx; (void)ofs; (void)json_buf; (void)json_bufsz;
2348 return -1;
2349}
2350
2351static inline int64_t lite3_ctx_json_enc_pretty_buf(lite3_ctx *ctx, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
2352{
2353 (void)ctx; (void)ofs; (void)json_buf; (void)json_bufsz;
2354 return -1;
2355}
2356#endif
2358
2359#ifdef __cplusplus
2360}
2361#endif
2362
2363#endif // LITE3_CONTEXT_API_H
#define LITE3_CONTEXT_BUF_SIZE_MIN
The minimum buffer size for a Lite³ context.
#define LITE3_NODE_ALIGNMENT
B-tree node alignment configuration.
Definition lite3.h:299
#define LITE3_NODE_SIZE_KC_OFFSET
Offset of the size_kc field inside struct node.
Definition lite3.h:350
static int lite3_ctx_arr_append_bytes(lite3_ctx *ctx, size_t ofs, const unsigned char *__restrict bytes, size_t bytes_len)
Append bytes to array.
static int lite3_ctx_arr_append_f64(lite3_ctx *ctx, size_t ofs, double value)
Append floating point to array.
static int lite3_ctx_arr_append_null(lite3_ctx *ctx, size_t ofs)
Append null to array.
static int lite3_ctx_arr_append_str_n(lite3_ctx *ctx, size_t ofs, const char *__restrict str, size_t str_len)
Append string to array by length.
static int lite3_ctx_arr_append_str(lite3_ctx *ctx, size_t ofs, const char *__restrict str)
Append string to array.
static int lite3_ctx_arr_append_obj(lite3_ctx *ctx, size_t ofs, size_t *__restrict out_ofs)
Append object to array.
static int lite3_ctx_arr_append_arr(lite3_ctx *ctx, size_t ofs, size_t *__restrict out_ofs)
Append array to array.
static int lite3_ctx_arr_append_i64(lite3_ctx *ctx, size_t ofs, int64_t value)
Append integer to array.
static int lite3_ctx_arr_append_bool(lite3_ctx *ctx, size_t ofs, bool value)
Append boolean to array.
static int lite3_ctx_arr_get_arr(lite3_ctx *ctx, size_t ofs, uint32_t index, size_t *__restrict out_ofs)
Get array by index.
static int lite3_ctx_arr_get_str(lite3_ctx *ctx, size_t ofs, uint32_t index, lite3_str *out)
Get string value by index.
static int lite3_ctx_arr_get_i64(lite3_ctx *ctx, size_t ofs, uint32_t index, int64_t *out)
Get integer value by index.
static int lite3_ctx_arr_get_bool(lite3_ctx *ctx, size_t ofs, uint32_t index, bool *out)
Get boolean value by index.
static int lite3_ctx_arr_get_bytes(lite3_ctx *ctx, size_t ofs, uint32_t index, lite3_bytes *out)
Get bytes value by index.
static int lite3_ctx_arr_get_obj(lite3_ctx *ctx, size_t ofs, uint32_t index, size_t *__restrict out_ofs)
Get object by index.
static int lite3_ctx_arr_get_f64(lite3_ctx *ctx, size_t ofs, uint32_t index, double *out)
Get floating point value by index.
static int lite3_ctx_arr_set_i64(lite3_ctx *ctx, size_t ofs, uint32_t index, int64_t value)
Set integer in array.
static int lite3_ctx_arr_set_arr(lite3_ctx *ctx, size_t ofs, uint32_t index, size_t *__restrict out_ofs)
Set array in array.
static int lite3_ctx_arr_set_str(lite3_ctx *ctx, size_t ofs, uint32_t index, const char *__restrict str)
Set string in array.
static int lite3_ctx_arr_set_f64(lite3_ctx *ctx, size_t ofs, uint32_t index, double value)
Set float in array.
static int lite3_ctx_arr_set_obj(lite3_ctx *ctx, size_t ofs, uint32_t index, size_t *__restrict out_ofs)
Set object in array.
static int lite3_ctx_arr_set_str_n(lite3_ctx *ctx, size_t ofs, uint32_t index, const char *__restrict str, size_t str_len)
Set string in array by length.
static int lite3_ctx_arr_set_bool(lite3_ctx *ctx, size_t ofs, uint32_t index, bool value)
Set boolean in array.
static int lite3_ctx_arr_set_bytes(lite3_ctx *ctx, size_t ofs, uint32_t index, const unsigned char *__restrict bytes, size_t bytes_len)
Set bytes in array.
static int lite3_ctx_arr_set_null(lite3_ctx *ctx, size_t ofs, uint32_t index)
Set null in array.
static int lite3_ctx_init_arr(lite3_ctx *ctx)
Initialize a Lite³ context as an array.
static int lite3_ctx_init_obj(lite3_ctx *ctx)
Initialize a Lite³ context as an object.
static int lite3_ctx_iter_create(lite3_ctx *ctx, size_t ofs, lite3_iter *out)
Create a lite3 iterator for the given object or array.
static int lite3_ctx_iter_next(lite3_ctx *ctx, lite3_iter *iter, lite3_str *out_key, size_t *out_val_ofs)
Get the next item from a lite3 iterator.
static int64_t lite3_ctx_json_enc_pretty_buf(lite3_ctx *ctx, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
Convert Lite³ to prettified JSON and write to output buffer.
static char * lite3_ctx_json_enc(lite3_ctx *ctx, size_t ofs, size_t *__restrict out_len)
Convert Lite³ to JSON string.
static int lite3_ctx_json_dec(lite3_ctx *ctx, const char *__restrict json_str, size_t json_len)
Convert JSON string to Lite³
static int lite3_ctx_json_print(lite3_ctx *ctx, size_t ofs)
Print Lite³ buffer as JSON to stdout
static int64_t lite3_ctx_json_enc_buf(lite3_ctx *ctx, size_t ofs, char *__restrict json_buf, size_t json_bufsz)
Convert Lite³ to JSON and write to output buffer.
static int lite3_ctx_json_dec_file(lite3_ctx *ctx, const char *__restrict path)
Convert JSON from file path to Lite³
static int lite3_ctx_json_dec_fp(lite3_ctx *ctx, FILE *fp)
Convert JSON from file pointer to Lite³
static char * lite3_ctx_json_enc_pretty(lite3_ctx *ctx, size_t ofs, size_t *__restrict out_len)
Convert Lite³ to JSON prettified string.
static lite3_ctx * lite3_ctx_create(void)
Create context with minimum size.
lite3_ctx * lite3_ctx_create_with_size(size_t bufsz)
Create context with custom size.
Definition ctx_api.c:75
void lite3_ctx_destroy(lite3_ctx *ctx)
Destroy context.
Definition ctx_api.c:229
lite3_ctx * lite3_ctx_create_take_ownership(unsigned char *buf, size_t buflen, size_t bufsz)
Create context by taking ownership of a buffer.
Definition ctx_api.c:126
lite3_ctx * lite3_ctx_create_from_buf(const unsigned char *buf, size_t buflen)
Create context by copying from a buffer.
Definition ctx_api.c:97
int lite3_ctx_import_from_buf(lite3_ctx *ctx, const unsigned char *buf, size_t buflen)
Copy data into existing context.
Definition ctx_api.c:193
static int lite3_ctx_count(lite3_ctx *ctx, size_t ofs, uint32_t *out)
Write back the number of object entries or array elements.
static void lite3_ctx_print(lite3_ctx *ctx)
View the internal structure of a Lite³ buffer.
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
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
Lite³ Buffer API Header.
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
Lite³ context struct.
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
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