@scriptc/cli-darwin-arm64 0.2.3 → 0.2.5
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.
- package/dist/THIRD_PARTY_NOTICES +1 -1
- package/dist/bin/scriptc +0 -0
- package/dist/bin/scriptc.json +1 -1
- package/dist/lib/declarations/scriptc-node-fallback.d.ts +915 -215
- package/dist/lib/declarations/scriptc-overrides.d.ts +5 -1
- package/dist/lib/declarations/scriptc.d.ts +22 -2
- package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
- package/dist/lib/llvm/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/runtime-pack.json +213 -213
- package/dist/lib/runtime-sources/package.json +1 -1
- package/dist/lib/runtime-sources/src/scr_array.c +317 -40
- package/dist/lib/runtime-sources/src/scr_async.test.ts +16 -6
- package/dist/lib/runtime-sources/src/scr_bigint.c +15 -0
- package/dist/lib/runtime-sources/src/scr_bytes.c +437 -216
- package/dist/lib/runtime-sources/src/scr_bytes.test.c +85 -0
- package/dist/lib/runtime-sources/src/scr_bytes_io.c +0 -34
- package/dist/lib/runtime-sources/src/scr_copying.c +12 -2
- package/dist/lib/runtime-sources/src/scr_cycle.c +84 -60
- package/dist/lib/runtime-sources/src/scr_json.c +494 -161
- package/dist/lib/runtime-sources/src/scr_json.test.c +323 -1
- package/dist/lib/runtime-sources/src/scr_json.test.ts +58 -25
- package/dist/lib/runtime-sources/src/scr_key.h +68 -0
- package/dist/lib/runtime-sources/src/scr_lib.c +177 -89
- package/dist/lib/runtime-sources/src/scr_map.c +268 -96
- package/dist/lib/runtime-sources/src/scr_number.c +2 -4
- package/dist/lib/runtime-sources/src/scr_numeric.h +25 -0
- package/dist/lib/runtime-sources/src/scr_numeric.test.c +37 -0
- package/dist/lib/runtime-sources/src/scr_numeric.test.ts +33 -0
- package/dist/lib/runtime-sources/src/scr_regex.c +255 -145
- package/dist/lib/runtime-sources/src/scr_runtime.h +76 -19
- package/dist/lib/runtime-sources/src/scr_string.c +184 -42
- package/package.json +1 -1
|
@@ -72,6 +72,7 @@ typedef struct ScrSidx {
|
|
|
72
72
|
const ScrStr *s; /* NULL = empty slot */
|
|
73
73
|
size_t u16len; /* SCR_U16_UNKNOWN until the whole current string */
|
|
74
74
|
size_t cu, cb; /* hot cursor: cb starts the char at unit cu */
|
|
75
|
+
size_t ascii_cu, ascii_cb, ascii_end; /* bounded, proven identity span */
|
|
75
76
|
ScrSidxPoint *points; /* sparse, ordered code-point-boundary anchors */
|
|
76
77
|
size_t npoints, cap; /* owned points length/capacity */
|
|
77
78
|
size_t indexed_cu; /* exact contiguous prefix indexed from byte zero */
|
|
@@ -112,8 +113,13 @@ static void scr_sidx_register_cleanup(void) {
|
|
|
112
113
|
|
|
113
114
|
#ifdef SCR_SIDX_TEST
|
|
114
115
|
static SCR_TL size_t scr_sidx_walk_steps;
|
|
115
|
-
|
|
116
|
+
static SCR_TL size_t scr_sidx_searches;
|
|
117
|
+
void scr_sidx_test_reset_steps(void) {
|
|
118
|
+
scr_sidx_walk_steps = 0;
|
|
119
|
+
scr_sidx_searches = 0;
|
|
120
|
+
}
|
|
116
121
|
size_t scr_sidx_test_walk_steps(void) { return scr_sidx_walk_steps; }
|
|
122
|
+
size_t scr_sidx_test_searches(void) { return scr_sidx_searches; }
|
|
117
123
|
void scr_sidx_test_reset_cache(void) { scr_sidx_reset_all(); }
|
|
118
124
|
size_t scr_sidx_test_entries(void) {
|
|
119
125
|
size_t n = 0;
|
|
@@ -128,8 +134,10 @@ size_t scr_sidx_test_points(void) {
|
|
|
128
134
|
return n;
|
|
129
135
|
}
|
|
130
136
|
#define SCR_SIDX_STEP() (scr_sidx_walk_steps++)
|
|
137
|
+
#define SCR_SIDX_SEARCH() (scr_sidx_searches++)
|
|
131
138
|
#else
|
|
132
139
|
#define SCR_SIDX_STEP() ((void)0)
|
|
140
|
+
#define SCR_SIDX_SEARCH() ((void)0)
|
|
133
141
|
#endif
|
|
134
142
|
|
|
135
143
|
static void scr_sidx_purge(const ScrStr *s) {
|
|
@@ -271,6 +279,7 @@ ScrStr *scr_str_alloc_raw(size_t len, size_t cap) {
|
|
|
271
279
|
}
|
|
272
280
|
|
|
273
281
|
ScrStr *scr_str_regrow(ScrStr *s, size_t newcap) {
|
|
282
|
+
if (newcap < s->len || newcap > SIZE_MAX - sizeof(ScrStr) - 1) scr_oom();
|
|
274
283
|
scr_short_forget(s);
|
|
275
284
|
scr_sidx_purge(s); /* realloc may move; the old address may be recycled */
|
|
276
285
|
ScrStr *r = realloc(s, sizeof(ScrStr) + newcap + 1);
|
|
@@ -300,6 +309,8 @@ void scr_str_release(ScrStr *s) {
|
|
|
300
309
|
}
|
|
301
310
|
|
|
302
311
|
ScrStr *scr_str_concat(ScrStr *a, ScrStr *b) {
|
|
312
|
+
if (a->len == 0) return scr_str_retain(b);
|
|
313
|
+
if (b->len == 0) return scr_str_retain(a);
|
|
303
314
|
if (a->len > SIZE_MAX - b->len - sizeof(ScrStr) - 1) scr_oom();
|
|
304
315
|
size_t newlen = a->len + b->len;
|
|
305
316
|
/* In-place append: a is uniquely owned by the caller's borrow (rc == 1 —
|
|
@@ -343,6 +354,32 @@ ScrStr *scr_str_concat(ScrStr *a, ScrStr *b) {
|
|
|
343
354
|
return s;
|
|
344
355
|
}
|
|
345
356
|
|
|
357
|
+
ScrStr *scr_str_concat_parts(ScrStr *const *parts, size_t count) {
|
|
358
|
+
const size_t limit = SIZE_MAX - sizeof(ScrStr) - 1;
|
|
359
|
+
size_t len = 0;
|
|
360
|
+
ScrStr *only = NULL;
|
|
361
|
+
size_t nonempty = 0;
|
|
362
|
+
for (size_t i = 0; i < count; i++) {
|
|
363
|
+
const size_t n = parts[i]->len;
|
|
364
|
+
if (n > limit - len) scr_oom();
|
|
365
|
+
len += n;
|
|
366
|
+
if (n != 0) {
|
|
367
|
+
only = parts[i];
|
|
368
|
+
nonempty++;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (nonempty == 1) return scr_str_retain(only);
|
|
372
|
+
ScrStr *out = scr_str_alloc_raw(len, len);
|
|
373
|
+
size_t offset = 0;
|
|
374
|
+
for (size_t i = 0; i < count; i++) {
|
|
375
|
+
const ScrStr *part = parts[i];
|
|
376
|
+
memcpy(out->data + offset, part->data, part->len);
|
|
377
|
+
offset += part->len;
|
|
378
|
+
}
|
|
379
|
+
out->data[len] = '\0';
|
|
380
|
+
return out;
|
|
381
|
+
}
|
|
382
|
+
|
|
346
383
|
bool scr_str_eq(ScrStr *a, ScrStr *b) {
|
|
347
384
|
return a == b || (a->len == b->len && memcmp(a->data, b->data, a->len) == 0);
|
|
348
385
|
}
|
|
@@ -750,9 +787,14 @@ static size_t scr_sidx_abs_diff(size_t a, size_t b) {
|
|
|
750
787
|
* sufficient; the hot cursor retains sequential-access locality. */
|
|
751
788
|
static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
|
|
752
789
|
size_t u16) {
|
|
790
|
+
/* A nearby cursor already bounds the walk. Searching the complete index
|
|
791
|
+
* first would make each sequential read depend on the receiver's size. */
|
|
792
|
+
if (e->cb <= s->len && scr_sidx_abs_diff(e->cu, u16) <= 16)
|
|
793
|
+
return (ScrSidxPoint){e->cu, e->cb};
|
|
753
794
|
ScrSidxPoint best = {0, 0};
|
|
754
795
|
size_t best_dist = u16;
|
|
755
796
|
if (e->npoints != 0) {
|
|
797
|
+
SCR_SIDX_SEARCH();
|
|
756
798
|
size_t lo = 0, hi = e->npoints;
|
|
757
799
|
while (lo < hi) {
|
|
758
800
|
size_t m = lo + (hi - lo) / 2;
|
|
@@ -783,9 +825,12 @@ static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
|
|
|
783
825
|
|
|
784
826
|
static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
|
|
785
827
|
size_t byte_off) {
|
|
828
|
+
if (e->cb <= s->len && scr_sidx_abs_diff(e->cb, byte_off) <= 16)
|
|
829
|
+
return (ScrSidxPoint){e->cu, e->cb};
|
|
786
830
|
ScrSidxPoint best = {0, 0};
|
|
787
831
|
size_t best_dist = byte_off;
|
|
788
832
|
if (e->npoints != 0) {
|
|
833
|
+
SCR_SIDX_SEARCH();
|
|
789
834
|
size_t lo = 0, hi = e->npoints;
|
|
790
835
|
while (lo < hi) {
|
|
791
836
|
size_t m = lo + (hi - lo) / 2;
|
|
@@ -814,6 +859,36 @@ static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
|
|
|
814
859
|
return best;
|
|
815
860
|
}
|
|
816
861
|
|
|
862
|
+
/* Cache only a bounded ASCII run at a resolved boundary. Local scans then
|
|
863
|
+
* use arithmetic even inside a mixed string. The bytes are immutable except
|
|
864
|
+
* for append, which preserves this prefix; eviction/reallocation clears the
|
|
865
|
+
* whole entry. No scan reads outside the receiver or allocates metadata. */
|
|
866
|
+
static void scr_sidx_ascii_run(const ScrStr *s, ScrSidx *e) {
|
|
867
|
+
size_t start = e->cb, end = start;
|
|
868
|
+
/* Center the window on the access so reverse scans reuse it too. A
|
|
869
|
+
* forward-only window would rescan its full width on every backward read. */
|
|
870
|
+
size_t lower = start < 128 ? 0 : start - 128;
|
|
871
|
+
while (start - lower >= 8) {
|
|
872
|
+
uint64_t word;
|
|
873
|
+
memcpy(&word, s->data + start - 8, 8);
|
|
874
|
+
if (word & UINT64_C(0x8080808080808080)) break;
|
|
875
|
+
start -= 8;
|
|
876
|
+
}
|
|
877
|
+
while (start > lower && (unsigned char)s->data[start - 1] < 0x80) start--;
|
|
878
|
+
size_t remaining = s->len - end;
|
|
879
|
+
size_t limit = end + (remaining < 128 ? remaining : 128);
|
|
880
|
+
while (limit - end >= 8) {
|
|
881
|
+
uint64_t word;
|
|
882
|
+
memcpy(&word, s->data + end, 8);
|
|
883
|
+
if (word & UINT64_C(0x8080808080808080)) break;
|
|
884
|
+
end += 8;
|
|
885
|
+
}
|
|
886
|
+
while (end < limit && (unsigned char)s->data[end] < 0x80) end++;
|
|
887
|
+
e->ascii_cu = e->cu - (e->cb - start);
|
|
888
|
+
e->ascii_cb = start;
|
|
889
|
+
e->ascii_end = end;
|
|
890
|
+
}
|
|
891
|
+
|
|
817
892
|
/* Convert a UTF-16 index to a byte offset from the closest sparse anchor or
|
|
818
893
|
* hot cursor. If u16 addresses the second (low-surrogate) unit of
|
|
819
894
|
* an astral char, *mid is set and the returned offset is the START of that
|
|
@@ -825,6 +900,12 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
825
900
|
*mid = false;
|
|
826
901
|
return u16 < s->len ? u16 : s->len;
|
|
827
902
|
}
|
|
903
|
+
if (u16 >= e->ascii_cu && u16 - e->ascii_cu < e->ascii_end - e->ascii_cb) {
|
|
904
|
+
e->cb = e->ascii_cb + (u16 - e->ascii_cu);
|
|
905
|
+
e->cu = u16;
|
|
906
|
+
*mid = false;
|
|
907
|
+
return e->cb;
|
|
908
|
+
}
|
|
828
909
|
scr_sidx_extend_to_u16(s, e, u16);
|
|
829
910
|
/* Extending a far-end lookup can just have proved identity. Do not
|
|
830
911
|
* materialize an index that the identity fast path will never consult. */
|
|
@@ -835,9 +916,31 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
835
916
|
scr_sidx_materialize_identity_prefix(s, e);
|
|
836
917
|
ScrSidxPoint near = scr_sidx_near_u16(s, e, u16);
|
|
837
918
|
size_t cu = near.cu, cb = near.cb;
|
|
838
|
-
while (cu > u16)
|
|
919
|
+
while (cu > u16) {
|
|
920
|
+
/* Eight bytes starting inside a sequence can reach back at most three
|
|
921
|
+
* more bytes to its lead. Such a span contains at most nine UTF-16
|
|
922
|
+
* units (seven ASCII bytes plus an astral pair), so it cannot overshoot
|
|
923
|
+
* a target at least nine units away. */
|
|
924
|
+
if (cu - u16 >= 9 && cb >= 8) {
|
|
925
|
+
size_t start = cb - 8;
|
|
926
|
+
while (start > 0 && ((unsigned char)s->data[start] & 0xC0) == 0x80)
|
|
927
|
+
start--;
|
|
928
|
+
cu -= scr_utf16_units_span(s->data + start, cb - start, NULL);
|
|
929
|
+
cb = start;
|
|
930
|
+
} else {
|
|
931
|
+
scr_sidx_back(s, &cu, &cb);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
839
934
|
bool m = false;
|
|
840
935
|
while (cu < u16 && cb < s->len) {
|
|
936
|
+
if (u16 - cu >= 9 && s->len - cb >= 8) {
|
|
937
|
+
size_t end = cb + 8;
|
|
938
|
+
while (end < s->len && ((unsigned char)s->data[end] & 0xC0) == 0x80)
|
|
939
|
+
end++;
|
|
940
|
+
cu += scr_utf16_units_span(s->data + cb, end - cb, NULL);
|
|
941
|
+
cb = end;
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
841
944
|
SCR_SIDX_STEP();
|
|
842
945
|
size_t seq = scr_utf8_seq_len((unsigned char)s->data[cb]);
|
|
843
946
|
size_t w = seq == 4 ? 2 : 1;
|
|
@@ -850,6 +953,8 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
850
953
|
}
|
|
851
954
|
e->cu = cu;
|
|
852
955
|
e->cb = cb;
|
|
956
|
+
if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
|
|
957
|
+
scr_sidx_ascii_run(s, e);
|
|
853
958
|
*mid = m;
|
|
854
959
|
return cb;
|
|
855
960
|
}
|
|
@@ -859,6 +964,11 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
859
964
|
static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
|
|
860
965
|
size_t byte_off) {
|
|
861
966
|
if (e->u16len == s->len) return byte_off; /* all ASCII */
|
|
967
|
+
if (byte_off >= e->ascii_cb && byte_off < e->ascii_end) {
|
|
968
|
+
e->cu = e->ascii_cu + (byte_off - e->ascii_cb);
|
|
969
|
+
e->cb = byte_off;
|
|
970
|
+
return e->cu;
|
|
971
|
+
}
|
|
862
972
|
/* A byte search result may be far beyond the existing prefix. Build the
|
|
863
973
|
* same sparse intervals first, then choose the closest boundary anchor. */
|
|
864
974
|
if (byte_off > e->indexed_cb) {
|
|
@@ -871,15 +981,17 @@ static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
|
|
|
871
981
|
scr_sidx_materialize_identity_prefix(s, e);
|
|
872
982
|
ScrSidxPoint near = scr_sidx_near_byte(s, e, byte_off);
|
|
873
983
|
size_t cu = near.cu, cb = near.cb;
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
984
|
+
/* Unlike unit-to-byte conversion, both endpoints are already exact byte
|
|
985
|
+
* boundaries. Count the whole span with the shared word-wise classifier. */
|
|
986
|
+
if (cb > byte_off)
|
|
987
|
+
cu -= scr_utf16_units_span(s->data + byte_off, cb - byte_off, NULL);
|
|
988
|
+
else
|
|
989
|
+
cu += scr_utf16_units_span(s->data + cb, byte_off - cb, NULL);
|
|
990
|
+
cb = byte_off;
|
|
881
991
|
e->cu = cu;
|
|
882
992
|
e->cb = cb;
|
|
993
|
+
if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
|
|
994
|
+
scr_sidx_ascii_run(s, e);
|
|
883
995
|
return cu;
|
|
884
996
|
}
|
|
885
997
|
|
|
@@ -890,16 +1002,21 @@ static double scr_to_integer_or_infinity(double x) {
|
|
|
890
1002
|
return trunc(x);
|
|
891
1003
|
}
|
|
892
1004
|
|
|
893
|
-
/*
|
|
1005
|
+
/* Byte substring search (needle and hay are both well-formed UTF-8,
|
|
894
1006
|
* so any byte-level match starts on a char boundary — UTF-8 is
|
|
895
1007
|
* self-synchronizing). Empty needle matches at hay. */
|
|
896
1008
|
static const char *scr_byte_find(const char *hay, size_t hay_len,
|
|
897
1009
|
const char *nee, size_t nee_len) {
|
|
898
1010
|
if (nee_len == 0) return hay;
|
|
899
1011
|
if (nee_len > hay_len) return NULL;
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1012
|
+
if (nee_len == 1) return memchr(hay, (unsigned char)nee[0], hay_len);
|
|
1013
|
+
size_t remaining = hay_len - nee_len + 1;
|
|
1014
|
+
while (remaining) {
|
|
1015
|
+
const char *found = memchr(hay, (unsigned char)nee[0], remaining);
|
|
1016
|
+
if (!found) return NULL;
|
|
1017
|
+
if (memcmp(found + 1, nee + 1, nee_len - 1) == 0) return found;
|
|
1018
|
+
remaining -= (size_t)(found - hay) + 1;
|
|
1019
|
+
hay = found + 1;
|
|
903
1020
|
}
|
|
904
1021
|
return NULL;
|
|
905
1022
|
}
|
|
@@ -952,14 +1069,18 @@ double scr_str_char_code_at(ScrStr *s, double i) {
|
|
|
952
1069
|
|
|
953
1070
|
double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
|
|
954
1071
|
double pos = scr_to_integer_or_infinity(fromIndex);
|
|
1072
|
+
if (needle->len > s->len) return -1.0;
|
|
955
1073
|
ScrSidx *e = scr_sidx(s);
|
|
956
|
-
size_t len16 = scr_sidx_len(s, e);
|
|
957
|
-
size_t start16 = pos <= 0 ? 0
|
|
958
|
-
: pos >= (double)len16 ? len16
|
|
959
|
-
: (size_t)pos;
|
|
960
1074
|
/* Per spec, the empty needle is found at the clamped fromIndex itself —
|
|
961
1075
|
* even when that index is between the halves of an astral pair. */
|
|
962
|
-
if (needle->len == 0)
|
|
1076
|
+
if (needle->len == 0) {
|
|
1077
|
+
size_t len16 = scr_sidx_len(s, e);
|
|
1078
|
+
return pos <= 0 ? 0 : pos >= (double)len16 ? (double)len16 : pos;
|
|
1079
|
+
}
|
|
1080
|
+
/* Byte length bounds UTF-16 length and fences the cast. Let the mapper
|
|
1081
|
+
* extend only as far as needed instead of indexing an unsearched suffix. */
|
|
1082
|
+
if (pos >= (double)s->len) return -1.0;
|
|
1083
|
+
size_t start16 = pos <= 0 ? 0 : (size_t)pos;
|
|
963
1084
|
bool mid;
|
|
964
1085
|
size_t start_b = scr_u16_to_byte_c(s, e, start16, &mid);
|
|
965
1086
|
/* A match can't begin on a low-surrogate half (needles are well-formed),
|
|
@@ -972,11 +1093,11 @@ double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
|
|
|
972
1093
|
return (double)scr_byte_to_u16_c(s, e, (size_t)(found - s->data));
|
|
973
1094
|
}
|
|
974
1095
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
*
|
|
1096
|
+
static ScrStr *scr_str_slice_units(ScrStr *s, ScrSidx *e,
|
|
1097
|
+
size_t from, size_t to);
|
|
1098
|
+
|
|
1099
|
+
/* Normalize once, then share slice's extraction without another cache
|
|
1100
|
+
* lookup, length query or floating-point boundary conversion. */
|
|
980
1101
|
ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
|
|
981
1102
|
ScrSidx *e = scr_sidx(s);
|
|
982
1103
|
double len16 = (double)scr_sidx_len(s, e);
|
|
@@ -984,7 +1105,8 @@ ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
|
|
|
984
1105
|
double b = scr_to_integer_or_infinity(end);
|
|
985
1106
|
double fa = a < 0 ? 0 : a > len16 ? len16 : a;
|
|
986
1107
|
double fb = b < 0 ? 0 : b > len16 ? len16 : b;
|
|
987
|
-
return fa < fb ?
|
|
1108
|
+
return fa < fb ? scr_str_slice_units(s, e, (size_t)fa, (size_t)fb)
|
|
1109
|
+
: scr_str_slice_units(s, e, (size_t)fb, (size_t)fa);
|
|
988
1110
|
}
|
|
989
1111
|
|
|
990
1112
|
bool scr_str_includes(ScrStr *s, ScrStr *needle) {
|
|
@@ -1008,22 +1130,27 @@ static size_t scr_str_clamp_u16_position(double position, size_t len16) {
|
|
|
1008
1130
|
}
|
|
1009
1131
|
|
|
1010
1132
|
bool scr_str_starts_with_from(ScrStr *s, ScrStr *needle, double position) {
|
|
1011
|
-
ScrSidx *e = scr_sidx(s);
|
|
1012
|
-
size_t len16 = scr_sidx_len(s, e);
|
|
1013
|
-
size_t start16 = scr_str_clamp_u16_position(position, len16);
|
|
1014
1133
|
if (needle->len == 0) return true;
|
|
1134
|
+
double pos = scr_to_integer_or_infinity(position);
|
|
1135
|
+
if (pos <= 0) return scr_str_starts_with(s, needle);
|
|
1136
|
+
if (pos >= (double)s->len || needle->len > s->len) return false;
|
|
1137
|
+
ScrSidx *e = scr_sidx(s);
|
|
1015
1138
|
bool mid;
|
|
1016
|
-
size_t start_byte = scr_u16_to_byte_c(s, e,
|
|
1139
|
+
size_t start_byte = scr_u16_to_byte_c(s, e, (size_t)pos, &mid);
|
|
1017
1140
|
return !mid && needle->len <= s->len - start_byte &&
|
|
1018
1141
|
memcmp(s->data + start_byte, needle->data, needle->len) == 0;
|
|
1019
1142
|
}
|
|
1020
1143
|
|
|
1021
1144
|
bool scr_str_ends_with_from(ScrStr *s, ScrStr *needle, double end_position) {
|
|
1145
|
+
if (needle->len == 0) return true;
|
|
1146
|
+
if (needle->len > s->len) return false;
|
|
1147
|
+
if (end_position >= (double)s->len) return scr_str_ends_with(s, needle);
|
|
1148
|
+
/* A second receiver lookup can evict the first receiver's entry. Resolve
|
|
1149
|
+
* the needle before borrowing the haystack entry for both conversions. */
|
|
1150
|
+
size_t needle16 = scr_sidx_len(needle, scr_sidx(needle));
|
|
1022
1151
|
ScrSidx *e = scr_sidx(s);
|
|
1023
1152
|
size_t len16 = scr_sidx_len(s, e);
|
|
1024
1153
|
size_t end16 = scr_str_clamp_u16_position(end_position, len16);
|
|
1025
|
-
size_t needle16 = scr_sidx_len(needle, scr_sidx(needle));
|
|
1026
|
-
if (needle16 == 0) return true;
|
|
1027
1154
|
if (needle16 > end16) return false;
|
|
1028
1155
|
bool start_mid, end_mid;
|
|
1029
1156
|
size_t start_byte = scr_u16_to_byte_c(s, e, end16 - needle16, &start_mid);
|
|
@@ -1048,6 +1175,11 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
|
|
|
1048
1175
|
size_t len16 = scr_sidx_len(s, e);
|
|
1049
1176
|
size_t from = scr_slice_boundary(scr_to_integer_or_infinity(start), len16);
|
|
1050
1177
|
size_t to = scr_slice_boundary(scr_to_integer_or_infinity(end), len16);
|
|
1178
|
+
return scr_str_slice_units(s, e, from, to);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
static ScrStr *scr_str_slice_units(ScrStr *s, ScrSidx *e,
|
|
1182
|
+
size_t from, size_t to) {
|
|
1051
1183
|
if (from >= to) return scr_str_empty();
|
|
1052
1184
|
|
|
1053
1185
|
bool from_mid, to_mid;
|
|
@@ -1064,18 +1196,16 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
|
|
|
1064
1196
|
/* Divergence: JS would emit the lone surrogate half; we emit U+FFFD. */
|
|
1065
1197
|
size_t total = content_len + (from_mid ? SCR_REPLACEMENT_LEN : 0) +
|
|
1066
1198
|
(to_mid ? SCR_REPLACEMENT_LEN : 0);
|
|
1067
|
-
|
|
1068
|
-
if (!tmp) scr_oom();
|
|
1199
|
+
ScrStr *r = scr_str_alloc(total, total);
|
|
1069
1200
|
size_t o = 0;
|
|
1070
1201
|
if (from_mid) {
|
|
1071
|
-
memcpy(
|
|
1202
|
+
memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
|
|
1072
1203
|
o += SCR_REPLACEMENT_LEN;
|
|
1073
1204
|
}
|
|
1074
|
-
memcpy(
|
|
1205
|
+
memcpy(r->data + o, s->data + content_b, content_len);
|
|
1075
1206
|
o += content_len;
|
|
1076
|
-
if (to_mid) memcpy(
|
|
1077
|
-
|
|
1078
|
-
free(tmp);
|
|
1207
|
+
if (to_mid) memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
|
|
1208
|
+
r->data[total] = '\0';
|
|
1079
1209
|
return r;
|
|
1080
1210
|
}
|
|
1081
1211
|
|
|
@@ -1184,6 +1314,18 @@ ScrStr *scr_str_trim_end(ScrStr *s) {
|
|
|
1184
1314
|
static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
|
|
1185
1315
|
scr_lit_fffd = {SIZE_MAX, 3, 3, "\xEF\xBF\xBD"};
|
|
1186
1316
|
|
|
1317
|
+
/* Split owns a fresh array and appends only present string values. Fill an
|
|
1318
|
+
* available dense slot directly; ordinary push handles growth and the sparse
|
|
1319
|
+
* boundary. The array remains valid after every append, including RC audit. */
|
|
1320
|
+
static void scr_str_split_append(ScrArr *out, ScrStr *value) {
|
|
1321
|
+
if (out->len < out->cap) {
|
|
1322
|
+
out->data[out->len] = (uint64_t)(uintptr_t)value;
|
|
1323
|
+
out->present[out->len++] = SCR_ARR_VALUE;
|
|
1324
|
+
} else {
|
|
1325
|
+
scr_arr_push_ref(out, value);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1187
1329
|
/* split(separator, limit) with a STRING separator (ECMA-262 22.1.3.23):
|
|
1188
1330
|
* limit is ToUint32'd; zero returns [] and reaching the limit stops before
|
|
1189
1331
|
* any later separator probes. The no-limit wrapper supplies 2^32-1.
|
|
@@ -1206,11 +1348,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
|
|
|
1206
1348
|
size_t adv;
|
|
1207
1349
|
uint32_t cp = scr_utf8_decode(s->data + i, &adv);
|
|
1208
1350
|
if (cp >= 0x10000) { /* two units in JS: both halves become U+FFFD */
|
|
1209
|
-
|
|
1351
|
+
scr_str_split_append(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
|
|
1210
1352
|
if (out->len == limit) return out;
|
|
1211
|
-
|
|
1353
|
+
scr_str_split_append(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
|
|
1212
1354
|
} else {
|
|
1213
|
-
|
|
1355
|
+
scr_str_split_append(out, scr_str_from_span(s->data + i, adv));
|
|
1214
1356
|
}
|
|
1215
1357
|
if (out->len == limit) return out;
|
|
1216
1358
|
i += adv;
|
|
@@ -1223,11 +1365,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
|
|
|
1223
1365
|
sep->data, sep->len);
|
|
1224
1366
|
if (!found) break;
|
|
1225
1367
|
size_t at = (size_t)(found - s->data);
|
|
1226
|
-
|
|
1368
|
+
scr_str_split_append(out, scr_str_from_span(s->data + start, at - start));
|
|
1227
1369
|
if (out->len == limit) return out;
|
|
1228
1370
|
start = at + sep->len;
|
|
1229
1371
|
}
|
|
1230
|
-
|
|
1372
|
+
scr_str_split_append(out, scr_str_from_span(s->data + start, s->len - start));
|
|
1231
1373
|
return out;
|
|
1232
1374
|
}
|
|
1233
1375
|
|