yeptris 0.6.18.2-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.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/README.adoc +141 -0
  3. data/ext/build_windows_native.rb +41 -0
  4. data/ext/libyeptris/extconf.rb +57 -0
  5. data/ext/yeptris_native/cbor_ruby.c +193 -0
  6. data/ext/yeptris_native/extconf.rb +47 -0
  7. data/ext/yeptris_native/json_ruby.c +354 -0
  8. data/ext/yeptris_native/yeptris_native.c +497 -0
  9. data/lib/yeptris/cbor.rb +130 -0
  10. data/lib/yeptris/document.rb +255 -0
  11. data/lib/yeptris/ffi.rb +426 -0
  12. data/lib/yeptris/json/descriptor.rb +266 -0
  13. data/lib/yeptris/json.rb +394 -0
  14. data/lib/yeptris/materializer.rb +354 -0
  15. data/lib/yeptris/native-3.4.so +0 -0
  16. data/lib/yeptris/node.rb +453 -0
  17. data/lib/yeptris/psych/class_loader.rb +24 -0
  18. data/lib/yeptris/psych/coder_shim.rb +55 -0
  19. data/lib/yeptris/psych/drop_in.rb +63 -0
  20. data/lib/yeptris/psych/encodable.rb +14 -0
  21. data/lib/yeptris/psych/handler.rb +90 -0
  22. data/lib/yeptris/psych/parser.rb +105 -0
  23. data/lib/yeptris/psych/scalar_scanner.rb +149 -0
  24. data/lib/yeptris/psych/visitors.rb +545 -0
  25. data/lib/yeptris/psych.rb +622 -0
  26. data/lib/yeptris/schema.rb +253 -0
  27. data/lib/yeptris/valueml.rb +455 -0
  28. data/lib/yeptris/yaml/descriptor.rb +56 -0
  29. data/lib/yeptris/yaml.rb +422 -0
  30. data/lib/yeptris.rb +113 -0
  31. data/libyeptris.so +0 -0
  32. data/vendor/libyeptris/CMakeLists.txt +254 -0
  33. data/vendor/libyeptris/cmake/yeptris-config.cmake.in +5 -0
  34. data/vendor/libyeptris/cmake/yeptris.pc.in +11 -0
  35. data/vendor/libyeptris/src/CMakeLists.txt +167 -0
  36. data/vendor/libyeptris/src/include/yeptris/api.h +32 -0
  37. data/vendor/libyeptris/src/include/yeptris/cbor.h +101 -0
  38. data/vendor/libyeptris/src/include/yeptris/dom.h +190 -0
  39. data/vendor/libyeptris/src/include/yeptris/emit.h +81 -0
  40. data/vendor/libyeptris/src/include/yeptris/error.h +41 -0
  41. data/vendor/libyeptris/src/include/yeptris/events.h +157 -0
  42. data/vendor/libyeptris/src/include/yeptris/json.h +45 -0
  43. data/vendor/libyeptris/src/include/yeptris/json.hpp +258 -0
  44. data/vendor/libyeptris/src/include/yeptris/jsonc_compat.h +115 -0
  45. data/vendor/libyeptris/src/include/yeptris/marshal.h +52 -0
  46. data/vendor/libyeptris/src/include/yeptris/parse.h +48 -0
  47. data/vendor/libyeptris/src/include/yeptris/plan.h +100 -0
  48. data/vendor/libyeptris/src/include/yeptris/resolve.h +71 -0
  49. data/vendor/libyeptris/src/include/yeptris/schema.h +121 -0
  50. data/vendor/libyeptris/src/include/yeptris/tape.h +123 -0
  51. data/vendor/libyeptris/src/include/yeptris/types.h +38 -0
  52. data/vendor/libyeptris/src/include/yeptris/values.h +102 -0
  53. data/vendor/libyeptris/src/include/yeptris/version.h.in +29 -0
  54. data/vendor/libyeptris/src/include/yeptris/visit.h +77 -0
  55. data/vendor/libyeptris/src/include/yeptris/yajl_compat.h +135 -0
  56. data/vendor/libyeptris/src/include/yeptris.h +23 -0
  57. data/vendor/libyeptris/src/yeptris/build.c +376 -0
  58. data/vendor/libyeptris/src/yeptris/cbor/cbor.h +25 -0
  59. data/vendor/libyeptris/src/yeptris/cbor/decode.c +981 -0
  60. data/vendor/libyeptris/src/yeptris/cbor/encode.c +835 -0
  61. data/vendor/libyeptris/src/yeptris/cbor/sink.h +58 -0
  62. data/vendor/libyeptris/src/yeptris/common/chartype.c +41 -0
  63. data/vendor/libyeptris/src/yeptris/common/chartype.h +77 -0
  64. data/vendor/libyeptris/src/yeptris/common/cpu.c +81 -0
  65. data/vendor/libyeptris/src/yeptris/common/cpu.h +40 -0
  66. data/vendor/libyeptris/src/yeptris/common/error.c +65 -0
  67. data/vendor/libyeptris/src/yeptris/common/error.h +79 -0
  68. data/vendor/libyeptris/src/yeptris/common/mutex.h +45 -0
  69. data/vendor/libyeptris/src/yeptris/common/nametab.c +275 -0
  70. data/vendor/libyeptris/src/yeptris/common/nametab.h +68 -0
  71. data/vendor/libyeptris/src/yeptris/common/port.h +74 -0
  72. data/vendor/libyeptris/src/yeptris/common/simd_text.c +49 -0
  73. data/vendor/libyeptris/src/yeptris/common/simd_text.h +295 -0
  74. data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +534 -0
  75. data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +662 -0
  76. data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +298 -0
  77. data/vendor/libyeptris/src/yeptris/common/string_view.c +34 -0
  78. data/vendor/libyeptris/src/yeptris/common/string_view.h +93 -0
  79. data/vendor/libyeptris/src/yeptris/doc.h +56 -0
  80. data/vendor/libyeptris/src/yeptris/dom/dom.c +1192 -0
  81. data/vendor/libyeptris/src/yeptris/dom/dom.h +312 -0
  82. data/vendor/libyeptris/src/yeptris/dom/hpool.c +107 -0
  83. data/vendor/libyeptris/src/yeptris/dom/mapindex.c +173 -0
  84. data/vendor/libyeptris/src/yeptris/dom/mapindex.h +61 -0
  85. data/vendor/libyeptris/src/yeptris/dom/mutate.c +431 -0
  86. data/vendor/libyeptris/src/yeptris/emit/emit.c +434 -0
  87. data/vendor/libyeptris/src/yeptris/emit/float/api.h +38 -0
  88. data/vendor/libyeptris/src/yeptris/emit/float/dragon.c +405 -0
  89. data/vendor/libyeptris/src/yeptris/emit/float/floatint.h +231 -0
  90. data/vendor/libyeptris/src/yeptris/emit/float/print.c +396 -0
  91. data/vendor/libyeptris/src/yeptris/emit/style.c +81 -0
  92. data/vendor/libyeptris/src/yeptris/emit/style.h +24 -0
  93. data/vendor/libyeptris/src/yeptris/emit/writer.c +816 -0
  94. data/vendor/libyeptris/src/yeptris/emit/writer.h +76 -0
  95. data/vendor/libyeptris/src/yeptris/encoding/bom.c +31 -0
  96. data/vendor/libyeptris/src/yeptris/encoding/encoding.h +63 -0
  97. data/vendor/libyeptris/src/yeptris/encoding/transcode.c +148 -0
  98. data/vendor/libyeptris/src/yeptris/encoding/utf8_validate.c +178 -0
  99. data/vendor/libyeptris/src/yeptris/events/capture.c +150 -0
  100. data/vendor/libyeptris/src/yeptris/events/capture.h +39 -0
  101. data/vendor/libyeptris/src/yeptris/events/iterparse.c +208 -0
  102. data/vendor/libyeptris/src/yeptris/events/pull.c +97 -0
  103. data/vendor/libyeptris/src/yeptris/events/push.c +104 -0
  104. data/vendor/libyeptris/src/yeptris/events/recorder.c +107 -0
  105. data/vendor/libyeptris/src/yeptris/events/values.c +527 -0
  106. data/vendor/libyeptris/src/yeptris/events/values_priv.h +51 -0
  107. data/vendor/libyeptris/src/yeptris/events/yaml_compat.c +86 -0
  108. data/vendor/libyeptris/src/yeptris/events/yaml_compat.h +90 -0
  109. data/vendor/libyeptris/src/yeptris/jsonapi/jsonc_compat.c +687 -0
  110. data/vendor/libyeptris/src/yeptris/jsonapi/yajl_compat.c +728 -0
  111. data/vendor/libyeptris/src/yeptris/marshal.c +782 -0
  112. data/vendor/libyeptris/src/yeptris/memory/allocator.c +20 -0
  113. data/vendor/libyeptris/src/yeptris/memory/allocator.h +43 -0
  114. data/vendor/libyeptris/src/yeptris/memory/arena.c +134 -0
  115. data/vendor/libyeptris/src/yeptris/memory/arena.h +52 -0
  116. data/vendor/libyeptris/src/yeptris/memory/pool.c +122 -0
  117. data/vendor/libyeptris/src/yeptris/memory/pool.h +36 -0
  118. data/vendor/libyeptris/src/yeptris/parse/engine.c +3698 -0
  119. data/vendor/libyeptris/src/yeptris/parse/engine.h +65 -0
  120. data/vendor/libyeptris/src/yeptris/parse/events.h +124 -0
  121. data/vendor/libyeptris/src/yeptris/parse/numbers.c +349 -0
  122. data/vendor/libyeptris/src/yeptris/parse/numbers.h +33 -0
  123. data/vendor/libyeptris/src/yeptris/parse/scalars.c +416 -0
  124. data/vendor/libyeptris/src/yeptris/parse/scalars.h +75 -0
  125. data/vendor/libyeptris/src/yeptris/parse.c +737 -0
  126. data/vendor/libyeptris/src/yeptris/plan.c +824 -0
  127. data/vendor/libyeptris/src/yeptris/resolve/compat11.c +334 -0
  128. data/vendor/libyeptris/src/yeptris/resolve/core12.c +143 -0
  129. data/vendor/libyeptris/src/yeptris/resolve/resolver.h +56 -0
  130. data/vendor/libyeptris/src/yeptris/resolve/tags.c +58 -0
  131. data/vendor/libyeptris/src/yeptris/scan/json.c +792 -0
  132. data/vendor/libyeptris/src/yeptris/scan/json.h +109 -0
  133. data/vendor/libyeptris/src/yeptris/scan/scan.c +463 -0
  134. data/vendor/libyeptris/src/yeptris/scan/scan.h +150 -0
  135. data/vendor/libyeptris/src/yeptris/schema.c +308 -0
  136. data/vendor/libyeptris/src/yeptris/tape.c +1308 -0
  137. data/vendor/libyeptris/src/yeptris/tape_in.h +19 -0
  138. data/vendor/libyeptris/src/yeptris/version.c +7 -0
  139. data/vendor/libyeptris/src/yeptris/visit/dom_visit.c +115 -0
  140. data/vendor/libyeptris/src/yeptris/visit/json_visit.c +293 -0
  141. data/vendor/libyeptris/src/yeptris/visit/yaml_visit.c +127 -0
  142. metadata +199 -0
@@ -0,0 +1,65 @@
1
+ /* engine.h — the one parser engine (TODO.impl/07).
2
+ *
3
+ * Non-recursive block machine + iterative flow kernel, producing events
4
+ * into any sink (DOM builder today; pull/recorder in 12). v1 runs the
5
+ * whole buffer in one call; resumable stepping lands with 12's streaming
6
+ * (recorded as the item's open phase). Depth guard rejects pathological
7
+ * nesting with an error, never a crash.
8
+ */
9
+ #ifndef YEP_ENGINE_H
10
+ #define YEP_ENGINE_H
11
+
12
+ #include "common/error.h"
13
+ #include "common/simd_text.h"
14
+ #include "memory/allocator.h"
15
+ #include "memory/pool.h"
16
+ #include "parse/events.h"
17
+
18
+ #ifdef __cplusplus
19
+ extern "C" {
20
+ #endif
21
+
22
+ typedef struct yep_engine yep_engine;
23
+
24
+ yep_engine* yep_engine_create(const yep_allocator* sys);
25
+ void yep_engine_destroy(yep_engine* e);
26
+
27
+ /* Parses [buf, buf+len) — must be validated UTF-8 (05). Returns 0 on
28
+ * success, -1 on parse error (see yep_engine_error), -2 sink abort. */
29
+ int yep_engine_run(yep_engine* e, const char* buf, size_t len, const yep_sink* sink);
30
+
31
+ /* Content-derived pre-sizing before run(): reserves the anchor interner
32
+ * from the stream's '&' occurrences (every anchor definition carries
33
+ * exactly one, so the count never undershoots). */
34
+ void yep_engine_prepare(yep_engine* e, const yep_text_stats* st);
35
+
36
+ /* Resumable stepping (TODO.impl/07): chunks accumulate; every feed
37
+ * parses the complete DOCUMENTS received so far (cut at `---` / `...`
38
+ * boundaries at column 0, outside quotes and flow) and keeps the
39
+ * trailing partial document buffered. final != 0 flushes it and ends
40
+ * the stream. STREAM markers bracket the whole stepped stream, not
41
+ * each step; each document's events arrive exactly once, in order.
42
+ * Returns 0, -1 parse error, -2 sink abort. */
43
+ int yep_engine_step(yep_engine* e, const char* chunk, size_t len, int final, const yep_sink* sink);
44
+
45
+ /* Detaches the finish pool (ownership moves to the caller; the engine
46
+ * allocates a fresh one if reused). Returns NULL when absent. */
47
+ yep_pool* yep_engine_detach_pool(yep_engine* e);
48
+
49
+ /* Implicit-typing schema for the next run (NULL: 1.2 core), and the
50
+ * runtime nesting limit. */
51
+ struct yep_resolver;
52
+ void yep_engine_set_resolver(yep_engine* e, const struct yep_resolver* r);
53
+ void yep_engine_set_max_depth(yep_engine* e, int depth);
54
+
55
+ /* Byte offset the last run reached (into that run's buffer); used by
56
+ * consumers that stop the engine at a boundary and resume. */
57
+ size_t yep_engine_pos(const yep_engine* e);
58
+
59
+ const yep_error* yep_engine_error(const yep_engine* e);
60
+
61
+ #ifdef __cplusplus
62
+ }
63
+ #endif
64
+
65
+ #endif /* YEP_ENGINE_H */
@@ -0,0 +1,124 @@
1
+ /* events.h — the one grammar vocabulary (TODO.impl/07).
2
+ *
3
+ * Every consumption model (DOM builder, pull, push, recorder — 11/12) is
4
+ * a sink over these events; the engine knows none of them (OCP). Values
5
+ * are borrowed either from the input buffer or from the engine's finish
6
+ * pool (folded/escaped content) — `borrowed` says which, so the DOM
7
+ * builder copies exactly what must outlive the engine.
8
+ */
9
+ #ifndef YEP_EVENTS_H
10
+ #define YEP_EVENTS_H
11
+
12
+ #include "common/string_view.h"
13
+
14
+ #ifdef __cplusplus
15
+ extern "C" {
16
+ #endif
17
+
18
+ typedef enum {
19
+ YEP_EV_NONE = 0,
20
+ YEP_EV_STREAM_START,
21
+ YEP_EV_STREAM_END,
22
+ YEP_EV_DOCUMENT_START,
23
+ YEP_EV_DOCUMENT_END,
24
+ YEP_EV_SEQ_START,
25
+ YEP_EV_SEQ_END,
26
+ YEP_EV_MAP_START,
27
+ YEP_EV_MAP_END,
28
+ YEP_EV_SCALAR,
29
+ YEP_EV_ALIAS,
30
+ } yep_event_type;
31
+
32
+ /* Mirrors libyaml's style set — the wire vocabulary of 12's compat layer. */
33
+ typedef enum {
34
+ YEP_STYLE_ANY = 0,
35
+ YEP_STYLE_PLAIN,
36
+ YEP_STYLE_SINGLE_QUOTED,
37
+ YEP_STYLE_DOUBLE_QUOTED,
38
+ YEP_STYLE_LITERAL,
39
+ YEP_STYLE_FOLDED,
40
+ } yep_scalar_style;
41
+
42
+ typedef struct yep_event {
43
+ yep_event_type type;
44
+ yep_view value; /* scalar content / alias name */
45
+ yep_view anchor; /* node properties, empty when absent */
46
+ yep_view tag;
47
+ uint8_t style; /* yep_scalar_style */
48
+ uint8_t implicit; /* scalar written without quotes/tag (plain implicit) */
49
+ uint8_t flow; /* collection opened in flow context */
50
+ uint8_t multiline; /* scalar spanned lines: may not be a simple key */
51
+ uint8_t tag_id; /* resolved implicit/explicit tag (resolve/resolver.h) */
52
+ uint8_t borrowed; /* 1: value borrows the INPUT; 0: engine finish pool */
53
+ uint32_t anchor_id; /* 1-based anchor ordinal (the engine's serial);
54
+ * on ALIAS: the TARGET's ordinal. 0 = none. Sinks
55
+ * that key on it skip the name hash entirely. */
56
+ uint32_t line; /* 1-based position of the node start */
57
+ uint32_t col;
58
+ } yep_event;
59
+
60
+ struct yep_block_value; /* value facts for on_block_pair (below) */
61
+
62
+ typedef struct yep_sink {
63
+ /* Returns 0 to continue, nonzero to abort the parse (sink error). */
64
+ int (*on_event)(void* ctx, const yep_event* ev);
65
+ void* ctx;
66
+ /* Fused flow fast path (TODO.restructure/53): validate AND build
67
+ * the span at p[open..len) in ONE walk (the grammar walker is
68
+ * scan/json.c's SSOT). Returns 1 = built and staged, *close set —
69
+ * the engine runs its close-based grammar checks next, then
70
+ * COMMITS or ROLLS BACK; 2 = grammar-valid but a map key exceeds
71
+ * the simple-key limit (nothing staged; the engine's pass 2 owns
72
+ * that error); 0 = not JSON-class (nothing staged; the general
73
+ * kernel); <0 = abort. Sinks that consume events (pull/push/
74
+ * recorder) leave the trio NULL. */
75
+ int (*on_flow_build)(void* ctx, const char* p, size_t open, size_t len, uint32_t line,
76
+ size_t line_start, yep_view anchor, yep_view tag, uint32_t anchor_id,
77
+ int max_depth, size_t* close);
78
+ int (*on_flow_commit)(void* ctx);
79
+ void (*on_flow_rollback)(void* ctx);
80
+ /* Optional block fast path (TODO.restructure/54): the engine's
81
+ * classified KEY arm offers the whole line pair — key scalar plus
82
+ * a classified value — before emitting any event. line/cols are
83
+ * the engine's position facts. Return 1 = both nodes built and
84
+ * placed, 0 = not handled (the engine emits the two events
85
+ * exactly as before), <0 = abort. */
86
+ int (*on_block_pair)(void* ctx, const yep_view* key, const struct yep_block_value* v,
87
+ uint32_t line, uint16_t key_col, uint16_t val_col);
88
+ /* Optional block-open fast path (TODO.restructure/57): a `key:`
89
+ * line whose value lives on FOLLOWING lines, when the engine is
90
+ * about to open a FRESH mapping. 1 = the sink built the map node
91
+ * (placed, stack pushed) and the key node — the engine opens its
92
+ * frame silently and skips both events; 0 = events as before. */
93
+ int (*on_block_open)(void* ctx, const yep_view* key, uint32_t line, uint16_t key_col);
94
+ /* Optional dash-item fast path (TODO.restructure/78): a classified
95
+ * `- value` plain item after the engine opened (or continued) the
96
+ * block sequence. 1 = the sink built and placed the item node,
97
+ * 0 = the engine emits the scalar event as before, <0 = abort. */
98
+ int (*on_block_item)(void* ctx, const struct yep_block_value* v);
99
+
100
+ /* Direct scalar path (TODO.restructure/79): the same node the
101
+ * YEP_EV_SCALAR event builds, minus the event seam — emit_now
102
+ * resolves the tag first (the typing SSOT stays in the engine)
103
+ * and calls here when present. NULL = the event path, unchanged. */
104
+ int (*on_scalar)(void* ctx, const struct yep_view* value, const struct yep_view* tag,
105
+ const struct yep_view* anchor, uint32_t anchor_id, uint8_t tag_id,
106
+ uint8_t style, uint8_t implicit, uint8_t flow, int borrowed);
107
+ } yep_sink;
108
+
109
+ /* Value facts for on_block_pair (the classified value classes the
110
+ * block arms own; spans are input-borrowed). */
111
+ typedef struct yep_block_value {
112
+ uint8_t cls; /* YEP_LVAL_PLAIN / _ALIAS / _ANCHOR_PLAIN */
113
+ uint8_t borrowed; /* 1: value borrows the input; 0: engine pool */
114
+ yep_view value; /* scalar content / alias name */
115
+ yep_view anchor; /* _ANCHOR_PLAIN: the &name span */
116
+ uint32_t anchor_id; /* engine ordinal: the definition (_ANCHOR_)
117
+ * or the resolved TARGET (_ALIAS_) */
118
+ } yep_block_value;
119
+
120
+ #ifdef __cplusplus
121
+ }
122
+ #endif
123
+
124
+ #endif /* YEP_EVENTS_H */
@@ -0,0 +1,349 @@
1
+ /* numbers.c — the typed-value conversion kernels (TODO.impl/08B).
2
+ *
3
+ * Extracted verbatim from parse.c's node accessors: behavior is
4
+ * pinned by the typed-accessor spec battery and the 20k randomized
5
+ * strtod cross-checks. */
6
+
7
+ #include <errno.h>
8
+ #include <math.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+
12
+ #include "numbers.h"
13
+
14
+ #define NUM_BUF 80
15
+
16
+ /* strips '_' and ',' into a NUL-terminated stack buffer; returns the
17
+ * cleaned length (the raw length when nothing needed stripping —
18
+ * callers then use the original bytes) */
19
+ static size_t num_clean(const char* p, uint32_t len, char* buf) {
20
+ if (memchr(p, '_', len) == NULL && memchr(p, ',', len) == NULL) {
21
+ return len; /* caller reads p directly */
22
+ }
23
+ size_t o = 0;
24
+ for (uint32_t i = 0; i < len && o + 1 < NUM_BUF; i++) {
25
+ char c = p[i];
26
+ if (c == '_' || c == ',') {
27
+ continue;
28
+ }
29
+ buf[o++] = c;
30
+ }
31
+ buf[o] = '\0';
32
+ return o;
33
+ }
34
+
35
+ /* Clinger-bounded exact decimal: mantissa < 2^53, adjusted
36
+ * exponent within +-22 — 23-entry pow10 table (08B) */
37
+ static const double k_pow10[23] = {
38
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
39
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
40
+ };
41
+
42
+ static int fast_double(const char* s, size_t len, double* out) {
43
+ size_t i = 0;
44
+ int neg = 0;
45
+ if (i < len && (s[i] == '-' || s[i] == '+')) {
46
+ neg = s[i] == '-';
47
+ i++;
48
+ }
49
+ uint64_t m = 0;
50
+ int digits = 0;
51
+ int dot = -1;
52
+ for (; i < len; i++) {
53
+ char c = s[i];
54
+ if (c == '.') {
55
+ if (dot >= 0) {
56
+ return 0;
57
+ }
58
+ dot = (int)digits;
59
+ continue;
60
+ }
61
+ if (c < '0' || c > '9') {
62
+ break;
63
+ }
64
+ if (digits >= 15) {
65
+ return 0; /* outside the exact range */
66
+ }
67
+ m = m * 10u + (uint64_t)(c - '0');
68
+ digits++;
69
+ }
70
+ if (digits == 0 || (i < len && s[i] != 'e' && s[i] != 'E')) {
71
+ return 0; /* empty mantissa or trailing junk */
72
+ }
73
+ int e10 = 0;
74
+ if (i < len) {
75
+ i++; /* e/E */
76
+ int eneg = 0;
77
+ if (i < len && (s[i] == '-' || s[i] == '+')) {
78
+ eneg = s[i] == '-';
79
+ i++;
80
+ }
81
+ if (i >= len) {
82
+ return 0;
83
+ }
84
+ for (; i < len; i++) {
85
+ if (s[i] < '0' || s[i] > '9') {
86
+ return 0;
87
+ }
88
+ e10 = e10 * 10 + (s[i] - '0');
89
+ if (e10 > 308) {
90
+ return 0;
91
+ }
92
+ }
93
+ if (eneg) {
94
+ e10 = -e10;
95
+ }
96
+ }
97
+ if (dot >= 0) {
98
+ e10 -= digits - dot;
99
+ }
100
+ if (e10 > 22 || e10 < -22 || m >= (1ull << 53)) {
101
+ return 0; /* outside Clinger's exact range */
102
+ }
103
+ if (e10 >= 0) {
104
+ double v = (double)m * k_pow10[e10];
105
+ *out = neg ? -v : v;
106
+ } else {
107
+ double v = (double)m / k_pow10[-e10];
108
+ *out = neg ? -v : v;
109
+ }
110
+ return 1;
111
+ }
112
+
113
+ int yep_num_i64(const char* p, uint32_t len, int64_t* out) {
114
+ if (p == NULL || len == 0) {
115
+ return 1;
116
+ }
117
+ char buf[NUM_BUF];
118
+ size_t l = num_clean(p, len, buf);
119
+ const char* num =
120
+ (l == len && memchr(p, '_', len) == NULL && memchr(p, ',', len) == NULL) ? p : buf;
121
+ if (num != p) {
122
+ /* cleaned copy already NUL-terminated by num_clean */
123
+ } else {
124
+ if (l >= NUM_BUF) {
125
+ return 1;
126
+ }
127
+ memcpy(buf, num, l);
128
+ buf[l] = '\0';
129
+ num = buf;
130
+ }
131
+ int base = 10;
132
+ const char* s = buf;
133
+ if (buf[0] == '-' || buf[0] == '+') {
134
+ s++;
135
+ }
136
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
137
+ base = 16;
138
+ } else if (s[0] == '0' && (s[1] == 'b' || s[1] == 'B')) {
139
+ base = 2;
140
+ } else if (s[0] == '0' && s[1] == 'o') {
141
+ memmove(buf + (size_t)(s - buf) + 1, s + 2, l - (size_t)(s - buf) - 1);
142
+ l -= 1;
143
+ buf[l] = '\0';
144
+ base = 8; /* 0o17 -> 017 octal */
145
+ } else if (s[0] == '0' && s[1] != '\0' && s[1] != '.') {
146
+ base = 8; /* compat leading-0 octal */
147
+ }
148
+ if (memchr(buf, ':', l) != NULL) {
149
+ /* Psych's sexagesimal fold, verbatim (scalar_scanner.rb):
150
+ * component e weighs 60 ** |e - 2| and the SIGN rides the
151
+ * first component only (-1:30 -> -3600 + 1800 = -1800, not
152
+ * -5400). A 2-component value is H:M, seconds implicitly
153
+ * zero (1:30 -> 5400). TODO.restructure/43 / issue #30. */
154
+ const char* q = buf;
155
+ long long sign = 1;
156
+ if (q[0] == '-' || q[0] == '+') {
157
+ if (q[0] == '-')
158
+ sign = -1;
159
+ q++;
160
+ }
161
+ long long v = 0;
162
+ while (*q >= '0' && *q <= '9') {
163
+ v = v * 10 + (*q - '0');
164
+ q++;
165
+ }
166
+ v *= 3600; /* e0 weight */
167
+ if (sign < 0)
168
+ v = -v;
169
+ int groups = 0;
170
+ while (*q == ':' && groups < 2) {
171
+ q++;
172
+ long long g = 0;
173
+ int d = 0;
174
+ while (*q >= '0' && *q <= '9') {
175
+ g = g * 10 + (*q - '0');
176
+ q++;
177
+ d++;
178
+ }
179
+ if (d == 0) {
180
+ return 1;
181
+ }
182
+ v += g * (groups == 0 ? 60 : 1); /* e1 then e2 */
183
+ groups++;
184
+ }
185
+ if (groups == 0 || *q != '\0') {
186
+ return 1;
187
+ }
188
+ *out = v;
189
+ return 0;
190
+ }
191
+ char* end = NULL;
192
+ errno = 0;
193
+ long long v = strtoll(buf, &end, base);
194
+ if (end == buf || *end != '\0' || errno == ERANGE) {
195
+ return 1;
196
+ }
197
+ *out = (int64_t)v;
198
+ return 0;
199
+ }
200
+
201
+ int yep_num_f64(const char* p, uint32_t len, double* out) {
202
+ if (p == NULL || len == 0) {
203
+ return 1;
204
+ }
205
+ char buf[NUM_BUF];
206
+ size_t l = num_clean(p, len, buf);
207
+ const char* num =
208
+ (l == len && memchr(p, '_', len) == NULL && memchr(p, ',', len) == NULL) ? p : buf;
209
+ /* 08B fast path: the common decimal shape converts exactly with
210
+ * integer arithmetic; everything else falls to strtod */
211
+ {
212
+ double fast;
213
+ if (fast_double(num, l, &fast)) {
214
+ *out = fast;
215
+ return 0;
216
+ }
217
+ }
218
+ if (num != p) {
219
+ /* cleaned copy is NUL-terminated */
220
+ } else {
221
+ if (l >= NUM_BUF) {
222
+ return 1;
223
+ }
224
+ memcpy(buf, num, l);
225
+ buf[l] = '\0';
226
+ num = buf;
227
+ }
228
+ /* .inf / .nan family (sign allowed on inf) */
229
+ {
230
+ const char* s = buf;
231
+ size_t sl = l;
232
+ if (s[0] == '-' || s[0] == '+') {
233
+ s++;
234
+ sl--;
235
+ }
236
+ if (sl == 4 && s[0] == '.') {
237
+ if ((s[1] == 'i' || s[1] == 'I') && (s[2] == 'n' || s[2] == 'N') &&
238
+ (s[3] == 'f' || s[3] == 'F')) {
239
+ *out = (buf[0] == '-') ? -INFINITY : INFINITY;
240
+ return 0;
241
+ }
242
+ if ((s[1] == 'n' || s[1] == 'N') && (s[2] == 'a' || s[2] == 'A') &&
243
+ (s[3] == 'n' || s[3] == 'N')) {
244
+ *out = NAN;
245
+ return 0;
246
+ }
247
+ }
248
+ }
249
+ /* sexagesimal float — Psych's fold: weights 60**|e-2|, sign on
250
+ * the first component, the fraction on the LAST component
251
+ * (1:30.5 -> 1*3600 + 30.5*60 = 5430.0). */
252
+ if (memchr(buf, ':', l) != NULL) {
253
+ const char* s = buf;
254
+ double sign = 1.0;
255
+ if (s[0] == '-' || s[0] == '+') {
256
+ if (s[0] == '-')
257
+ sign = -1.0;
258
+ s++;
259
+ }
260
+ double v = 0.0;
261
+ const char* q = s;
262
+ while (*q >= '0' && *q <= '9') {
263
+ v = v * 10.0 + (*q - '0');
264
+ q++;
265
+ }
266
+ v *= 3600.0;
267
+ v *= sign;
268
+ int groups = 0;
269
+ double last = 0.0;
270
+ double weight = 60.0;
271
+ for (;;) {
272
+ if (*q != ':' || groups >= 2)
273
+ break;
274
+ q++;
275
+ double g = 0.0;
276
+ int d = 0;
277
+ while (*q >= '0' && *q <= '9') {
278
+ g = g * 10.0 + (*q - '0');
279
+ q++;
280
+ d++;
281
+ }
282
+ if (d == 0) {
283
+ return 1;
284
+ }
285
+ if (*q == '.') {
286
+ double frac = 0.0, scale = 0.1;
287
+ q++;
288
+ while (*q >= '0' && *q <= '9') {
289
+ frac += (*q - '0') * scale;
290
+ scale /= 10.0;
291
+ q++;
292
+ }
293
+ g += frac;
294
+ }
295
+ v += g * weight;
296
+ weight = 1.0; /* e2 */
297
+ last = g;
298
+ groups++;
299
+ }
300
+ (void)last;
301
+ if (groups == 0 || *q != '\0') {
302
+ return 1;
303
+ }
304
+ *out = v;
305
+ return 0;
306
+ }
307
+ char* end = NULL;
308
+ errno = 0;
309
+ double v = strtod(buf, &end);
310
+ if (end == buf || *end != '\0') {
311
+ return 1;
312
+ }
313
+ (void)errno;
314
+ *out = v;
315
+ return 0;
316
+ }
317
+
318
+ int yep_num_bool(const char* p, uint32_t len) {
319
+ static const char* k_true[] = {"true", "True", "TRUE", "y", "Y", "yes",
320
+ "Yes", "YES", "on", "On", "ON"};
321
+ for (size_t i = 0; i < sizeof(k_true) / sizeof(k_true[0]); i++) {
322
+ size_t m = strlen(k_true[i]);
323
+ if (len == m && memcmp(p, k_true[i], m) == 0) {
324
+ return 1;
325
+ }
326
+ }
327
+ return 0;
328
+ }
329
+
330
+ int yep_num_bool_ci(const char* p, uint32_t len) {
331
+ /* the compat resolver matches bool words case-insensitively;
332
+ * truth follows the same rule (Psych's scanner downcases) */
333
+ static const char* k_true[] = {"y", "yes", "true", "on"};
334
+ char buf[8];
335
+ if (len == 0 || len > 5) {
336
+ return 0;
337
+ }
338
+ for (uint32_t i = 0; i < len; i++) {
339
+ char c = p[i];
340
+ buf[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
341
+ }
342
+ for (size_t i = 0; i < sizeof(k_true) / sizeof(k_true[0]); i++) {
343
+ size_t m = strlen(k_true[i]);
344
+ if (len == m && memcmp(buf, k_true[i], m) == 0) {
345
+ return 1;
346
+ }
347
+ }
348
+ return 0;
349
+ }
@@ -0,0 +1,33 @@
1
+ /* numbers.h — the typed-value conversion kernels (TODO.impl/08B).
2
+ *
3
+ * ONE home for text->int64/double/bool: the node typed accessors,
4
+ * the value stream (values.c), and any future consumer ride these.
5
+ * Pure functions over (pointer, length) — no handles, no state. */
6
+ #ifndef YEP_NUMBERS_H
7
+ #define YEP_NUMBERS_H
8
+
9
+ #include <stdint.h>
10
+ #include <yeptris/api.h>
11
+
12
+ #ifdef __cplusplus
13
+ extern "C" {
14
+ #endif
15
+
16
+ /* Separator-carrying YAML number text (digits, '_', ','; radix
17
+ * forms 0x/0o/0b/leading-0; sexagesimal for the compat schema).
18
+ * Returns 0 and sets *out on success, nonzero otherwise. */
19
+ YEPTRIS_API int yep_num_i64(const char* p, uint32_t len, int64_t* out);
20
+ YEPTRIS_API int yep_num_f64(const char* p, uint32_t len, double* out);
21
+
22
+ /* The resolver's true-word set (true/True/TRUE/y/Y/yes/Yes/YES/on/
23
+ * On/ON); anything else the BOOL tag accepted is false. */
24
+ YEPTRIS_API int yep_num_bool(const char* p, uint32_t len);
25
+
26
+ /* Case-insensitive truth (the compat resolver's matching rule). */
27
+ YEPTRIS_API int yep_num_bool_ci(const char* p, uint32_t len);
28
+
29
+ #ifdef __cplusplus
30
+ }
31
+ #endif
32
+
33
+ #endif /* YEP_NUMBERS_H */