yeptris 0.6.51.0-arm-linux-eabihf → 0.6.53.0-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/ext/yeptris_native/yeptris_native.c +11 -1
- data/lib/yeptris/3.4/native.so +0 -0
- data/lib/yeptris/document.rb +12 -5
- data/lib/yeptris/psych/parser.rb +4 -0
- data/lib/yeptris/psych.rb +15 -2
- data/lib/yeptris/valueml.rb +23 -31
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/yeptris/cbor/from_marshal.c +7 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +15 -8
- data/vendor/libyeptris/src/yeptris/dom/dom.h +8 -2
- data/vendor/libyeptris/src/yeptris/dom/ytape.c +2 -2
- data/vendor/libyeptris/src/yeptris/emit/emit.c +4 -0
- data/vendor/libyeptris/src/yeptris/emit/style.c +9 -191
- data/vendor/libyeptris/src/yeptris/emit/writer.c +149 -35
- data/vendor/libyeptris/src/yeptris/marshal.c +10 -5
- data/vendor/libyeptris/src/yeptris/parse/engine.c +197 -68
- data/vendor/libyeptris/src/yeptris/parse/events.h +2 -2
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +2 -1
- data/vendor/libyeptris/src/yeptris/resolve/core12.c +3 -1
- data/vendor/libyeptris/src/yeptris/scan/json.c +6 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +202 -1
- data/vendor/libyeptris/src/yeptris/scan/scan.h +12 -1
- metadata +1 -1
|
@@ -49,7 +49,7 @@ typedef enum {
|
|
|
49
49
|
|
|
50
50
|
/* One open collection frame (the engine's indentation stack). */
|
|
51
51
|
typedef struct {
|
|
52
|
-
|
|
52
|
+
uint32_t col;
|
|
53
53
|
uint8_t kind;
|
|
54
54
|
uint8_t inline_doc; /* opened on the --- line: deeper keys only */
|
|
55
55
|
} yep_frame;
|
|
@@ -163,7 +163,7 @@ struct yep_engine {
|
|
|
163
163
|
int last_root_flow; /* a root-level flow node just completed */
|
|
164
164
|
int tag_undef; /* an unresolved !handle! was seen (QLJ7) */
|
|
165
165
|
int doc_inline; /* content node opened on the --- line */
|
|
166
|
-
|
|
166
|
+
uint32_t flow_floor; /* parent column of the current block-level flow */
|
|
167
167
|
int flow_enforce; /* flow continuation lines must out-indent it */
|
|
168
168
|
int compat_grammar; /* 11-COMPAT: libyaml/psych grammar parity —
|
|
169
169
|
* the flow indent floor (9C9N/VJP3) is a
|
|
@@ -176,8 +176,8 @@ struct yep_engine {
|
|
|
176
176
|
|
|
177
177
|
/* ------------------------------------------------------------ forwards */
|
|
178
178
|
|
|
179
|
-
static int e_node(yep_engine* e, yep_ctx ctx,
|
|
180
|
-
static int e_parse_value(yep_engine* e, yep_ctx ctx,
|
|
179
|
+
static int e_node(yep_engine* e, yep_ctx ctx, uint32_t floor_col);
|
|
180
|
+
static int e_parse_value(yep_engine* e, yep_ctx ctx, uint32_t floor_col);
|
|
181
181
|
|
|
182
182
|
/* ---------------------------------------------------------------- util */
|
|
183
183
|
|
|
@@ -379,7 +379,8 @@ static int e_comment_at(const yep_engine* e) {
|
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
static int e_at_eol(yep_engine* e) {
|
|
382
|
-
return e->pos >= e->len || e->p[e->pos] == '\n' || e->p[e->pos] == '\r' || e_comment_at(e)
|
|
382
|
+
return e->pos >= e->len || e->p[e->pos] == '\n' || e->p[e->pos] == '\r' || e_comment_at(e) ||
|
|
383
|
+
yep_scan_mb_break_len(e->p, e->len, e->pos) > 0;
|
|
383
384
|
}
|
|
384
385
|
|
|
385
386
|
static int e_skip_to_eol(yep_engine* e) {
|
|
@@ -461,7 +462,7 @@ static uint32_t anchor_define(yep_engine* e, yep_view name) {
|
|
|
461
462
|
/* Opens a collection frame unless the top frame already continues at
|
|
462
463
|
* exactly this column (sibling entries reuse it). anchor/tag ride the
|
|
463
464
|
* START event. Returns 0 on success. */
|
|
464
|
-
static int e_open_seq(yep_engine* e,
|
|
465
|
+
static int e_open_seq(yep_engine* e, uint32_t col, uint32_t line, uint32_t coln, yep_view anchor,
|
|
465
466
|
yep_view tag, uint32_t anchor_id) {
|
|
466
467
|
if (e->depth > 0 && e->frames[e->depth - 1].kind == YEP_FRAME_SEQ &&
|
|
467
468
|
e->frames[e->depth - 1].col == col) {
|
|
@@ -499,7 +500,7 @@ static int e_open_seq(yep_engine* e, uint16_t col, uint32_t line, uint32_t coln,
|
|
|
499
500
|
|
|
500
501
|
/* silent: the sink's on_block_open built the node — push the frame
|
|
501
502
|
* without emitting (TODO.restructure/57). */
|
|
502
|
-
static int e_open_map(yep_engine* e,
|
|
503
|
+
static int e_open_map(yep_engine* e, uint32_t col, uint32_t line, uint32_t coln, yep_view anchor,
|
|
503
504
|
yep_view tag, uint32_t anchor_id, int silent) {
|
|
504
505
|
if (e->depth > 0 && e->frames[e->depth - 1].kind == YEP_FRAME_MAP &&
|
|
505
506
|
e->frames[e->depth - 1].col == col) {
|
|
@@ -554,7 +555,7 @@ static int e_flush_q_value(yep_engine* e) {
|
|
|
554
555
|
* value arrived inline) the innermost '?' pending resolves — without
|
|
555
556
|
* this pop the stack keeps a stale entry and the outer pair's null
|
|
556
557
|
* flushes inside the wrong map (the nightly's run 38387614146). */
|
|
557
|
-
static int e_pair_value_done(yep_engine* e, yep_ctx ctx,
|
|
558
|
+
static int e_pair_value_done(yep_engine* e, yep_ctx ctx, uint32_t key_col) {
|
|
558
559
|
/* the pair's own level, BEFORE its value parse: the value may open
|
|
559
560
|
* deeper frames ("? a:\n ? b<EOF>") and a post-parse depth read
|
|
560
561
|
* then matches the DEEPER pair's pending slot, popping the wrong
|
|
@@ -603,7 +604,7 @@ static int e_close_to(yep_engine* e, int to_depth) {
|
|
|
603
604
|
/* ------------------------------------------------------------- scalars */
|
|
604
605
|
|
|
605
606
|
/* Quoted scalar at the opening quote; spans lines when needed. */
|
|
606
|
-
static int e_quoted_floor(yep_engine* e, yep_event* ev,
|
|
607
|
+
static int e_quoted_floor(yep_engine* e, yep_event* ev, uint32_t min_indent, int enforce) {
|
|
607
608
|
unsigned char q = (unsigned char)e->p[e->pos];
|
|
608
609
|
size_t content_start = e->pos + 1;
|
|
609
610
|
int has_esc = 0;
|
|
@@ -884,12 +885,12 @@ static int e_block_scalar(yep_engine* e, yep_event* ev, int parent_col) {
|
|
|
884
885
|
if (content_indent <= parent_col) {
|
|
885
886
|
break; /* no block content */
|
|
886
887
|
}
|
|
887
|
-
} else if (li.indent <= parent_col) {
|
|
888
|
+
} else if ((int)li.indent <= parent_col) {
|
|
888
889
|
break; /* dedent ends the block */
|
|
889
|
-
} else if (li.indent < content_indent && li.indent <= parent_col) {
|
|
890
|
+
} else if ((int)li.indent < content_indent && (int)li.indent <= parent_col) {
|
|
890
891
|
break;
|
|
891
892
|
}
|
|
892
|
-
if (li.indent < content_indent) {
|
|
893
|
+
if ((int)li.indent < content_indent) {
|
|
893
894
|
break;
|
|
894
895
|
}
|
|
895
896
|
}
|
|
@@ -901,10 +902,10 @@ static int e_block_scalar(yep_engine* e, yep_event* ev, int parent_col) {
|
|
|
901
902
|
if (content_indent <= parent_col) {
|
|
902
903
|
break;
|
|
903
904
|
}
|
|
904
|
-
} else if (li.indent < content_indent) {
|
|
905
|
+
} else if ((int)li.indent < content_indent) {
|
|
905
906
|
break;
|
|
906
907
|
}
|
|
907
|
-
if (li.indent >= content_indent) {
|
|
908
|
+
if ((int)li.indent >= content_indent) {
|
|
908
909
|
uint32_t from2 = li.offset + (uint32_t)content_indent;
|
|
909
910
|
if (e->fold_n >= YEP_MAX_FOLD_LINES) {
|
|
910
911
|
return e_fail(e, YEP_ERR_MEMORY, e->pos);
|
|
@@ -944,7 +945,7 @@ static int e_block_scalar(yep_engine* e, yep_event* ev, int parent_col) {
|
|
|
944
945
|
}
|
|
945
946
|
/* a blank line whose spaces extend past the content indent is
|
|
946
947
|
* CONTENT (kept verbatim); otherwise it is a pure break */
|
|
947
|
-
if (content_indent >= 0 && li.indent > content_indent) {
|
|
948
|
+
if (content_indent >= 0 && (int)li.indent > content_indent) {
|
|
948
949
|
if (e->fold_n >= YEP_MAX_FOLD_LINES) {
|
|
949
950
|
return e_fail(e, YEP_ERR_MEMORY, e->pos);
|
|
950
951
|
}
|
|
@@ -995,7 +996,7 @@ static int e_block_scalar(yep_engine* e, yep_event* ev, int parent_col) {
|
|
|
995
996
|
/* leading blank lines belong to the block content */
|
|
996
997
|
e->fold[e->fold_n].breaks_before = saw_content ? pending_breaks + 1 : pending_breaks;
|
|
997
998
|
e->fold[e->fold_n].more_indented =
|
|
998
|
-
li.indent > content_indent ||
|
|
999
|
+
(int)li.indent > content_indent ||
|
|
999
1000
|
(from < li.end && (e->p[from] == ' ' || e->p[from] == '\t'));
|
|
1000
1001
|
e->fold_n++;
|
|
1001
1002
|
saw_content = 1;
|
|
@@ -1892,7 +1893,7 @@ static int e_flow_key_after(const char* p, size_t len, size_t close) {
|
|
|
1892
1893
|
* rejects it, and the fast path must agree (the nightly's run
|
|
1893
1894
|
* 38280372447: whole vs chunked split across the fast/slow paths and
|
|
1894
1895
|
* produced two different verdicts for the same bytes). */
|
|
1895
|
-
static int e_flow_floor_ok(const char* p, size_t open, size_t close,
|
|
1896
|
+
static int e_flow_floor_ok(const char* p, size_t open, size_t close, uint32_t floor) {
|
|
1896
1897
|
size_t j = open;
|
|
1897
1898
|
while (j < close) {
|
|
1898
1899
|
/* the break rule is the scan's: \n, or a \r the next byte does
|
|
@@ -3035,7 +3036,7 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
|
|
|
3035
3036
|
|
|
3036
3037
|
/* Plain (optionally anchored) value: emit, fold continuations, land at
|
|
3037
3038
|
* the line end. root_ctx is 0 — every arm has pushed a frame. */
|
|
3038
|
-
static int e_shape_plain_value(yep_engine* e, const yep_line_shape* sh,
|
|
3039
|
+
static int e_shape_plain_value(yep_engine* e, const yep_line_shape* sh, uint32_t floor,
|
|
3039
3040
|
yep_view anchor, uint32_t anchor_id) {
|
|
3040
3041
|
yep_event ev;
|
|
3041
3042
|
e_event_init(&ev, YEP_EV_SCALAR);
|
|
@@ -3077,7 +3078,7 @@ static int e_shape_plain_value(yep_engine* e, const yep_line_shape* sh, uint16_t
|
|
|
3077
3078
|
|
|
3078
3079
|
/* Flow value: the JSON fast path first; anything else restores the
|
|
3079
3080
|
* cursor and runs the value chain (which re-derives the flow arms). */
|
|
3080
|
-
static int e_shape_flow_value(yep_engine* e, const yep_line_shape* sh,
|
|
3081
|
+
static int e_shape_flow_value(yep_engine* e, const yep_line_shape* sh, uint32_t floor,
|
|
3081
3082
|
yep_ctx next) {
|
|
3082
3083
|
yep_view none = {NULL, 0};
|
|
3083
3084
|
e->pos = sh->val_start;
|
|
@@ -3118,7 +3119,7 @@ static int e_shape_alias_value(yep_engine* e, const yep_line_shape* sh, int unde
|
|
|
3118
3119
|
if (e_simple_key_ok(e, sh->val_start, e->pos) != 0) {
|
|
3119
3120
|
return -1;
|
|
3120
3121
|
}
|
|
3121
|
-
|
|
3122
|
+
uint32_t key_col = e_col(e, sh->val_start);
|
|
3122
3123
|
int rc = e_open_map(e, key_col, e->line, key_col + 1, none, none, 0, 0);
|
|
3123
3124
|
if (rc != 0) {
|
|
3124
3125
|
return rc;
|
|
@@ -3140,7 +3141,7 @@ static int e_shape_alias_value(yep_engine* e, const yep_line_shape* sh, int unde
|
|
|
3140
3141
|
* emit it: the pair path takes the whole line without events, and
|
|
3141
3142
|
* building kv up front discarded ~48 stores per classified line
|
|
3142
3143
|
* (TODO.restructure/63 phase 1). */
|
|
3143
|
-
static void e_key_event(const yep_engine* e, const yep_line_shape* sh,
|
|
3144
|
+
static void e_key_event(const yep_engine* e, const yep_line_shape* sh, uint32_t key_col,
|
|
3144
3145
|
uint32_t line, yep_event* kv) {
|
|
3145
3146
|
e_event_init(kv, YEP_EV_SCALAR);
|
|
3146
3147
|
kv->style = YEP_STYLE_PLAIN;
|
|
@@ -3155,7 +3156,7 @@ static void e_key_event(const yep_engine* e, const yep_line_shape* sh, uint16_t
|
|
|
3155
3156
|
e_pos_mark(e, sh->key_end, &kv->end_line, &kv->end_col);
|
|
3156
3157
|
}
|
|
3157
3158
|
|
|
3158
|
-
static int e_classified(yep_engine* e,
|
|
3159
|
+
static int e_classified(yep_engine* e, uint32_t floor_col) {
|
|
3159
3160
|
yep_line_info li = e_line_info_here(e);
|
|
3160
3161
|
if (e->pos != e->line_start + li.indent) {
|
|
3161
3162
|
return 0; /* mid-line entry: the chain keeps its dispatch */
|
|
@@ -3176,7 +3177,7 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
3176
3177
|
default:
|
|
3177
3178
|
return 0;
|
|
3178
3179
|
}
|
|
3179
|
-
|
|
3180
|
+
uint32_t col = e_col(e, e->pos);
|
|
3180
3181
|
int rc = e_open_seq(e, col, e->line, col + 1, none, none, 0);
|
|
3181
3182
|
if (rc != 0) {
|
|
3182
3183
|
return rc;
|
|
@@ -3202,7 +3203,7 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
3202
3203
|
if (e_simple_key_ok(e, sh->key_start, sh->key_end) != 0) {
|
|
3203
3204
|
return -1;
|
|
3204
3205
|
}
|
|
3205
|
-
|
|
3206
|
+
uint32_t key_col = e_col(e, e->pos);
|
|
3206
3207
|
/* `key:` with the value on following lines, opening a FRESH map:
|
|
3207
3208
|
* the sink may build map+key in one call (TODO.restructure/57) —
|
|
3208
3209
|
* the engine then opens its frame silently. Sibling keys (the map
|
|
@@ -3240,7 +3241,7 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
3240
3241
|
/* the pair facts are captured BEFORE the fold: e_plain_multiline
|
|
3241
3242
|
* advances line/pos across continuations */
|
|
3242
3243
|
uint32_t pair_line = e->line;
|
|
3243
|
-
|
|
3244
|
+
uint32_t pair_val_col = e_col(e, sh->val_start);
|
|
3244
3245
|
yep_block_value v;
|
|
3245
3246
|
memset(&v, 0, sizeof(v));
|
|
3246
3247
|
v.cls = (uint8_t)sh->val;
|
|
@@ -3374,7 +3375,7 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
3374
3375
|
* pend props (parsed at the parent's value position on an earlier line)
|
|
3375
3376
|
* belong to the VALUE node as a whole — a collection START event when
|
|
3376
3377
|
* the value is a collection. */
|
|
3377
|
-
static int e_node(yep_engine* e, yep_ctx ctx,
|
|
3378
|
+
static int e_node(yep_engine* e, yep_ctx ctx, uint32_t floor_col) {
|
|
3378
3379
|
size_t node_at = e->pos;
|
|
3379
3380
|
yep_view pend_a = e->pend_anchor, pend_t = e->pend_tag;
|
|
3380
3381
|
uint32_t pend_aid = e->pend_anchor_id;
|
|
@@ -3481,7 +3482,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3481
3482
|
if (!yep_view_is_empty(anchor) || !yep_view_is_empty(tag)) {
|
|
3482
3483
|
return e_fail(e, YEP_ERR_UNEXPECTED, e->pos); /* "&a - x" */
|
|
3483
3484
|
}
|
|
3484
|
-
|
|
3485
|
+
uint32_t col = e_col(e, e->pos);
|
|
3485
3486
|
int rc = e_open_seq(e, col, e->line, col + 1, node_a, node_t, node_aid);
|
|
3486
3487
|
if (rc != 0) {
|
|
3487
3488
|
return rc;
|
|
@@ -3514,7 +3515,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3514
3515
|
if (e->pos > 0 && e->p[e->pos - 1] == '\t') {
|
|
3515
3516
|
return e_fail(e, YEP_ERR_UNEXPECTED, e->pos); /* "?\t-" (Y79Y) */
|
|
3516
3517
|
}
|
|
3517
|
-
|
|
3518
|
+
uint32_t col = e_col(e, e->pos);
|
|
3518
3519
|
int rc = e_open_map(e, col, e->line, col + 1, pend_a, pend_t, pend_aid, 0);
|
|
3519
3520
|
if (rc != 0) {
|
|
3520
3521
|
return rc;
|
|
@@ -3638,7 +3639,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3638
3639
|
if (e_simple_key_ok(e, node_at, e->pos) != 0) {
|
|
3639
3640
|
return -1;
|
|
3640
3641
|
}
|
|
3641
|
-
|
|
3642
|
+
uint32_t key_col = e_col(e, node_at);
|
|
3642
3643
|
int rc = e_open_map(e, key_col, e->line, key_col + 1, pend_a, pend_t, pend_aid, 0);
|
|
3643
3644
|
if (rc != 0) {
|
|
3644
3645
|
return rc;
|
|
@@ -3682,7 +3683,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3682
3683
|
if (e_simple_key_ok(e, node_at, e->pos) != 0) {
|
|
3683
3684
|
return -1;
|
|
3684
3685
|
}
|
|
3685
|
-
|
|
3686
|
+
uint32_t key_col = e_col(e, node_at);
|
|
3686
3687
|
int rc = e_open_map(e, key_col, e->line, key_col + 1, pend_a, pend_t, pend_aid, 0);
|
|
3687
3688
|
if (rc != 0) {
|
|
3688
3689
|
return rc;
|
|
@@ -3721,7 +3722,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3721
3722
|
if (e_simple_key_ok(e, node_at, e->pos) != 0) {
|
|
3722
3723
|
return -1;
|
|
3723
3724
|
}
|
|
3724
|
-
|
|
3725
|
+
uint32_t key_col = e_col(e, node_at);
|
|
3725
3726
|
int rc = e_open_map(e, key_col, e->line, key_col + 1, pend_a, pend_t, pend_aid, 0);
|
|
3726
3727
|
if (rc != 0) {
|
|
3727
3728
|
return rc;
|
|
@@ -3776,7 +3777,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3776
3777
|
if (e->doc_inline && (!yep_view_is_empty(anchor) || !yep_view_is_empty(tag))) {
|
|
3777
3778
|
return e_fail(e, YEP_ERR_UNEXPECTED, e->pos); /* "--- &a k: v" */
|
|
3778
3779
|
}
|
|
3779
|
-
|
|
3780
|
+
uint32_t key_col = e_col(e, node_at);
|
|
3780
3781
|
int rc = e_open_map(e, key_col, e->line, key_col + 1, pend_a, pend_t, pend_aid, 0);
|
|
3781
3782
|
if (rc != 0) {
|
|
3782
3783
|
return rc;
|
|
@@ -3836,7 +3837,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3836
3837
|
}
|
|
3837
3838
|
|
|
3838
3839
|
/* Value after "key:" / "-" / "?": on this line, or on following lines. */
|
|
3839
|
-
static int e_parse_value(yep_engine* e, yep_ctx ctx,
|
|
3840
|
+
static int e_parse_value(yep_engine* e, yep_ctx ctx, uint32_t floor_col) {
|
|
3840
3841
|
e_skip_inline_space(e);
|
|
3841
3842
|
if (!e_at_eol(e)) {
|
|
3842
3843
|
if (ctx == YEP_CTX_AFTER_COLON && e->p[e->pos] == '-' &&
|
|
@@ -3848,7 +3849,7 @@ static int e_parse_value(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3848
3849
|
(e->pos + 1 >= e->len || e->p[e->pos + 1] == ' ' || e->p[e->pos + 1] == '\t' ||
|
|
3849
3850
|
e->p[e->pos + 1] == '\n' || e->p[e->pos + 1] == '\r')) {
|
|
3850
3851
|
/* "- :" — a compact pair with an empty key */
|
|
3851
|
-
|
|
3852
|
+
uint32_t col = e_col(e, e->pos);
|
|
3852
3853
|
int rc = e_open_map(e, col, e->line, col + 1, e->pend_anchor, e->pend_tag,
|
|
3853
3854
|
e->pend_anchor_id, 0);
|
|
3854
3855
|
if (rc != 0) {
|
|
@@ -3890,6 +3891,16 @@ static int e_parse_value(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3890
3891
|
if (e->pos >= e->len) {
|
|
3891
3892
|
goto empty_value;
|
|
3892
3893
|
}
|
|
3894
|
+
/* a raw NEL/LS/PS here is this line's break: consume it exactly
|
|
3895
|
+
* as the BLANK branch below consumes an LF-ended empty line —
|
|
3896
|
+
* yep_scan_line's line model does not treat a break byte at the
|
|
3897
|
+
* loop head as a line end, so without this the props-only line
|
|
3898
|
+
* re-entered e_node on the break byte (rows 1-2) and the marker
|
|
3899
|
+
* became the scalar's value (row 5's consume-first form) */
|
|
3900
|
+
if (yep_scan_mb_break_len(e->p, e->len, e->pos) > 0) {
|
|
3901
|
+
e_line_done(e, e->pos);
|
|
3902
|
+
continue;
|
|
3903
|
+
}
|
|
3893
3904
|
yep_line_info li;
|
|
3894
3905
|
if (e->pos == e->line_start) {
|
|
3895
3906
|
/* seed the memo: the fast arms re-read this line's facts —
|
|
@@ -4190,15 +4201,10 @@ yep_engine* yep_engine_create(const yep_allocator* sys) {
|
|
|
4190
4201
|
* length is not strlen()'s: the INPUT may carry NUL bytes of its own,
|
|
4191
4202
|
* and a strlen() of the copy truncates the run at the first one (the
|
|
4192
4203
|
* nightly's run 38524928004: "\0\n---\r<U+2028>" whole-parsed as an
|
|
4193
|
-
* empty stream while the chunked cut skipped the copy).
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
return p;
|
|
4198
|
-
}
|
|
4199
|
-
e->norm_buf = out;
|
|
4200
|
-
return out;
|
|
4201
|
-
}
|
|
4204
|
+
* empty stream while the chunked cut skipped the copy). The context
|
|
4205
|
+
* walk behind the copy lives below (issue #638); since #839 the
|
|
4206
|
+
* chunked route threads it across --- cuts so every document
|
|
4207
|
+
* normalizes to the same bytes the one-buffer walk produces. */
|
|
4202
4208
|
|
|
4203
4209
|
/* The NEL/LS/PS -> '\n' copy (the one-shot path rides this BEFORE the
|
|
4204
4210
|
* engine so the normalized bytes own the document's `transcoded` slot;
|
|
@@ -4247,6 +4253,13 @@ typedef struct yep_norm_ctx {
|
|
|
4247
4253
|
int bs_content;
|
|
4248
4254
|
uint32_t bs_indent; /* the header line's indent; (uint32_t)-1 = the
|
|
4249
4255
|
* doc-inline root rule (markers only) */
|
|
4256
|
+
uint8_t started; /* at least one byte consumed: the walk's i == 0
|
|
4257
|
+
* clauses are stream-start, not buffer-start —
|
|
4258
|
+
* the chunked route resumes mid-stream at a ---
|
|
4259
|
+
* cut, and the carried context must say so */
|
|
4260
|
+
unsigned char prev; /* the last consumed byte (valid when started):
|
|
4261
|
+
* the '#' and line-start tests peek p[i - 1],
|
|
4262
|
+
* which at a resumed buffer is carried state */
|
|
4250
4263
|
} yep_norm_ctx;
|
|
4251
4264
|
|
|
4252
4265
|
typedef struct yep_norm_tok {
|
|
@@ -4404,8 +4417,12 @@ static yep_norm_tok norm_step(yep_norm_ctx* c, const char* p, size_t len, size_t
|
|
|
4404
4417
|
norm_break_arms(c);
|
|
4405
4418
|
return t;
|
|
4406
4419
|
}
|
|
4407
|
-
|
|
4408
|
-
|
|
4420
|
+
/* the i == 0 clauses below are STREAM start: `started`/`prev` carry
|
|
4421
|
+
* them across the chunked route's per-document resumes (issue #839)
|
|
4422
|
+
* — a fresh context at a --- cut would otherwise read the resumed
|
|
4423
|
+
* buffer's first byte as a line start the whole walk never saw */
|
|
4424
|
+
if (ch == '#' && (!c->started || c->at_break || c->prev == '\n' || c->prev == '\r' ||
|
|
4425
|
+
c->prev == ' ' || c->prev == '\t')) {
|
|
4409
4426
|
c->in_comment = 1;
|
|
4410
4427
|
c->at_break = 0;
|
|
4411
4428
|
return t;
|
|
@@ -4418,7 +4435,7 @@ static yep_norm_tok norm_step(yep_norm_ctx* c, const char* p, size_t len, size_t
|
|
|
4418
4435
|
return t;
|
|
4419
4436
|
}
|
|
4420
4437
|
|
|
4421
|
-
int line_start = (
|
|
4438
|
+
int line_start = (!c->started || c->at_break || c->prev == '\n' || c->prev == '\r');
|
|
4422
4439
|
|
|
4423
4440
|
/* block scalars: inside the fold no quote opens and every break
|
|
4424
4441
|
* keeps its fold; the region ends at a col-0 marker, a %-line
|
|
@@ -4508,7 +4525,7 @@ static yep_norm_tok norm_step(yep_norm_ctx* c, const char* p, size_t len, size_t
|
|
|
4508
4525
|
if (!c->bs_open && ch == '-' && i + 2 < len && p[i + 1] == '-' && p[i + 2] == '-' &&
|
|
4509
4526
|
(i + 3 >= len || p[i + 3] == ' ' || p[i + 3] == '\t' || p[i + 3] == '\n' ||
|
|
4510
4527
|
p[i + 3] == '\r') &&
|
|
4511
|
-
(c->at_break ||
|
|
4528
|
+
(c->at_break || !c->started)) {
|
|
4512
4529
|
c->in_flow = 0; /* the marker bounds the document even when the
|
|
4513
4530
|
* walk still believes a flow is open (the same
|
|
4514
4531
|
* round-35 law as the in-quote rescue) */
|
|
@@ -4552,22 +4569,80 @@ static yep_norm_tok norm_step(yep_norm_ctx* c, const char* p, size_t len, size_t
|
|
|
4552
4569
|
}
|
|
4553
4570
|
c->tok_start = 0;
|
|
4554
4571
|
}
|
|
4555
|
-
if (ch == '
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4572
|
+
if ((ch == '[' || ch == '{') && (c->tok_start || c->prev == ':')) {
|
|
4573
|
+
/* a flow opener begins a token slot — at a token position, or
|
|
4574
|
+
* directly after the value ':' ("k:{a: 1}" opens; the blank
|
|
4575
|
+
* twin "k: {" rides tok_start already). Unconditioned, a
|
|
4576
|
+
* plain's interior '[' ("ya200%[") opened a PHANTOM flow whose
|
|
4577
|
+
* ',' armed the next token slot and a following "!<" opened a
|
|
4578
|
+
* phantom verbatim — breaks inside verbatim ride unnormalized,
|
|
4579
|
+
* the raw NELs defeated the line-facts kernel, and the plain
|
|
4580
|
+
* fold rendered one fold-SPACE per break instead of the n-1
|
|
4581
|
+
* newline tally (the r98 nightly — the #836 phantom's flow
|
|
4582
|
+
* half; the comma half landed in #836 itself). */
|
|
4583
|
+
c->tok_start = 1;
|
|
4560
4584
|
c->in_flow++;
|
|
4561
|
-
} else if (ch == '
|
|
4585
|
+
} else if (ch == ',') {
|
|
4586
|
+
/* flow separators glue the next token — THE COMMA IN FLOW
|
|
4587
|
+
* ONLY. The unconditioned arm let a BLOCK plain's interior
|
|
4588
|
+
* comma arm tok_start, a following "!<" opened a phantom
|
|
4589
|
+
* verbatim tag that swallowed the rest of the input (breaks
|
|
4590
|
+
* inside ride unnormalized), and the raw NEL/LS/PS bytes then
|
|
4591
|
+
* defeated the line-facts kernel's \n/\r law — the plain
|
|
4592
|
+
* fold's blank-line tally lost them (the r96 nightly,
|
|
4593
|
+
* yeptris#836, "b,,,!<!<"+NEL^3). ':' stays unconditioned:
|
|
4594
|
+
* the BLOCK value position rides it ("k: 'x'" opens the
|
|
4595
|
+
* quote, the NormLsPs pins). */
|
|
4562
4596
|
if (c->in_flow > 0) {
|
|
4563
|
-
c->
|
|
4597
|
+
c->tok_start = 1;
|
|
4598
|
+
}
|
|
4599
|
+
} else if (ch == ':') {
|
|
4600
|
+
/* the separator law (#833's own predicate): a ':' arms the
|
|
4601
|
+
* next token slot only before a blank/EOL/EOF — "k: 'x'"
|
|
4602
|
+
* opens the value quote (the NormLsPs pins) while an
|
|
4603
|
+
* interior "x:!<" of a block plain does NOT (the phantom
|
|
4604
|
+
* verbatim again, the #836 colon-led twin) */
|
|
4605
|
+
if (i + 1 >= len || p[i + 1] == ' ' || p[i + 1] == '\t' || p[i + 1] == '\n' ||
|
|
4606
|
+
p[i + 1] == '\r') {
|
|
4607
|
+
c->tok_start = 1;
|
|
4564
4608
|
}
|
|
4609
|
+
} else if (ch == ']' || ch == '}') {
|
|
4610
|
+
c->tok_start = 1;
|
|
4565
4611
|
}
|
|
4566
4612
|
return t;
|
|
4567
4613
|
}
|
|
4568
4614
|
|
|
4615
|
+
char* yep_engine_normalize_breaks(const yep_allocator* sys, const char* p, size_t len,
|
|
4616
|
+
size_t* out_len, int* kept_raw);
|
|
4617
|
+
|
|
4618
|
+
static char* norm_breaks_run(const yep_allocator* sys, const char* p, size_t len, size_t* out_len,
|
|
4619
|
+
int* kept_raw, yep_norm_ctx* ctx);
|
|
4620
|
+
|
|
4569
4621
|
char* yep_engine_normalize_breaks(const yep_allocator* sys, const char* p, size_t len,
|
|
4570
4622
|
size_t* out_len, int* kept_raw) {
|
|
4623
|
+
return norm_breaks_run(sys, p, len, out_len, kept_raw, NULL);
|
|
4624
|
+
}
|
|
4625
|
+
|
|
4626
|
+
/* The context-threaded core (#839). ctx == NULL is the one-shot form:
|
|
4627
|
+
* fresh state, and the !exotic early exit stands (no walk, no state).
|
|
4628
|
+
* A non-NULL ctx rides in the step state: the chunked route parses
|
|
4629
|
+
* whole documents, so the walk never sees a mid-construct cut — the
|
|
4630
|
+
* divergence was the RESUME state. A --- cut lands exactly where the
|
|
4631
|
+
* whole walk holds some carried state (an open quote it has not been
|
|
4632
|
+
* rescued from, at_break, the raw prev byte); resuming fresh re-lexes
|
|
4633
|
+
* the marker line differently ("--- 'tail": whole's rescue leaves
|
|
4634
|
+
* tok_start 0 so the apostrophe is content, a fresh context's
|
|
4635
|
+
* tok_start 1 opens a quote). Carrying, never resetting: doc N's walk
|
|
4636
|
+
* sees the same bytes with the same state whole holds at the cut, so
|
|
4637
|
+
* doc N + 1's start state equals whole's there — the induction makes
|
|
4638
|
+
* the concatenated documents byte-identical to the one-buffer walk.
|
|
4639
|
+
* The probe ALWAYS runs in this form (even without exotic leads): the
|
|
4640
|
+
* carried state must advance over every byte, or the next resume
|
|
4641
|
+
* starts stale. Both outcomes keep zero-copy semantics: a document
|
|
4642
|
+
* whose exotic bytes all ride raw is used as-is, and those raw bytes
|
|
4643
|
+
* are exactly what the one-buffer walk's copy carries for them. */
|
|
4644
|
+
static char* norm_breaks_run(const yep_allocator* sys, const char* p, size_t len, size_t* out_len,
|
|
4645
|
+
int* kept_raw, yep_norm_ctx* ctx) {
|
|
4571
4646
|
if (kept_raw != NULL) {
|
|
4572
4647
|
*kept_raw = 0;
|
|
4573
4648
|
}
|
|
@@ -4584,15 +4659,21 @@ char* yep_engine_normalize_breaks(const yep_allocator* sys, const char* p, size_
|
|
|
4584
4659
|
exotic = 1; /* any NEL/LS/PS lead byte needs the context walk */
|
|
4585
4660
|
break;
|
|
4586
4661
|
}
|
|
4587
|
-
if (!exotic) {
|
|
4588
|
-
return NULL;
|
|
4589
|
-
}
|
|
4590
4662
|
yep_norm_ctx probe;
|
|
4591
|
-
|
|
4592
|
-
|
|
4663
|
+
if (ctx != NULL) {
|
|
4664
|
+
probe = *ctx;
|
|
4665
|
+
} else {
|
|
4666
|
+
if (!exotic) {
|
|
4667
|
+
return NULL;
|
|
4668
|
+
}
|
|
4669
|
+
memset(&probe, 0, sizeof(probe));
|
|
4670
|
+
probe.tok_start = 1;
|
|
4671
|
+
}
|
|
4593
4672
|
int found = 0;
|
|
4594
4673
|
for (size_t j = 0; j < len;) {
|
|
4595
4674
|
yep_norm_tok t = norm_step(&probe, p, len, j);
|
|
4675
|
+
probe.started = 1;
|
|
4676
|
+
probe.prev = (unsigned char)p[j + t.n - 1];
|
|
4596
4677
|
if (t.fold_off >= 0) {
|
|
4597
4678
|
found = 1;
|
|
4598
4679
|
break;
|
|
@@ -4600,22 +4681,34 @@ char* yep_engine_normalize_breaks(const yep_allocator* sys, const char* p, size_
|
|
|
4600
4681
|
j += t.n;
|
|
4601
4682
|
}
|
|
4602
4683
|
if (!found) {
|
|
4603
|
-
if (
|
|
4604
|
-
*
|
|
4684
|
+
if (ctx != NULL) {
|
|
4685
|
+
*ctx = probe; /* the carried state advanced even with no fold */
|
|
4686
|
+
} else {
|
|
4687
|
+
if (kept_raw != NULL) {
|
|
4688
|
+
*kept_raw = 1; /* every exotic byte rides raw */
|
|
4689
|
+
}
|
|
4690
|
+
return NULL; /* the exotic bytes all ride inside quoted regions:
|
|
4691
|
+
* the zero-copy path keeps them raw (the fix) */
|
|
4605
4692
|
}
|
|
4606
|
-
return NULL;
|
|
4607
|
-
* the zero-copy path keeps them raw (the fix) */
|
|
4693
|
+
return NULL;
|
|
4608
4694
|
}
|
|
4609
4695
|
char* out = yep_alloc(sys, len + 1);
|
|
4610
4696
|
if (out == NULL) {
|
|
4611
4697
|
return NULL;
|
|
4612
4698
|
}
|
|
4613
4699
|
yep_norm_ctx cp;
|
|
4614
|
-
|
|
4615
|
-
|
|
4700
|
+
if (ctx != NULL) {
|
|
4701
|
+
cp = *ctx; /* restart from the same carried state: the probe's
|
|
4702
|
+
* partial walk (it broke at the fold) is discarded */
|
|
4703
|
+
} else {
|
|
4704
|
+
memset(&cp, 0, sizeof(cp));
|
|
4705
|
+
cp.tok_start = 1;
|
|
4706
|
+
}
|
|
4616
4707
|
size_t o = 0;
|
|
4617
4708
|
for (size_t j = 0; j < len;) {
|
|
4618
4709
|
yep_norm_tok t = norm_step(&cp, p, len, j);
|
|
4710
|
+
cp.started = 1;
|
|
4711
|
+
cp.prev = (unsigned char)p[j + t.n - 1];
|
|
4619
4712
|
if (t.fold_off < 0) {
|
|
4620
4713
|
if (kept_raw != NULL && *kept_raw == 0) {
|
|
4621
4714
|
for (size_t m = 0; m + 1 < t.n; m++) {
|
|
@@ -4641,6 +4734,19 @@ char* yep_engine_normalize_breaks(const yep_allocator* sys, const char* p, size_
|
|
|
4641
4734
|
if (out_len != NULL) {
|
|
4642
4735
|
*out_len = o;
|
|
4643
4736
|
}
|
|
4737
|
+
if (ctx != NULL) {
|
|
4738
|
+
*ctx = cp;
|
|
4739
|
+
}
|
|
4740
|
+
return out;
|
|
4741
|
+
}
|
|
4742
|
+
|
|
4743
|
+
static const char* e_normalize_breaks(yep_engine* e, const char* p, size_t len, size_t* out_len,
|
|
4744
|
+
yep_norm_ctx* ctx) {
|
|
4745
|
+
char* out = norm_breaks_run(e->sys, p, len, out_len, NULL, ctx);
|
|
4746
|
+
if (out == NULL) {
|
|
4747
|
+
return p;
|
|
4748
|
+
}
|
|
4749
|
+
e->norm_buf = out;
|
|
4644
4750
|
return out;
|
|
4645
4751
|
}
|
|
4646
4752
|
|
|
@@ -4667,6 +4773,11 @@ typedef struct yep_stepstate {
|
|
|
4667
4773
|
int at_break; /* the previous position was a line break
|
|
4668
4774
|
* (multibyte breaks leave a non-break byte as
|
|
4669
4775
|
* p[i-1], so the '#' prev-byte test misses them) */
|
|
4776
|
+
yep_norm_ctx nctx; /* the break normalizer's carried context (#839):
|
|
4777
|
+
* each document's walk resumes with exactly the
|
|
4778
|
+
* state the whole-stream walk holds at the ---
|
|
4779
|
+
* cut, so per-document normalization is
|
|
4780
|
+
* byte-identical to the one-buffer walk */
|
|
4670
4781
|
} yep_stepstate;
|
|
4671
4782
|
|
|
4672
4783
|
static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep_sink* sink,
|
|
@@ -4823,6 +4934,19 @@ static size_t step_scan(yep_stepstate* st) {
|
|
|
4823
4934
|
st->tok_start = 1;
|
|
4824
4935
|
st->word_led = 0;
|
|
4825
4936
|
st->at_break = 1;
|
|
4937
|
+
} else if (c == '\r' && (i + 1 >= st->len || (unsigned char)p[i + 1] != '\n')) {
|
|
4938
|
+
/* a lone CR is a line break too (CRLF rides the \n arm
|
|
4939
|
+
* next iteration; the state is identical either way).
|
|
4940
|
+
* Missing this arm kept the scan inside a comment whose
|
|
4941
|
+
* line ended CR, the tab-led `{ {?` flow opener on the
|
|
4942
|
+
* next line went untracked, and the cut landed at the
|
|
4943
|
+
* following --- INSIDE the engine's open flow (the r97
|
|
4944
|
+
* nightly, yeptris#839: whole errored at the flow's ---
|
|
4945
|
+
* while chunked cut and errored at the cut edge) */
|
|
4946
|
+
st->in_comment = 0;
|
|
4947
|
+
st->tok_start = 1;
|
|
4948
|
+
st->word_led = 0;
|
|
4949
|
+
st->at_break = 1;
|
|
4826
4950
|
} else if (c == 0xC2 && i + 1 < st->len && (unsigned char)p[i + 1] == 0x85) {
|
|
4827
4951
|
i++;
|
|
4828
4952
|
st->in_comment = 0;
|
|
@@ -5180,6 +5304,10 @@ int yep_engine_step(yep_engine* e, const char* chunk, size_t len, int final, con
|
|
|
5180
5304
|
}
|
|
5181
5305
|
yep_stepstate* st = e->step;
|
|
5182
5306
|
st->tok_start = 1; /* the buffer starts at a line start */
|
|
5307
|
+
if (st->nctx.started == 0) {
|
|
5308
|
+
st->nctx.tok_start = 1; /* the stream's first walk: the same
|
|
5309
|
+
* fresh state the one-shot starts */
|
|
5310
|
+
}
|
|
5183
5311
|
if (len > 0) {
|
|
5184
5312
|
if (st->len + len > st->cap) {
|
|
5185
5313
|
size_t cap = st->cap ? st->cap : 4096;
|
|
@@ -5245,7 +5373,8 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
5245
5373
|
* it, and the next transcode replaces it. */
|
|
5246
5374
|
e->parsing_final = emit_end;
|
|
5247
5375
|
size_t norm_len = len;
|
|
5248
|
-
|
|
5376
|
+
yep_norm_ctx* nctx = e->step != NULL ? &((yep_stepstate*)e->step)->nctx : NULL;
|
|
5377
|
+
e->p = e_normalize_breaks(e, buf, len, &norm_len, nctx);
|
|
5249
5378
|
e->len = norm_len;
|
|
5250
5379
|
e->pos = 0;
|
|
5251
5380
|
e->line = 1 + e->line_base;
|
|
@@ -5303,7 +5432,7 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
5303
5432
|
e_fail(e, YEP_ERR_TAB_IN_INDENT, e->pos + li.indent);
|
|
5304
5433
|
goto fail;
|
|
5305
5434
|
}
|
|
5306
|
-
li.indent = (
|
|
5435
|
+
li.indent = (uint32_t)(t - li.offset);
|
|
5307
5436
|
}
|
|
5308
5437
|
if (li.flags & YEP_LF_DIRECTIVE) {
|
|
5309
5438
|
if (doc_open) {
|
|
@@ -5623,7 +5752,7 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
5623
5752
|
* dash-blank test is computed once per line (TODO.restructure/75
|
|
5624
5753
|
* — it was spelled out twice below); the top frame loads once
|
|
5625
5754
|
* per iteration. */
|
|
5626
|
-
|
|
5755
|
+
uint32_t c = li.indent;
|
|
5627
5756
|
const int dash_blank =
|
|
5628
5757
|
li.first == '-' &&
|
|
5629
5758
|
(li.offset + li.indent + 1 >= e->len || e->p[li.offset + li.indent + 1] == ' ' ||
|
|
@@ -90,13 +90,13 @@ typedef struct yep_sink {
|
|
|
90
90
|
* placed, 0 = not handled (the engine emits the two events
|
|
91
91
|
* exactly as before), <0 = abort. */
|
|
92
92
|
int (*on_block_pair)(void* ctx, const yep_view* key, const struct yep_block_value* v,
|
|
93
|
-
uint32_t line,
|
|
93
|
+
uint32_t line, uint32_t key_col, uint32_t val_col);
|
|
94
94
|
/* Optional block-open fast path (TODO.restructure/57): a `key:`
|
|
95
95
|
* line whose value lives on FOLLOWING lines, when the engine is
|
|
96
96
|
* about to open a FRESH mapping. 1 = the sink built the map node
|
|
97
97
|
* (placed, stack pushed) and the key node — the engine opens its
|
|
98
98
|
* frame silently and skips both events; 0 = events as before. */
|
|
99
|
-
int (*on_block_open)(void* ctx, const yep_view* key, uint32_t line,
|
|
99
|
+
int (*on_block_open)(void* ctx, const yep_view* key, uint32_t line, uint32_t key_col);
|
|
100
100
|
/* Optional dash-item fast path (TODO.restructure/78): a classified
|
|
101
101
|
* `- value` plain item after the engine opened (or continued) the
|
|
102
102
|
* block sequence. 1 = the sink built and placed the item node,
|
|
@@ -248,7 +248,8 @@ static yep_tag_id compat11(void* ctx, const char* p, uint32_t n) {
|
|
|
248
248
|
if (n - i > 2 && p[i] == '0' && (p[i + 1] == 'b' || p[i + 1] == 'B')) {
|
|
249
249
|
return is_digits_us(p + i + 2, n - i - 2) ? 1 : 0;
|
|
250
250
|
}
|
|
251
|
-
if (n - i > 2 && p[i] == '0' &&
|
|
251
|
+
if (n - i > 2 && p[i] == '0' &&
|
|
252
|
+
p[i + 1] == 'x') { /* lowercase only — psych keeps "0X1A" a String */
|
|
252
253
|
uint32_t k = i + 2;
|
|
253
254
|
if (p[k] == '_') {
|
|
254
255
|
k++;
|
|
@@ -78,7 +78,9 @@ static yep_tag_id core12(void* ctx, const char* p, uint32_t n) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
if (n - i > 2 && p[i] == '0' &&
|
|
81
|
+
if (n - i > 2 && p[i] == '0' &&
|
|
82
|
+
p[i + 1] == 'x') { /* lowercase only: the core schema's int regexp; "0X1A" rides a string
|
|
83
|
+
(psych agrees) */
|
|
82
84
|
for (uint32_t k = i + 2; k < n; k++) {
|
|
83
85
|
char c = p[k];
|
|
84
86
|
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
|