yeptris 0.6.5.4 → 0.6.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/libyeptris/extconf.rb +57 -0
- data/lib/yeptris/ffi.rb +12 -15
- data/lib/yeptris/json.rb +5 -2
- data/lib/yeptris/psych.rb +76 -3
- data/lib/yeptris.rb +36 -14
- data/vendor/libyeptris/CMakeLists.txt +254 -0
- data/vendor/libyeptris/cmake/yeptris-config.cmake.in +5 -0
- data/vendor/libyeptris/cmake/yeptris.pc.in +11 -0
- data/vendor/libyeptris/src/CMakeLists.txt +167 -0
- data/vendor/libyeptris/src/include/yeptris/api.h +32 -0
- data/vendor/libyeptris/src/include/yeptris/cbor.h +101 -0
- data/vendor/libyeptris/src/include/yeptris/dom.h +181 -0
- data/vendor/libyeptris/src/include/yeptris/emit.h +81 -0
- data/vendor/libyeptris/src/include/yeptris/error.h +41 -0
- data/vendor/libyeptris/src/include/yeptris/events.h +157 -0
- data/vendor/libyeptris/src/include/yeptris/json.h +45 -0
- data/vendor/libyeptris/src/include/yeptris/json.hpp +258 -0
- data/vendor/libyeptris/src/include/yeptris/jsonc_compat.h +115 -0
- data/vendor/libyeptris/src/include/yeptris/marshal.h +52 -0
- data/vendor/libyeptris/src/include/yeptris/parse.h +48 -0
- data/vendor/libyeptris/src/include/yeptris/plan.h +100 -0
- data/vendor/libyeptris/src/include/yeptris/resolve.h +71 -0
- data/vendor/libyeptris/src/include/yeptris/schema.h +119 -0
- data/vendor/libyeptris/src/include/yeptris/tape.h +99 -0
- data/vendor/libyeptris/src/include/yeptris/types.h +38 -0
- data/vendor/libyeptris/src/include/yeptris/values.h +102 -0
- data/vendor/libyeptris/src/include/yeptris/version.h.in +29 -0
- data/vendor/libyeptris/src/include/yeptris/visit.h +77 -0
- data/vendor/libyeptris/src/include/yeptris/yajl_compat.h +135 -0
- data/vendor/libyeptris/src/include/yeptris.h +23 -0
- data/vendor/libyeptris/src/yeptris/build.c +371 -0
- data/vendor/libyeptris/src/yeptris/cbor/cbor.h +25 -0
- data/vendor/libyeptris/src/yeptris/cbor/decode.c +846 -0
- data/vendor/libyeptris/src/yeptris/cbor/encode.c +824 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.c +41 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.h +77 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.c +81 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.h +40 -0
- data/vendor/libyeptris/src/yeptris/common/error.c +65 -0
- data/vendor/libyeptris/src/yeptris/common/error.h +79 -0
- data/vendor/libyeptris/src/yeptris/common/mutex.h +45 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.c +275 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.h +68 -0
- data/vendor/libyeptris/src/yeptris/common/port.h +74 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.c +49 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.h +295 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +534 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +662 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +298 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.c +34 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.h +93 -0
- data/vendor/libyeptris/src/yeptris/doc.h +37 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +973 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.h +290 -0
- data/vendor/libyeptris/src/yeptris/dom/hpool.c +107 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.c +173 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.h +61 -0
- data/vendor/libyeptris/src/yeptris/dom/mutate.c +429 -0
- data/vendor/libyeptris/src/yeptris/emit/emit.c +349 -0
- data/vendor/libyeptris/src/yeptris/emit/float/api.h +38 -0
- data/vendor/libyeptris/src/yeptris/emit/float/dragon.c +405 -0
- data/vendor/libyeptris/src/yeptris/emit/float/floatint.h +203 -0
- data/vendor/libyeptris/src/yeptris/emit/float/print.c +396 -0
- data/vendor/libyeptris/src/yeptris/emit/style.c +81 -0
- data/vendor/libyeptris/src/yeptris/emit/style.h +24 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +746 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.h +61 -0
- data/vendor/libyeptris/src/yeptris/encoding/bom.c +31 -0
- data/vendor/libyeptris/src/yeptris/encoding/encoding.h +63 -0
- data/vendor/libyeptris/src/yeptris/encoding/transcode.c +148 -0
- data/vendor/libyeptris/src/yeptris/encoding/utf8_validate.c +178 -0
- data/vendor/libyeptris/src/yeptris/events/capture.c +150 -0
- data/vendor/libyeptris/src/yeptris/events/capture.h +39 -0
- data/vendor/libyeptris/src/yeptris/events/iterparse.c +208 -0
- data/vendor/libyeptris/src/yeptris/events/pull.c +97 -0
- data/vendor/libyeptris/src/yeptris/events/push.c +104 -0
- data/vendor/libyeptris/src/yeptris/events/recorder.c +107 -0
- data/vendor/libyeptris/src/yeptris/events/values.c +527 -0
- data/vendor/libyeptris/src/yeptris/events/values_priv.h +51 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.c +86 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.h +90 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/jsonc_compat.c +687 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/yajl_compat.c +728 -0
- data/vendor/libyeptris/src/yeptris/marshal.c +744 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.c +20 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.h +43 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.c +134 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.h +52 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.c +115 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.h +36 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.c +3689 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.h +65 -0
- data/vendor/libyeptris/src/yeptris/parse/events.h +124 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.c +349 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.h +33 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.c +416 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.h +75 -0
- data/vendor/libyeptris/src/yeptris/parse.c +650 -0
- data/vendor/libyeptris/src/yeptris/plan.c +817 -0
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +334 -0
- data/vendor/libyeptris/src/yeptris/resolve/core12.c +143 -0
- data/vendor/libyeptris/src/yeptris/resolve/resolver.h +56 -0
- data/vendor/libyeptris/src/yeptris/resolve/tags.c +58 -0
- data/vendor/libyeptris/src/yeptris/scan/json.c +792 -0
- data/vendor/libyeptris/src/yeptris/scan/json.h +109 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +463 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.h +150 -0
- data/vendor/libyeptris/src/yeptris/schema.c +238 -0
- data/vendor/libyeptris/src/yeptris/tape.c +1292 -0
- data/vendor/libyeptris/src/yeptris/version.c +7 -0
- data/vendor/libyeptris/src/yeptris/visit/dom_visit.c +115 -0
- data/vendor/libyeptris/src/yeptris/visit/json_visit.c +293 -0
- data/vendor/libyeptris/src/yeptris/visit/yaml_visit.c +127 -0
- metadata +112 -2
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* yajl_compat.h — the yajl generator migration layer (TODO.impl/21).
|
|
2
|
+
*
|
|
3
|
+
* REAL yajl_gen symbol names over the yeptris core: users link
|
|
4
|
+
* -lyeptris-yajl instead of -lyajl and change nothing else. The
|
|
5
|
+
* generator validates call order (yajl's own state machine) and
|
|
6
|
+
* builds a Yeptris document; get_buf serializes JSON (beautify
|
|
7
|
+
* selects the pretty writer, default compact).
|
|
8
|
+
*
|
|
9
|
+
* v2 scope: the generator (yajl_gen_*) and the SAX parser
|
|
10
|
+
* (yajl_alloc/yajl_parse/...). The parser accumulates yajl_parse
|
|
11
|
+
* feeds and delivers all callbacks at yajl_complete_parse (the core
|
|
12
|
+
* parses whole documents; timing is batched, order and content are
|
|
13
|
+
* yajl's). Strict RFC 8259 always; yajl_allow_comments masks
|
|
14
|
+
* JavaScript comments (block star-slash, line double-slash) outside
|
|
15
|
+
* strings before the strict parse — offsets preserved, yajl's exact
|
|
16
|
+
* semantics. Unsupported options (trailing garbage / multiple
|
|
17
|
+
* values / partial values) are rejected at yajl_config time: zero,
|
|
18
|
+
* per yajl's own error contract.
|
|
19
|
+
*/
|
|
20
|
+
#ifndef YEPTRIS_YAJL_COMPAT_H
|
|
21
|
+
#define YEPTRIS_YAJL_COMPAT_H
|
|
22
|
+
|
|
23
|
+
#include <stddef.h>
|
|
24
|
+
|
|
25
|
+
#ifdef __cplusplus
|
|
26
|
+
extern "C" {
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
typedef enum {
|
|
30
|
+
yajl_gen_status_ok = 0,
|
|
31
|
+
yajl_gen_keys_must_be_strings, /* 1 */
|
|
32
|
+
yajl_max_depth_exceeded, /* unused: depth-guarded builder */
|
|
33
|
+
yajl_gen_in_error_state = 3,
|
|
34
|
+
yajl_gen_generation_complete, /* 4: gen after get_buf without clear */
|
|
35
|
+
yajl_gen_invalid_string = 5 /* NULL bytes with len 0 handled; reserved */
|
|
36
|
+
} yajl_gen_status;
|
|
37
|
+
|
|
38
|
+
typedef enum {
|
|
39
|
+
yajl_gen_beautify = 1, /* int: pretty output */
|
|
40
|
+
yajl_gen_indent_string = 2, /* const char*: reserved (fixed 2-space) */
|
|
41
|
+
yajl_gen_validate_utf8 = 3 /* int: always on (the front-end validates) */
|
|
42
|
+
} yajl_gen_option;
|
|
43
|
+
|
|
44
|
+
typedef struct yajl_gen_t* yajl_gen;
|
|
45
|
+
typedef struct yajl_alloc_funcs_t yajl_alloc_funcs;
|
|
46
|
+
|
|
47
|
+
/* NULL alloc (the yajl default) uses the system allocator. */
|
|
48
|
+
yajl_gen yajl_gen_alloc(const yajl_alloc_funcs* afs);
|
|
49
|
+
void yajl_gen_free(yajl_gen g);
|
|
50
|
+
void yajl_gen_reset(yajl_gen g, const char* sep_ignored);
|
|
51
|
+
|
|
52
|
+
/* var-args: (yajl_gen_beautify, int). Returns 1 on success. */
|
|
53
|
+
int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...);
|
|
54
|
+
|
|
55
|
+
yajl_gen_status yajl_gen_map_open(yajl_gen g);
|
|
56
|
+
yajl_gen_status yajl_gen_map_close(yajl_gen g);
|
|
57
|
+
yajl_gen_status yajl_gen_array_open(yajl_gen g);
|
|
58
|
+
yajl_gen_status yajl_gen_array_close(yajl_gen g);
|
|
59
|
+
|
|
60
|
+
/* In a map, the first call per entry is the KEY: it must be a
|
|
61
|
+
* string (yajl accepts raw bytes; keys serialize JSON-quoted). */
|
|
62
|
+
yajl_gen_status yajl_gen_string(yajl_gen g, const unsigned char* str, size_t len);
|
|
63
|
+
yajl_gen_status yajl_gen_integer(yajl_gen g, long long n);
|
|
64
|
+
yajl_gen_status yajl_gen_double(yajl_gen g, double d);
|
|
65
|
+
yajl_gen_status yajl_gen_number(yajl_gen g, const char* s, size_t len);
|
|
66
|
+
yajl_gen_status yajl_gen_null(yajl_gen g);
|
|
67
|
+
yajl_gen_status yajl_gen_bool(yajl_gen g, int b);
|
|
68
|
+
|
|
69
|
+
/* The serialized document (owned by the generator; valid until the
|
|
70
|
+
* next generating call or reset). Empty until the ROOT closes. */
|
|
71
|
+
const unsigned char* yajl_gen_get_buf(yajl_gen g, size_t* len);
|
|
72
|
+
void yajl_gen_clear(yajl_gen g);
|
|
73
|
+
|
|
74
|
+
/* ---- SAX parser ------------------------------------------------------- */
|
|
75
|
+
|
|
76
|
+
typedef enum { yajl_status_ok = 0, yajl_status_client_canceled, yajl_status_error } yajl_status;
|
|
77
|
+
|
|
78
|
+
const char* yajl_status_to_string(yajl_status code);
|
|
79
|
+
|
|
80
|
+
/* Zero return from a callback cancels the parse
|
|
81
|
+
* (yajl_status_client_canceled). When yajl_number is set it carries
|
|
82
|
+
* EVERY number in string form; yajl_integer/yajl_double are then
|
|
83
|
+
* ignored (yajl's own precedence). */
|
|
84
|
+
typedef struct {
|
|
85
|
+
int (*yajl_null)(void* ctx);
|
|
86
|
+
int (*yajl_boolean)(void* ctx, int boolVal);
|
|
87
|
+
int (*yajl_integer)(void* ctx, long long integerVal);
|
|
88
|
+
int (*yajl_double)(void* ctx, double doubleVal);
|
|
89
|
+
int (*yajl_number)(void* ctx, const char* numberVal, size_t numberLen);
|
|
90
|
+
int (*yajl_string)(void* ctx, const unsigned char* stringVal, size_t stringLen);
|
|
91
|
+
int (*yajl_start_map)(void* ctx);
|
|
92
|
+
int (*yajl_map_key)(void* ctx, const unsigned char* key, size_t stringLen);
|
|
93
|
+
int (*yajl_end_map)(void* ctx);
|
|
94
|
+
int (*yajl_start_array)(void* ctx);
|
|
95
|
+
int (*yajl_end_array)(void* ctx);
|
|
96
|
+
} yajl_callbacks;
|
|
97
|
+
|
|
98
|
+
typedef enum {
|
|
99
|
+
yajl_allow_comments = 0x01, /* JS comments masked, offsets kept */
|
|
100
|
+
yajl_dont_validate_strings = 0x02, /* accepted no-op: always on */
|
|
101
|
+
yajl_allow_trailing_garbage = 0x04,
|
|
102
|
+
yajl_allow_multiple_values = 0x08,
|
|
103
|
+
yajl_allow_partial_values = 0x10
|
|
104
|
+
} yajl_option;
|
|
105
|
+
|
|
106
|
+
typedef struct yajl_handle_t* yajl_handle;
|
|
107
|
+
|
|
108
|
+
/* callbacks may be NULL (pure validation). afs accepted, ignored. */
|
|
109
|
+
yajl_handle yajl_alloc(const yajl_callbacks* callbacks, yajl_alloc_funcs* afs, void* ctx);
|
|
110
|
+
void yajl_free(yajl_handle handle);
|
|
111
|
+
|
|
112
|
+
/* var-args int option: 1 on, 0 off. Returns 0 on unknown/unsupported
|
|
113
|
+
* options (trailing garbage / multiple values / partial values). */
|
|
114
|
+
int yajl_config(yajl_handle h, yajl_option opt, ...);
|
|
115
|
+
|
|
116
|
+
/* Accumulates feeds; callbacks fire at complete_parse. After an
|
|
117
|
+
* error or cancel the handle stays in that state. */
|
|
118
|
+
yajl_status yajl_parse(yajl_handle hand, const unsigned char* jsonText, size_t jsonTextLength);
|
|
119
|
+
yajl_status yajl_complete_parse(yajl_handle hand);
|
|
120
|
+
|
|
121
|
+
/* Malloc'd message (free with yajl_free_error); NULL when no error.
|
|
122
|
+
* verbose adds the offending line and a caret. */
|
|
123
|
+
unsigned char* yajl_get_error(yajl_handle hand, int verbose, const unsigned char* jsonText,
|
|
124
|
+
size_t jsonTextLength);
|
|
125
|
+
void yajl_free_error(yajl_handle hand, unsigned char* str);
|
|
126
|
+
|
|
127
|
+
/* Bytes consumed: the whole input once complete; on error, the
|
|
128
|
+
* offset of the violation. */
|
|
129
|
+
size_t yajl_get_bytes_consumed(yajl_handle hand);
|
|
130
|
+
|
|
131
|
+
#ifdef __cplusplus
|
|
132
|
+
}
|
|
133
|
+
#endif
|
|
134
|
+
|
|
135
|
+
#endif /* YEPTRIS_YAJL_COMPAT_H */
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* yeptris.h — umbrella header for libyeptris.
|
|
2
|
+
*
|
|
3
|
+
* Ultra-fast YAML 1.2 parser, emitter and streamer in C; the YAML
|
|
4
|
+
* counterpart of libleptris. Subsystem headers grow with their items
|
|
5
|
+
* (TODO.impl/01-20); this file only includes the public surface.
|
|
6
|
+
*/
|
|
7
|
+
#ifndef YEPTRIS_H
|
|
8
|
+
#define YEPTRIS_H
|
|
9
|
+
|
|
10
|
+
#include <yeptris/api.h>
|
|
11
|
+
#include <yeptris/dom.h>
|
|
12
|
+
#include <yeptris/emit.h>
|
|
13
|
+
#include <yeptris/error.h>
|
|
14
|
+
#ifdef YEPTRIS_WITH_CBOR
|
|
15
|
+
#include <yeptris/cbor.h>
|
|
16
|
+
#endif
|
|
17
|
+
#include <yeptris/events.h>
|
|
18
|
+
#include <yeptris/parse.h>
|
|
19
|
+
#include <yeptris/resolve.h>
|
|
20
|
+
#include <yeptris/types.h>
|
|
21
|
+
#include <yeptris/version.h>
|
|
22
|
+
|
|
23
|
+
#endif /* YEPTRIS_H */
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/* build.c — the public from-scratch construction API (TODO.impl/11
|
|
2
|
+
* phase 3). Thin: argument checking + handle wrapping over the dom
|
|
3
|
+
* mutation primitives. The emitter and every query API work on
|
|
4
|
+
* synthesized documents unchanged — same nodes, same invariants. */
|
|
5
|
+
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
|
|
9
|
+
#include <yeptris.h>
|
|
10
|
+
|
|
11
|
+
#include "doc.h"
|
|
12
|
+
#include "dom/dom.h"
|
|
13
|
+
#include "memory/allocator.h"
|
|
14
|
+
|
|
15
|
+
static yeptris_document* doc_of(YeptrisDocument handle) {
|
|
16
|
+
return (yeptris_document*)handle;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static yeptris_node* node_of(YeptrisNode handle) {
|
|
20
|
+
return (yeptris_node*)handle;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
YEPTRIS_API YeptrisDocument yeptris_document_new(void) {
|
|
24
|
+
const yep_allocator* sys = yep_system_allocator();
|
|
25
|
+
yep_dom* dom = yep_dom_create(sys);
|
|
26
|
+
if (dom == NULL) {
|
|
27
|
+
return NULL;
|
|
28
|
+
}
|
|
29
|
+
yeptris_document* doc = yep_alloc(sys, sizeof(yeptris_document));
|
|
30
|
+
if (doc == NULL) {
|
|
31
|
+
yep_dom_destroy(dom);
|
|
32
|
+
return NULL;
|
|
33
|
+
}
|
|
34
|
+
memset(doc, 0, sizeof(*doc));
|
|
35
|
+
doc->dom = dom;
|
|
36
|
+
doc->sys = sys;
|
|
37
|
+
return (YeptrisDocument)doc;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
YEPTRIS_API int yeptris_document_set_root(YeptrisDocument handle, YeptrisNode root) {
|
|
41
|
+
yeptris_document* doc = doc_of(handle);
|
|
42
|
+
yeptris_node* n = node_of(root);
|
|
43
|
+
if (doc == NULL || n == NULL || n->doc != doc) {
|
|
44
|
+
return YEPTRIS_ERROR_PARSE;
|
|
45
|
+
}
|
|
46
|
+
int rc = yep_mut_add_root(doc->dom, n->id);
|
|
47
|
+
return rc == 0 ? YEPTRIS_OK
|
|
48
|
+
: (rc == -1 ? YEPTRIS_ERROR_MEMORY
|
|
49
|
+
: (rc == -3 ? YEPTRIS_ERROR_DEPTH : YEPTRIS_ERROR_ARG));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
YEPTRIS_API YeptrisNode yeptris_node_new_mapping(YeptrisDocument handle) {
|
|
53
|
+
yeptris_document* doc = doc_of(handle);
|
|
54
|
+
if (doc == NULL) {
|
|
55
|
+
return NULL;
|
|
56
|
+
}
|
|
57
|
+
uint32_t id = yep_mut_map(doc->dom, 0);
|
|
58
|
+
return id == UINT32_MAX ? NULL : (YeptrisNode)yep_handle_new(doc, id);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
YEPTRIS_API YeptrisNode yeptris_node_new_sequence(YeptrisDocument handle) {
|
|
62
|
+
yeptris_document* doc = doc_of(handle);
|
|
63
|
+
if (doc == NULL) {
|
|
64
|
+
return NULL;
|
|
65
|
+
}
|
|
66
|
+
uint32_t id = yep_mut_seq(doc->dom, 0);
|
|
67
|
+
return id == UINT32_MAX ? NULL : (YeptrisNode)yep_handle_new(doc, id);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Memory: the value is copied into the document (nothing is borrowed
|
|
71
|
+
* from the caller). Plain style types the copy through the resolver,
|
|
72
|
+
* quoted styles force string — identical to parse-time typing. */
|
|
73
|
+
YEPTRIS_API YeptrisNode yeptris_node_new_scalar(YeptrisDocument handle, const char* value,
|
|
74
|
+
size_t len, YeptrisScalarStyle style) {
|
|
75
|
+
yeptris_document* doc = doc_of(handle);
|
|
76
|
+
if (doc == NULL || (value == NULL && len > 0) || style < YEPTRIS_STYLE_PLAIN ||
|
|
77
|
+
style > YEPTRIS_STYLE_FOLDED) {
|
|
78
|
+
return NULL;
|
|
79
|
+
}
|
|
80
|
+
uint32_t id = yep_mut_scalar(doc->dom, value, len, (uint8_t)style);
|
|
81
|
+
return id == UINT32_MAX ? NULL : (YeptrisNode)yep_handle_new(doc, id);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static int mut_status(int rc) {
|
|
85
|
+
switch (rc) {
|
|
86
|
+
case 0:
|
|
87
|
+
case 1: /* map_set replaced — success for the caller */
|
|
88
|
+
return YEPTRIS_OK;
|
|
89
|
+
case -1:
|
|
90
|
+
return YEPTRIS_ERROR_MEMORY;
|
|
91
|
+
case -3:
|
|
92
|
+
return YEPTRIS_ERROR_DEPTH;
|
|
93
|
+
default: /* -2 duplicate key, -4 double-attach */
|
|
94
|
+
return YEPTRIS_ERROR_PARSE;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static int same_doc(YeptrisNode parent, YeptrisNode child) {
|
|
99
|
+
yeptris_node* p = node_of(parent);
|
|
100
|
+
yeptris_node* c = node_of(child);
|
|
101
|
+
return p != NULL && c != NULL && p->doc == c->doc;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
YEPTRIS_API int yeptris_node_map_add(YeptrisNode handle, const char* key, size_t key_len,
|
|
105
|
+
YeptrisNode value) {
|
|
106
|
+
yeptris_node* m = node_of(handle);
|
|
107
|
+
if (m == NULL || key == NULL || !same_doc(handle, value)) {
|
|
108
|
+
return YEPTRIS_ERROR_ARG;
|
|
109
|
+
}
|
|
110
|
+
return mut_status(yep_mut_map_add(m->doc->dom, m->id, key, key_len, node_of(value)->id));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Replace-or-add (json-c semantics): an existing key keeps its
|
|
114
|
+
* position and swaps the value; a new key appends. */
|
|
115
|
+
YEPTRIS_API int yeptris_node_map_set(YeptrisNode handle, const char* key, size_t key_len,
|
|
116
|
+
YeptrisNode value) {
|
|
117
|
+
yeptris_node* m = node_of(handle);
|
|
118
|
+
if (m == NULL || key == NULL || !same_doc(handle, value)) {
|
|
119
|
+
return YEPTRIS_ERROR_ARG;
|
|
120
|
+
}
|
|
121
|
+
return mut_status(yep_mut_map_set(m->doc->dom, m->id, key, key_len, node_of(value)->id));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
YEPTRIS_API int yeptris_node_seq_add(YeptrisNode handle, YeptrisNode value) {
|
|
125
|
+
yeptris_node* s = node_of(handle);
|
|
126
|
+
if (s == NULL || !same_doc(handle, value)) {
|
|
127
|
+
return YEPTRIS_ERROR_ARG;
|
|
128
|
+
}
|
|
129
|
+
return mut_status(yep_mut_seq_add(s->doc->dom, s->id, node_of(value)->id));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
YEPTRIS_API int yeptris_node_seq_set(YeptrisNode handle, size_t index, YeptrisNode value) {
|
|
133
|
+
yeptris_node* s = node_of(handle);
|
|
134
|
+
if (s == NULL || !same_doc(handle, value)) {
|
|
135
|
+
return YEPTRIS_ERROR_ARG;
|
|
136
|
+
}
|
|
137
|
+
return mut_status(yep_mut_seq_set(s->doc->dom, s->id, (uint32_t)index, node_of(value)->id));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
YEPTRIS_API int yeptris_node_seq_del(YeptrisNode handle, size_t index) {
|
|
141
|
+
yeptris_node* s = node_of(handle);
|
|
142
|
+
if (s == NULL) {
|
|
143
|
+
return YEPTRIS_ERROR_ARG;
|
|
144
|
+
}
|
|
145
|
+
return yep_mut_seq_del(s->doc->dom, s->id, (uint32_t)index) == 0 ? YEPTRIS_OK
|
|
146
|
+
: YEPTRIS_ERROR_PARSE;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* The removed subtree stays document-owned (arena lifetime); its
|
|
150
|
+
* handle remains valid but unreachable from the root. */
|
|
151
|
+
YEPTRIS_API int yeptris_node_set_anchor(YeptrisNode handle, const char* name, size_t len) {
|
|
152
|
+
yeptris_node* n = node_of(handle);
|
|
153
|
+
if (n == NULL || name == NULL) {
|
|
154
|
+
return YEPTRIS_ERROR_ARG;
|
|
155
|
+
}
|
|
156
|
+
return yep_mut_set_anchor(n->doc->dom, n->id, name, len) == 0 ? YEPTRIS_OK : YEPTRIS_ERROR_ARG;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
YEPTRIS_API int yeptris_node_set_tag(YeptrisNode handle, const char* tag, size_t len) {
|
|
160
|
+
yeptris_node* n = node_of(handle);
|
|
161
|
+
if (n == NULL || tag == NULL) {
|
|
162
|
+
return YEPTRIS_ERROR_ARG;
|
|
163
|
+
}
|
|
164
|
+
return yep_mut_set_tag(n->doc->dom, n->id, tag, len) == 0 ? YEPTRIS_OK : YEPTRIS_ERROR_ARG;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
YEPTRIS_API YeptrisNode yeptris_node_new_alias(YeptrisDocument handle, YeptrisNode target,
|
|
168
|
+
const char* name, size_t len) {
|
|
169
|
+
yeptris_document* doc = doc_of(handle);
|
|
170
|
+
yeptris_node* t = node_of(target);
|
|
171
|
+
if (doc == NULL || t == NULL || t->doc != doc || name == NULL) {
|
|
172
|
+
return NULL;
|
|
173
|
+
}
|
|
174
|
+
uint32_t id = yep_mut_new_alias(doc->dom, t->id, name, len);
|
|
175
|
+
return id == UINT32_MAX ? NULL : (YeptrisNode)yep_handle_new(doc, id);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
YEPTRIS_API int yeptris_node_map_add_node(YeptrisNode handle, YeptrisNode key, YeptrisNode value) {
|
|
179
|
+
yeptris_node* m = node_of(handle);
|
|
180
|
+
if (m == NULL || !same_doc(handle, key) || !same_doc(handle, value)) {
|
|
181
|
+
return YEPTRIS_ERROR_ARG;
|
|
182
|
+
}
|
|
183
|
+
return mut_status(
|
|
184
|
+
yep_mut_map_add_node(m->doc->dom, m->id, node_of(key)->id, node_of(value)->id));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
YEPTRIS_API int yeptris_node_map_del(YeptrisNode handle, const char* key, size_t key_len) {
|
|
188
|
+
yeptris_node* m = node_of(handle);
|
|
189
|
+
if (m == NULL || key == NULL) {
|
|
190
|
+
return YEPTRIS_ERROR_ARG;
|
|
191
|
+
}
|
|
192
|
+
return yep_mut_map_del(m->doc->dom, m->id, key, key_len) == 0 ? YEPTRIS_OK
|
|
193
|
+
: YEPTRIS_ERROR_PARSE;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* ---- bulk build --------------------------------------------------------
|
|
197
|
+
*
|
|
198
|
+
* One call, one tree: entries walk in document order (the same shape
|
|
199
|
+
* as the event stream), pairing and linking ride the mutation
|
|
200
|
+
* primitives unchanged — dup checks, depth caps, and per-link depth
|
|
201
|
+
* fixups all come along for free (DRY with the public builder). */
|
|
202
|
+
YEPTRIS_API YeptrisStatus yeptris_document_build(YeptrisDocument handle,
|
|
203
|
+
const YeptrisBuildEntry* entries, size_t count,
|
|
204
|
+
const char* blob, size_t blob_len) {
|
|
205
|
+
yeptris_document* doc = doc_of(handle);
|
|
206
|
+
if (doc == NULL || (entries == NULL && count != 0) || (blob == NULL && blob_len != 0)) {
|
|
207
|
+
return YEPTRIS_ERROR_ARG;
|
|
208
|
+
}
|
|
209
|
+
struct frame {
|
|
210
|
+
uint32_t id;
|
|
211
|
+
uint8_t is_map;
|
|
212
|
+
uint8_t key_pending;
|
|
213
|
+
};
|
|
214
|
+
if (count > (SIZE_MAX / 2) / sizeof(struct frame)) {
|
|
215
|
+
return YEPTRIS_ERROR_ARG;
|
|
216
|
+
}
|
|
217
|
+
struct frame* st = yep_alloc(doc->dom->sys, (count + 1) * sizeof(*st));
|
|
218
|
+
if (st == NULL) {
|
|
219
|
+
return YEPTRIS_ERROR_MEMORY;
|
|
220
|
+
}
|
|
221
|
+
int depth = 0;
|
|
222
|
+
uint32_t root = UINT32_MAX;
|
|
223
|
+
uint32_t root_closed = 0;
|
|
224
|
+
uint32_t pending_key = UINT32_MAX; /* map frame's buffered key */
|
|
225
|
+
uint32_t last_id = UINT32_MAX; /* TAG applies here (#300) */
|
|
226
|
+
YeptrisStatus rc = YEPTRIS_OK;
|
|
227
|
+
for (size_t i = 0; i < count && rc == YEPTRIS_OK; i++) {
|
|
228
|
+
const YeptrisBuildEntry* e = &entries[i];
|
|
229
|
+
if (root_closed) {
|
|
230
|
+
rc = YEPTRIS_ERROR_PARSE; /* the document ended; more entries */
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
if (e->off > blob_len || e->len > blob_len - e->off) {
|
|
234
|
+
rc = YEPTRIS_ERROR_PARSE; /* slice out of range */
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
uint32_t id = UINT32_MAX; /* set by every arm that reaches the place; MSVC wants the init */
|
|
238
|
+
switch (e->op) {
|
|
239
|
+
case YEPTRIS_BUILD_SCALAR: {
|
|
240
|
+
id = yep_mut_scalar(doc->dom, blob + e->off, e->len, e->style);
|
|
241
|
+
if (id == UINT32_MAX) {
|
|
242
|
+
rc = YEPTRIS_ERROR_MEMORY;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
case YEPTRIS_BUILD_SEQ:
|
|
248
|
+
id = yep_mut_seq(doc->dom, 0);
|
|
249
|
+
if (id == UINT32_MAX) {
|
|
250
|
+
rc = YEPTRIS_ERROR_MEMORY;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
break;
|
|
254
|
+
case YEPTRIS_BUILD_MAP:
|
|
255
|
+
id = yep_mut_map(doc->dom, 0);
|
|
256
|
+
if (id == UINT32_MAX) {
|
|
257
|
+
rc = YEPTRIS_ERROR_MEMORY;
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
break;
|
|
261
|
+
case YEPTRIS_BUILD_END:
|
|
262
|
+
if (depth == 0) {
|
|
263
|
+
rc = YEPTRIS_ERROR_PARSE; /* END with nothing open */
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
depth--;
|
|
267
|
+
if (depth == 0) {
|
|
268
|
+
root_closed = 1; /* the root just completed */
|
|
269
|
+
}
|
|
270
|
+
if (st[depth].is_map && st[depth].key_pending) {
|
|
271
|
+
st[depth].key_pending = 0; /* a closed container was the value */
|
|
272
|
+
}
|
|
273
|
+
continue;
|
|
274
|
+
case YEPTRIS_BUILD_TAG:
|
|
275
|
+
/* #300: apply an explicit tag to the last-placed node —
|
|
276
|
+
* the bulk ABI otherwise cannot express tags. Placed
|
|
277
|
+
* immediately after the entry it tags. */
|
|
278
|
+
if (last_id == UINT32_MAX) {
|
|
279
|
+
rc = YEPTRIS_ERROR_PARSE; /* TAG with nothing placed */
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
if (yep_mut_set_tag(doc->dom, last_id, blob + e->off, e->len) != 0) {
|
|
283
|
+
rc = YEPTRIS_ERROR_MEMORY;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
continue;
|
|
287
|
+
default:
|
|
288
|
+
rc = YEPTRIS_ERROR_PARSE; /* unknown op */
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
if (rc != YEPTRIS_OK) {
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
last_id = id; /* TAG entries target this (#300) */
|
|
295
|
+
/* place the fresh node */
|
|
296
|
+
if (depth == 0) {
|
|
297
|
+
if (root != UINT32_MAX) {
|
|
298
|
+
rc = YEPTRIS_ERROR_PARSE; /* two roots */
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
root = id; /* a single scalar root needs no END */
|
|
302
|
+
root_closed = (e->op != YEPTRIS_BUILD_SEQ && e->op != YEPTRIS_BUILD_MAP) ? 1 : 0;
|
|
303
|
+
if (!root_closed) {
|
|
304
|
+
st[depth].id = id;
|
|
305
|
+
st[depth].is_map = (e->op == YEPTRIS_BUILD_MAP);
|
|
306
|
+
st[depth].key_pending = 0;
|
|
307
|
+
depth = 1;
|
|
308
|
+
}
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
struct frame* top = &st[depth - 1];
|
|
312
|
+
if (top->is_map) {
|
|
313
|
+
if (!top->key_pending) {
|
|
314
|
+
top->key_pending = 1;
|
|
315
|
+
pending_key = id;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
/* the check-free pairing twin: document-order entries
|
|
319
|
+
* from a host mapping cannot duplicate, and map_add's
|
|
320
|
+
* linear dup scan is O(n^2) on wide maps */
|
|
321
|
+
int mrc = yep_mut_map_append(doc->dom, top->id, pending_key, id);
|
|
322
|
+
if (mrc == 0) {
|
|
323
|
+
top->key_pending = 0;
|
|
324
|
+
pending_key = UINT32_MAX;
|
|
325
|
+
} else {
|
|
326
|
+
rc = (mrc == -3) ? YEPTRIS_ERROR_DEPTH
|
|
327
|
+
: (mrc == -1 ? YEPTRIS_ERROR_ARG : YEPTRIS_ERROR_MEMORY);
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
int src_ = yep_mut_seq_add(doc->dom, top->id, id);
|
|
331
|
+
if (src_ != 0) {
|
|
332
|
+
rc = (src_ == -3) ? YEPTRIS_ERROR_DEPTH
|
|
333
|
+
: (src_ == -1 ? YEPTRIS_ERROR_ARG : YEPTRIS_ERROR_MEMORY);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (rc == YEPTRIS_OK && (e->op == YEPTRIS_BUILD_SEQ || e->op == YEPTRIS_BUILD_MAP)) {
|
|
337
|
+
if ((size_t)depth >= (size_t)YEP_DOM_MAX_DEPTH) {
|
|
338
|
+
rc = YEPTRIS_ERROR_DEPTH;
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
st[depth].id = id;
|
|
342
|
+
st[depth].is_map = (e->op == YEPTRIS_BUILD_MAP);
|
|
343
|
+
st[depth].key_pending = 0;
|
|
344
|
+
depth++;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (rc == YEPTRIS_OK) {
|
|
348
|
+
if (depth > 1 || (depth == 1)) {
|
|
349
|
+
rc = YEPTRIS_ERROR_PARSE; /* an unclosed container */
|
|
350
|
+
} else if (root == UINT32_MAX) {
|
|
351
|
+
rc = YEPTRIS_ERROR_PARSE; /* no root */
|
|
352
|
+
} else if (pending_key != UINT32_MAX) {
|
|
353
|
+
rc = YEPTRIS_ERROR_PARSE; /* a key without its value */
|
|
354
|
+
} else {
|
|
355
|
+
int arc = yep_mut_add_root(doc->dom, root);
|
|
356
|
+
if (arc == 0) {
|
|
357
|
+
rc = YEPTRIS_OK;
|
|
358
|
+
} else if (arc == -4) {
|
|
359
|
+
rc = YEPTRIS_ERROR_PARSE;
|
|
360
|
+
} else if (arc == -3) {
|
|
361
|
+
rc = YEPTRIS_ERROR_DEPTH;
|
|
362
|
+
} else if (arc == -1) {
|
|
363
|
+
rc = YEPTRIS_ERROR_MEMORY;
|
|
364
|
+
} else {
|
|
365
|
+
rc = YEPTRIS_ERROR_ARG;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
yep_free(doc->dom->sys, st);
|
|
370
|
+
return rc;
|
|
371
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* cbor.h — the CBOR (RFC 8949) codec's internal interface
|
|
2
|
+
* (TODO.cbor/01). The public surface is <yeptris/cbor.h>. */
|
|
3
|
+
#ifndef YEP_CBOR_H
|
|
4
|
+
#define YEP_CBOR_H
|
|
5
|
+
|
|
6
|
+
#include <stdint.h>
|
|
7
|
+
|
|
8
|
+
#include "../dom/dom.h"
|
|
9
|
+
|
|
10
|
+
#ifdef __cplusplus
|
|
11
|
+
extern "C" {
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
/* one data item: bytes -> the shared DOM (the plan's item 01) */
|
|
15
|
+
/* One data item. consumed (may be NULL): when given, returns the
|
|
16
|
+
* item's byte extent and TRAILING BYTES ARE NOT an error (the
|
|
17
|
+
* sequence loop steps on them); NULL keeps the one-item contract. */
|
|
18
|
+
int yep_cbor_decode_dom(yep_dom* d, const unsigned char* p, size_t len, int strict,
|
|
19
|
+
size_t* consumed);
|
|
20
|
+
|
|
21
|
+
#ifdef __cplusplus
|
|
22
|
+
}
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
#endif /* YEP_CBOR_H */
|