yeptris 0.6.60.1-arm-linux-eabihf → 0.6.61.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/yaml.rb +10 -0
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/include/yeptris/parse.h +21 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +12 -1
- data/vendor/libyeptris/src/yeptris/dom/ytape.c +56 -7
- data/vendor/libyeptris/src/yeptris/emit/emit.c +8 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +85 -10
- data/vendor/libyeptris/src/yeptris/emit/writer.h +10 -7
- data/vendor/libyeptris/src/yeptris/events/values.c +22 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.c +490 -90
- data/vendor/libyeptris/src/yeptris/parse/engine.h +5 -0
- data/vendor/libyeptris/src/yeptris/parse/stream_iter.c +33 -1
- data/vendor/libyeptris/src/yeptris/parse.c +43 -1
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +2 -5
- data/vendor/libyeptris/src/yeptris/resolve/resolver.h +18 -0
- data/vendor/libyeptris/src/yeptris/resolve/tags.c +192 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +22 -7
- data/vendor/libyeptris/src/yeptris/tape.c +24 -5
- metadata +1 -1
|
@@ -53,6 +53,11 @@ int yep_engine_step(yep_engine* e, const char* chunk, size_t len, int final, con
|
|
|
53
53
|
* allocates a fresh one if reused). Returns NULL when absent. */
|
|
54
54
|
yep_pool* yep_engine_detach_pool(yep_engine* e);
|
|
55
55
|
|
|
56
|
+
/* Detaches the run's break-normalizer copy (ownership moves to the
|
|
57
|
+
* caller; the caller owns the returned buffer once detached). Returns
|
|
58
|
+
* NULL when the run kept the input zero-copy. */
|
|
59
|
+
char* yep_engine_detach_norm_buf(yep_engine* e, size_t* len_out);
|
|
60
|
+
|
|
56
61
|
/* Implicit-typing schema for the next run (NULL: 1.2 core), and the
|
|
57
62
|
* runtime nesting limit. */
|
|
58
63
|
struct yep_resolver;
|
|
@@ -67,6 +67,9 @@ struct yeptris_stream_iter {
|
|
|
67
67
|
YeptrisStatus last_status; /* the LAST next()'s per-document verdict */
|
|
68
68
|
uint32_t last_line;
|
|
69
69
|
uint32_t last_col;
|
|
70
|
+
size_t last_off; /* the last SUCCESSFUL document's slice
|
|
71
|
+
* in the (post-gate) buffer space */
|
|
72
|
+
size_t last_len;
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
yeptris_stream_iter* yeptris_stream_iter_new(const char* buf, size_t len,
|
|
@@ -127,6 +130,8 @@ static void it_fail(struct yeptris_stream_iter* it, YeptrisStatus st, uint32_t l
|
|
|
127
130
|
it->last_status = st;
|
|
128
131
|
it->last_line = line;
|
|
129
132
|
it->last_col = col;
|
|
133
|
+
it->last_len = 0; /* the slice accessor must not serve a stale frame
|
|
134
|
+
* (the success path sets off/len right after) */
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
static int engine_opts(yep_engine* eng, const YeptrisParseOptions* opts) {
|
|
@@ -290,12 +295,14 @@ YeptrisStatus yeptris_stream_iter_next(struct yeptris_stream_iter* it, YeptrisDo
|
|
|
290
295
|
}
|
|
291
296
|
return it->last_status;
|
|
292
297
|
}
|
|
298
|
+
it_fail(it, YEPTRIS_OK, 0, 0);
|
|
299
|
+
it->last_off = it->cursor;
|
|
300
|
+
it->last_len = pos;
|
|
293
301
|
it->cursor += pos;
|
|
294
302
|
it->index++;
|
|
295
303
|
if (index != NULL) {
|
|
296
304
|
*index = it->index - 1;
|
|
297
305
|
}
|
|
298
|
-
it_fail(it, YEPTRIS_OK, 0, 0);
|
|
299
306
|
*out = doc;
|
|
300
307
|
return YEPTRIS_OK;
|
|
301
308
|
}
|
|
@@ -315,6 +322,31 @@ YeptrisStatus yeptris_stream_iter_status(const struct yeptris_stream_iter* it, u
|
|
|
315
322
|
return it->last_status;
|
|
316
323
|
}
|
|
317
324
|
|
|
325
|
+
/* The last successful document's slice (parse.h): the host's value
|
|
326
|
+
* route re-parses exactly these bytes — one typing SSOT. */
|
|
327
|
+
YeptrisStatus yeptris_stream_iter_slice(const struct yeptris_stream_iter* it, size_t* off,
|
|
328
|
+
size_t* len) {
|
|
329
|
+
if (it == NULL || off == NULL || len == NULL) {
|
|
330
|
+
return YEPTRIS_ERROR_ARG;
|
|
331
|
+
}
|
|
332
|
+
if (it->last_status != YEPTRIS_OK || it->last_len == 0) {
|
|
333
|
+
return YEPTRIS_ERROR_ARG; /* a failure or the stream end was the last step */
|
|
334
|
+
}
|
|
335
|
+
*off = it->last_off;
|
|
336
|
+
*len = it->last_len;
|
|
337
|
+
return YEPTRIS_OK;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
YeptrisStatus yeptris_stream_iter_buffer(const struct yeptris_stream_iter* it, const char** buf,
|
|
341
|
+
size_t* len) {
|
|
342
|
+
if (it == NULL || buf == NULL || len == NULL) {
|
|
343
|
+
return YEPTRIS_ERROR_ARG;
|
|
344
|
+
}
|
|
345
|
+
*buf = it->buf;
|
|
346
|
+
*len = it->len;
|
|
347
|
+
return YEPTRIS_OK;
|
|
348
|
+
}
|
|
349
|
+
|
|
318
350
|
void yeptris_stream_iter_free(struct yeptris_stream_iter* it) {
|
|
319
351
|
if (it == NULL) {
|
|
320
352
|
return;
|
|
@@ -458,6 +458,11 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
458
458
|
int norm_kept_raw = 0; /* raw NEL/LS/PS survived the quote-aware
|
|
459
459
|
* walk: the engine route owns the document
|
|
460
460
|
* (the tape runner predates the cut) */
|
|
461
|
+
char* nbuf = NULL; /* the engine's break-normalizer copy (#953):
|
|
462
|
+
* DOM and tape scalar slices point INTO it,
|
|
463
|
+
* so the document must own it like the
|
|
464
|
+
* finish pool and transcoded */
|
|
465
|
+
size_t nblen = 0;
|
|
461
466
|
|
|
462
467
|
if (parse_frontend(buf, len, sys, json_mode, &data, &data_len, &transcoded, &transcoded_len,
|
|
463
468
|
&norm_kept_raw, &st) != 0) {
|
|
@@ -600,8 +605,11 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
600
605
|
}
|
|
601
606
|
/* Resolved tags, folded and escaped scalars live in the engine's
|
|
602
607
|
* finish pool; the document must own it or every such string would
|
|
603
|
-
* dangle at engine teardown (found by ASAN).
|
|
608
|
+
* dangle at engine teardown (found by ASAN). The break-normalizer
|
|
609
|
+
* copy is the same law (#953): scalar value slices in the DOM and
|
|
610
|
+
* the packed tape point INTO it. */
|
|
604
611
|
yep_pool* finish = yep_engine_detach_pool(eng);
|
|
612
|
+
nbuf = yep_engine_detach_norm_buf(eng, &nblen);
|
|
605
613
|
yep_engine_destroy(eng);
|
|
606
614
|
|
|
607
615
|
/* Empty stream (no documents): NULL document with YEPTRIS_OK. */
|
|
@@ -613,6 +621,9 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
613
621
|
}
|
|
614
622
|
yep_pool_destroy(finish);
|
|
615
623
|
yep_free(sys, transcoded);
|
|
624
|
+
if (nbuf != NULL) {
|
|
625
|
+
yep_free(sys, nbuf); /* not parked: no document survives */
|
|
626
|
+
}
|
|
616
627
|
if (status != NULL) {
|
|
617
628
|
*status = YEPTRIS_OK;
|
|
618
629
|
}
|
|
@@ -631,6 +642,9 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
631
642
|
yep_dom_destroy(dom);
|
|
632
643
|
yep_pool_destroy(finish);
|
|
633
644
|
yep_free(sys, transcoded);
|
|
645
|
+
if (nbuf != NULL) {
|
|
646
|
+
yep_free(sys, nbuf); /* not parked: no document survives */
|
|
647
|
+
}
|
|
634
648
|
st = YEPTRIS_ERROR_MEMORY;
|
|
635
649
|
goto fail;
|
|
636
650
|
}
|
|
@@ -640,6 +654,31 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
640
654
|
: YEPTRIS_SCHEMA_12_CORE;
|
|
641
655
|
doc->transcoded = transcoded;
|
|
642
656
|
doc->transcoded_len = transcoded_len;
|
|
657
|
+
if (nbuf != NULL) {
|
|
658
|
+
/* #953: the engine re-normalized THIS run (raw NEL/LS/PS rode
|
|
659
|
+
* quoted regions past the front-end), so every engine event
|
|
660
|
+
* view points INTO nbuf — and the lazy tape stored those
|
|
661
|
+
* pointers ABSOLUTE (they fall outside yt.input's range, so
|
|
662
|
+
* the span recorder kept them verbatim). The document owns
|
|
663
|
+
* nbuf like the finish pool, whichever copy the slot held. */
|
|
664
|
+
if (have_tape) {
|
|
665
|
+
/* rebase the tape's span base onto the doc-owned copy:
|
|
666
|
+
* materialization's input_base offsets against LIVE bytes.
|
|
667
|
+
* `transcoded` is referenced by no record (the engine
|
|
668
|
+
* parsed nbuf only) — release it. */
|
|
669
|
+
yt.input = nbuf;
|
|
670
|
+
yt.input_len = nblen;
|
|
671
|
+
yep_free(sys, transcoded);
|
|
672
|
+
transcoded = NULL;
|
|
673
|
+
doc->transcoded = (unsigned char*)nbuf;
|
|
674
|
+
doc->transcoded_len = nblen;
|
|
675
|
+
} else {
|
|
676
|
+
/* eager: the dom copied every scalar during the run (the
|
|
677
|
+
* borrowed views offset against input_base = transcoded);
|
|
678
|
+
* nbuf has no post-run reader — the slot keeps transcoded */
|
|
679
|
+
yep_free(sys, nbuf);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
643
682
|
doc->input = buf;
|
|
644
683
|
doc->finish_pool = finish; /* NULL on the eager route */
|
|
645
684
|
doc->lazy_tape = NULL;
|
|
@@ -650,6 +689,9 @@ static YeptrisDocument parse_impl(const char* buf, size_t len, const YeptrisPars
|
|
|
650
689
|
ytap_free(&yt);
|
|
651
690
|
yep_pool_destroy(finish);
|
|
652
691
|
yep_free(sys, transcoded);
|
|
692
|
+
if (nbuf != NULL) {
|
|
693
|
+
yep_free(sys, nbuf); /* not parked: no document survives */
|
|
694
|
+
}
|
|
653
695
|
yep_free(sys, doc);
|
|
654
696
|
st = YEPTRIS_ERROR_MEMORY;
|
|
655
697
|
goto fail;
|
|
@@ -65,11 +65,8 @@ static yep_tag_id compat11(void* ctx, const char* p, uint32_t n) {
|
|
|
65
65
|
if (n == 0 || eq(p, n, "~") || ci_eq3(p, n, "null")) {
|
|
66
66
|
return 4; /* null: psych nil for ""/"~"/null (any case) */
|
|
67
67
|
}
|
|
68
|
-
if (
|
|
69
|
-
return 3;
|
|
70
|
-
}
|
|
71
|
-
if (ci_eq3(p, n, "no") || ci_eq3(p, n, "false") || ci_eq3(p, n, "off") || ci_eq3(p, n, "n")) {
|
|
72
|
-
return 3;
|
|
68
|
+
if (yep_tag_bool_value(p, n) >= 0) {
|
|
69
|
+
return 3; /* the one bool table (tags.c): true/false sets ci */
|
|
73
70
|
}
|
|
74
71
|
if (eq(p, n, "=")) {
|
|
75
72
|
return 10; /* value */
|
|
@@ -82,4 +82,22 @@ yep_tag_id yep_tag_from_uri(const char* p, uint32_t len);
|
|
|
82
82
|
* portably). */
|
|
83
83
|
const char* yep_tag_float_word(const char* p, uint32_t len);
|
|
84
84
|
|
|
85
|
+
/* The BOOL truth table for a resolved-bool view: 1 true, 0 false,
|
|
86
|
+
* -1 not a bool word. One table, two consumers: compat11's classify
|
|
87
|
+
* and the canonical/JSON emitter's BOOL arm — the DOM stores only the
|
|
88
|
+
* tag + source text, so the emitter re-asks the table (#937: guessing
|
|
89
|
+
* the value from the text's length spelled every non-4-char true-word
|
|
90
|
+
* false). The ci union of the families' sets (core's true/false forms
|
|
91
|
+
* are in the compat superset), so no family fact is needed. */
|
|
92
|
+
int yep_tag_bool_value(const char* p, uint32_t len);
|
|
93
|
+
|
|
94
|
+
/* Decode a resolved-INT view to its value through the family's own
|
|
95
|
+
* accepted forms: radix prefixes 0x/0o in both (0b and the leading-0
|
|
96
|
+
* octal + _/,/sexagesimal forms only when compat — core spells
|
|
97
|
+
* leading-0 decimal), digits otherwise. Overflow beyond the int64
|
|
98
|
+
* range returns nonzero and *out is untouched. The canonical/JSON
|
|
99
|
+
* emitter's INT arm (#937: source text like 0x1F is not a JSON
|
|
100
|
+
* token). */
|
|
101
|
+
int yep_tag_int64(const char* p, uint32_t len, int compat, int64_t* out);
|
|
102
|
+
|
|
85
103
|
#endif /* YEP_RESOLVER_H */
|
|
@@ -56,3 +56,195 @@ const char* yep_tag_float_word(const char* p, uint32_t len) {
|
|
|
56
56
|
}
|
|
57
57
|
return NULL;
|
|
58
58
|
}
|
|
59
|
+
|
|
60
|
+
static int ci_eq(const char* p, uint32_t n, const char* s) {
|
|
61
|
+
uint32_t m = 0;
|
|
62
|
+
while (s[m] != '\0') {
|
|
63
|
+
m++;
|
|
64
|
+
}
|
|
65
|
+
if (n != m) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
for (uint32_t k = 0; k < n; k++) {
|
|
69
|
+
char a = p[k], b = s[k];
|
|
70
|
+
if (a >= 'A' && a <= 'Z') {
|
|
71
|
+
a = (char)(a - 'A' + 'a');
|
|
72
|
+
}
|
|
73
|
+
if (b >= 'A' && b <= 'Z') {
|
|
74
|
+
b = (char)(b - 'A' + 'a');
|
|
75
|
+
}
|
|
76
|
+
if (a != b) {
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
int yep_tag_bool_value(const char* p, uint32_t len) {
|
|
84
|
+
static const char* const words[8] = {"y", "yes", "true", "on", "n", "no", "false", "off"};
|
|
85
|
+
for (unsigned i = 0; i < 8; i++) {
|
|
86
|
+
if (ci_eq(p, len, words[i])) {
|
|
87
|
+
return i < 4 ? 1 : 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return -1;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* One base-denominated digit with overflow detection (uint64 keeps
|
|
94
|
+
* the INT64_MIN magnitude representable). */
|
|
95
|
+
static int acc_digit(uint64_t* acc, int base, int dv) {
|
|
96
|
+
uint64_t na = *acc * (uint64_t)base;
|
|
97
|
+
if (na / (uint64_t)base != *acc) {
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
na += (uint64_t)dv;
|
|
101
|
+
if (na < *acc) {
|
|
102
|
+
return 1;
|
|
103
|
+
}
|
|
104
|
+
*acc = na;
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
int yep_tag_int64(const char* p, uint32_t n, int compat, int64_t* out) {
|
|
109
|
+
uint32_t i = 0;
|
|
110
|
+
int neg = 0;
|
|
111
|
+
if (n == 0) {
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
if (p[0] == '-' || p[0] == '+') {
|
|
115
|
+
neg = p[0] == '-';
|
|
116
|
+
i = 1;
|
|
117
|
+
if (i >= n) {
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/* radix prefixes first (both families, lowercase only — "0X1A"
|
|
122
|
+
* rides a string in core AND compat; 0o is core's spelling, 0b
|
|
123
|
+
* compat's), then compat's leading-0 octal, then the plain
|
|
124
|
+
* decimal/sexagesimal walk */
|
|
125
|
+
uint64_t acc = 0;
|
|
126
|
+
int digits = 0;
|
|
127
|
+
int base = 10;
|
|
128
|
+
uint32_t d = i;
|
|
129
|
+
if (n - i > 2 && p[i] == '0' && p[i + 1] == 'x') {
|
|
130
|
+
base = 16;
|
|
131
|
+
d = i + 2;
|
|
132
|
+
if (compat && p[d] == '_') {
|
|
133
|
+
d++;
|
|
134
|
+
if (p[d] == '_') {
|
|
135
|
+
return 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} else if (n - i > 2 && p[i] == '0' && p[i + 1] == 'o') {
|
|
139
|
+
if (compat) {
|
|
140
|
+
return 1; /* 0o is not a compat form (psych) */
|
|
141
|
+
}
|
|
142
|
+
base = 8;
|
|
143
|
+
d = i + 2;
|
|
144
|
+
} else if (compat && n - i > 2 && p[i] == '0' && p[i + 1] == 'b') {
|
|
145
|
+
base = 2;
|
|
146
|
+
d = i + 2;
|
|
147
|
+
if (p[d] == '_') {
|
|
148
|
+
d++;
|
|
149
|
+
if (p[d] == '_') {
|
|
150
|
+
return 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} else if (compat && p[i] == '0' && n - i >= 2) {
|
|
154
|
+
/* leading-0 octal (psych): 0[_]*[0-7][0-7_]* — the radix
|
|
155
|
+
* prefixes above never reach this arm */
|
|
156
|
+
base = 8;
|
|
157
|
+
d = i + 1;
|
|
158
|
+
while (d < n && p[d] == '_') {
|
|
159
|
+
d++;
|
|
160
|
+
}
|
|
161
|
+
if (d >= n) {
|
|
162
|
+
*out = 0; /* plain "0" / "000" */
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
} else if (compat && p[i] == '0' && n - i == 1) {
|
|
166
|
+
*out = 0;
|
|
167
|
+
return 0;
|
|
168
|
+
} else if (compat && p[i] >= '0' && p[i] <= '9') {
|
|
169
|
+
/* sexagesimal int (compat only): d[d_,]*(:[0-5]?d){1,2} — the
|
|
170
|
+
* fractional form is float-tagged and never reaches here, but
|
|
171
|
+
* a '.' still refuses (the decode must not guess). '_' and ','
|
|
172
|
+
* are the compat separators (psych legacy). */
|
|
173
|
+
uint32_t k = i;
|
|
174
|
+
while (k < n && ((p[k] >= '0' && p[k] <= '9') || p[k] == '_' || p[k] == ',')) {
|
|
175
|
+
if (p[k] != '_' && p[k] != ',') {
|
|
176
|
+
if (acc_digit(&acc, 10, p[k] - '0')) {
|
|
177
|
+
return 1;
|
|
178
|
+
}
|
|
179
|
+
digits = 1;
|
|
180
|
+
}
|
|
181
|
+
k++;
|
|
182
|
+
}
|
|
183
|
+
if (k < n && p[k] == ':') {
|
|
184
|
+
while (k < n && p[k] == ':') {
|
|
185
|
+
k++;
|
|
186
|
+
int gd = 0;
|
|
187
|
+
int g = 0;
|
|
188
|
+
while (k < n && p[k] >= '0' && p[k] <= '9' && gd < 2) {
|
|
189
|
+
g = g * 10 + (p[k] - '0');
|
|
190
|
+
gd++;
|
|
191
|
+
k++;
|
|
192
|
+
}
|
|
193
|
+
if (gd < 1 || g > 59) {
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
196
|
+
if (acc_digit(&acc, 60, g)) {
|
|
197
|
+
return 1;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (k == n) {
|
|
201
|
+
*out = neg ? -(int64_t)acc : (int64_t)acc;
|
|
202
|
+
return 0;
|
|
203
|
+
}
|
|
204
|
+
return 1;
|
|
205
|
+
}
|
|
206
|
+
/* a ':'-less digit span: the plain decimal path below would
|
|
207
|
+
* re-read it — answer directly */
|
|
208
|
+
if (k == n && digits) {
|
|
209
|
+
*out = neg ? -(int64_t)acc : (int64_t)acc;
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
return 1;
|
|
213
|
+
}
|
|
214
|
+
acc = 0;
|
|
215
|
+
digits = 0;
|
|
216
|
+
for (uint32_t k = d; k < n; k++) {
|
|
217
|
+
char c = p[k];
|
|
218
|
+
int dv;
|
|
219
|
+
if (c >= '0' && c <= '9') {
|
|
220
|
+
dv = c - '0';
|
|
221
|
+
} else if (base == 16 && c >= 'a' && c <= 'f') {
|
|
222
|
+
dv = c - 'a' + 10;
|
|
223
|
+
} else if (base == 16 && c >= 'A' && c <= 'F') {
|
|
224
|
+
dv = c - 'A' + 10;
|
|
225
|
+
} else if (compat && (c == '_' || c == ',')) {
|
|
226
|
+
continue;
|
|
227
|
+
} else {
|
|
228
|
+
return 1;
|
|
229
|
+
}
|
|
230
|
+
if (base != 16 && dv >= base) {
|
|
231
|
+
return 1;
|
|
232
|
+
}
|
|
233
|
+
if (acc_digit(&acc, base, dv)) {
|
|
234
|
+
return 1;
|
|
235
|
+
}
|
|
236
|
+
digits = 1;
|
|
237
|
+
}
|
|
238
|
+
if (!digits) {
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
if (neg && acc == (uint64_t)INT64_MAX + 1u) {
|
|
242
|
+
*out = INT64_MIN;
|
|
243
|
+
return 0;
|
|
244
|
+
}
|
|
245
|
+
if (acc > (uint64_t)INT64_MAX) {
|
|
246
|
+
return 1;
|
|
247
|
+
}
|
|
248
|
+
*out = neg ? -(int64_t)acc : (int64_t)acc;
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
@@ -689,18 +689,33 @@ yep_span yep_scan_plain(const char* p, size_t len, size_t pos, int flow) {
|
|
|
689
689
|
size_t at = (hit < 0) ? len : i + (size_t)hit;
|
|
690
690
|
/* a multibyte break inside the piece ends it like an EOL: the
|
|
691
691
|
* byte stopset cannot see NEL/LS/PS, and the continuation
|
|
692
|
-
* would ride across the break into the next line's tokens
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
692
|
+
* would ride across the break into the next line's tokens.
|
|
693
|
+
* EVERY lead byte in the piece must be tested: the first lead
|
|
694
|
+
* can be an ordinary multibyte character (the r169 yen U+00A5
|
|
695
|
+
* leading a NEL run) while a later one is a break — testing
|
|
696
|
+
* the first lead only declined the check there and rode the
|
|
697
|
+
* break raw into the scalar (the false-lead ride, the r74
|
|
698
|
+
* plain-ends-at-NEL law defeated by the lead's own position). */
|
|
699
|
+
int mb_broken = 0;
|
|
700
|
+
for (size_t scan = i; at > scan;) {
|
|
701
|
+
const char* lead = (const char*)memchr(p + scan, 0xC2, at - scan);
|
|
702
|
+
const char* lead2 = (const char*)memchr(p + scan, 0xE2, at - scan);
|
|
696
703
|
const char* first =
|
|
697
704
|
(lead && lead2) ? (lead < lead2 ? lead : lead2) : (lead ? lead : lead2);
|
|
698
|
-
if (first
|
|
705
|
+
if (first == NULL) {
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
if (yep_scan_mb_break_len(p, len, (size_t)(first - p)) > 0) {
|
|
699
709
|
at = (size_t)(first - p);
|
|
700
|
-
|
|
701
|
-
s.term = YEP_TERM_EOL;
|
|
710
|
+
mb_broken = 1;
|
|
702
711
|
break;
|
|
703
712
|
}
|
|
713
|
+
scan = (size_t)(first - p) + 1; /* a false lead: advance past it */
|
|
714
|
+
}
|
|
715
|
+
if (mb_broken) {
|
|
716
|
+
i = at;
|
|
717
|
+
s.term = YEP_TERM_EOL;
|
|
718
|
+
break;
|
|
704
719
|
}
|
|
705
720
|
unsigned char c = (at < len) ? (unsigned char)p[at] : 0;
|
|
706
721
|
|
|
@@ -1278,13 +1278,32 @@ ldone:
|
|
|
1278
1278
|
* Y79Y#4 error: defer to the engine, whose e_flow_ws owns the law
|
|
1279
1279
|
* -- the walk's whitespace loops treat the tab as separation, which
|
|
1280
1280
|
* accepted exactly the span the marshal drain's engine rejected,
|
|
1281
|
-
* splitting parseable from marshalable (the nightly's round 120)
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1281
|
+
* splitting parseable from marshalable (the nightly's round 120).
|
|
1282
|
+
* clean_only skips the scan: its byte guarantees already rejected
|
|
1283
|
+
* every tab in the span (LWS stops on one, the string c0 sweeps
|
|
1284
|
+
* and the tail reject it), so the pair cannot exist there. The
|
|
1285
|
+
* lenient lane rides memchr — a '\n'-hit vector pass instead of a
|
|
1286
|
+
* two-compare byte loop over the whole span (13% of json-doc). */
|
|
1287
|
+
if (!cl) {
|
|
1288
|
+
size_t k = open + 1;
|
|
1289
|
+
while (k < len) {
|
|
1290
|
+
const char* nl = (const char*)memchr(p + k, '\n', len - k);
|
|
1291
|
+
if (nl == NULL) {
|
|
1292
|
+
break;
|
|
1293
|
+
}
|
|
1294
|
+
k = (size_t)(nl - p) + 1;
|
|
1295
|
+
if (k < len && p[k] == '\t') {
|
|
1296
|
+
yeptris_tape_free(t);
|
|
1297
|
+
return YEPTRIS_ERROR_PARSE;
|
|
1298
|
+
}
|
|
1286
1299
|
}
|
|
1287
1300
|
}
|
|
1301
|
+
/* the >1024 simple-key verdict settles HERE when no key crossed the
|
|
1302
|
+
* raw cap in lmapcolon: chars <= bytes closes the char budget too,
|
|
1303
|
+
* so no key can violate the law — without this, every clean
|
|
1304
|
+
* document paid yep_tape_long_simple_key's full-tape re-walk (16%
|
|
1305
|
+
* of json-doc parse, the #739 residual) */
|
|
1306
|
+
t->_long_key_known = 1;
|
|
1288
1307
|
t->count = count;
|
|
1289
1308
|
t->_src = p;
|
|
1290
1309
|
t->_srclen = len;
|