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.
- checksums.yaml +7 -0
- data/README.adoc +141 -0
- data/ext/build_windows_native.rb +41 -0
- data/ext/libyeptris/extconf.rb +57 -0
- data/ext/yeptris_native/cbor_ruby.c +193 -0
- data/ext/yeptris_native/extconf.rb +47 -0
- data/ext/yeptris_native/json_ruby.c +354 -0
- data/ext/yeptris_native/yeptris_native.c +497 -0
- data/lib/yeptris/cbor.rb +130 -0
- data/lib/yeptris/document.rb +255 -0
- data/lib/yeptris/ffi.rb +426 -0
- data/lib/yeptris/json/descriptor.rb +266 -0
- data/lib/yeptris/json.rb +394 -0
- data/lib/yeptris/materializer.rb +354 -0
- data/lib/yeptris/native-3.4.so +0 -0
- data/lib/yeptris/node.rb +453 -0
- data/lib/yeptris/psych/class_loader.rb +24 -0
- data/lib/yeptris/psych/coder_shim.rb +55 -0
- data/lib/yeptris/psych/drop_in.rb +63 -0
- data/lib/yeptris/psych/encodable.rb +14 -0
- data/lib/yeptris/psych/handler.rb +90 -0
- data/lib/yeptris/psych/parser.rb +105 -0
- data/lib/yeptris/psych/scalar_scanner.rb +149 -0
- data/lib/yeptris/psych/visitors.rb +545 -0
- data/lib/yeptris/psych.rb +622 -0
- data/lib/yeptris/schema.rb +253 -0
- data/lib/yeptris/valueml.rb +455 -0
- data/lib/yeptris/yaml/descriptor.rb +56 -0
- data/lib/yeptris/yaml.rb +422 -0
- data/lib/yeptris.rb +113 -0
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +254 -0
- data/vendor/libyeptris/cmake/yeptris-config.cmake.in +5 -0
- data/vendor/libyeptris/cmake/yeptris.pc.in +11 -0
- data/vendor/libyeptris/src/CMakeLists.txt +167 -0
- data/vendor/libyeptris/src/include/yeptris/api.h +32 -0
- data/vendor/libyeptris/src/include/yeptris/cbor.h +101 -0
- data/vendor/libyeptris/src/include/yeptris/dom.h +190 -0
- data/vendor/libyeptris/src/include/yeptris/emit.h +81 -0
- data/vendor/libyeptris/src/include/yeptris/error.h +41 -0
- data/vendor/libyeptris/src/include/yeptris/events.h +157 -0
- data/vendor/libyeptris/src/include/yeptris/json.h +45 -0
- data/vendor/libyeptris/src/include/yeptris/json.hpp +258 -0
- data/vendor/libyeptris/src/include/yeptris/jsonc_compat.h +115 -0
- data/vendor/libyeptris/src/include/yeptris/marshal.h +52 -0
- data/vendor/libyeptris/src/include/yeptris/parse.h +48 -0
- data/vendor/libyeptris/src/include/yeptris/plan.h +100 -0
- data/vendor/libyeptris/src/include/yeptris/resolve.h +71 -0
- data/vendor/libyeptris/src/include/yeptris/schema.h +121 -0
- data/vendor/libyeptris/src/include/yeptris/tape.h +123 -0
- data/vendor/libyeptris/src/include/yeptris/types.h +38 -0
- data/vendor/libyeptris/src/include/yeptris/values.h +102 -0
- data/vendor/libyeptris/src/include/yeptris/version.h.in +29 -0
- data/vendor/libyeptris/src/include/yeptris/visit.h +77 -0
- data/vendor/libyeptris/src/include/yeptris/yajl_compat.h +135 -0
- data/vendor/libyeptris/src/include/yeptris.h +23 -0
- data/vendor/libyeptris/src/yeptris/build.c +376 -0
- data/vendor/libyeptris/src/yeptris/cbor/cbor.h +25 -0
- data/vendor/libyeptris/src/yeptris/cbor/decode.c +981 -0
- data/vendor/libyeptris/src/yeptris/cbor/encode.c +835 -0
- data/vendor/libyeptris/src/yeptris/cbor/sink.h +58 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.c +41 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.h +77 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.c +81 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.h +40 -0
- data/vendor/libyeptris/src/yeptris/common/error.c +65 -0
- data/vendor/libyeptris/src/yeptris/common/error.h +79 -0
- data/vendor/libyeptris/src/yeptris/common/mutex.h +45 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.c +275 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.h +68 -0
- data/vendor/libyeptris/src/yeptris/common/port.h +74 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.c +49 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.h +295 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +534 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +662 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +298 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.c +34 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.h +93 -0
- data/vendor/libyeptris/src/yeptris/doc.h +56 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +1192 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.h +312 -0
- data/vendor/libyeptris/src/yeptris/dom/hpool.c +107 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.c +173 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.h +61 -0
- data/vendor/libyeptris/src/yeptris/dom/mutate.c +431 -0
- data/vendor/libyeptris/src/yeptris/emit/emit.c +434 -0
- data/vendor/libyeptris/src/yeptris/emit/float/api.h +38 -0
- data/vendor/libyeptris/src/yeptris/emit/float/dragon.c +405 -0
- data/vendor/libyeptris/src/yeptris/emit/float/floatint.h +231 -0
- data/vendor/libyeptris/src/yeptris/emit/float/print.c +396 -0
- data/vendor/libyeptris/src/yeptris/emit/style.c +81 -0
- data/vendor/libyeptris/src/yeptris/emit/style.h +24 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +816 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.h +76 -0
- data/vendor/libyeptris/src/yeptris/encoding/bom.c +31 -0
- data/vendor/libyeptris/src/yeptris/encoding/encoding.h +63 -0
- data/vendor/libyeptris/src/yeptris/encoding/transcode.c +148 -0
- data/vendor/libyeptris/src/yeptris/encoding/utf8_validate.c +178 -0
- data/vendor/libyeptris/src/yeptris/events/capture.c +150 -0
- data/vendor/libyeptris/src/yeptris/events/capture.h +39 -0
- data/vendor/libyeptris/src/yeptris/events/iterparse.c +208 -0
- data/vendor/libyeptris/src/yeptris/events/pull.c +97 -0
- data/vendor/libyeptris/src/yeptris/events/push.c +104 -0
- data/vendor/libyeptris/src/yeptris/events/recorder.c +107 -0
- data/vendor/libyeptris/src/yeptris/events/values.c +527 -0
- data/vendor/libyeptris/src/yeptris/events/values_priv.h +51 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.c +86 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.h +90 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/jsonc_compat.c +687 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/yajl_compat.c +728 -0
- data/vendor/libyeptris/src/yeptris/marshal.c +782 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.c +20 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.h +43 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.c +134 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.h +52 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.c +122 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.h +36 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.c +3698 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.h +65 -0
- data/vendor/libyeptris/src/yeptris/parse/events.h +124 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.c +349 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.h +33 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.c +416 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.h +75 -0
- data/vendor/libyeptris/src/yeptris/parse.c +737 -0
- data/vendor/libyeptris/src/yeptris/plan.c +824 -0
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +334 -0
- data/vendor/libyeptris/src/yeptris/resolve/core12.c +143 -0
- data/vendor/libyeptris/src/yeptris/resolve/resolver.h +56 -0
- data/vendor/libyeptris/src/yeptris/resolve/tags.c +58 -0
- data/vendor/libyeptris/src/yeptris/scan/json.c +792 -0
- data/vendor/libyeptris/src/yeptris/scan/json.h +109 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +463 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.h +150 -0
- data/vendor/libyeptris/src/yeptris/schema.c +308 -0
- data/vendor/libyeptris/src/yeptris/tape.c +1308 -0
- data/vendor/libyeptris/src/yeptris/tape_in.h +19 -0
- data/vendor/libyeptris/src/yeptris/version.c +7 -0
- data/vendor/libyeptris/src/yeptris/visit/dom_visit.c +115 -0
- data/vendor/libyeptris/src/yeptris/visit/json_visit.c +293 -0
- data/vendor/libyeptris/src/yeptris/visit/yaml_visit.c +127 -0
- 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 */
|