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,662 @@
1
+ /* simd_text_neon.c — NEON kernels (TODO.impl/04).
2
+ *
3
+ * NEON is architectural on AArch64, so this TU needs no extra -m flags.
4
+ * 16-byte chunks, scalar tails. scan_stats accumulates vertically
5
+ * (vpadalq into u16 lanes, one reduce per batch — the leptris count
6
+ * lesson); the single-char kernels still reduce UADDV over 0/1 lanes
7
+ * (the sizing ops are the ≥8×-vs-scalar acceptance target). Position
8
+ * queries reduce through a stack movemask helper — correct first, and
9
+ * the perf ledger records it as a refinement candidate if 06's
10
+ * profiles care. stopset_find is vectorized (TODO.restructure/68,
11
+ * nibble-class tbl).
12
+ */
13
+
14
+ #include "port.h" /* defines YEP_ARCH_* — must precede the guard below */
15
+
16
+ #if defined(YEP_ARCH_AARCH64)
17
+
18
+ #include <arm_neon.h>
19
+ #include <stdint.h>
20
+ #include <string.h>
21
+
22
+ #include "simd_text.h"
23
+
24
+ #define YEP_NEON_CHUNK 16
25
+
26
+ static inline uint8x16_t yep_neon_load(const char* p) {
27
+ return vld1q_u8((const uint8_t*)(const void*)p);
28
+ }
29
+
30
+ static inline uint8x16_t yep_neon_eq(const char* p, uint8_t c) {
31
+ return vceqq_u8(yep_neon_load(p), vdupq_n_u8(c));
32
+ }
33
+
34
+ /* 0x00/0xFF lanes -> per-lane bitmask. LE: widening form — the two
35
+ * mask bits of each byte pair land in one u16 lane, a shift vector
36
+ * spreads them to their final positions, ONE u16 reduce (the leptris
37
+ * scan_events shape; no stack spill). vshlq_u16's shift vector is the
38
+ * ACLE-mandated int16x8_t (the GCC-aarch64 lesson, leptris #487).
39
+ * BE keeps the endian-neutral pow2-table spill. */
40
+ #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
41
+ __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
42
+ static inline uint16_t yep_neon_bits(uint8x16_t m) {
43
+ static const uint8_t pow2[16] = {1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128};
44
+ uint8_t tmp[16];
45
+ vst1q_u8(tmp, vandq_u8(m, vld1q_u8(pow2)));
46
+ uint16_t lo = (uint16_t)(tmp[0] | tmp[1] | tmp[2] | tmp[3] | tmp[4] | tmp[5] | tmp[6] | tmp[7]);
47
+ uint16_t hi =
48
+ (uint16_t)(tmp[8] | tmp[9] | tmp[10] | tmp[11] | tmp[12] | tmp[13] | tmp[14] | tmp[15]);
49
+ return (uint16_t)(lo | (uint16_t)(hi << 8));
50
+ }
51
+ #else
52
+ static inline uint16_t yep_neon_bits(uint8x16_t m) {
53
+ static const int16x8_t spread = {0, 2, 4, 6, 8, 10, 12, 14}; /* lane k -> bit 2k */
54
+ /* per u16 lane: byte 2k carries bit 7 (u16 bit 7), byte 2k+1
55
+ * carries bit 15; >>7 lands b0 at bit 0, >>14 lands b1 at bit 1
56
+ * (bit 7 shifted out), &3 drops b1's >>7 residue at bit 8 */
57
+ uint16x8_t p = vreinterpretq_u16_u8(vandq_u8(m, vdupq_n_u8(0x80)));
58
+ uint16x8_t r = vandq_u16(vorrq_u16(vshrq_n_u16(p, 7), vshrq_n_u16(p, 14)), vdupq_n_u16(3));
59
+ return (uint16_t)vaddvq_u16(vshlq_u16(r, spread));
60
+ }
61
+ #endif
62
+
63
+ /* Occurrences of c in one chunk: UADDV over 0/1 lanes. */
64
+ static inline size_t yep_neon_chunk_count(const char* p, uint8_t c) {
65
+ uint8x16_t one = vandq_u8(yep_neon_eq(p, c), vdupq_n_u8(1));
66
+ return (size_t)vaddvq_u8(one);
67
+ }
68
+
69
+ static int yep_neon_contains(const char* s, size_t len, char c) {
70
+ size_t i = 0;
71
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
72
+ if (yep_neon_chunk_count(s + i, (uint8_t)c) != 0) {
73
+ return 1;
74
+ }
75
+ }
76
+ return yep_text_contains_scalar(s + i, len - i, c);
77
+ }
78
+
79
+ static ptrdiff_t yep_neon_find(const char* s, size_t len, char c) {
80
+ size_t i = 0;
81
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
82
+ uint16_t m = yep_neon_bits(yep_neon_eq(s + i, (uint8_t)c));
83
+ if (m) {
84
+ return (ptrdiff_t)(i + (size_t)__builtin_ctz(m));
85
+ }
86
+ }
87
+ ptrdiff_t tail = yep_text_find_scalar(s + i, len - i, c);
88
+ return tail < 0 ? -1 : (ptrdiff_t)i + tail;
89
+ }
90
+
91
+ static size_t yep_neon_count(const char* s, size_t len, char c) {
92
+ size_t n = 0, i = 0;
93
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
94
+ n += yep_neon_chunk_count(s + i, (uint8_t)c);
95
+ }
96
+ return n + yep_text_count_char_scalar(s + i, len - i, c);
97
+ }
98
+
99
+ static void yep_neon_count3(const char* s, size_t len, char c0, char c1, char c2, size_t* n0,
100
+ size_t* n1, size_t* n2) {
101
+ size_t a = 0, b = 0, d = 0, i = 0;
102
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
103
+ a += yep_neon_chunk_count(s + i, (uint8_t)c0);
104
+ b += yep_neon_chunk_count(s + i, (uint8_t)c1);
105
+ d += yep_neon_chunk_count(s + i, (uint8_t)c2);
106
+ }
107
+ size_t ta = 0, tb = 0, td = 0;
108
+ yep_text_count3_scalar(s + i, len - i, c0, c1, c2, &ta, &tb, &td);
109
+ *n0 = a + ta;
110
+ *n1 = b + tb;
111
+ *n2 = d + td;
112
+ }
113
+
114
+ static void yep_neon_copy_count3(char* dst, const char* src, size_t len, char c0, char c1, char c2,
115
+ size_t* n0, size_t* n1, size_t* n2) {
116
+ size_t a = 0, b = 0, d = 0, i = 0;
117
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
118
+ uint8x16_t v = yep_neon_load(src + i);
119
+ vst1q_u8((uint8_t*)(void*)(dst + i), v);
120
+ a += (size_t)vaddvq_u8(vandq_u8(vceqq_u8(v, vdupq_n_u8((uint8_t)c0)), vdupq_n_u8(1)));
121
+ b += (size_t)vaddvq_u8(vandq_u8(vceqq_u8(v, vdupq_n_u8((uint8_t)c1)), vdupq_n_u8(1)));
122
+ d += (size_t)vaddvq_u8(vandq_u8(vceqq_u8(v, vdupq_n_u8((uint8_t)c2)), vdupq_n_u8(1)));
123
+ }
124
+ if (i < len) {
125
+ memcpy(dst + i, src + i, len - i);
126
+ }
127
+ size_t ta = 0, tb = 0, td = 0;
128
+ if (i < len) { /* NULL dst + 0 offset is still UB to form */
129
+ yep_text_count3_scalar(dst + i, len - i, c0, c1, c2, &ta, &tb, &td);
130
+ }
131
+ *n0 = a + ta;
132
+ *n1 = b + tb;
133
+ *n2 = d + td;
134
+ }
135
+
136
+ static ptrdiff_t yep_neon_find_not(const char* s, size_t len, char c) {
137
+ const uint8x16_t kc = vdupq_n_u8((uint8_t)c);
138
+ size_t i = 0;
139
+ /* 32 B per iteration (TODO.restructure/74): one shared constant,
140
+ * one bits-test per two vectors; the hit half re-tests alone */
141
+ for (; i + 2 * YEP_NEON_CHUNK <= len; i += 2 * YEP_NEON_CHUNK) {
142
+ uint8x16_t ne0 = vmvnq_u8(vceqq_u8(yep_neon_load(s + i), kc));
143
+ uint8x16_t ne1 = vmvnq_u8(vceqq_u8(yep_neon_load(s + i + 16), kc));
144
+ uint16_t m0 = yep_neon_bits(ne0);
145
+ uint16_t m1 = yep_neon_bits(ne1);
146
+ if (m0) {
147
+ return (ptrdiff_t)(i + (size_t)__builtin_ctz(m0));
148
+ }
149
+ if (m1) {
150
+ return (ptrdiff_t)(i + 16 + (size_t)__builtin_ctz(m1));
151
+ }
152
+ }
153
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
154
+ uint16_t m = yep_neon_bits(vmvnq_u8(yep_neon_eq(s + i, (uint8_t)c)));
155
+ if (m) {
156
+ return (ptrdiff_t)(i + (size_t)__builtin_ctz(m));
157
+ }
158
+ }
159
+ ptrdiff_t tail = yep_text_find_not_scalar(s + i, len - i, c);
160
+ return tail < 0 ? -1 : (ptrdiff_t)i + tail;
161
+ }
162
+
163
+ static ptrdiff_t yep_neon_find3(const char* s, size_t len, char c0, char c1, char c2) {
164
+ if (len < 3) {
165
+ return -1;
166
+ }
167
+ size_t i = 0;
168
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
169
+ uint16_t m = yep_neon_bits(yep_neon_eq(s + i, (uint8_t)c0));
170
+ while (m) {
171
+ size_t k = (size_t)__builtin_ctz(m);
172
+ size_t at = i + k;
173
+ if (at + 2 < len && s[at + 1] == c1 && s[at + 2] == c2) {
174
+ return (ptrdiff_t)at;
175
+ }
176
+ m = (uint16_t)(m & (m - 1));
177
+ }
178
+ }
179
+ ptrdiff_t tail = yep_text_find3_scalar(s + i, len - i, c0, c1, c2);
180
+ return tail < 0 ? -1 : (ptrdiff_t)i + tail;
181
+ }
182
+
183
+ static ptrdiff_t yep_neon_qbc_find(const char* s, size_t len) {
184
+ size_t i = 0;
185
+ for (; i + YEP_NEON_CHUNK <= len; i += YEP_NEON_CHUNK) {
186
+ uint8x16_t v = yep_neon_load(s + i);
187
+ uint8x16_t m =
188
+ vorrq_u8(vorrq_u8(vceqq_u8(v, vdupq_n_u8('"')), vceqq_u8(v, vdupq_n_u8('\\'))),
189
+ vcltq_u8(v, vdupq_n_u8(0x20)));
190
+ uint16_t bits = yep_neon_bits(m);
191
+ if (bits != 0) {
192
+ return (ptrdiff_t)(i + (size_t)__builtin_ctz((uint32_t)bits));
193
+ }
194
+ }
195
+ ptrdiff_t r = yep_text_qbc_find_scalar(s + i, len - i);
196
+ return r < 0 ? r : (ptrdiff_t)i + r;
197
+ }
198
+
199
+ static ptrdiff_t yep_neon_quote_scan(const char* s, size_t len, char q, int* has_escape) {
200
+ int esc = 0;
201
+ size_t i = 0;
202
+ while (i < len) {
203
+ int did_break = 0;
204
+ for (; i + YEP_NEON_CHUNK <= len;) {
205
+ uint16_t mq = yep_neon_bits(yep_neon_eq(s + i, (uint8_t)q));
206
+ uint16_t mb = 0;
207
+ if (q == '"') {
208
+ mb = yep_neon_bits(yep_neon_eq(s + i, (uint8_t)'\\'));
209
+ }
210
+ if (mq == 0 && mb == 0) {
211
+ i += YEP_NEON_CHUNK;
212
+ continue;
213
+ }
214
+ size_t kq = mq ? (size_t)__builtin_ctz(mq) : SIZE_MAX;
215
+ size_t kb = mb ? (size_t)__builtin_ctz(mb) : SIZE_MAX;
216
+ if (q == '"' && kb < kq) {
217
+ esc = 1;
218
+ i += kb + 2; /* skip the escaped byte */
219
+ did_break = 1;
220
+ break;
221
+ }
222
+ if (q == '\'' && i + kq + 1 < len && s[i + kq + 1] == '\'') {
223
+ esc = 1;
224
+ i += kq + 2; /* doubled quote inside a single-quoted scalar */
225
+ did_break = 1;
226
+ break;
227
+ }
228
+ if (has_escape != NULL) {
229
+ *has_escape = esc;
230
+ }
231
+ return (ptrdiff_t)(i + kq);
232
+ }
233
+ if (did_break) {
234
+ continue;
235
+ }
236
+ int tail_esc = 0;
237
+ ptrdiff_t r = yep_text_quote_scan_scalar(s + i, len - i, q, &tail_esc);
238
+ esc |= tail_esc;
239
+ if (r >= 0) {
240
+ if (has_escape != NULL) {
241
+ *has_escape = esc;
242
+ }
243
+ return (ptrdiff_t)i + r;
244
+ }
245
+ break;
246
+ }
247
+ if (has_escape != NULL) {
248
+ *has_escape = esc;
249
+ }
250
+ return -1;
251
+ }
252
+
253
+ static void yep_neon_scan_stats(const char* s, size_t len, yep_text_stats* out) {
254
+ if (s == NULL || len == 0) {
255
+ memset(out, 0, sizeof(*out));
256
+ return;
257
+ }
258
+
259
+ const uint8x16_t ktab = vdupq_n_u8('\n'), kcomma = vdupq_n_u8(','), kdash = vdupq_n_u8('-'),
260
+ kcolon = vdupq_n_u8(':'), kbrk = vdupq_n_u8('['), kbrce = vdupq_n_u8('{'),
261
+ kdq = vdupq_n_u8('"'), ksq = vdupq_n_u8('\''), kpipe = vdupq_n_u8('|'),
262
+ kamp = vdupq_n_u8('&');
263
+ const uint8x16_t k80 = vdupq_n_u8(0x80), ktab9 = vdupq_n_u8('\t'), klf = vdupq_n_u8('\n'),
264
+ kcr = vdupq_n_u8('\r'), kdel = vdupq_n_u8(0x7F), klow20 = vdupq_n_u8(0x20);
265
+ const uint8x16_t one = vdupq_n_u8(1);
266
+ /* vertical accumulation (leptris NEON lesson, its 0.19.x count_char):
267
+ * a per-chunk UADDV reduce serializes on the vector->GPR boundary —
268
+ * ten of them per chunk starved the loop. Pairwise-add-accumulate
269
+ * into u16 lanes, reduce once per batch. The u16 constraint is on
270
+ * the REDUCE, not just the lanes: vaddvq_u16 returns uint16_t, so
271
+ * the batch total must stay under 65536 — batches of 4095 chunks
272
+ * sum to at most 65520 (lane peak 8190). Presence flags fold the
273
+ * same way (OR is idempotent — one vmaxv at the end replaces the
274
+ * per-chunk ones). */
275
+ uint16x8_t a_nl = vdupq_n_u16(0), a_co = vdupq_n_u16(0), a_da = vdupq_n_u16(0),
276
+ a_cl = vdupq_n_u16(0), a_br = vdupq_n_u16(0), a_bc = vdupq_n_u16(0),
277
+ a_dq = vdupq_n_u16(0), a_sq = vdupq_n_u16(0), a_pi = vdupq_n_u16(0),
278
+ a_am = vdupq_n_u16(0);
279
+ uint8x16_t any_hi = vdupq_n_u8(0), any_bad = vdupq_n_u8(0);
280
+ size_t c_nl = 0, c_co = 0, c_da = 0, c_cl = 0, c_br = 0, c_bc = 0, c_dq = 0, c_sq = 0, c_pi = 0,
281
+ c_am = 0;
282
+ size_t i = 0;
283
+ #define YEP_STATS_DRAIN() \
284
+ do { \
285
+ c_nl += (size_t)vaddvq_u16(a_nl); \
286
+ a_nl = vdupq_n_u16(0); \
287
+ c_co += (size_t)vaddvq_u16(a_co); \
288
+ a_co = vdupq_n_u16(0); \
289
+ c_da += (size_t)vaddvq_u16(a_da); \
290
+ a_da = vdupq_n_u16(0); \
291
+ c_cl += (size_t)vaddvq_u16(a_cl); \
292
+ a_cl = vdupq_n_u16(0); \
293
+ c_br += (size_t)vaddvq_u16(a_br); \
294
+ a_br = vdupq_n_u16(0); \
295
+ c_bc += (size_t)vaddvq_u16(a_bc); \
296
+ a_bc = vdupq_n_u16(0); \
297
+ c_dq += (size_t)vaddvq_u16(a_dq); \
298
+ a_dq = vdupq_n_u16(0); \
299
+ c_sq += (size_t)vaddvq_u16(a_sq); \
300
+ a_sq = vdupq_n_u16(0); \
301
+ c_pi += (size_t)vaddvq_u16(a_pi); \
302
+ a_pi = vdupq_n_u16(0); \
303
+ c_am += (size_t)vaddvq_u16(a_am); \
304
+ a_am = vdupq_n_u16(0); \
305
+ } while (0)
306
+ while (i + 16 <= len) {
307
+ size_t end = i + 65504; /* 4095 inner chunks: reduce stays u16 */
308
+ if (end + 16 > len) {
309
+ end = len - 16; /* the last inner iteration starts here */
310
+ }
311
+ for (; i <= end; i += 16) {
312
+ uint8x16_t v = vld1q_u8((const uint8_t*)(const void*)(s + i));
313
+ any_hi = vorrq_u8(any_hi, vcgeq_u8(v, k80)); /* any non-ASCII byte */
314
+ a_nl = vpadalq_u8(a_nl, vandq_u8(vceqq_u8(v, ktab), one));
315
+ a_co = vpadalq_u8(a_co, vandq_u8(vceqq_u8(v, kcomma), one));
316
+ a_da = vpadalq_u8(a_da, vandq_u8(vceqq_u8(v, kdash), one));
317
+ a_cl = vpadalq_u8(a_cl, vandq_u8(vceqq_u8(v, kcolon), one));
318
+ a_br = vpadalq_u8(a_br, vandq_u8(vceqq_u8(v, kbrk), one));
319
+ a_bc = vpadalq_u8(a_bc, vandq_u8(vceqq_u8(v, kbrce), one));
320
+ a_dq = vpadalq_u8(a_dq, vandq_u8(vceqq_u8(v, kdq), one));
321
+ a_sq = vpadalq_u8(a_sq, vandq_u8(vceqq_u8(v, ksq), one));
322
+ a_pi = vpadalq_u8(a_pi, vandq_u8(vceqq_u8(v, kpipe), one));
323
+ a_am = vpadalq_u8(a_am, vandq_u8(vceqq_u8(v, kamp), one));
324
+ /* c-printable-ASCII violations, non-ASCII masked out:
325
+ * b < 0x20 except TAB/LF/CR, plus DEL */
326
+ uint8x16_t is_ascii = vcltzq_s8(vreinterpretq_s8_u8(veorq_u8(v, k80)));
327
+ uint8x16_t lo = vcltq_u8(v, klow20);
328
+ uint8x16_t allowed =
329
+ vorrq_u8(vceqq_u8(v, ktab9), vorrq_u8(vceqq_u8(v, klf), vceqq_u8(v, kcr)));
330
+ any_bad = vorrq_u8(
331
+ any_bad, vandq_u8(is_ascii, vorrq_u8(vbicq_u8(lo, allowed), vceqq_u8(v, kdel))));
332
+ }
333
+ if (i + 16 > len) {
334
+ break;
335
+ }
336
+ YEP_STATS_DRAIN();
337
+ }
338
+ YEP_STATS_DRAIN();
339
+ #undef YEP_STATS_DRAIN
340
+ yep_text_stats tail = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
341
+ yep_text_scan_stats_scalar(s + i, len - i, &tail);
342
+ out->nl = c_nl + tail.nl;
343
+ out->comma = c_co + tail.comma;
344
+ out->dash = c_da + tail.dash;
345
+ out->colon = c_cl + tail.colon;
346
+ out->bracket = c_br + tail.bracket;
347
+ out->brace = c_bc + tail.brace;
348
+ out->dq = c_dq + tail.dq;
349
+ out->sq = c_sq + tail.sq;
350
+ out->pipe = c_pi + tail.pipe;
351
+ out->amp = c_am + tail.amp;
352
+ out->nonascii = (vmaxvq_u8(any_hi) != 0) || tail.nonascii;
353
+ out->bad_printable = (vmaxvq_u8(any_bad) != 0) || tail.bad_printable;
354
+ }
355
+
356
+ static int yep_neon_gate_scan(const char* s, size_t len) {
357
+ const uint8x16_t sp = vdupq_n_u8(0x20), del = vdupq_n_u8(0x7F), hi = vdupq_n_u8(0x80);
358
+ const uint8x16_t tab = vdupq_n_u8(0x09), lf = vdupq_n_u8(0x0A), cr = vdupq_n_u8(0x0D);
359
+ size_t i = 0;
360
+ for (; i + 16 <= len; i += 16) {
361
+ uint8x16_t x = vld1q_u8((const uint8_t*)(s + i));
362
+ uint8x16_t ctrl = vcltq_u8(x, sp); /* C0 complete: 0x1F included */
363
+ uint8x16_t allow = vorrq_u8(vceqq_u8(x, tab), vorrq_u8(vceqq_u8(x, lf), vceqq_u8(x, cr)));
364
+ uint8x16_t nonascii = vcgeq_u8(x, hi);
365
+ uint8x16_t bad = vorrq_u8(vorrq_u8(vbicq_u8(ctrl, allow), nonascii), vceqq_u8(x, del));
366
+ if (vmaxvq_u32(vreinterpretq_u32_u8(bad)) != 0) {
367
+ return 1;
368
+ }
369
+ }
370
+ return yep_text_gate_scan_scalar(s + i, len - i);
371
+ }
372
+
373
+ /* First member byte via two tbl lookups per nibble-class group
374
+ * (TODO.restructure/68): lane matches iff lo[b&15] & hi[b>>4] != 0 —
375
+ * exact for the whole class, so the first nonzero lane IS the answer.
376
+ * The hit chunk spills one 16-byte vector and scans it scalar (a span
377
+ * hits once, at its end). */
378
+ static ptrdiff_t yep_neon_stopset_find(const yep_stopset* ss, const char* s, size_t len) {
379
+ /* two loaded groups is the sweet spot (every YAML stop class is
380
+ * 1-2); wider classes take the scalar bitmap walk */
381
+ if (ss->groups == 0 || ss->groups > 2) {
382
+ return yep_text_stopset_find_scalar(ss, s, len);
383
+ }
384
+ const uint8x16_t tlo0 = vld1q_u8(ss->lo[0]), thi0 = vld1q_u8(ss->hi[0]);
385
+ const uint8x16_t tlo1 = vld1q_u8(ss->lo[1]), thi1 = vld1q_u8(ss->hi[1]);
386
+ const uint8x16_t f = vdupq_n_u8(15);
387
+ const int two = ss->groups > 1;
388
+ size_t i = 0;
389
+ /* 32 B per iteration (TODO.restructure/74): the tbl work for both
390
+ * vectors interleaves while their loads stream; one vmaxv covers
391
+ * both halves — the hit half spills alone */
392
+ for (; i + 32 <= len; i += 32) {
393
+ uint8x16_t v0 = vld1q_u8((const uint8_t*)(const void*)(s + i));
394
+ uint8x16_t v1 = vld1q_u8((const uint8_t*)(const void*)(s + i + 16));
395
+ uint8x16_t m0 =
396
+ vandq_u8(vqtbl1q_u8(tlo0, vandq_u8(v0, f)), vqtbl1q_u8(thi0, vshrq_n_u8(v0, 4)));
397
+ uint8x16_t m1 =
398
+ vandq_u8(vqtbl1q_u8(tlo0, vandq_u8(v1, f)), vqtbl1q_u8(thi0, vshrq_n_u8(v1, 4)));
399
+ if (two) {
400
+ m0 = vorrq_u8(m0, vandq_u8(vqtbl1q_u8(tlo1, vandq_u8(v0, f)),
401
+ vqtbl1q_u8(thi1, vshrq_n_u8(v0, 4))));
402
+ m1 = vorrq_u8(m1, vandq_u8(vqtbl1q_u8(tlo1, vandq_u8(v1, f)),
403
+ vqtbl1q_u8(thi1, vshrq_n_u8(v1, 4))));
404
+ }
405
+ uint8x16_t many = vorrq_u8(m0, m1);
406
+ if (vmaxvq_u8(many) != 0) {
407
+ unsigned char hit[16] __attribute__((aligned(16)));
408
+ if (vmaxvq_u8(m0) != 0) {
409
+ vst1q_u8(hit, m0);
410
+ for (int k = 0; k < 16; k++) {
411
+ if (hit[k] != 0) {
412
+ return (ptrdiff_t)(i + (size_t)k);
413
+ }
414
+ }
415
+ }
416
+ vst1q_u8(hit, m1);
417
+ for (int k = 0; k < 16; k++) {
418
+ if (hit[k] != 0) {
419
+ return (ptrdiff_t)(i + 16 + (size_t)k);
420
+ }
421
+ }
422
+ }
423
+ }
424
+ for (; i + 16 <= len; i += 16) {
425
+ uint8x16_t v = vld1q_u8((const uint8_t*)(const void*)(s + i));
426
+ uint8x16_t lo = vandq_u8(v, f), hi = vshrq_n_u8(v, 4);
427
+ uint8x16_t m = vandq_u8(vqtbl1q_u8(tlo0, lo), vqtbl1q_u8(thi0, hi));
428
+ if (two) {
429
+ m = vorrq_u8(m, vandq_u8(vqtbl1q_u8(tlo1, lo), vqtbl1q_u8(thi1, hi)));
430
+ }
431
+ if (vmaxvq_u8(m) != 0) {
432
+ unsigned char hit[16] __attribute__((aligned(16)));
433
+ vst1q_u8(hit, m);
434
+ for (int k = 0; k < 16; k++) {
435
+ if (hit[k] != 0) {
436
+ return (ptrdiff_t)(i + (size_t)k);
437
+ }
438
+ }
439
+ }
440
+ }
441
+ ptrdiff_t tail = yep_text_stopset_find_scalar(ss, s + i, len - i);
442
+ return tail < 0 ? -1 : (ptrdiff_t)i + tail;
443
+ }
444
+
445
+ /* The fused line-facts sweep (TODO.restructure/76): one pass over the
446
+ * line's chunks produces break/non-space/stop masks; a chunk spills
447
+ * only when it carries a still-missing fact (usually chunk 0 carries
448
+ * all three). Any fact the vector loop cannot land falls to one exact
449
+ * scalar sweep of the whole span — rare (long lines whose break sits
450
+ * in the tail) and always correct. */
451
+ static void yep_neon_line_facts(const char* s, size_t len, size_t pos, yep_line_facts* out) {
452
+ /* The SWAR walk is BOTH the short-line test and the short-line
453
+ * answer: a break inside 64 bytes settles the facts there — the
454
+ * previous shape paid a 32-byte byte probe and then rescanned the
455
+ * whole line (the double scan was the dominant short-line cost).
456
+ * 76 measured the vector sweep 2x slower at 16-32 byte lines; 84
457
+ * pinned the gate at the LINE, not the remaining buffer. */
458
+ if (yep_text_line_facts_capped(s, len, pos, 128, out)) {
459
+ return;
460
+ }
461
+ const uint8x16_t ksp = vdupq_n_u8(' '), knl = vdupq_n_u8('\n'), kcr = vdupq_n_u8('\r'),
462
+ kco = vdupq_n_u8(':'), khash = vdupq_n_u8('#');
463
+ size_t i = pos;
464
+ int have_end = 0, have_indent = 0, have_stop = 0;
465
+ uint32_t end = 0, indent = 0, stop = 0;
466
+ for (; i + 16 <= len; i += 16) {
467
+ if (have_end) {
468
+ break; /* indent <= end, stop < end: settled or absent */
469
+ }
470
+ uint8x16_t v = vld1q_u8((const uint8_t*)(const void*)(s + i));
471
+ uint8x16_t br = vorrq_u8(vceqq_u8(v, knl), vceqq_u8(v, kcr));
472
+ int br_any = (int)vmaxvq_u8(br);
473
+ if (!have_indent) {
474
+ if (vmaxvq_u8(vmvnq_u8(vceqq_u8(v, ksp))) != 0) {
475
+ for (int k = 0; k < 16; k++) {
476
+ if (s[i + k] != ' ') { /* extract from source: no spill */
477
+ indent = (uint32_t)(i + (size_t)k);
478
+ have_indent = 1;
479
+ break;
480
+ }
481
+ }
482
+ }
483
+ }
484
+ if (br_any) {
485
+ for (int k = 0; k < 16; k++) {
486
+ if (s[i + k] == '\n' || s[i + k] == '\r') {
487
+ end = (uint32_t)(i + (size_t)k);
488
+ have_end = 1;
489
+ break;
490
+ }
491
+ }
492
+ }
493
+ if (!have_stop && have_indent) {
494
+ uint8x16_t st = vorrq_u8(br, vorrq_u8(vceqq_u8(v, kco), vceqq_u8(v, khash)));
495
+ if (vmaxvq_u8(st) != 0) {
496
+ size_t from = indent > i ? (size_t)(indent - i) : 0;
497
+ size_t lim = 16;
498
+ if (have_end && end < (uint32_t)(i + 16)) {
499
+ lim = (size_t)(end - i); /* stop is strictly before end */
500
+ }
501
+ for (size_t k = from; k < lim; k++) {
502
+ char c = s[i + k];
503
+ if (c == '\n' || c == '\r' || c == '#' || c == ':') {
504
+ stop = (uint32_t)(i + k);
505
+ have_stop = 1;
506
+ break;
507
+ }
508
+ }
509
+ }
510
+ }
511
+ }
512
+ uint32_t stop_set = 0;
513
+ if (!have_end || !have_indent || !have_stop) {
514
+ /* continuation from the chunk cursor (a 17-31 byte line runs
515
+ * one vector chunk then at most 15 scalar bytes; a stop in
516
+ * [indent, i) cannot exist when have_stop is still 0 — that
517
+ * chunk's set-probe was zero) */
518
+ yep_line_facts t;
519
+ yep_text_line_facts_scalar(s, len, i, &t);
520
+ if (!have_end) {
521
+ end = t.end;
522
+ }
523
+ if (!have_indent) {
524
+ indent = t.indent;
525
+ }
526
+ if (!have_stop) {
527
+ if (have_end) {
528
+ stop = end; /* end settled: no stop existed before it */
529
+ stop_set = 0;
530
+ } else {
531
+ stop = t.stop;
532
+ stop_set = t.stop_set;
533
+ }
534
+ }
535
+ }
536
+ out->end = end;
537
+ out->indent = indent;
538
+ out->stop = stop;
539
+ out->stop_set = have_stop ? 1u : stop_set;
540
+ }
541
+
542
+ /* The flow-kernel chunk classifier: two 16-byte halves -> four
543
+ * byte-class masks. Chunks are exactly 32 bytes except the final
544
+ * partial one, which the scalar reference settles (the contract reads
545
+ * exactly n bytes; a vld1q on a tail would stride past the end). */
546
+ yep_chunk_masks yep_text_json_chunk_neon(const char* p, size_t n) {
547
+ if (n < 32) {
548
+ return yep_text_json_chunk_scalar(p, n);
549
+ }
550
+ yep_chunk_masks m = {0, 0, 0, 0, 0, 0xFFFFFFFFu};
551
+ const uint8x16_t dq = vdupq_n_u8('"'), dbs = vdupq_n_u8('\\');
552
+ const uint8x16_t c0t = vdupq_n_u8(0x20);
553
+ const uint8x16_t op = vdupq_n_u8('{'), cl = vdupq_n_u8('}');
554
+ const uint8x16_t ls = vdupq_n_u8('['), rs = vdupq_n_u8(']');
555
+ const uint8x16_t cm = vdupq_n_u8(','), co = vdupq_n_u8(':');
556
+ const uint8x16_t d0 = vdupq_n_u8('0'), d9 = vdupq_n_u8('9');
557
+ const uint8x16_t da = vdupq_n_u8('-'), dt = vdupq_n_u8('t');
558
+ const uint8x16_t df = vdupq_n_u8('f'), dn = vdupq_n_u8('n');
559
+ for (unsigned half = 0; half < 2; half++) {
560
+ uint8x16_t v = vld1q_u8((const uint8_t*)(const void*)(p + 16 * half));
561
+ uint32_t q = yep_neon_bits(vceqq_u8(v, dq));
562
+ uint32_t b = yep_neon_bits(vceqq_u8(v, dbs));
563
+ uint32_t s = yep_neon_bits(vorrq_u8(vorrq_u8(vorrq_u8(vceqq_u8(v, op), vceqq_u8(v, cl)),
564
+ vorrq_u8(vceqq_u8(v, ls), vceqq_u8(v, rs))),
565
+ vorrq_u8(vceqq_u8(v, cm), vceqq_u8(v, co))));
566
+ uint32_t vs = yep_neon_bits(
567
+ vorrq_u8(vorrq_u8(vandq_u8(vcgeq_u8(v, d0), vcleq_u8(v, d9)), vceqq_u8(v, da)),
568
+ vorrq_u8(vorrq_u8(vceqq_u8(v, dt), vceqq_u8(v, df)), vceqq_u8(v, dn))));
569
+ uint32_t c = yep_neon_bits(vcltq_u8(v, c0t));
570
+ if (half) {
571
+ q <<= 16;
572
+ b <<= 16;
573
+ s <<= 16;
574
+ vs <<= 16;
575
+ c <<= 16;
576
+ }
577
+ m.quote |= q;
578
+ m.bs |= b;
579
+ m.structurals |= s;
580
+ m.valstart |= vs;
581
+ m.c0 |= c;
582
+ }
583
+ return m;
584
+ }
585
+
586
+ /* The JSON structural indexer (the token-contract front): vector
587
+ * classification of 64-byte blocks into QUOTE/BS/OP/WS u64 masks
588
+ * (four 16-byte halves each), then the shared mask resolver (the
589
+ * simdjson identity set, simd_text.h). The final partial block
590
+ * builds its masks byte-wise — no loads past len. */
591
+ int yep_text_json_stage1_neon(const char* p, size_t len, uint32_t* idx, size_t* nidx) {
592
+ size_t n = 0;
593
+ uint64_t prev_in_string = 0, esc_carry = 0, follows_carry = 0;
594
+ size_t off = 0;
595
+ const uint8x16_t dq = vdupq_n_u8('"'), dbs = vdupq_n_u8('\\');
596
+ const uint8x16_t d1 = vdupq_n_u8('{'), d2 = vdupq_n_u8('}');
597
+ const uint8x16_t d3 = vdupq_n_u8('['), d4 = vdupq_n_u8(']');
598
+ const uint8x16_t d5 = vdupq_n_u8(','), d6 = vdupq_n_u8(':');
599
+ const uint8x16_t wsp = vdupq_n_u8(' '), wtab = vdupq_n_u8('\t');
600
+ const uint8x16_t wnl = vdupq_n_u8('\n'), wcr = vdupq_n_u8('\r');
601
+ for (; off + 64 <= len; off += 64) {
602
+ uint64_t q = 0, bs = 0, op = 0, ws = 0;
603
+ for (unsigned half = 0; half < 4; half++) {
604
+ uint8x16_t v = vld1q_u8((const uint8_t*)(const void*)(p + off + 16 * half));
605
+ uint64_t fq = yep_neon_bits(vceqq_u8(v, dq));
606
+ uint64_t fb = yep_neon_bits(vceqq_u8(v, dbs));
607
+ uint64_t fo =
608
+ yep_neon_bits(vorrq_u8(vorrq_u8(vorrq_u8(vceqq_u8(v, d1), vceqq_u8(v, d2)),
609
+ vorrq_u8(vceqq_u8(v, d3), vceqq_u8(v, d4))),
610
+ vorrq_u8(vceqq_u8(v, d5), vceqq_u8(v, d6))));
611
+ uint64_t fw = yep_neon_bits(vorrq_u8(vorrq_u8(vceqq_u8(v, wsp), vceqq_u8(v, wtab)),
612
+ vorrq_u8(vceqq_u8(v, wnl), vceqq_u8(v, wcr))));
613
+ q |= fq << (16 * half);
614
+ bs |= fb << (16 * half);
615
+ op |= fo << (16 * half);
616
+ ws |= fw << (16 * half);
617
+ }
618
+ n = yep_json_stage1_resolve(q, bs, op, ws, ~0ull, &prev_in_string, &esc_carry,
619
+ &follows_carry, off, idx, n);
620
+ }
621
+ if (off < len) { /* the tail: byte-wise masks, no loads past len */
622
+ size_t cn = len - off;
623
+ uint64_t q = 0, bs = 0, op = 0, ws = 0;
624
+ for (size_t k = 0; k < cn; k++) {
625
+ unsigned char c = (unsigned char)p[off + k];
626
+ uint64_t bit = 1ull << k;
627
+ if (c == '"') {
628
+ q |= bit;
629
+ } else if (c == '\\') {
630
+ bs |= bit;
631
+ } else if (c == '{' || c == '}' || c == '[' || c == ']' || c == ',' || c == ':') {
632
+ op |= bit;
633
+ } else if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
634
+ ws |= bit;
635
+ }
636
+ }
637
+ n = yep_json_stage1_resolve(q, bs, op, ws, (1ull << cn) - 1ull, &prev_in_string, &esc_carry,
638
+ &follows_carry, off, idx, n);
639
+ }
640
+ *nidx = n;
641
+ return prev_in_string ? 0 : 1;
642
+ }
643
+
644
+ const yep_text_kernels yep_text_kernels_neon = {
645
+ yep_neon_contains,
646
+ yep_neon_find,
647
+ yep_neon_find3,
648
+ yep_neon_count,
649
+ yep_neon_count3,
650
+ yep_neon_copy_count3,
651
+ yep_neon_find_not,
652
+ yep_neon_stopset_find,
653
+ yep_neon_quote_scan,
654
+ yep_neon_scan_stats,
655
+ yep_neon_qbc_find,
656
+ yep_neon_gate_scan,
657
+ yep_neon_line_facts,
658
+ yep_text_json_chunk_neon,
659
+ yep_text_json_stage1_neon,
660
+ };
661
+
662
+ #endif /* YEP_ARCH_AARCH64 */