@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
|
@@ -13,10 +13,9 @@
|
|
|
13
13
|
* lre_compile rejects aborts with a clear
|
|
14
14
|
* message (Node throws SyntaxError at parse time — documented divergence;
|
|
15
15
|
* rare, since tsc's parser has already syntax-checked the literal).
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* like Node. Correctness-first: the conversion is O(n) per call.
|
|
16
|
+
* - ASCII subjects borrow their existing bytes; other subjects use a
|
|
17
|
+
* per-call UTF-16 conversion. Both engine representations report UTF-16
|
|
18
|
+
* code-unit indices, matching .length/slice/charCodeAt.
|
|
20
19
|
* - Match loops mirror quickjs.c's own (JS_RegExpDelete /
|
|
21
20
|
* js_regexp_Symbol_replace): capture buffers are sized by
|
|
22
21
|
* lre_get_alloc_count (NOT capture_count*2 — the executor writes
|
|
@@ -304,6 +303,8 @@ ScrStr *scr_regex_to_string(ScrRegex *re) {
|
|
|
304
303
|
/* Subject as freshly-malloc'd UTF-16 code units (strings are well-formed
|
|
305
304
|
* UTF-8, so no validation). Unit count ≤ byte count. */
|
|
306
305
|
static uint16_t *scr_to_utf16(const ScrStr *s, int *plen) {
|
|
306
|
+
if (s->len > (size_t)INT32_MAX - 1 || s->len > SIZE_MAX / sizeof(uint16_t))
|
|
307
|
+
scr_regex_oom();
|
|
307
308
|
uint16_t *u = malloc((s->len ? s->len : 1) * sizeof(uint16_t));
|
|
308
309
|
if (!u) scr_regex_oom();
|
|
309
310
|
int n = 0;
|
|
@@ -339,53 +340,98 @@ static uint16_t *scr_to_utf16(const ScrStr *s, int *plen) {
|
|
|
339
340
|
return u;
|
|
340
341
|
}
|
|
341
342
|
|
|
342
|
-
/*
|
|
343
|
-
*
|
|
344
|
-
|
|
345
|
-
*
|
|
343
|
+
/* Decode one UTF-16 code point. A boundary that splits a surrogate pair
|
|
344
|
+
* produces U+FFFD, as in the runtime's string slicing contract. */
|
|
345
|
+
static uint32_t scr_regex_codepoint(const uint16_t *units, int *index, int end) {
|
|
346
|
+
uint32_t cp = units[(*index)++];
|
|
347
|
+
if (cp >= 0xD800 && cp < 0xDC00 && *index < end &&
|
|
348
|
+
units[*index] >= 0xDC00 && units[*index] < 0xE000)
|
|
349
|
+
return 0x10000 + ((cp - 0xD800) << 10) + (units[(*index)++] - 0xDC00);
|
|
350
|
+
return cp >= 0xD800 && cp < 0xE000 ? 0xFFFD : cp;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
static size_t scr_regex_encode(char *out, uint32_t cp) {
|
|
354
|
+
if (cp < 0x80) {
|
|
355
|
+
out[0] = (char)cp;
|
|
356
|
+
return 1;
|
|
357
|
+
}
|
|
358
|
+
if (cp < 0x800) {
|
|
359
|
+
out[0] = (char)(0xC0 | (cp >> 6));
|
|
360
|
+
out[1] = (char)(0x80 | (cp & 0x3F));
|
|
361
|
+
return 2;
|
|
362
|
+
}
|
|
363
|
+
if (cp < 0x10000) {
|
|
364
|
+
out[0] = (char)(0xE0 | (cp >> 12));
|
|
365
|
+
out[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
|
|
366
|
+
out[2] = (char)(0x80 | (cp & 0x3F));
|
|
367
|
+
return 3;
|
|
368
|
+
}
|
|
369
|
+
out[0] = (char)(0xF0 | (cp >> 18));
|
|
370
|
+
out[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
|
|
371
|
+
out[2] = (char)(0x80 | ((cp >> 6) & 0x3F));
|
|
372
|
+
out[3] = (char)(0x80 | (cp & 0x3F));
|
|
373
|
+
return 4;
|
|
374
|
+
}
|
|
375
|
+
|
|
346
376
|
static void scr_jb_put_utf16(ScrJsonBuf *b, const uint16_t *u, int start, int end) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
} else if (cp >= 0xD800 && cp < 0xE000) {
|
|
354
|
-
cp = 0xFFFD;
|
|
355
|
-
}
|
|
356
|
-
if (cp < 0x80) {
|
|
357
|
-
scr_jb_putc(b, (char)cp);
|
|
358
|
-
} else if (cp < 0x800) {
|
|
359
|
-
scr_jb_putc(b, (char)(0xC0 | (cp >> 6)));
|
|
360
|
-
scr_jb_putc(b, (char)(0x80 | (cp & 0x3F)));
|
|
361
|
-
} else if (cp < 0x10000) {
|
|
362
|
-
scr_jb_putc(b, (char)(0xE0 | (cp >> 12)));
|
|
363
|
-
scr_jb_putc(b, (char)(0x80 | ((cp >> 6) & 0x3F)));
|
|
364
|
-
scr_jb_putc(b, (char)(0x80 | (cp & 0x3F)));
|
|
365
|
-
} else {
|
|
366
|
-
scr_jb_putc(b, (char)(0xF0 | (cp >> 18)));
|
|
367
|
-
scr_jb_putc(b, (char)(0x80 | ((cp >> 12) & 0x3F)));
|
|
368
|
-
scr_jb_putc(b, (char)(0x80 | ((cp >> 6) & 0x3F)));
|
|
369
|
-
scr_jb_putc(b, (char)(0x80 | (cp & 0x3F)));
|
|
377
|
+
char bytes[256];
|
|
378
|
+
size_t used = 0;
|
|
379
|
+
for (int i = start; i < end;) {
|
|
380
|
+
if (used > sizeof bytes - 4) {
|
|
381
|
+
scr_jb_write(b, bytes, used);
|
|
382
|
+
used = 0;
|
|
370
383
|
}
|
|
384
|
+
used += scr_regex_encode(bytes + used, scr_regex_codepoint(u, &i, end));
|
|
371
385
|
}
|
|
386
|
+
scr_jb_write(b, bytes, used);
|
|
372
387
|
}
|
|
373
388
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
389
|
+
/* Matching owns only the converted subject and oversized register buffer.
|
|
390
|
+
* The caller keeps the original immutable string alive. ASCII bytes are
|
|
391
|
+
* already the engine's one-byte representation, even under /u or /i. */
|
|
392
|
+
typedef struct ScrRegexInput {
|
|
393
|
+
const uint8_t *data;
|
|
394
|
+
uint16_t *utf16;
|
|
395
|
+
int len;
|
|
396
|
+
int wide;
|
|
397
|
+
uint8_t **capture;
|
|
398
|
+
uint8_t *registers[32];
|
|
399
|
+
} ScrRegexInput;
|
|
400
|
+
|
|
401
|
+
static bool scr_text_ascii(const ScrStr *s) {
|
|
402
|
+
size_t i = 0;
|
|
403
|
+
for (; s->len - i >= sizeof(uint64_t); i += sizeof(uint64_t)) {
|
|
404
|
+
uint64_t word;
|
|
405
|
+
memcpy(&word, s->data + i, sizeof word);
|
|
406
|
+
if (word & UINT64_C(0x8080808080808080)) return false;
|
|
407
|
+
}
|
|
408
|
+
for (; i < s->len; i++) {
|
|
409
|
+
if ((unsigned char)s->data[i] >= 0x80) return false;
|
|
410
|
+
}
|
|
411
|
+
return true;
|
|
379
412
|
}
|
|
380
413
|
|
|
381
|
-
|
|
414
|
+
static void scr_regex_input_init(ScrRegexInput *input, const uint8_t *bc,
|
|
415
|
+
const ScrStr *s) {
|
|
416
|
+
if (s->len > (size_t)INT32_MAX - 1) scr_regex_oom();
|
|
417
|
+
input->wide = !scr_text_ascii(s);
|
|
418
|
+
input->utf16 = input->wide ? scr_to_utf16(s, &input->len) : NULL;
|
|
419
|
+
input->data = input->wide ? (const uint8_t *)input->utf16 : (const uint8_t *)s->data;
|
|
420
|
+
if (!input->wide) input->len = (int)s->len;
|
|
421
|
+
/* The executor writes temporary registers beyond the capture pairs. */
|
|
422
|
+
int count = lre_get_alloc_count(bc);
|
|
423
|
+
input->capture = count <= 32 ? input->registers : malloc((size_t)count * sizeof(uint8_t *));
|
|
424
|
+
if (!input->capture) scr_regex_oom();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
static void scr_regex_input_dispose(ScrRegexInput *input) {
|
|
428
|
+
if (input->capture != input->registers) free(input->capture);
|
|
429
|
+
free(input->utf16);
|
|
430
|
+
}
|
|
382
431
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
static int scr_exec(uint8_t **capture, const uint8_t *bc, const uint16_t *u,
|
|
387
|
-
int index, int len) {
|
|
388
|
-
int rc = lre_exec(capture, bc, (const uint8_t *)u, index, len, 1, lre_opaque());
|
|
432
|
+
static int scr_exec(ScrRegexInput *input, const uint8_t *bc, int index) {
|
|
433
|
+
int rc = lre_exec(input->capture, bc, input->data, index, input->len,
|
|
434
|
+
input->wide, lre_opaque());
|
|
389
435
|
if (rc < 0) {
|
|
390
436
|
fflush(stdout);
|
|
391
437
|
scr_trap("scriptc: regular expression execution failed\n");
|
|
@@ -393,24 +439,43 @@ static int scr_exec(uint8_t **capture, const uint8_t *bc, const uint16_t *u,
|
|
|
393
439
|
return rc;
|
|
394
440
|
}
|
|
395
441
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (
|
|
403
|
-
|
|
442
|
+
static int scr_capture_index(const ScrRegexInput *input, const uint8_t *capture) {
|
|
443
|
+
return (int)((capture - input->data) >> input->wide);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
static void scr_regex_put_span(ScrJsonBuf *b, const ScrRegexInput *input,
|
|
447
|
+
int start, int end) {
|
|
448
|
+
if (input->wide) scr_jb_put_utf16(b, input->utf16, start, end);
|
|
449
|
+
else scr_jb_write(b, (const char *)input->data + start, (size_t)(end - start));
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
static ScrStr *scr_regex_span(const ScrRegexInput *input, int start, int end) {
|
|
453
|
+
if (!input->wide)
|
|
454
|
+
return scr_str_new((const char *)input->data + start, (size_t)(end - start));
|
|
455
|
+
/* Captures have a known span: allocate its exact UTF-8 length instead
|
|
456
|
+
* of inheriting a general builder's size hint from an earlier document. */
|
|
457
|
+
size_t bytes = 0;
|
|
458
|
+
for (int i = start; i < end;) {
|
|
459
|
+
uint32_t cp = scr_regex_codepoint(input->utf16, &i, end);
|
|
460
|
+
size_t width = cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4;
|
|
461
|
+
if (width > SIZE_MAX - sizeof(ScrStr) - 1 - bytes) scr_regex_oom();
|
|
462
|
+
bytes += width;
|
|
463
|
+
}
|
|
464
|
+
ScrStr *out = scr_str_alloc_raw(bytes, bytes);
|
|
465
|
+
size_t offset = 0;
|
|
466
|
+
for (int i = start; i < end;)
|
|
467
|
+
offset += scr_regex_encode(out->data + offset, scr_regex_codepoint(input->utf16, &i, end));
|
|
468
|
+
out->data[bytes] = '\0';
|
|
469
|
+
return out;
|
|
404
470
|
}
|
|
405
471
|
|
|
406
472
|
/* ECMA-262 AdvanceStringIndex: past a whole surrogate pair under /u, one
|
|
407
|
-
* code unit otherwise
|
|
408
|
-
*
|
|
409
|
-
|
|
410
|
-
if (unicode && i + 1 < len &&
|
|
411
|
-
u[i + 1] >= 0xDC00 && u[i + 1] < 0xE000)
|
|
473
|
+
* code unit otherwise. ASCII cannot contain a surrogate pair. */
|
|
474
|
+
static int scr_advance(const ScrRegexInput *input, int i, bool unicode) {
|
|
475
|
+
const uint16_t *u = input->utf16;
|
|
476
|
+
if (unicode && input->wide && i + 1 < input->len &&
|
|
477
|
+
u[i] >= 0xD800 && u[i] < 0xDC00 && u[i + 1] >= 0xDC00 && u[i + 1] < 0xE000)
|
|
412
478
|
return i + 2;
|
|
413
|
-
}
|
|
414
479
|
return i + 1;
|
|
415
480
|
}
|
|
416
481
|
|
|
@@ -427,40 +492,17 @@ static int scr_regex_start(ScrRegex *re, int len) {
|
|
|
427
492
|
return (int)floor(index);
|
|
428
493
|
}
|
|
429
494
|
|
|
430
|
-
/* A predicate needs only
|
|
431
|
-
* result metadata. Short ASCII subjects already have the engine's one-byte
|
|
432
|
-
* representation. Bound that scan so a long mixed-text subject does not
|
|
433
|
-
* traverse an ASCII prefix twice before matching. Other subjects use exec's
|
|
434
|
-
* UTF-16 conversion. Register storage is bounded by alloc_count, not captures. */
|
|
495
|
+
/* A predicate needs only boundaries; it never materializes result strings. */
|
|
435
496
|
bool scr_regex_test(ScrRegex *re, ScrStr *s) {
|
|
436
497
|
uint8_t *bc = scr_regex_bc(re);
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
for (; ascii && s->len - i >= sizeof(uint64_t); i += sizeof(uint64_t)) {
|
|
440
|
-
uint64_t word;
|
|
441
|
-
memcpy(&word, s->data + i, sizeof word);
|
|
442
|
-
if (word & UINT64_C(0x8080808080808080)) ascii = false;
|
|
443
|
-
}
|
|
444
|
-
for (; ascii && i < s->len; i++) {
|
|
445
|
-
if ((unsigned char)s->data[i] >= 0x80) ascii = false;
|
|
446
|
-
}
|
|
447
|
-
int len;
|
|
448
|
-
uint16_t *converted = ascii ? NULL : scr_to_utf16(s, &len);
|
|
449
|
-
const uint8_t *subject = ascii ? (const uint8_t *)s->data : (const uint8_t *)converted;
|
|
450
|
-
if (ascii) len = (int)s->len;
|
|
451
|
-
uint8_t *registers[32];
|
|
452
|
-
uint8_t **capture = lre_get_alloc_count(bc) <= 32 ? registers : scr_capture_alloc(bc);
|
|
498
|
+
ScrRegexInput input;
|
|
499
|
+
scr_regex_input_init(&input, bc, s);
|
|
453
500
|
bool stateful = (lre_get_flags(bc) & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) != 0;
|
|
454
|
-
int pos = stateful ? scr_regex_start(re, len) : 0;
|
|
455
|
-
int rc = pos < 0 ? 0 :
|
|
456
|
-
if (rc < 0) {
|
|
457
|
-
fflush(stdout);
|
|
458
|
-
scr_trap("scriptc: regular expression execution failed\n");
|
|
459
|
-
}
|
|
501
|
+
int pos = stateful ? scr_regex_start(re, input.len) : 0;
|
|
502
|
+
int rc = pos < 0 ? 0 : scr_exec(&input, bc, pos);
|
|
460
503
|
if (stateful) re->last_index = rc == 1
|
|
461
|
-
? (double)(
|
|
462
|
-
|
|
463
|
-
free(converted);
|
|
504
|
+
? (double)scr_capture_index(&input, input.capture[1]) : 0;
|
|
505
|
+
scr_regex_input_dispose(&input);
|
|
464
506
|
return rc == 1;
|
|
465
507
|
}
|
|
466
508
|
|
|
@@ -474,20 +516,20 @@ bool scr_regex_test(ScrRegex *re, ScrStr *s) {
|
|
|
474
516
|
ScrArr *scr_regex_exec(ScrStr *s, ScrRegex *re) {
|
|
475
517
|
uint8_t *bc = scr_regex_bc(re);
|
|
476
518
|
bool stateful = (lre_get_flags(bc) & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) != 0;
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
519
|
+
ScrRegexInput input;
|
|
520
|
+
scr_regex_input_init(&input, bc, s);
|
|
521
|
+
int len = input.len;
|
|
522
|
+
uint8_t **capture = input.capture;
|
|
480
523
|
int pos = stateful ? scr_regex_start(re, len) : 0;
|
|
481
|
-
int rc = pos < 0 ? 0 : scr_exec(
|
|
524
|
+
int rc = pos < 0 ? 0 : scr_exec(&input, bc, pos);
|
|
482
525
|
if (stateful) re->last_index = rc == 1
|
|
483
|
-
? (double)(
|
|
526
|
+
? (double)scr_capture_index(&input, capture[1]) : 0;
|
|
484
527
|
ScrArr *out = NULL;
|
|
485
528
|
if (rc == 1) {
|
|
486
|
-
const uint8_t *ubase = (const uint8_t *)u;
|
|
487
529
|
int count = lre_get_capture_count(bc);
|
|
488
530
|
out = scr_arr_new(SCR_ELEM_STR, (size_t)count);
|
|
489
531
|
out->metadata = scr_dyn_new_obj();
|
|
490
|
-
scr_dyn_obj_set(out->metadata, "index", 5, scr_dyn_new_num((double)(
|
|
532
|
+
scr_dyn_obj_set(out->metadata, "index", 5, scr_dyn_new_num((double)scr_capture_index(&input, capture[0])));
|
|
491
533
|
scr_dyn_obj_set(out->metadata, "input", 5, scr_dyn_new_str(s));
|
|
492
534
|
for (int k = 0; k < count; k++) {
|
|
493
535
|
const uint8_t *cs = capture[2 * k], *ce = capture[2 * k + 1];
|
|
@@ -495,12 +537,11 @@ ScrArr *scr_regex_exec(ScrStr *s, ScrRegex *re) {
|
|
|
495
537
|
scr_arr_set_undefined(out, (double)out->len);
|
|
496
538
|
} else {
|
|
497
539
|
scr_arr_push_ref(
|
|
498
|
-
out,
|
|
540
|
+
out, scr_regex_span(&input, scr_capture_index(&input, cs), scr_capture_index(&input, ce)));
|
|
499
541
|
}
|
|
500
542
|
}
|
|
501
543
|
}
|
|
502
|
-
|
|
503
|
-
free(u);
|
|
544
|
+
scr_regex_input_dispose(&input);
|
|
504
545
|
return out; /* +1, or NULL (no match) */
|
|
505
546
|
}
|
|
506
547
|
|
|
@@ -515,22 +556,21 @@ ScrArr *scr_regex_match(ScrStr *s, ScrRegex *re) {
|
|
|
515
556
|
if (!(flags & LRE_FLAG_GLOBAL)) return scr_regex_exec(s, re);
|
|
516
557
|
re->last_index = 0;
|
|
517
558
|
bool unicode = (flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
559
|
+
ScrRegexInput input;
|
|
560
|
+
scr_regex_input_init(&input, bc, s);
|
|
561
|
+
int len = input.len;
|
|
562
|
+
uint8_t **capture = input.capture;
|
|
522
563
|
ScrArr *out = NULL;
|
|
523
564
|
int pos = scr_regex_start(re, len);
|
|
524
565
|
if (pos < 0) pos = len + 1;
|
|
525
|
-
while (pos <= len && scr_exec(
|
|
526
|
-
int start = (
|
|
527
|
-
int end = (
|
|
566
|
+
while (pos <= len && scr_exec(&input, bc, pos) == 1) {
|
|
567
|
+
int start = scr_capture_index(&input, capture[0]);
|
|
568
|
+
int end = scr_capture_index(&input, capture[1]);
|
|
528
569
|
if (!out) out = scr_arr_new(SCR_ELEM_STR, 4);
|
|
529
|
-
scr_arr_push_ref(out,
|
|
530
|
-
pos = start == end ? scr_advance(
|
|
570
|
+
scr_arr_push_ref(out, scr_regex_span(&input, start, end));
|
|
571
|
+
pos = start == end ? scr_advance(&input, end, unicode) : end;
|
|
531
572
|
}
|
|
532
|
-
|
|
533
|
-
free(u);
|
|
573
|
+
scr_regex_input_dispose(&input);
|
|
534
574
|
return out;
|
|
535
575
|
}
|
|
536
576
|
|
|
@@ -543,14 +583,13 @@ ScrArr *scr_regex_match(ScrStr *s, ScrRegex *re) {
|
|
|
543
583
|
* bytecode omits the implicit forward scan) — exactly Node. */
|
|
544
584
|
double scr_regex_search(ScrStr *s, ScrRegex *re) {
|
|
545
585
|
uint8_t *bc = scr_regex_bc(re);
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
uint8_t **capture =
|
|
549
|
-
int rc = scr_exec(
|
|
586
|
+
ScrRegexInput input;
|
|
587
|
+
scr_regex_input_init(&input, bc, s);
|
|
588
|
+
uint8_t **capture = input.capture;
|
|
589
|
+
int rc = scr_exec(&input, bc, 0);
|
|
550
590
|
double out = -1;
|
|
551
|
-
if (rc == 1) out = (double)(
|
|
552
|
-
|
|
553
|
-
free(u);
|
|
591
|
+
if (rc == 1) out = (double)scr_capture_index(&input, capture[0]);
|
|
592
|
+
scr_regex_input_dispose(&input);
|
|
554
593
|
return out;
|
|
555
594
|
}
|
|
556
595
|
|
|
@@ -574,17 +613,17 @@ static ScrArr *scr_regex_match_all_core(ScrStr *s, ScrRegex *re, ScrArr *indices
|
|
|
574
613
|
}
|
|
575
614
|
bool unicode = (re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0;
|
|
576
615
|
int capture_count = lre_get_capture_count(bc);
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
616
|
+
ScrRegexInput input;
|
|
617
|
+
scr_regex_input_init(&input, bc, s);
|
|
618
|
+
int len = input.len;
|
|
619
|
+
uint8_t **capture = input.capture;
|
|
581
620
|
ScrArr *out = scr_arr_new(SCR_ELEM_ARR, 4);
|
|
582
621
|
int pos = scr_regex_start(re, len);
|
|
583
622
|
if (pos < 0) pos = len + 1;
|
|
584
623
|
while (pos <= len) {
|
|
585
|
-
if (scr_exec(
|
|
586
|
-
int start = (
|
|
587
|
-
int end = (
|
|
624
|
+
if (scr_exec(&input, bc, pos) != 1) break;
|
|
625
|
+
int start = scr_capture_index(&input, capture[0]);
|
|
626
|
+
int end = scr_capture_index(&input, capture[1]);
|
|
588
627
|
ScrArr *row = scr_arr_new(SCR_ELEM_STR, (size_t)capture_count);
|
|
589
628
|
for (int k = 0; k < capture_count; k++) {
|
|
590
629
|
const uint8_t *cs = capture[2 * k], *ce = capture[2 * k + 1];
|
|
@@ -592,15 +631,14 @@ static ScrArr *scr_regex_match_all_core(ScrStr *s, ScrRegex *re, ScrArr *indices
|
|
|
592
631
|
scr_arr_set_undefined(row, (double)row->len);
|
|
593
632
|
} else {
|
|
594
633
|
scr_arr_push_ref(
|
|
595
|
-
row,
|
|
634
|
+
row, scr_regex_span(&input, scr_capture_index(&input, cs), scr_capture_index(&input, ce)));
|
|
596
635
|
}
|
|
597
636
|
}
|
|
598
637
|
scr_arr_push_ref(out, row);
|
|
599
638
|
if (indices != NULL) scr_arr_push_f64(indices, (double)start);
|
|
600
|
-
pos = end == start ? scr_advance(
|
|
639
|
+
pos = end == start ? scr_advance(&input, end, unicode) : end;
|
|
601
640
|
}
|
|
602
|
-
|
|
603
|
-
free(u);
|
|
641
|
+
scr_regex_input_dispose(&input);
|
|
604
642
|
return out; /* +1 (possibly empty — Node's no-match drain is []) */
|
|
605
643
|
}
|
|
606
644
|
|
|
@@ -628,17 +666,18 @@ ScrArr *scr_regex_match_all_into(ScrStr *s, ScrRegex *re, ScrArr *indices) {
|
|
|
628
666
|
* — also Node's unterminated-'$<name' answer either way. The template is
|
|
629
667
|
* scanned byte-wise: every '$' directive is ASCII, and UTF-8 continuation
|
|
630
668
|
* bytes can never alias it. */
|
|
631
|
-
static void scr_put_substitution(ScrJsonBuf *b, const
|
|
669
|
+
static void scr_put_substitution(ScrJsonBuf *b, const ScrRegexInput *input,
|
|
632
670
|
int start, int end, uint8_t **capture,
|
|
633
671
|
int capture_count, const char *groupnames,
|
|
634
672
|
const ScrStr *rep) {
|
|
635
|
-
const uint8_t *ubase = (const uint8_t *)u;
|
|
636
673
|
size_t i = 0;
|
|
637
674
|
while (i < rep->len) {
|
|
638
675
|
char c = rep->data[i];
|
|
639
676
|
if (c != '$' || i + 1 >= rep->len) {
|
|
640
|
-
|
|
641
|
-
|
|
677
|
+
const char *next = memchr(rep->data + i + 1, '$', rep->len - i - 1);
|
|
678
|
+
size_t end = next ? (size_t)(next - rep->data) : rep->len;
|
|
679
|
+
scr_jb_write(b, rep->data + i, end - i);
|
|
680
|
+
i = end;
|
|
642
681
|
continue;
|
|
643
682
|
}
|
|
644
683
|
char c1 = rep->data[i + 1];
|
|
@@ -646,13 +685,13 @@ static void scr_put_substitution(ScrJsonBuf *b, const uint16_t *u, int len,
|
|
|
646
685
|
scr_jb_putc(b, '$');
|
|
647
686
|
i += 2;
|
|
648
687
|
} else if (c1 == '&') {
|
|
649
|
-
|
|
688
|
+
scr_regex_put_span(b, input, start, end);
|
|
650
689
|
i += 2;
|
|
651
690
|
} else if (c1 == '`') {
|
|
652
|
-
|
|
691
|
+
scr_regex_put_span(b, input, 0, start);
|
|
653
692
|
i += 2;
|
|
654
693
|
} else if (c1 == '\'') {
|
|
655
|
-
|
|
694
|
+
scr_regex_put_span(b, input, end, input->len);
|
|
656
695
|
i += 2;
|
|
657
696
|
} else if (c1 >= '0' && c1 <= '9') {
|
|
658
697
|
int k = c1 - '0';
|
|
@@ -667,7 +706,7 @@ static void scr_put_substitution(ScrJsonBuf *b, const uint16_t *u, int len,
|
|
|
667
706
|
if (k >= 1 && k < capture_count) {
|
|
668
707
|
const uint8_t *cs = capture[2 * k], *ce = capture[2 * k + 1];
|
|
669
708
|
if (cs && ce) {
|
|
670
|
-
|
|
709
|
+
scr_regex_put_span(b, input, scr_capture_index(input, cs), scr_capture_index(input, ce));
|
|
671
710
|
}
|
|
672
711
|
i += adv;
|
|
673
712
|
} else {
|
|
@@ -693,7 +732,7 @@ static void scr_put_substitution(ScrJsonBuf *b, const uint16_t *u, int len,
|
|
|
693
732
|
if (glen == name_len && memcmp(p, name, name_len) == 0) {
|
|
694
733
|
const uint8_t *cs = capture[2 * k], *ce = capture[2 * k + 1];
|
|
695
734
|
if (cs && ce) {
|
|
696
|
-
|
|
735
|
+
scr_regex_put_span(b, input, scr_capture_index(input, cs), scr_capture_index(input, ce));
|
|
697
736
|
break; /* at most one duplicate participates */
|
|
698
737
|
}
|
|
699
738
|
}
|
|
@@ -718,31 +757,34 @@ static ScrStr *scr_replace_impl(ScrStr *s, ScrRegex *re, ScrStr *rep) {
|
|
|
718
757
|
bool unicode = (re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0;
|
|
719
758
|
int capture_count = lre_get_capture_count(bc);
|
|
720
759
|
const char *groupnames = lre_get_groupnames(bc);
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
760
|
+
ScrRegexInput input;
|
|
761
|
+
scr_regex_input_init(&input, bc, s);
|
|
762
|
+
int len = input.len;
|
|
763
|
+
uint8_t **capture = input.capture;
|
|
725
764
|
ScrJsonBuf b;
|
|
726
765
|
scr_jb_init(&b);
|
|
727
766
|
if (global) re->last_index = 0;
|
|
728
767
|
int next = 0, pos = sticky ? scr_regex_start(re, len) : 0;
|
|
729
768
|
if (pos < 0) pos = len + 1;
|
|
730
769
|
if (sticky && !global) re->last_index = 0;
|
|
770
|
+
bool matched = false;
|
|
771
|
+
bool literal = memchr(rep->data, '$', rep->len) == NULL;
|
|
731
772
|
while (pos <= len) {
|
|
732
|
-
if (scr_exec(
|
|
733
|
-
|
|
734
|
-
int
|
|
773
|
+
if (scr_exec(&input, bc, pos) != 1) break;
|
|
774
|
+
matched = true;
|
|
775
|
+
int start = scr_capture_index(&input, capture[0]);
|
|
776
|
+
int end = scr_capture_index(&input, capture[1]);
|
|
735
777
|
if (sticky && !global) re->last_index = end;
|
|
736
|
-
|
|
737
|
-
|
|
778
|
+
scr_regex_put_span(&b, &input, next, start);
|
|
779
|
+
if (literal) scr_jb_put_str(&b, rep);
|
|
780
|
+
else scr_put_substitution(&b, &input, start, end, capture, capture_count, groupnames, rep);
|
|
738
781
|
next = end;
|
|
739
782
|
if (!global) break;
|
|
740
|
-
pos = end == start ? scr_advance(
|
|
783
|
+
pos = end == start ? scr_advance(&input, end, unicode) : end;
|
|
741
784
|
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
return scr_jb_finish(&b);
|
|
785
|
+
if (matched) scr_regex_put_span(&b, &input, next, len);
|
|
786
|
+
scr_regex_input_dispose(&input);
|
|
787
|
+
return matched ? scr_jb_finish(&b) : scr_str_retain(s);
|
|
746
788
|
}
|
|
747
789
|
|
|
748
790
|
ScrStr *scr_regex_replace(ScrStr *s, ScrRegex *re, ScrStr *rep) {
|
|
@@ -825,10 +867,10 @@ ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit_num) {
|
|
|
825
867
|
int re_flags = lre_get_flags(bc);
|
|
826
868
|
bool unicode = (re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0;
|
|
827
869
|
bool sticky = (re_flags & LRE_FLAG_STICKY) != 0;
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
870
|
+
ScrRegexInput input;
|
|
871
|
+
scr_regex_input_init(&input, bc, s);
|
|
872
|
+
int len = input.len;
|
|
873
|
+
uint8_t **capture = input.capture;
|
|
832
874
|
ScrArr *out = scr_arr_new(SCR_ELEM_STR, 0);
|
|
833
875
|
|
|
834
876
|
/* ECMA-262 22.2.6.14 (Symbol.split). The spec probes every
|
|
@@ -838,31 +880,30 @@ ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit_num) {
|
|
|
838
880
|
* loop. A genuinely sticky pattern keeps the spec's probe-and-advance. */
|
|
839
881
|
if (len == 0) {
|
|
840
882
|
/* Empty subject: one probe — a match yields [], no match yields [""]. */
|
|
841
|
-
if (scr_exec(
|
|
883
|
+
if (scr_exec(&input, bc, 0) != 1) {
|
|
842
884
|
scr_arr_push_ref(out, scr_str_new("", 0));
|
|
843
885
|
}
|
|
844
|
-
|
|
845
|
-
free(u);
|
|
886
|
+
scr_regex_input_dispose(&input);
|
|
846
887
|
return out;
|
|
847
888
|
}
|
|
848
889
|
int p = 0, q = 0;
|
|
849
890
|
while (q < len) {
|
|
850
|
-
if (scr_exec(
|
|
891
|
+
if (scr_exec(&input, bc, q) != 1) {
|
|
851
892
|
if (!sticky) break; /* no match anywhere right of q */
|
|
852
|
-
q = scr_advance(
|
|
893
|
+
q = scr_advance(&input, q, unicode);
|
|
853
894
|
continue;
|
|
854
895
|
}
|
|
855
|
-
int start = (
|
|
856
|
-
int end = (
|
|
896
|
+
int start = scr_capture_index(&input, capture[0]);
|
|
897
|
+
int end = scr_capture_index(&input, capture[1]);
|
|
857
898
|
/* The sticky algorithm never probes the position after the subject.
|
|
858
899
|
* A forward search can find a zero-width match there; exclude it. */
|
|
859
900
|
if (start == len) break;
|
|
860
901
|
if (end == p) {
|
|
861
902
|
/* Zero-length match adjacent to the previous split point: advance
|
|
862
903
|
* (start == q == p here — the search cannot skip a match). */
|
|
863
|
-
q = scr_advance(
|
|
904
|
+
q = scr_advance(&input, start, unicode);
|
|
864
905
|
} else {
|
|
865
|
-
scr_arr_push_ref(out,
|
|
906
|
+
scr_arr_push_ref(out, scr_regex_span(&input, p, start));
|
|
866
907
|
if (out->len == limit) goto done;
|
|
867
908
|
for (int group = 1; group < capture_count; group++) {
|
|
868
909
|
const uint8_t *from = capture[2 * group];
|
|
@@ -872,8 +913,8 @@ ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit_num) {
|
|
|
872
913
|
// distinct from both empty strings and holes.
|
|
873
914
|
scr_arr_set_undefined(out, (double)out->len);
|
|
874
915
|
} else {
|
|
875
|
-
scr_arr_push_ref(out,
|
|
876
|
-
(
|
|
916
|
+
scr_arr_push_ref(out, scr_regex_span(&input,
|
|
917
|
+
scr_capture_index(&input, from), scr_capture_index(&input, to)));
|
|
877
918
|
}
|
|
878
919
|
if (out->len == limit) goto done;
|
|
879
920
|
}
|
|
@@ -881,10 +922,9 @@ ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit_num) {
|
|
|
881
922
|
q = p;
|
|
882
923
|
}
|
|
883
924
|
}
|
|
884
|
-
scr_arr_push_ref(out,
|
|
925
|
+
scr_arr_push_ref(out, scr_regex_span(&input, p, len));
|
|
885
926
|
done:
|
|
886
|
-
|
|
887
|
-
free(u);
|
|
927
|
+
scr_regex_input_dispose(&input);
|
|
888
928
|
return out;
|
|
889
929
|
}
|
|
890
930
|
|
|
@@ -985,10 +1025,38 @@ static void scr_case_put_cp(ScrJsonBuf *b, uint32_t cp) {
|
|
|
985
1025
|
}
|
|
986
1026
|
|
|
987
1027
|
static ScrStr *scr_str_case_conv(const ScrStr *s, int to_lower) {
|
|
1028
|
+
unsigned char first = to_lower ? 'A' : 'a';
|
|
1029
|
+
unsigned char last = to_lower ? 'Z' : 'z';
|
|
1030
|
+
if (scr_text_ascii(s)) {
|
|
1031
|
+
size_t changed = 0;
|
|
1032
|
+
while (changed < s->len &&
|
|
1033
|
+
((unsigned char)s->data[changed] < first || (unsigned char)s->data[changed] > last))
|
|
1034
|
+
changed++;
|
|
1035
|
+
if (changed == s->len) return scr_str_retain((ScrStr *)s);
|
|
1036
|
+
ScrStr *out = scr_str_alloc_raw(s->len, s->len);
|
|
1037
|
+
memcpy(out->data, s->data, changed);
|
|
1038
|
+
for (size_t i = changed; i < s->len; i++) {
|
|
1039
|
+
unsigned char c = (unsigned char)s->data[i];
|
|
1040
|
+
out->data[i] = (char)(c >= first && c <= last ? c ^ 0x20 : c);
|
|
1041
|
+
}
|
|
1042
|
+
out->data[s->len] = '\0';
|
|
1043
|
+
return out;
|
|
1044
|
+
}
|
|
988
1045
|
ScrJsonBuf b;
|
|
989
1046
|
scr_jb_init(&b);
|
|
990
1047
|
uint32_t res[LRE_CC_RES_LEN_MAX];
|
|
991
1048
|
for (size_t i = 0; i < s->len;) {
|
|
1049
|
+
if ((unsigned char)s->data[i] < 0x80) {
|
|
1050
|
+
size_t start = i;
|
|
1051
|
+
while (i < s->len && (unsigned char)s->data[i] < 0x80) i++;
|
|
1052
|
+
size_t output = b.len;
|
|
1053
|
+
scr_jb_write(&b, s->data + start, i - start);
|
|
1054
|
+
for (size_t j = output; j < b.len; j++) {
|
|
1055
|
+
unsigned char c = (unsigned char)b.data[j];
|
|
1056
|
+
if (c >= first && c <= last) b.data[j] = (char)(c ^ 0x20);
|
|
1057
|
+
}
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
992
1060
|
size_t adv;
|
|
993
1061
|
uint32_t c = scr_case_decode(s->data + i, &adv);
|
|
994
1062
|
int l;
|
|
@@ -1024,6 +1092,9 @@ ScrStr *scr_str_normalize(const ScrStr *s, const ScrStr *form) {
|
|
|
1024
1092
|
scr_throw_error(SCR_ERR_RANGE, scr_str_new(message, sizeof message - 1));
|
|
1025
1093
|
return NULL;
|
|
1026
1094
|
}
|
|
1095
|
+
/* Every ASCII string is already normalized in all four forms. Validate
|
|
1096
|
+
* the form first: even an empty subject must reject an invalid form. */
|
|
1097
|
+
if (scr_text_ascii(s)) return scr_str_retain((ScrStr *)s);
|
|
1027
1098
|
if (s->len > INT32_MAX / sizeof(uint32_t)) scr_regex_oom();
|
|
1028
1099
|
uint32_t *input = malloc((s->len + 1) * sizeof(uint32_t));
|
|
1029
1100
|
if (!input) scr_regex_oom();
|