@scriptc/cli-darwin-arm64 0.2.4 → 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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 +181 -181
- package/dist/lib/runtime-sources/package.json +1 -1
- package/dist/lib/runtime-sources/src/scr_array.c +267 -6
- package/dist/lib/runtime-sources/src/scr_async.test.ts +16 -6
- 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_json.c +479 -150
- 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 +132 -73
- package/dist/lib/runtime-sources/src/scr_map.c +50 -66
- 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 +238 -167
- package/dist/lib/runtime-sources/src/scr_runtime.h +37 -6
- package/dist/lib/runtime-sources/src/scr_string.c +155 -42
- package/package.json +1 -1
|
@@ -1032,7 +1032,7 @@ typedef struct ScrArr {
|
|
|
1032
1032
|
void (*elem_release)(void *);
|
|
1033
1033
|
ScrTraceFn elem_trace;
|
|
1034
1034
|
uint64_t *data;
|
|
1035
|
-
uint8_t *present; /* one
|
|
1035
|
+
uint8_t *present; /* one state per dense slot; heap arrays share data allocation */
|
|
1036
1036
|
struct ScrArrSparseSlot *sparse;
|
|
1037
1037
|
size_t sparse_len;
|
|
1038
1038
|
size_t sparse_cap;
|
|
@@ -1111,6 +1111,13 @@ void scr_arr_copy_range(ScrArr *dst, size_t dst_start, const ScrArr *src,
|
|
|
1111
1111
|
void scr_arr_copy_range_ex(ScrArr *dst, size_t dst_start, const ScrArr *src,
|
|
1112
1112
|
size_t src_start, size_t count, bool reverse,
|
|
1113
1113
|
bool materialize_holes);
|
|
1114
|
+
/* Mutating indexed operations borrow the receiver and value, preserve
|
|
1115
|
+
* sparse presence, and return the receiver retained. */
|
|
1116
|
+
ScrArr *scr_arr_copy_within(ScrArr *a, double target, double start, double end);
|
|
1117
|
+
ScrArr *scr_arr_fill_f64(ScrArr *a, double value, double start, double end);
|
|
1118
|
+
ScrArr *scr_arr_fill_bool(ScrArr *a, bool value, double start, double end);
|
|
1119
|
+
ScrArr *scr_arr_fill_ref(ScrArr *a, void *value, double start, double end);
|
|
1120
|
+
ScrArr *scr_arr_fill_undefined(ScrArr *a, double start, double end);
|
|
1114
1121
|
/* Math.max(...xs) / Math.min(...xs) over an f64-element array: the JS
|
|
1115
1122
|
* fold (NaN poisons, ±0 by the JS preferences, empty → ∓Infinity). */
|
|
1116
1123
|
double scr_math_max_arr(ScrArr *a);
|
|
@@ -1170,6 +1177,10 @@ ScrArr *scr_arr_with_undefined(ScrArr *a, double index);
|
|
|
1170
1177
|
double scr_arr_push_f64(ScrArr *a, double v);
|
|
1171
1178
|
double scr_arr_push_bool(ScrArr *a, bool v);
|
|
1172
1179
|
double scr_arr_push_ref(ScrArr *a, void *v);
|
|
1180
|
+
/* Compiler-built slot buffers do not alias array storage. Both operations
|
|
1181
|
+
* move ownership of every slot and preserve the evaluated argument order. */
|
|
1182
|
+
double scr_arr_push_many(ScrArr *a, size_t count, const uint64_t *slots);
|
|
1183
|
+
double scr_arr_unshift_many(ScrArr *a, size_t count, const uint64_t *slots);
|
|
1173
1184
|
/* Append a same-element-kind array through the JS iterator contract: holes
|
|
1174
1185
|
* become present undefined states. The source is borrowed and self-spread
|
|
1175
1186
|
* duplicates the original indexed state. */
|
|
@@ -1394,7 +1405,7 @@ typedef struct ScrMap {
|
|
|
1394
1405
|
size_t nlive; /* live entries (Map.size) */
|
|
1395
1406
|
size_t ecap; /* entries capacity */
|
|
1396
1407
|
ScrMapEntry *entries;
|
|
1397
|
-
size_t nbuckets; /* power of two
|
|
1408
|
+
size_t nbuckets; /* zero for small linear maps; otherwise power of two >= 2 * nentries */
|
|
1398
1409
|
size_t *buckets; /* entry indices; SIZE_MAX = empty */
|
|
1399
1410
|
size_t iter_depth; /* > 0: an iteration is active — no compaction */
|
|
1400
1411
|
const ScrMapDynOps *dyn_ops;
|
|
@@ -3681,7 +3692,7 @@ typedef struct ScrJsval ScrJsval; /* opaque island cell (C11 repeat; the
|
|
|
3681
3692
|
* result as an owned (+1) dyn value. `args` entries are BORROWED. */
|
|
3682
3693
|
typedef ScrDyn *(*ScrDynThunk)(ScrClosure *clo, ScrDyn *const *args, size_t argc);
|
|
3683
3694
|
|
|
3684
|
-
/* Object member. Keys
|
|
3695
|
+
/* Object member. Keys own shared immutable UTF-8 bytes (NUL-terminated for
|
|
3685
3696
|
* convenience; key_len excludes the NUL) — duplicate keys were already
|
|
3686
3697
|
* collapsed at parse time (later wins, like JS JSON.parse). */
|
|
3687
3698
|
typedef struct {
|
|
@@ -3690,13 +3701,22 @@ typedef struct {
|
|
|
3690
3701
|
ScrDyn *value; /* owned */
|
|
3691
3702
|
ScrDyn *getter; /* owned when this is an accessor property */
|
|
3692
3703
|
ScrDyn *setter; /* owned when this is an accessor property */
|
|
3693
|
-
bool accessor;
|
|
3704
|
+
bool accessor : 1;
|
|
3705
|
+
/* Snapshot written by trace before visiting children. Collected teardown
|
|
3706
|
+
* must not inspect the value: an earlier cycle member may already be freed.
|
|
3707
|
+
* Ordinary mutations need not maintain this collector-only decision. */
|
|
3708
|
+
bool value_traced : 1;
|
|
3694
3709
|
/* Ordinary object insertion sets all three attributes true. */
|
|
3695
3710
|
bool writable;
|
|
3696
3711
|
bool enumerable;
|
|
3697
3712
|
bool configurable;
|
|
3698
3713
|
} ScrDynEntry;
|
|
3699
3714
|
|
|
3715
|
+
_Static_assert(sizeof(ScrDynEntry) == (sizeof(void *) == 8 ? 48 : 24),
|
|
3716
|
+
"LLVM checked-object readers use the target entry stride");
|
|
3717
|
+
_Static_assert(offsetof(ScrDynEntry, value) == 2 * sizeof(void *),
|
|
3718
|
+
"LLVM checked-object readers use the third pointer-sized field");
|
|
3719
|
+
|
|
3700
3720
|
struct ScrDyn {
|
|
3701
3721
|
size_t rc; /* SIZE_MAX = immortal (unused for dyn; kept per convention) */
|
|
3702
3722
|
ScrDynKind kind;
|
|
@@ -3739,6 +3759,7 @@ struct ScrDyn {
|
|
|
3739
3759
|
* interfaces may request a fresh snapshot with the true arm. */
|
|
3740
3760
|
void *source_identity;
|
|
3741
3761
|
ScrDyn *(*source_access)(void *, bool materialize);
|
|
3762
|
+
struct ScrDynObjectIndex *index; /* optional wide-object lookup; owns no values */
|
|
3742
3763
|
} obj; /* owned */
|
|
3743
3764
|
/* SCR_DYN_FUNC: the boxed closure (owned) + its call descriptor. `sig`
|
|
3744
3765
|
* and `name` are static compiler-emitted literals (never freed); name
|
|
@@ -3925,6 +3946,12 @@ void scr_dyn_install_async_iterator_symbol(ScrDyn *key);
|
|
|
3925
3946
|
ScrDyn *scr_dyn_array_values_function(void);
|
|
3926
3947
|
ScrDyn *scr_dyn_array_from_iterator(const ScrDyn *value);
|
|
3927
3948
|
ScrDyn *scr_dyn_iterator_result(ScrDyn *value);
|
|
3949
|
+
/* Internal consumption of a captured builtin next method. Check can_step
|
|
3950
|
+
* once before entering the loop. step returns an owned ordinary value;
|
|
3951
|
+
* read step_done immediately afterward, before running any user code. */
|
|
3952
|
+
bool scr_dyn_iterator_can_step(const ScrDyn *iterator, const ScrDyn *next);
|
|
3953
|
+
ScrDyn *scr_dyn_iterator_step(const ScrDyn *iterator);
|
|
3954
|
+
bool scr_dyn_iterator_step_done(const ScrDyn *iterator);
|
|
3928
3955
|
/* The ordinary object snapshot plus a retained typed source. source_access
|
|
3929
3956
|
* releases that source when materialize=false and returns a fresh snapshot
|
|
3930
3957
|
* when true. */
|
|
@@ -4524,6 +4551,8 @@ typedef struct {
|
|
|
4524
4551
|
} ScrJsonBuf;
|
|
4525
4552
|
|
|
4526
4553
|
void scr_jb_init(ScrJsonBuf *b);
|
|
4554
|
+
/* Append a borrowed byte span verbatim, including embedded NUL bytes. */
|
|
4555
|
+
void scr_jb_write(ScrJsonBuf *b, const char *s, size_t n);
|
|
4527
4556
|
/* Append one borrowed runtime string verbatim (no JSON quoting). */
|
|
4528
4557
|
void scr_jb_put_str(ScrJsonBuf *b, const ScrStr *s);
|
|
4529
4558
|
/* Push a container onto the circular-detection stack before serializing
|
|
@@ -5819,9 +5848,10 @@ ScrBytes *scr_array_buffer_view_dv(ScrDyn *, ScrDyn *, ScrDyn *);
|
|
|
5819
5848
|
/* Native callback boundary: exact owned u8 copy. NULL with len == 0 is an
|
|
5820
5849
|
* empty span. */
|
|
5821
5850
|
ScrBytes *scr_bytes_from_data(const uint8_t *data, size_t len); /* +1 */
|
|
5851
|
+
ScrBytes *scr_bytes_take_data(uint8_t *data, size_t len); /* +1, consumes malloc storage */
|
|
5822
5852
|
|
|
5823
|
-
/*
|
|
5824
|
-
*
|
|
5853
|
+
/* Same-element-kind copy, preserving the raw representation. Cross-kind
|
|
5854
|
+
* construction uses scr_bytes_convert. Borrows src. Never throws. */
|
|
5825
5855
|
ScrBytes *scr_bytes_copy(const ScrBytes *src); /* +1 */
|
|
5826
5856
|
|
|
5827
5857
|
/* `new Uint8Array([1, 2, 3])` / Buffer.from(number[]): each f64 element
|
|
@@ -5985,6 +6015,7 @@ ScrStr *scr_text_decode_legacy(const ScrBytes *b, double encoding);
|
|
|
5985
6015
|
* "utf16le" writes LE code units, surrogate pairs included. Borrows
|
|
5986
6016
|
* both; +1 u8 result. Never throws. */
|
|
5987
6017
|
ScrBytes *scr_bytes_from_str(const ScrStr *s, const ScrStr *enc);
|
|
6018
|
+
ScrBytes *scr_bytes_from_str_checked(const ScrStr *s, const ScrStr *enc);
|
|
5988
6019
|
|
|
5989
6020
|
/* Buffer.byteLength(string, enc) — enc NORMALIZED like from_str — and
|
|
5990
6021
|
* Buffer.isEncoding(name) (case-insensitive over Node's alias set).
|
|
@@ -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) {
|
|
@@ -779,9 +787,14 @@ static size_t scr_sidx_abs_diff(size_t a, size_t b) {
|
|
|
779
787
|
* sufficient; the hot cursor retains sequential-access locality. */
|
|
780
788
|
static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
|
|
781
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};
|
|
782
794
|
ScrSidxPoint best = {0, 0};
|
|
783
795
|
size_t best_dist = u16;
|
|
784
796
|
if (e->npoints != 0) {
|
|
797
|
+
SCR_SIDX_SEARCH();
|
|
785
798
|
size_t lo = 0, hi = e->npoints;
|
|
786
799
|
while (lo < hi) {
|
|
787
800
|
size_t m = lo + (hi - lo) / 2;
|
|
@@ -812,9 +825,12 @@ static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
|
|
|
812
825
|
|
|
813
826
|
static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
|
|
814
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};
|
|
815
830
|
ScrSidxPoint best = {0, 0};
|
|
816
831
|
size_t best_dist = byte_off;
|
|
817
832
|
if (e->npoints != 0) {
|
|
833
|
+
SCR_SIDX_SEARCH();
|
|
818
834
|
size_t lo = 0, hi = e->npoints;
|
|
819
835
|
while (lo < hi) {
|
|
820
836
|
size_t m = lo + (hi - lo) / 2;
|
|
@@ -843,6 +859,36 @@ static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
|
|
|
843
859
|
return best;
|
|
844
860
|
}
|
|
845
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
|
+
|
|
846
892
|
/* Convert a UTF-16 index to a byte offset from the closest sparse anchor or
|
|
847
893
|
* hot cursor. If u16 addresses the second (low-surrogate) unit of
|
|
848
894
|
* an astral char, *mid is set and the returned offset is the START of that
|
|
@@ -854,6 +900,12 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
854
900
|
*mid = false;
|
|
855
901
|
return u16 < s->len ? u16 : s->len;
|
|
856
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
|
+
}
|
|
857
909
|
scr_sidx_extend_to_u16(s, e, u16);
|
|
858
910
|
/* Extending a far-end lookup can just have proved identity. Do not
|
|
859
911
|
* materialize an index that the identity fast path will never consult. */
|
|
@@ -864,9 +916,31 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
864
916
|
scr_sidx_materialize_identity_prefix(s, e);
|
|
865
917
|
ScrSidxPoint near = scr_sidx_near_u16(s, e, u16);
|
|
866
918
|
size_t cu = near.cu, cb = near.cb;
|
|
867
|
-
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
|
+
}
|
|
868
934
|
bool m = false;
|
|
869
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
|
+
}
|
|
870
944
|
SCR_SIDX_STEP();
|
|
871
945
|
size_t seq = scr_utf8_seq_len((unsigned char)s->data[cb]);
|
|
872
946
|
size_t w = seq == 4 ? 2 : 1;
|
|
@@ -879,6 +953,8 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
879
953
|
}
|
|
880
954
|
e->cu = cu;
|
|
881
955
|
e->cb = cb;
|
|
956
|
+
if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
|
|
957
|
+
scr_sidx_ascii_run(s, e);
|
|
882
958
|
*mid = m;
|
|
883
959
|
return cb;
|
|
884
960
|
}
|
|
@@ -888,6 +964,11 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
|
|
|
888
964
|
static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
|
|
889
965
|
size_t byte_off) {
|
|
890
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
|
+
}
|
|
891
972
|
/* A byte search result may be far beyond the existing prefix. Build the
|
|
892
973
|
* same sparse intervals first, then choose the closest boundary anchor. */
|
|
893
974
|
if (byte_off > e->indexed_cb) {
|
|
@@ -900,15 +981,17 @@ static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
|
|
|
900
981
|
scr_sidx_materialize_identity_prefix(s, e);
|
|
901
982
|
ScrSidxPoint near = scr_sidx_near_byte(s, e, byte_off);
|
|
902
983
|
size_t cu = near.cu, cb = near.cb;
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
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;
|
|
910
991
|
e->cu = cu;
|
|
911
992
|
e->cb = cb;
|
|
993
|
+
if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
|
|
994
|
+
scr_sidx_ascii_run(s, e);
|
|
912
995
|
return cu;
|
|
913
996
|
}
|
|
914
997
|
|
|
@@ -919,16 +1002,21 @@ static double scr_to_integer_or_infinity(double x) {
|
|
|
919
1002
|
return trunc(x);
|
|
920
1003
|
}
|
|
921
1004
|
|
|
922
|
-
/*
|
|
1005
|
+
/* Byte substring search (needle and hay are both well-formed UTF-8,
|
|
923
1006
|
* so any byte-level match starts on a char boundary — UTF-8 is
|
|
924
1007
|
* self-synchronizing). Empty needle matches at hay. */
|
|
925
1008
|
static const char *scr_byte_find(const char *hay, size_t hay_len,
|
|
926
1009
|
const char *nee, size_t nee_len) {
|
|
927
1010
|
if (nee_len == 0) return hay;
|
|
928
1011
|
if (nee_len > hay_len) return NULL;
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
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;
|
|
932
1020
|
}
|
|
933
1021
|
return NULL;
|
|
934
1022
|
}
|
|
@@ -981,14 +1069,18 @@ double scr_str_char_code_at(ScrStr *s, double i) {
|
|
|
981
1069
|
|
|
982
1070
|
double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
|
|
983
1071
|
double pos = scr_to_integer_or_infinity(fromIndex);
|
|
1072
|
+
if (needle->len > s->len) return -1.0;
|
|
984
1073
|
ScrSidx *e = scr_sidx(s);
|
|
985
|
-
size_t len16 = scr_sidx_len(s, e);
|
|
986
|
-
size_t start16 = pos <= 0 ? 0
|
|
987
|
-
: pos >= (double)len16 ? len16
|
|
988
|
-
: (size_t)pos;
|
|
989
1074
|
/* Per spec, the empty needle is found at the clamped fromIndex itself —
|
|
990
1075
|
* even when that index is between the halves of an astral pair. */
|
|
991
|
-
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;
|
|
992
1084
|
bool mid;
|
|
993
1085
|
size_t start_b = scr_u16_to_byte_c(s, e, start16, &mid);
|
|
994
1086
|
/* A match can't begin on a low-surrogate half (needles are well-formed),
|
|
@@ -1001,11 +1093,11 @@ double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
|
|
|
1001
1093
|
return (double)scr_byte_to_u16_c(s, e, (size_t)(found - s->data));
|
|
1002
1094
|
}
|
|
1003
1095
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
*
|
|
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. */
|
|
1009
1101
|
ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
|
|
1010
1102
|
ScrSidx *e = scr_sidx(s);
|
|
1011
1103
|
double len16 = (double)scr_sidx_len(s, e);
|
|
@@ -1013,7 +1105,8 @@ ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
|
|
|
1013
1105
|
double b = scr_to_integer_or_infinity(end);
|
|
1014
1106
|
double fa = a < 0 ? 0 : a > len16 ? len16 : a;
|
|
1015
1107
|
double fb = b < 0 ? 0 : b > len16 ? len16 : b;
|
|
1016
|
-
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);
|
|
1017
1110
|
}
|
|
1018
1111
|
|
|
1019
1112
|
bool scr_str_includes(ScrStr *s, ScrStr *needle) {
|
|
@@ -1037,22 +1130,27 @@ static size_t scr_str_clamp_u16_position(double position, size_t len16) {
|
|
|
1037
1130
|
}
|
|
1038
1131
|
|
|
1039
1132
|
bool scr_str_starts_with_from(ScrStr *s, ScrStr *needle, double position) {
|
|
1040
|
-
ScrSidx *e = scr_sidx(s);
|
|
1041
|
-
size_t len16 = scr_sidx_len(s, e);
|
|
1042
|
-
size_t start16 = scr_str_clamp_u16_position(position, len16);
|
|
1043
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);
|
|
1044
1138
|
bool mid;
|
|
1045
|
-
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);
|
|
1046
1140
|
return !mid && needle->len <= s->len - start_byte &&
|
|
1047
1141
|
memcmp(s->data + start_byte, needle->data, needle->len) == 0;
|
|
1048
1142
|
}
|
|
1049
1143
|
|
|
1050
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));
|
|
1051
1151
|
ScrSidx *e = scr_sidx(s);
|
|
1052
1152
|
size_t len16 = scr_sidx_len(s, e);
|
|
1053
1153
|
size_t end16 = scr_str_clamp_u16_position(end_position, len16);
|
|
1054
|
-
size_t needle16 = scr_sidx_len(needle, scr_sidx(needle));
|
|
1055
|
-
if (needle16 == 0) return true;
|
|
1056
1154
|
if (needle16 > end16) return false;
|
|
1057
1155
|
bool start_mid, end_mid;
|
|
1058
1156
|
size_t start_byte = scr_u16_to_byte_c(s, e, end16 - needle16, &start_mid);
|
|
@@ -1077,6 +1175,11 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
|
|
|
1077
1175
|
size_t len16 = scr_sidx_len(s, e);
|
|
1078
1176
|
size_t from = scr_slice_boundary(scr_to_integer_or_infinity(start), len16);
|
|
1079
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) {
|
|
1080
1183
|
if (from >= to) return scr_str_empty();
|
|
1081
1184
|
|
|
1082
1185
|
bool from_mid, to_mid;
|
|
@@ -1093,18 +1196,16 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
|
|
|
1093
1196
|
/* Divergence: JS would emit the lone surrogate half; we emit U+FFFD. */
|
|
1094
1197
|
size_t total = content_len + (from_mid ? SCR_REPLACEMENT_LEN : 0) +
|
|
1095
1198
|
(to_mid ? SCR_REPLACEMENT_LEN : 0);
|
|
1096
|
-
|
|
1097
|
-
if (!tmp) scr_oom();
|
|
1199
|
+
ScrStr *r = scr_str_alloc(total, total);
|
|
1098
1200
|
size_t o = 0;
|
|
1099
1201
|
if (from_mid) {
|
|
1100
|
-
memcpy(
|
|
1202
|
+
memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
|
|
1101
1203
|
o += SCR_REPLACEMENT_LEN;
|
|
1102
1204
|
}
|
|
1103
|
-
memcpy(
|
|
1205
|
+
memcpy(r->data + o, s->data + content_b, content_len);
|
|
1104
1206
|
o += content_len;
|
|
1105
|
-
if (to_mid) memcpy(
|
|
1106
|
-
|
|
1107
|
-
free(tmp);
|
|
1207
|
+
if (to_mid) memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
|
|
1208
|
+
r->data[total] = '\0';
|
|
1108
1209
|
return r;
|
|
1109
1210
|
}
|
|
1110
1211
|
|
|
@@ -1213,6 +1314,18 @@ ScrStr *scr_str_trim_end(ScrStr *s) {
|
|
|
1213
1314
|
static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
|
|
1214
1315
|
scr_lit_fffd = {SIZE_MAX, 3, 3, "\xEF\xBF\xBD"};
|
|
1215
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
|
+
|
|
1216
1329
|
/* split(separator, limit) with a STRING separator (ECMA-262 22.1.3.23):
|
|
1217
1330
|
* limit is ToUint32'd; zero returns [] and reaching the limit stops before
|
|
1218
1331
|
* any later separator probes. The no-limit wrapper supplies 2^32-1.
|
|
@@ -1235,11 +1348,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
|
|
|
1235
1348
|
size_t adv;
|
|
1236
1349
|
uint32_t cp = scr_utf8_decode(s->data + i, &adv);
|
|
1237
1350
|
if (cp >= 0x10000) { /* two units in JS: both halves become U+FFFD */
|
|
1238
|
-
|
|
1351
|
+
scr_str_split_append(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
|
|
1239
1352
|
if (out->len == limit) return out;
|
|
1240
|
-
|
|
1353
|
+
scr_str_split_append(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
|
|
1241
1354
|
} else {
|
|
1242
|
-
|
|
1355
|
+
scr_str_split_append(out, scr_str_from_span(s->data + i, adv));
|
|
1243
1356
|
}
|
|
1244
1357
|
if (out->len == limit) return out;
|
|
1245
1358
|
i += adv;
|
|
@@ -1252,11 +1365,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
|
|
|
1252
1365
|
sep->data, sep->len);
|
|
1253
1366
|
if (!found) break;
|
|
1254
1367
|
size_t at = (size_t)(found - s->data);
|
|
1255
|
-
|
|
1368
|
+
scr_str_split_append(out, scr_str_from_span(s->data + start, at - start));
|
|
1256
1369
|
if (out->len == limit) return out;
|
|
1257
1370
|
start = at + sep->len;
|
|
1258
1371
|
}
|
|
1259
|
-
|
|
1372
|
+
scr_str_split_append(out, scr_str_from_span(s->data + start, s->len - start));
|
|
1260
1373
|
return out;
|
|
1261
1374
|
}
|
|
1262
1375
|
|