yeptris 0.6.57.1-arm-linux-eabihf → 0.6.59.1-arm-linux-eabihf
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/yeptris_native/version.h +2 -2
- data/lib/yeptris/3.4/native.so +0 -0
- data/lib/yeptris/document.rb +15 -0
- data/lib/yeptris/ffi.rb +93 -0
- data/lib/yeptris/psych/visitors.rb +16 -6
- data/lib/yeptris/psych.rb +11 -5
- data/lib/yeptris/validation.rb +320 -0
- data/lib/yeptris/yaml.rb +67 -6
- data/lib/yeptris.rb +2 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/CMakeLists.txt +6 -0
- data/vendor/libyeptris/src/include/yeptris/error.h +2 -1
- data/vendor/libyeptris/src/include/yeptris/resolve.h +3 -1
- data/vendor/libyeptris/src/include/yeptris/validate.h +200 -0
- data/vendor/libyeptris/src/include/yeptris.h +1 -0
- data/vendor/libyeptris/src/yeptris/parse.c +24 -10
- data/vendor/libyeptris/src/yeptris/resolve/json12.c +103 -0
- data/vendor/libyeptris/src/yeptris/resolve/resolver.h +9 -0
- data/vendor/libyeptris/src/yeptris/validate/compile.c +270 -0
- data/vendor/libyeptris/src/yeptris/validate/internal.h +131 -0
- data/vendor/libyeptris/src/yeptris/validate/jsonschema.c +1392 -0
- data/vendor/libyeptris/src/yeptris/validate/regexp.c +1134 -0
- data/vendor/libyeptris/src/yeptris/validate/validate.c +900 -0
- metadata +9 -1
data/lib/yeptris.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Yeptris
|
|
4
4
|
# The gem's version lives in the parent namespace's file — the last
|
|
5
5
|
# internal require (yeptris/version) retired with it.
|
|
6
|
-
VERSION = "0.6.
|
|
6
|
+
VERSION = "0.6.59.1".freeze
|
|
7
7
|
|
|
8
8
|
# Informational notices are OPT-IN (yeptris-ruby#217): consumers
|
|
9
9
|
# embed yeptris inside CLIs that assert clean stderr, and a
|
|
@@ -54,6 +54,7 @@ module Yeptris
|
|
|
54
54
|
autoload :ValueML, "yeptris/valueml"
|
|
55
55
|
autoload :Psych, "yeptris/psych"
|
|
56
56
|
autoload :Schema, "yeptris/schema"
|
|
57
|
+
autoload :Validation, "yeptris/validation"
|
|
57
58
|
autoload :CBOR, "yeptris/cbor"
|
|
58
59
|
end
|
|
59
60
|
|
data/libyeptris.so
CHANGED
|
Binary file
|
|
@@ -39,9 +39,14 @@ set(YEPTRIS_SOURCES
|
|
|
39
39
|
yeptris/resolve/tags.c
|
|
40
40
|
yeptris/resolve/core12.c
|
|
41
41
|
yeptris/resolve/compat11.c
|
|
42
|
+
yeptris/resolve/json12.c
|
|
42
43
|
yeptris/parse/numbers.c
|
|
43
44
|
yeptris/events/values.c
|
|
44
45
|
yeptris/schema.c
|
|
46
|
+
yeptris/validate/regexp.c
|
|
47
|
+
yeptris/validate/validate.c
|
|
48
|
+
yeptris/validate/compile.c
|
|
49
|
+
yeptris/validate/jsonschema.c
|
|
45
50
|
yeptris/tape.c
|
|
46
51
|
yeptris/plan.c
|
|
47
52
|
|
|
@@ -95,6 +100,7 @@ set(YEPTRIS_PUBLIC_HEADERS
|
|
|
95
100
|
${CMAKE_CURRENT_SOURCE_DIR}/include/yeptris/parse.h
|
|
96
101
|
${CMAKE_CURRENT_SOURCE_DIR}/include/yeptris/values.h
|
|
97
102
|
${CMAKE_CURRENT_SOURCE_DIR}/include/yeptris/schema.h
|
|
103
|
+
${CMAKE_CURRENT_SOURCE_DIR}/include/yeptris/validate.h
|
|
98
104
|
${CMAKE_CURRENT_SOURCE_DIR}/include/yeptris/tape.h
|
|
99
105
|
${CMAKE_CURRENT_SOURCE_DIR}/include/yeptris/plan.h
|
|
100
106
|
${CMAKE_CURRENT_SOURCE_DIR}/include/yeptris/marshal.h
|
|
@@ -25,7 +25,8 @@ typedef enum {
|
|
|
25
25
|
YEPTRIS_ERROR_ARG = 6, /* invalid argument (NULL handle, bad option) */
|
|
26
26
|
YEPTRIS_ERROR_UNSUPPORTED = 7, /* requested feature not built in */
|
|
27
27
|
YEPTRIS_ERROR_INTERNAL = 8, /* invariant violation — a bug, please report */
|
|
28
|
-
YEPTRIS_ERROR_SCHEMA = 9,
|
|
28
|
+
YEPTRIS_ERROR_SCHEMA = 9, /* validation: the report carries diagnostics (#882);
|
|
29
|
+
* descriptor materialization: REQUIRED missing (#238) */
|
|
29
30
|
} YeptrisStatus;
|
|
30
31
|
|
|
31
32
|
/* Message of the most recent failure on the calling thread, with its
|
|
@@ -40,10 +40,12 @@ typedef enum {
|
|
|
40
40
|
YEPTRIS_TAG_CUSTOM = 11,
|
|
41
41
|
} YeptrisTagId;
|
|
42
42
|
|
|
43
|
-
/* Schemas. */
|
|
43
|
+
/* Schemas. Appending only — bindings hard-code the values (test_abi). */
|
|
44
44
|
typedef enum {
|
|
45
45
|
YEPTRIS_SCHEMA_12_CORE = 0, /* default: the yaml-test-suite target */
|
|
46
46
|
YEPTRIS_SCHEMA_11_COMPAT, /* libyaml/Psych implicit typing */
|
|
47
|
+
YEPTRIS_SCHEMA_12_JSON, /* spec 10.2: JSON productions; plain
|
|
48
|
+
* scalars matching none are errors (#882) */
|
|
47
49
|
} YeptrisSchema;
|
|
48
50
|
|
|
49
51
|
/* Canonical tag URI for a core id ("tag:yaml.org,2002:str"); NULL for
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/* validate.h — the validation face (issue #882).
|
|
2
|
+
*
|
|
3
|
+
* Two checks over one engine pass:
|
|
4
|
+
*
|
|
5
|
+
* 1. SCHEMA-FAMILY validation (`yeptris_validate`): parse + validate
|
|
6
|
+
* fused. Under YEPTRIS_SCHEMA_12_CORE the walk checks explicit-tag
|
|
7
|
+
* consistency (spec 10.3 resolution) and mapping-key uniqueness
|
|
8
|
+
* (spec 3.2.1.3: keys compare by canonical form — 0o13 and 0xB
|
|
9
|
+
* are the same key). Under YEPTRIS_SCHEMA_12_JSON the spec 10.2
|
|
10
|
+
* family applies: every PLAIN scalar must match a JSON production
|
|
11
|
+
* (the table's `*` -> Error row), mapping keys must be strings,
|
|
12
|
+
* non-JSON tags are rejected; core checks still run.
|
|
13
|
+
*
|
|
14
|
+
* 2. JSON SCHEMA validation (`yeptris_json_schema_validate`): the
|
|
15
|
+
* schema arrives as bytes (parsed with the same engine), the
|
|
16
|
+
* target against it — draft 2020-12 keyword subset (see the entry
|
|
17
|
+
* comment). Unknown keywords are ignored, per 2020-12.
|
|
18
|
+
*
|
|
19
|
+
* Every diagnostic carries a JSON-pointer instance path ("/a/b/0" —
|
|
20
|
+
* ~0/~1 escaped), a YEPTRIS_DIAG_* code, a bounded expected/got
|
|
21
|
+
* detail, and the offending node's 1-based line/column (0 = unknown:
|
|
22
|
+
* scalars whose bytes the DOM owns in its arena have no input
|
|
23
|
+
* position; the path still identifies them exactly).
|
|
24
|
+
*
|
|
25
|
+
* Results are WHOLE REPORTS: one call, no per-diagnostic callback —
|
|
26
|
+
* the caller drains the flat array and frees the report once.
|
|
27
|
+
*/
|
|
28
|
+
#ifndef YEPTRIS_VALIDATE_H
|
|
29
|
+
#define YEPTRIS_VALIDATE_H
|
|
30
|
+
|
|
31
|
+
#include <stddef.h>
|
|
32
|
+
#include <stdint.h>
|
|
33
|
+
|
|
34
|
+
#include <yeptris/api.h>
|
|
35
|
+
#include <yeptris/error.h>
|
|
36
|
+
#include <yeptris/parse.h> /* YeptrisDocument, YeptrisSchema */
|
|
37
|
+
#include <yeptris/types.h>
|
|
38
|
+
|
|
39
|
+
#ifdef __cplusplus
|
|
40
|
+
extern "C" {
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
/* Diagnostic codes. Appending only — bindings hard-code the values
|
|
44
|
+
* (test_abi pins the head). */
|
|
45
|
+
typedef enum {
|
|
46
|
+
YEPTRIS_DIAG_NONE = 0,
|
|
47
|
+
/* the schema-family walk */
|
|
48
|
+
YEPTRIS_DIAG_TAG_MISMATCH = 1, /* explicit tag contradicts content */
|
|
49
|
+
YEPTRIS_DIAG_KEY_NOT_STRING = 2, /* json12: mapping key is not a string */
|
|
50
|
+
YEPTRIS_DIAG_NON_JSON_TYPE = 3, /* json12: plain scalar matches no
|
|
51
|
+
* JSON production / carries a
|
|
52
|
+
* non-JSON tag (spec 10.2.2 Error) */
|
|
53
|
+
YEPTRIS_DIAG_DUPLICATE_KEY = 4, /* equal keys in one mapping */
|
|
54
|
+
/* the JSON Schema walk */
|
|
55
|
+
YEPTRIS_DIAG_TYPE = 5,
|
|
56
|
+
YEPTRIS_DIAG_REQUIRED = 6,
|
|
57
|
+
YEPTRIS_DIAG_ENUM = 7,
|
|
58
|
+
YEPTRIS_DIAG_CONST = 8,
|
|
59
|
+
YEPTRIS_DIAG_PATTERN = 9,
|
|
60
|
+
YEPTRIS_DIAG_MINIMUM = 10,
|
|
61
|
+
YEPTRIS_DIAG_MAXIMUM = 11,
|
|
62
|
+
YEPTRIS_DIAG_EXCLUSIVE_MINIMUM = 12,
|
|
63
|
+
YEPTRIS_DIAG_EXCLUSIVE_MAXIMUM = 13,
|
|
64
|
+
YEPTRIS_DIAG_MIN_LENGTH = 14,
|
|
65
|
+
YEPTRIS_DIAG_MAX_LENGTH = 15,
|
|
66
|
+
YEPTRIS_DIAG_MIN_ITEMS = 16,
|
|
67
|
+
YEPTRIS_DIAG_MAX_ITEMS = 17,
|
|
68
|
+
YEPTRIS_DIAG_UNIQUE_ITEMS = 18,
|
|
69
|
+
YEPTRIS_DIAG_ADDITIONAL_PROPERTY = 19,
|
|
70
|
+
YEPTRIS_DIAG_ANY_OF = 20,
|
|
71
|
+
YEPTRIS_DIAG_ONE_OF = 21,
|
|
72
|
+
YEPTRIS_DIAG_NOT = 22,
|
|
73
|
+
YEPTRIS_DIAG_REF = 23, /* $ref unresolvable / chain too deep */
|
|
74
|
+
YEPTRIS_DIAG_FALSE_SCHEMA = 24, /* the schema is `false` here */
|
|
75
|
+
YEPTRIS_DIAG_DEPTH = 25, /* recursion guard tripped */
|
|
76
|
+
YEPTRIS_DIAG_LIMIT = 26, /* report truncated (the sentinel
|
|
77
|
+
* rides the LAST slot; more
|
|
78
|
+
* diagnostics were dropped) */
|
|
79
|
+
/* the 2020-12 sweep (#885 item 2) */
|
|
80
|
+
YEPTRIS_DIAG_MULTIPLE_OF = 27,
|
|
81
|
+
YEPTRIS_DIAG_MIN_PROPERTIES = 28,
|
|
82
|
+
YEPTRIS_DIAG_MAX_PROPERTIES = 29,
|
|
83
|
+
YEPTRIS_DIAG_CONTAINS = 30,
|
|
84
|
+
YEPTRIS_DIAG_MIN_CONTAINS = 31,
|
|
85
|
+
YEPTRIS_DIAG_MAX_CONTAINS = 32,
|
|
86
|
+
YEPTRIS_DIAG_DEPENDENT_REQUIRED = 33,
|
|
87
|
+
} YeptrisDiagCode;
|
|
88
|
+
|
|
89
|
+
/* Bounded diagnostic text; always NUL-terminated (over-long paths and
|
|
90
|
+
* details truncate — the same discipline as the error channel). */
|
|
91
|
+
#define YEPTRIS_DIAG_PATH_MAX 256
|
|
92
|
+
#define YEPTRIS_DIAG_DETAIL_MAX 128
|
|
93
|
+
|
|
94
|
+
typedef struct yeptris_diagnostic {
|
|
95
|
+
uint32_t code; /* YeptrisDiagCode */
|
|
96
|
+
uint32_t line; /* 1-based; 0 = unknown */
|
|
97
|
+
uint32_t col; /* 1-based; 0 = unknown */
|
|
98
|
+
uint32_t offset;
|
|
99
|
+
char path[YEPTRIS_DIAG_PATH_MAX];
|
|
100
|
+
char detail[YEPTRIS_DIAG_DETAIL_MAX];
|
|
101
|
+
} yeptris_diagnostic;
|
|
102
|
+
YEPTRIS_CT_ASSERT(sizeof(yeptris_diagnostic) ==
|
|
103
|
+
16 + YEPTRIS_DIAG_PATH_MAX + YEPTRIS_DIAG_DETAIL_MAX);
|
|
104
|
+
|
|
105
|
+
/* The diagnostics list. Opaque; free it with
|
|
106
|
+
* yeptris_validate_report_free (one call, everything). */
|
|
107
|
+
typedef struct yeptris_validate_report yeptris_validate_report;
|
|
108
|
+
|
|
109
|
+
/* Diagnostic count (0 = the document is valid). */
|
|
110
|
+
YEPTRIS_API size_t yeptris_validate_report_count(const yeptris_validate_report* report);
|
|
111
|
+
|
|
112
|
+
/* Diagnostic i (0-based); NULL out of range. Memory: borrowed from the
|
|
113
|
+
* report — valid until yeptris_validate_report_free. */
|
|
114
|
+
YEPTRIS_API const yeptris_diagnostic*
|
|
115
|
+
yeptris_validate_report_at(const yeptris_validate_report* report, size_t index);
|
|
116
|
+
|
|
117
|
+
YEPTRIS_API void yeptris_validate_report_free(yeptris_validate_report* report);
|
|
118
|
+
|
|
119
|
+
/* Parses `buf` (the same front door as yeptris_parse_ex: encodings,
|
|
120
|
+
* BOM, NEL normalization) and validates every document of the stream
|
|
121
|
+
* against `schema`. Paths are root-relative per document.
|
|
122
|
+
*
|
|
123
|
+
* Status: YEPTRIS_OK (valid; *out is a report — possibly with zero
|
|
124
|
+
* diagnostics for an empty stream); YEPTRIS_ERROR_SCHEMA (invalid:
|
|
125
|
+
* drain *out); YEPTRIS_ERROR_PARSE / DEPTH / ENCODING / MEMORY (the
|
|
126
|
+
* parse itself failed; *out stays NULL); YEPTRIS_ERROR_ARG.
|
|
127
|
+
*
|
|
128
|
+
* Memory: the caller owns *out; free it with
|
|
129
|
+
* yeptris_validate_report_free. */
|
|
130
|
+
YEPTRIS_API YeptrisStatus yeptris_validate(const char* buf, size_t len, YeptrisSchema schema,
|
|
131
|
+
yeptris_validate_report** out);
|
|
132
|
+
|
|
133
|
+
/* Validates an already-parsed document (or stream). The document is
|
|
134
|
+
* not modified; the report borrows nothing from it. */
|
|
135
|
+
YEPTRIS_API YeptrisStatus yeptris_validate_document(YeptrisDocument doc, YeptrisSchema schema,
|
|
136
|
+
yeptris_validate_report** out);
|
|
137
|
+
|
|
138
|
+
/* JSON Schema draft 2020-12 subset (#882 slice 2; #885 item 2). `schema`
|
|
139
|
+
* is parsed with the same engine (JSON is YAML flow); document 0 of the
|
|
140
|
+
* stream is the schema. Keyword subset: type, enum, const, pattern,
|
|
141
|
+
* minimum/maximum/exclusiveMinimum/exclusiveMaximum (numeric, 2020-12
|
|
142
|
+
* form), multipleOf (libm-free quotient test), minLength/maxLength
|
|
143
|
+
* (code points), minItems/maxItems, uniqueItems, contains (+ the
|
|
144
|
+
* minContains/maxContains qualifiers), items (+ prefixItems; the
|
|
145
|
+
* draft-07 array form rides as prefixItems), properties, required,
|
|
146
|
+
* patternProperties, propertyNames, minProperties/maxProperties,
|
|
147
|
+
* additionalProperties (bool or schema; excludes patternProperties
|
|
148
|
+
* matches), dependentRequired, dependentSchemas, if/then/else,
|
|
149
|
+
* allOf/anyOf/oneOf/not, $ref (LOCAL "#/..." pointers only — $defs and
|
|
150
|
+
* definitions both resolve). Boolean schemas (`true`/`false`) apply.
|
|
151
|
+
* Unknown keywords and known keywords with unreadable values are
|
|
152
|
+
* ignored (2020-12). Instance types ride the core-schema resolution
|
|
153
|
+
* (the YAML->JSON data model): "y" is boolean, 1.0 is integer.
|
|
154
|
+
*
|
|
155
|
+
* Status: as yeptris_validate, plus YEPTRIS_ERROR_ARG when the schema
|
|
156
|
+
* bytes hold no document, and YEPTRIS_ERROR_PARSE when they do not
|
|
157
|
+
* parse. A $ref that resolves nowhere is a DIAG_REF diagnostic, not a
|
|
158
|
+
* status. Recursion is depth-guarded (the engine's guard): a
|
|
159
|
+
* self-referential $ref over a deep or cyclic chain reports DIAG_DEPTH
|
|
160
|
+
* / DIAG_REF — never a crash. */
|
|
161
|
+
YEPTRIS_API YeptrisStatus yeptris_json_schema_validate(const char* schema, size_t schema_len,
|
|
162
|
+
const char* buf, size_t len,
|
|
163
|
+
yeptris_validate_report** out);
|
|
164
|
+
|
|
165
|
+
/* The COMPILED SCHEMA — the leptris-XSD economy (#885 item 3): parse
|
|
166
|
+
* the schema ONCE, validate MANY instance streams against the retained
|
|
167
|
+
* model. The handle owns everything it reads: the schema bytes (copied
|
|
168
|
+
* — the retained DOM's views borrow them), the parsed document, and
|
|
169
|
+
* the pattern kernel's compiled programs (the XSD content-model
|
|
170
|
+
* analog: `(a+)+$` compiles once here, not once per validated string
|
|
171
|
+
* the way the one-shot face pays). yeptris_schema_compile returns NULL
|
|
172
|
+
* on failure; yeptris_last_error() carries the why (bad arguments,
|
|
173
|
+
* bytes that hold no document, a schema that does not parse,
|
|
174
|
+
* allocation failure).
|
|
175
|
+
*
|
|
176
|
+
* yeptris_schema_validate keeps yeptris_json_schema_validate's exact
|
|
177
|
+
* status/report contract; diagnostics enumerate every miss across
|
|
178
|
+
* every document of the instance stream. yeptris_schema_free releases
|
|
179
|
+
* the handle and everything it owns in ONE call (no refcounting) —
|
|
180
|
+
* afterwards the handle is DEAD: passing it anywhere is undefined,
|
|
181
|
+
* exactly like a freed document. NULL is accepted (a no-op).
|
|
182
|
+
*
|
|
183
|
+
* Thread law: one schema handle per thread, like documents — the
|
|
184
|
+
* handle is immutable after compile (the pattern programs are built at
|
|
185
|
+
* compile time), so read-only sharing across threads is safe; reports
|
|
186
|
+
* are per-call and caller-owned. */
|
|
187
|
+
typedef struct yeptris_schema yeptris_schema;
|
|
188
|
+
|
|
189
|
+
YEPTRIS_API yeptris_schema* yeptris_schema_compile(const char* bytes, size_t n);
|
|
190
|
+
|
|
191
|
+
YEPTRIS_API YeptrisStatus yeptris_schema_validate(yeptris_schema* s, const char* buf, size_t len,
|
|
192
|
+
yeptris_validate_report** out);
|
|
193
|
+
|
|
194
|
+
YEPTRIS_API void yeptris_schema_free(yeptris_schema* s);
|
|
195
|
+
|
|
196
|
+
#ifdef __cplusplus
|
|
197
|
+
}
|
|
198
|
+
#endif
|
|
199
|
+
|
|
200
|
+
#endif /* YEPTRIS_VALIDATE_H */
|
|
@@ -236,10 +236,15 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
236
236
|
goto fail;
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
+
/* a NULL/0-byte stream is a valid empty input: parse it through a
|
|
240
|
+
* non-null base so the BOM arithmetic never computes NULL+0
|
|
241
|
+
* (clang's UBSan flags the zero-offset-null form; gcc's does not —
|
|
242
|
+
* the schema-econ BadInputs pin surfaced it on the macOS arm64 leg) */
|
|
243
|
+
const char* src = buf != NULL ? buf : "";
|
|
239
244
|
const yep_allocator* sys = yep_system_allocator();
|
|
240
245
|
|
|
241
246
|
/* Encoding front-end: BOM sniff; borrow UTF-8, transcode the rest. */
|
|
242
|
-
const char* data =
|
|
247
|
+
const char* data = src;
|
|
243
248
|
size_t data_len = len;
|
|
244
249
|
unsigned char* transcoded = NULL;
|
|
245
250
|
size_t transcoded_len = 0;
|
|
@@ -256,8 +261,8 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
256
261
|
goto engine_enter;
|
|
257
262
|
}
|
|
258
263
|
|
|
259
|
-
size_t bom = yep_bom_sniff((const unsigned char*)
|
|
260
|
-
data =
|
|
264
|
+
size_t bom = yep_bom_sniff((const unsigned char*)src, len, &enc);
|
|
265
|
+
data = src + bom;
|
|
261
266
|
data_len = len - bom;
|
|
262
267
|
|
|
263
268
|
if (enc == YEP_ENC_UTF16LE || enc == YEP_ENC_UTF16BE || enc == YEP_ENC_UTF32LE ||
|
|
@@ -325,9 +330,13 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
325
330
|
engine_enter:
|
|
326
331
|
eng = yep_engine_create(sys);
|
|
327
332
|
if (opts != NULL) {
|
|
333
|
+
/* the typing SSOT: the family's resolver (compat11 when asked,
|
|
334
|
+
* json12 for the 12_JSON validation family, core12 otherwise) */
|
|
328
335
|
yep_engine_set_resolver(eng, opts->schema == YEPTRIS_SCHEMA_11_COMPAT
|
|
329
336
|
? yep_resolver_compat11()
|
|
330
|
-
:
|
|
337
|
+
: (opts->schema == YEPTRIS_SCHEMA_12_JSON
|
|
338
|
+
? yep_resolver_json12()
|
|
339
|
+
: yep_resolver_core12()));
|
|
331
340
|
if (opts->schema == YEPTRIS_SCHEMA_11_COMPAT) {
|
|
332
341
|
/* the compat schema is the psych/libyaml surface: its grammar
|
|
333
342
|
* must accept what libyaml accepts (the flow floor is suite-
|
|
@@ -357,9 +366,13 @@ engine_enter:
|
|
|
357
366
|
}
|
|
358
367
|
/* the direct builders resolve with the engine's schema (the typing
|
|
359
368
|
* SSOT — one resolver decision per scalar, whichever path builds) */
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
369
|
+
if (opts != NULL && opts->schema == YEPTRIS_SCHEMA_11_COMPAT) {
|
|
370
|
+
dom->resolver = yep_resolver_compat11();
|
|
371
|
+
} else if (opts != NULL && opts->schema == YEPTRIS_SCHEMA_12_JSON) {
|
|
372
|
+
dom->resolver = yep_resolver_json12();
|
|
373
|
+
} else {
|
|
374
|
+
dom->resolver = yep_resolver_core12();
|
|
375
|
+
}
|
|
363
376
|
/* BEFORE the run: input-slice strings borrow as views (zero copy)
|
|
364
377
|
* — the document keeps `transcoded` alive for exactly this. Set
|
|
365
378
|
* after, every scalar was arena-copied (found 2026-09-10). */
|
|
@@ -422,6 +435,8 @@ engine_enter:
|
|
|
422
435
|
} else if (have_tape && !norm_kept_raw &&
|
|
423
436
|
ytap_fused_run(&yt, (opts != NULL && opts->schema == YEPTRIS_SCHEMA_11_COMPAT)
|
|
424
437
|
? yep_resolver_compat11()
|
|
438
|
+
: (opts != NULL && opts->schema == YEPTRIS_SCHEMA_12_JSON)
|
|
439
|
+
? yep_resolver_json12()
|
|
425
440
|
: yep_resolver_core12()) == 0) {
|
|
426
441
|
/* the fused block runner owned the whole document — the engine
|
|
427
442
|
* never runs (TODO.restructure/79). Its only cost was the parse
|
|
@@ -496,9 +511,8 @@ engine_enter:
|
|
|
496
511
|
}
|
|
497
512
|
yep_mutex_init(&doc->lazy_mu);
|
|
498
513
|
doc->sys = sys;
|
|
499
|
-
doc->schema = (opts != NULL && opts->schema
|
|
500
|
-
|
|
501
|
-
: YEPTRIS_SCHEMA_12_CORE;
|
|
514
|
+
doc->schema = (opts != NULL && opts->schema != YEPTRIS_SCHEMA_12_CORE) ? opts->schema
|
|
515
|
+
: YEPTRIS_SCHEMA_12_CORE;
|
|
502
516
|
doc->transcoded = transcoded;
|
|
503
517
|
doc->transcoded_len = transcoded_len;
|
|
504
518
|
doc->input = buf;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* json12.c — the spec 10.2 JSON schema resolver (#882).
|
|
2
|
+
*
|
|
3
|
+
* The productions are the spec 10.2.2 table (1.2.2 erratum kept: the
|
|
4
|
+
* float regex needs NO digits after the dot — "0." is a float):
|
|
5
|
+
* null: null
|
|
6
|
+
* bool: true | false
|
|
7
|
+
* int: -? ( 0 | [1-9] [0-9]* )
|
|
8
|
+
* float: -? ( 0 | [1-9] [0-9]* ) ( \. [0-9]* )? ( [eE] [-+]? [0-9]+ )?
|
|
9
|
+
* * -> Error (the validator's business; the resolver stays str)
|
|
10
|
+
*
|
|
11
|
+
* Deliberately NOT accepted (the core schema's extensions): "True"/
|
|
12
|
+
* "False"/"NULL" casings, "~"/empty nulls, +signs, 0o/0x radix, .inf/
|
|
13
|
+
* .nan, underscores. The example-10.8 Invalid list pins each one.
|
|
14
|
+
*
|
|
15
|
+
* Shape: yep_json12_plain is the ONE classifier — the resolver wraps
|
|
16
|
+
* it, and the validator re-asks it per plain scalar (no second truth
|
|
17
|
+
* table anywhere). Parse never errors here: a scalar outside the
|
|
18
|
+
* productions resolves str so the DOM stays family-neutral; the
|
|
19
|
+
* validation face turns the spec's Error row into diagnostics.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
#include <stdint.h>
|
|
23
|
+
#include <string.h>
|
|
24
|
+
|
|
25
|
+
#include "resolver.h"
|
|
26
|
+
|
|
27
|
+
/* JSON int: -?(0|[1-9][0-9]*); optionally continues as the float
|
|
28
|
+
* production (the int regex is a prefix of the float one). Returns 1
|
|
29
|
+
* (int), 2 (float), 0 (no production). */
|
|
30
|
+
int yep_json12_plain(const char* p, uint32_t n) {
|
|
31
|
+
if (n == 0) {
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
if (n == 4 && memcmp(p, "null", 4) == 0) {
|
|
35
|
+
return 4; /* null */
|
|
36
|
+
}
|
|
37
|
+
if (n == 4 && memcmp(p, "true", 4) == 0) {
|
|
38
|
+
return 3; /* bool */
|
|
39
|
+
}
|
|
40
|
+
if (n == 5 && memcmp(p, "false", 5) == 0) {
|
|
41
|
+
return 3;
|
|
42
|
+
}
|
|
43
|
+
uint32_t i = (p[0] == '-') ? 1 : 0;
|
|
44
|
+
if (i >= n) {
|
|
45
|
+
return 0; /* lone "-" (or empty after the prefix check) */
|
|
46
|
+
}
|
|
47
|
+
/* int part: 0 | [1-9][0-9]* — no +sign, no leading zeros */
|
|
48
|
+
if (p[i] == '0') {
|
|
49
|
+
i++;
|
|
50
|
+
} else if (p[i] >= '1' && p[i] <= '9') {
|
|
51
|
+
i++;
|
|
52
|
+
while (i < n && p[i] >= '0' && p[i] <= '9') {
|
|
53
|
+
i++;
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
if (i == n) {
|
|
59
|
+
return 1; /* bare int */
|
|
60
|
+
}
|
|
61
|
+
/* float tail: (\.[0-9]*)? ([eE][-+]?[0-9]+)? — at least one of the
|
|
62
|
+
* two must be present (a bare int already returned) */
|
|
63
|
+
int floaty = 0;
|
|
64
|
+
if (p[i] == '.') {
|
|
65
|
+
floaty = 1;
|
|
66
|
+
i++;
|
|
67
|
+
while (i < n && p[i] >= '0' && p[i] <= '9') {
|
|
68
|
+
i++; /* digits optional after the dot (1.2.2 erratum) */
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (i < n && (p[i] == 'e' || p[i] == 'E')) {
|
|
72
|
+
i++;
|
|
73
|
+
if (i < n && (p[i] == '+' || p[i] == '-')) {
|
|
74
|
+
i++;
|
|
75
|
+
}
|
|
76
|
+
int ed = 0;
|
|
77
|
+
while (i < n && p[i] >= '0' && p[i] <= '9') {
|
|
78
|
+
i++;
|
|
79
|
+
ed = 1;
|
|
80
|
+
}
|
|
81
|
+
if (!ed) {
|
|
82
|
+
return 0; /* exponent sign(s) with no digits */
|
|
83
|
+
}
|
|
84
|
+
floaty = 1;
|
|
85
|
+
}
|
|
86
|
+
return (floaty && i == n) ? 2 : 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static yep_tag_id json12(void* ctx, const char* p, uint32_t n) {
|
|
90
|
+
(void)ctx;
|
|
91
|
+
return (yep_tag_id)yep_json12_plain(p, n);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static yep_tag_id json12_number(void* ctx, int is_float) {
|
|
95
|
+
(void)ctx;
|
|
96
|
+
return is_float ? 2 : 1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static const yep_resolver k_json12 = {json12, json12_number, NULL};
|
|
100
|
+
|
|
101
|
+
const yep_resolver* yep_resolver_json12(void) {
|
|
102
|
+
return &k_json12;
|
|
103
|
+
}
|
|
@@ -40,6 +40,15 @@ static inline yep_tag_id yep_resolve_number(const yep_resolver* r, int is_float)
|
|
|
40
40
|
const yep_resolver* yep_resolver_core12(void);
|
|
41
41
|
const yep_resolver* yep_resolver_compat11(void);
|
|
42
42
|
|
|
43
|
+
/* The spec 10.2 JSON schema resolver (#882): null/true/false exact,
|
|
44
|
+
* the JSON int and float productions, everything else str. Parse stays
|
|
45
|
+
* lenient — the VALIDATOR flags plain scalars that matched no
|
|
46
|
+
* production (the spec's `*` -> Error row) through the classifier. */
|
|
47
|
+
const yep_resolver* yep_resolver_json12(void);
|
|
48
|
+
/* 1 when the plain span matches a JSON-schema production. The one
|
|
49
|
+
* truth table for the 12_JSON family (validate/ re-asks it). */
|
|
50
|
+
int yep_json12_plain(const char* p, uint32_t n);
|
|
51
|
+
|
|
43
52
|
/* core tag id <-> canonical URI (tags.c is the identity SSOT). */
|
|
44
53
|
const char* yep_tag_uri(yep_tag_id id);
|
|
45
54
|
|