@scriptc/cli-darwin-x64 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-x64/artifacts/dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_copying.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_number.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/package.json +1 -1
- package/dist/lib/runtime-darwin-x64/runtime-pack.json +183 -183
- 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
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* encoding conversions (utf8 with WHATWG replacement, hex, base64) match
|
|
8
8
|
* Node byte-for-byte — the differential corpus holds them to it. */
|
|
9
9
|
#include "scr_runtime.h"
|
|
10
|
+
#include "scr_numeric.h"
|
|
10
11
|
#include "scr_text_decoder_labels.h"
|
|
11
12
|
#ifdef SCR_TEXT_DECODER_LEGACY
|
|
12
13
|
#include "scr_text_decoder_data.h"
|
|
@@ -116,13 +117,16 @@ double scr_bytes_to_u8_clamp(double value) {
|
|
|
116
117
|
|
|
117
118
|
/* ── lifecycle ─────────────────────────────────────────────────────────── */
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
/* Adopt private malloc storage without clearing or copying its contents. The
|
|
121
|
+
* caller transfers ownership; views keep it alive through the usual owner. */
|
|
122
|
+
ScrBytes *scr_bytes_take_data(uint8_t *data, size_t len) {
|
|
123
|
+
if (!data && len) scr_trap("scriptc: NULL owned byte storage\n");
|
|
120
124
|
ScrBytes *b = malloc(sizeof(ScrBytes));
|
|
121
125
|
if (!b) scr_bytes_oom();
|
|
122
126
|
b->rc = 1;
|
|
123
127
|
b->len = len;
|
|
124
|
-
b->elem =
|
|
125
|
-
b->data =
|
|
128
|
+
b->elem = SCR_BYTES_U8;
|
|
129
|
+
b->data = data ? data : malloc(1);
|
|
126
130
|
if (!b->data) scr_bytes_oom();
|
|
127
131
|
b->backing = NULL;
|
|
128
132
|
b->is_buffer = false;
|
|
@@ -134,6 +138,27 @@ static ScrBytes *scr_bytes_alloc(ScrBytesElem elem, size_t len) {
|
|
|
134
138
|
return b;
|
|
135
139
|
}
|
|
136
140
|
|
|
141
|
+
/* Only complete, non-observable initialization may use private storage. */
|
|
142
|
+
static ScrBytes *scr_bytes_alloc_private(ScrBytesElem elem, size_t len) {
|
|
143
|
+
size_t width = scr_bytes_elem_size(elem);
|
|
144
|
+
if (len > SIZE_MAX / width) scr_bytes_oom();
|
|
145
|
+
uint8_t *data = malloc(len ? len * width : 1);
|
|
146
|
+
if (!data) scr_bytes_oom();
|
|
147
|
+
ScrBytes *b = scr_bytes_take_data(data, len);
|
|
148
|
+
b->elem = elem;
|
|
149
|
+
return b;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static ScrBytes *scr_bytes_alloc(ScrBytesElem elem, size_t len) {
|
|
153
|
+
size_t width = scr_bytes_elem_size(elem);
|
|
154
|
+
if (len > SIZE_MAX / width) scr_bytes_oom();
|
|
155
|
+
uint8_t *data = calloc(len ? len : 1, width);
|
|
156
|
+
if (!data) scr_bytes_oom();
|
|
157
|
+
ScrBytes *b = scr_bytes_take_data(data, len);
|
|
158
|
+
b->elem = elem;
|
|
159
|
+
return b;
|
|
160
|
+
}
|
|
161
|
+
|
|
137
162
|
ScrBytes *scr_bytes_from_external(void *data, size_t length) {
|
|
138
163
|
ScrBytes *b = scr_bytes_alloc(SCR_BYTES_U8, 0);
|
|
139
164
|
/* Keep the owned empty allocation for NULL/zero-length views: existing
|
|
@@ -168,13 +193,13 @@ ScrBytes *scr_bytes_from_data(const uint8_t *data, size_t len) {
|
|
|
168
193
|
if (data == NULL && len != 0) {
|
|
169
194
|
scr_trap("scriptc: native callback passed a NULL span with nonzero length\n");
|
|
170
195
|
}
|
|
171
|
-
ScrBytes *b =
|
|
196
|
+
ScrBytes *b = scr_bytes_alloc_private(SCR_BYTES_U8, len);
|
|
172
197
|
if (len != 0) memcpy(b->data, data, len);
|
|
173
198
|
return b;
|
|
174
199
|
}
|
|
175
200
|
|
|
176
201
|
ScrBytes *scr_bytes_copy(const ScrBytes *src) {
|
|
177
|
-
ScrBytes *b =
|
|
202
|
+
ScrBytes *b = scr_bytes_alloc_private(src->elem, src->len);
|
|
178
203
|
memcpy(b->data, src->data, src->len * scr_bytes_elem_size(src->elem));
|
|
179
204
|
return b;
|
|
180
205
|
}
|
|
@@ -190,13 +215,6 @@ ScrBytes *scr_bytes_as_buffer(ScrBytes *bytes) {
|
|
|
190
215
|
return scr_bytes_retain(bytes);
|
|
191
216
|
}
|
|
192
217
|
|
|
193
|
-
ScrBytes *scr_bytes_convert(ScrBytesElem elem, const ScrBytes *src) {
|
|
194
|
-
if (elem == src->elem) return scr_bytes_copy(src);
|
|
195
|
-
ScrBytes *out = scr_bytes_alloc(elem, src->len);
|
|
196
|
-
for (size_t i = 0; i < src->len; i++) scr_bytes_set(out, (double)i, scr_bytes_get(src, (double)i));
|
|
197
|
-
return out;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
218
|
void scr_bytes_release(ScrBytes *b) {
|
|
201
219
|
if (!b || b->rc == SIZE_MAX) return; /* NULL: an uninitialized `let` local */
|
|
202
220
|
if (--b->rc == 0) {
|
|
@@ -246,11 +264,7 @@ static size_t scr_bytes_check_index(const ScrBytes *b, double i) {
|
|
|
246
264
|
/* ToUint32: NaN/±Infinity → 0, truncate toward zero, wrap mod 2^32.
|
|
247
265
|
* ToUint8 is its low byte (2^8 divides 2^32, so the residues agree). */
|
|
248
266
|
static uint32_t scr_bytes_to_u32(double v) {
|
|
249
|
-
|
|
250
|
-
double t = trunc(v);
|
|
251
|
-
t = fmod(t, 4294967296.0);
|
|
252
|
-
if (t < 0) t += 4294967296.0;
|
|
253
|
-
return (uint32_t)t;
|
|
267
|
+
return scr_numeric_to_u32(v);
|
|
254
268
|
}
|
|
255
269
|
|
|
256
270
|
double scr_bytes_get(const ScrBytes *b, double i) {
|
|
@@ -336,6 +350,86 @@ void scr_bytes_set(ScrBytes *b, double i, double v) {
|
|
|
336
350
|
}
|
|
337
351
|
}
|
|
338
352
|
|
|
353
|
+
/* Dispatch once per bounded block, not once per element. Loads and stores
|
|
354
|
+
* use memcpy so views and external storage need no stronger alignment or
|
|
355
|
+
* aliasing promise. A bounded scratch block avoids a kind-pair code matrix. */
|
|
356
|
+
static void scr_bytes_read_numbers(double *out, const uint8_t *src, ScrBytesElem elem, size_t count) {
|
|
357
|
+
#define SCR_READ_NUMBERS(kind, type) \
|
|
358
|
+
case kind: \
|
|
359
|
+
for (size_t i = 0; i < count; i++) { \
|
|
360
|
+
type value; \
|
|
361
|
+
memcpy(&value, src + i * sizeof value, sizeof value); \
|
|
362
|
+
out[i] = (double)value; \
|
|
363
|
+
} \
|
|
364
|
+
return
|
|
365
|
+
switch (elem) {
|
|
366
|
+
case SCR_BYTES_U8C:
|
|
367
|
+
SCR_READ_NUMBERS(SCR_BYTES_U8, uint8_t);
|
|
368
|
+
SCR_READ_NUMBERS(SCR_BYTES_I8, int8_t);
|
|
369
|
+
SCR_READ_NUMBERS(SCR_BYTES_U16, uint16_t);
|
|
370
|
+
SCR_READ_NUMBERS(SCR_BYTES_I16, int16_t);
|
|
371
|
+
SCR_READ_NUMBERS(SCR_BYTES_U32, uint32_t);
|
|
372
|
+
SCR_READ_NUMBERS(SCR_BYTES_I32, int32_t);
|
|
373
|
+
SCR_READ_NUMBERS(SCR_BYTES_F32, float);
|
|
374
|
+
SCR_READ_NUMBERS(SCR_BYTES_F64, double);
|
|
375
|
+
}
|
|
376
|
+
#undef SCR_READ_NUMBERS
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
static void scr_bytes_write_numbers(uint8_t *dst, ScrBytesElem elem, const double *src, size_t count) {
|
|
380
|
+
#define SCR_WRITE_NUMBERS(type, expression) \
|
|
381
|
+
for (size_t i = 0; i < count; i++) { \
|
|
382
|
+
type value = (expression); \
|
|
383
|
+
memcpy(dst + i * sizeof value, &value, sizeof value); \
|
|
384
|
+
} \
|
|
385
|
+
return
|
|
386
|
+
switch (elem) {
|
|
387
|
+
case SCR_BYTES_U8: case SCR_BYTES_I8: {
|
|
388
|
+
SCR_WRITE_NUMBERS(uint8_t, (uint8_t)scr_numeric_to_u32(src[i]));
|
|
389
|
+
}
|
|
390
|
+
case SCR_BYTES_U8C: {
|
|
391
|
+
SCR_WRITE_NUMBERS(uint8_t, (uint8_t)scr_bytes_to_u8_clamp(src[i]));
|
|
392
|
+
}
|
|
393
|
+
case SCR_BYTES_U16: case SCR_BYTES_I16: {
|
|
394
|
+
SCR_WRITE_NUMBERS(uint16_t, (uint16_t)scr_numeric_to_u32(src[i]));
|
|
395
|
+
}
|
|
396
|
+
case SCR_BYTES_U32: case SCR_BYTES_I32: {
|
|
397
|
+
SCR_WRITE_NUMBERS(uint32_t, scr_numeric_to_u32(src[i]));
|
|
398
|
+
}
|
|
399
|
+
case SCR_BYTES_F32: {
|
|
400
|
+
SCR_WRITE_NUMBERS(float, (float)src[i]);
|
|
401
|
+
}
|
|
402
|
+
case SCR_BYTES_F64: {
|
|
403
|
+
memcpy(dst, src, count * sizeof(double));
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
#undef SCR_WRITE_NUMBERS
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/* Caller guarantees disjoint spans, or snapshots the source before entry. */
|
|
411
|
+
static void scr_bytes_convert_span(uint8_t *dst, ScrBytesElem dest_elem,
|
|
412
|
+
const uint8_t *src, ScrBytesElem src_elem, size_t count) {
|
|
413
|
+
size_t source_width = scr_bytes_elem_size(src_elem);
|
|
414
|
+
size_t dest_width = scr_bytes_elem_size(dest_elem);
|
|
415
|
+
double values[128];
|
|
416
|
+
while (count) {
|
|
417
|
+
size_t block = count < 128 ? count : 128;
|
|
418
|
+
scr_bytes_read_numbers(values, src, src_elem, block);
|
|
419
|
+
scr_bytes_write_numbers(dst, dest_elem, values, block);
|
|
420
|
+
src += block * source_width;
|
|
421
|
+
dst += block * dest_width;
|
|
422
|
+
count -= block;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
ScrBytes *scr_bytes_convert(ScrBytesElem elem, const ScrBytes *src) {
|
|
427
|
+
if (elem == src->elem) return scr_bytes_copy(src);
|
|
428
|
+
ScrBytes *out = scr_bytes_alloc_private(elem, src->len);
|
|
429
|
+
scr_bytes_convert_span(out->data, elem, src->data, src->elem, src->len);
|
|
430
|
+
return out;
|
|
431
|
+
}
|
|
432
|
+
|
|
339
433
|
/* ── slice (copy) / subarray (view) ────────────────────────────────────── */
|
|
340
434
|
|
|
341
435
|
/* Relative index: ToIntegerOrInfinity, negatives from the end, clamped. */
|
|
@@ -353,7 +447,7 @@ ScrBytes *scr_bytes_slice(const ScrBytes *b, double start, double end) {
|
|
|
353
447
|
size_t e = scr_bytes_rel_index(end, b->len);
|
|
354
448
|
size_t count = e > s ? e - s : 0;
|
|
355
449
|
size_t esize = scr_bytes_elem_size(b->elem);
|
|
356
|
-
ScrBytes *out =
|
|
450
|
+
ScrBytes *out = scr_bytes_alloc_private(b->elem, count);
|
|
357
451
|
memcpy(out->data, b->data + s * esize, count * esize);
|
|
358
452
|
return out;
|
|
359
453
|
}
|
|
@@ -376,7 +470,23 @@ ScrBytes *scr_bytes_copy_within(ScrBytes *b, double target, double start, double
|
|
|
376
470
|
ScrBytes *scr_bytes_fill_elem(ScrBytes *b, double v, double start, double end) {
|
|
377
471
|
size_t s = scr_bytes_rel_index(start, b->len);
|
|
378
472
|
size_t e = scr_bytes_rel_index(end, b->len);
|
|
379
|
-
|
|
473
|
+
if (e > s) {
|
|
474
|
+
size_t width = scr_bytes_elem_size(b->elem);
|
|
475
|
+
uint8_t pattern[8];
|
|
476
|
+
scr_bytes_write_numbers(pattern, b->elem, &v, 1);
|
|
477
|
+
uint8_t *dst = b->data + s * width;
|
|
478
|
+
size_t bytes = (e - s) * width;
|
|
479
|
+
if (width == 1) memset(dst, pattern[0], bytes);
|
|
480
|
+
else {
|
|
481
|
+
memcpy(dst, pattern, width);
|
|
482
|
+
size_t filled = width;
|
|
483
|
+
while (filled < bytes) {
|
|
484
|
+
size_t copy = filled < bytes - filled ? filled : bytes - filled;
|
|
485
|
+
memcpy(dst + filled, dst, copy);
|
|
486
|
+
filled += copy;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
380
490
|
return scr_bytes_retain(b);
|
|
381
491
|
}
|
|
382
492
|
|
|
@@ -414,16 +524,27 @@ void scr_bytes_set_from(ScrBytes *dst, const ScrBytes *src, double offset) {
|
|
|
414
524
|
scr_throw_error_msg(SCR_ERR_RANGE, msg, sizeof msg - 1);
|
|
415
525
|
return;
|
|
416
526
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
copy->len * scr_bytes_elem_size(copy->elem));
|
|
422
|
-
scr_bytes_release(copy);
|
|
527
|
+
size_t width = scr_bytes_elem_size(dst->elem);
|
|
528
|
+
uint8_t *target = dst->data + (size_t)t * width;
|
|
529
|
+
if (dst->elem == src->elem) {
|
|
530
|
+
memmove(target, src->data, src->len * width);
|
|
423
531
|
return;
|
|
424
532
|
}
|
|
425
|
-
size_t
|
|
426
|
-
|
|
533
|
+
size_t source_bytes = src->len * scr_bytes_elem_size(src->elem);
|
|
534
|
+
size_t dest_bytes = src->len * width;
|
|
535
|
+
uintptr_t to = (uintptr_t)target, from = (uintptr_t)src->data;
|
|
536
|
+
bool overlap = to <= from ? from - to < dest_bytes : to - from < source_bytes;
|
|
537
|
+
if (overlap) {
|
|
538
|
+
/* Snapshot raw source bytes before cross-kind writes. Distinct external
|
|
539
|
+
* wrappers can alias even without a shared backing identity. */
|
|
540
|
+
uint8_t *copy = malloc(source_bytes ? source_bytes : 1);
|
|
541
|
+
if (!copy) scr_bytes_oom();
|
|
542
|
+
memcpy(copy, src->data, source_bytes);
|
|
543
|
+
scr_bytes_convert_span(target, dst->elem, copy, src->elem, src->len);
|
|
544
|
+
free(copy);
|
|
545
|
+
} else {
|
|
546
|
+
scr_bytes_convert_span(target, dst->elem, src->data, src->elem, src->len);
|
|
547
|
+
}
|
|
427
548
|
}
|
|
428
549
|
|
|
429
550
|
/* Checked-native array-like sources. Runtime objects with an unsupported
|
|
@@ -766,79 +887,85 @@ static void scr_td_invalid(const char *encoding) {
|
|
|
766
887
|
scr_throw_error_msg_code(SCR_ERR_TYPE, message, (size_t)n, "ERR_ENCODING_INVALID_ENCODED_DATA");
|
|
767
888
|
}
|
|
768
889
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
890
|
+
/* Stop before the first non-ASCII byte; every word load stays in the span. */
|
|
891
|
+
static size_t scr_bytes_ascii_prefix(const uint8_t *data, size_t len) {
|
|
892
|
+
size_t i = 0;
|
|
893
|
+
while (len - i >= sizeof(uint64_t)) {
|
|
894
|
+
uint64_t word;
|
|
895
|
+
memcpy(&word, data + i, sizeof word);
|
|
896
|
+
if (word & UINT64_C(0x8080808080808080)) break;
|
|
897
|
+
i += sizeof word;
|
|
772
898
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
if (byte
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
needed = 3; cp = byte & 0x7;
|
|
803
|
-
} else {
|
|
804
|
-
if (fatal) { free(out); scr_td_invalid("utf-8"); return NULL; }
|
|
805
|
-
memcpy(out + o, "\xef\xbf\xbd", 3);
|
|
806
|
-
o += 3;
|
|
807
|
-
}
|
|
808
|
-
continue;
|
|
809
|
-
}
|
|
810
|
-
if (byte < lower || byte > upper) {
|
|
811
|
-
/* Invalid continuation: replace the subpart, REPROCESS this byte. */
|
|
812
|
-
if (fatal) { free(out); scr_td_invalid("utf-8"); return NULL; }
|
|
813
|
-
memcpy(out + o, "\xef\xbf\xbd", 3);
|
|
814
|
-
o += 3;
|
|
815
|
-
needed = 0; lower = 0x80; upper = 0xbf;
|
|
816
|
-
i--;
|
|
817
|
-
continue;
|
|
818
|
-
}
|
|
819
|
-
lower = 0x80; upper = 0xbf;
|
|
820
|
-
cp = (cp << 6) | (byte & 0x3f);
|
|
821
|
-
if (--needed == 0) {
|
|
822
|
-
/* Re-encode the (valid, non-surrogate, <= 10FFFF) code point. */
|
|
823
|
-
if (cp <= 0x7f) {
|
|
824
|
-
out[o++] = (char)cp;
|
|
825
|
-
} else if (cp <= 0x7ff) {
|
|
826
|
-
out[o++] = (char)(0xc0 | (cp >> 6));
|
|
827
|
-
out[o++] = (char)(0x80 | (cp & 0x3f));
|
|
828
|
-
} else if (cp <= 0xffff) {
|
|
829
|
-
out[o++] = (char)(0xe0 | (cp >> 12));
|
|
830
|
-
out[o++] = (char)(0x80 | ((cp >> 6) & 0x3f));
|
|
831
|
-
out[o++] = (char)(0x80 | (cp & 0x3f));
|
|
832
|
-
} else {
|
|
833
|
-
out[o++] = (char)(0xf0 | (cp >> 18));
|
|
834
|
-
out[o++] = (char)(0x80 | ((cp >> 12) & 0x3f));
|
|
835
|
-
out[o++] = (char)(0x80 | ((cp >> 6) & 0x3f));
|
|
836
|
-
out[o++] = (char)(0x80 | (cp & 0x3f));
|
|
899
|
+
while (i < len && data[i] < 0x80) i++;
|
|
900
|
+
return i;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/* Length of the well-formed prefix. On failure, next skips exactly the
|
|
904
|
+
* maximal invalid subpart; an offending continuation is reprocessed. */
|
|
905
|
+
static size_t scr_bytes_utf8_prefix(const uint8_t *data, size_t len, size_t *next) {
|
|
906
|
+
size_t i = 0;
|
|
907
|
+
while (i < len) {
|
|
908
|
+
i += scr_bytes_ascii_prefix(data + i, len - i);
|
|
909
|
+
if (i == len) break;
|
|
910
|
+
size_t start = i;
|
|
911
|
+
unsigned byte = data[i++], count;
|
|
912
|
+
unsigned low = 0x80, high = 0xbf;
|
|
913
|
+
if (byte < 0x80) continue;
|
|
914
|
+
if (byte >= 0xc2 && byte <= 0xdf) count = 1;
|
|
915
|
+
else if (byte >= 0xe0 && byte <= 0xef) {
|
|
916
|
+
count = 2;
|
|
917
|
+
if (byte == 0xe0) low = 0xa0;
|
|
918
|
+
if (byte == 0xed) high = 0x9f;
|
|
919
|
+
} else if (byte >= 0xf0 && byte <= 0xf4) {
|
|
920
|
+
count = 3;
|
|
921
|
+
if (byte == 0xf0) low = 0x90;
|
|
922
|
+
if (byte == 0xf4) high = 0x8f;
|
|
923
|
+
} else { *next = i; return start; }
|
|
924
|
+
for (unsigned j = 0; j < count; j++) {
|
|
925
|
+
if (i == len || data[i] < low || data[i] > high) {
|
|
926
|
+
*next = i;
|
|
927
|
+
return start;
|
|
837
928
|
}
|
|
929
|
+
i++;
|
|
930
|
+
low = 0x80;
|
|
931
|
+
high = 0xbf;
|
|
838
932
|
}
|
|
839
933
|
}
|
|
840
|
-
|
|
841
|
-
|
|
934
|
+
*next = len;
|
|
935
|
+
return len;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/* Measure first, then write into final string storage. Invalid input can
|
|
939
|
+
* expand, but neither valid prefixes nor retained output need a 3x buffer. */
|
|
940
|
+
static size_t scr_bytes_utf8_repair(const uint8_t *in, size_t n,
|
|
941
|
+
size_t prefix, size_t next, char *out) {
|
|
942
|
+
size_t written = 0, offset = 0;
|
|
943
|
+
for (;;) {
|
|
944
|
+
if (prefix > SIZE_MAX - written) scr_bytes_oom();
|
|
945
|
+
if (out && prefix) memcpy(out + written, in + offset, prefix);
|
|
946
|
+
written += prefix;
|
|
947
|
+
if (prefix == n - offset) return written;
|
|
948
|
+
if (written > SIZE_MAX - 3) scr_bytes_oom();
|
|
949
|
+
if (out) memcpy(out + written, "\xef\xbf\xbd", 3);
|
|
950
|
+
written += 3;
|
|
951
|
+
offset += next;
|
|
952
|
+
prefix = scr_bytes_utf8_prefix(in + offset, n - offset, &next);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
static ScrStr *scr_bytes_decode_utf8_options(const uint8_t *in, size_t n, bool fatal) {
|
|
957
|
+
if (in == NULL && n != 0) {
|
|
958
|
+
scr_trap("scriptc: native callback passed a NULL span with nonzero length\n");
|
|
959
|
+
}
|
|
960
|
+
if (n == 0) return scr_str_new("", 0);
|
|
961
|
+
size_t next;
|
|
962
|
+
size_t prefix = scr_bytes_utf8_prefix(in, n, &next);
|
|
963
|
+
if (prefix == n) return scr_str_new((const char *)in, n);
|
|
964
|
+
if (fatal) { scr_td_invalid("utf-8"); return NULL; }
|
|
965
|
+
size_t length = scr_bytes_utf8_repair(in, n, prefix, next, NULL);
|
|
966
|
+
ScrStr *s = scr_str_alloc_raw(length, length);
|
|
967
|
+
scr_bytes_utf8_repair(in, n, prefix, next, s->data);
|
|
968
|
+
s->data[length] = '\0';
|
|
842
969
|
return s;
|
|
843
970
|
}
|
|
844
971
|
|
|
@@ -1109,23 +1236,30 @@ static ScrStr *scr_bytes_encode_b64(const uint8_t *in, size_t n, bool url) {
|
|
|
1109
1236
|
static const char url_abc[] =
|
|
1110
1237
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
1111
1238
|
const char *abc = url ? url_abc : std_abc;
|
|
1112
|
-
size_t
|
|
1113
|
-
|
|
1114
|
-
if (
|
|
1115
|
-
size_t
|
|
1116
|
-
|
|
1239
|
+
size_t groups = n / 3, tail = n % 3;
|
|
1240
|
+
size_t suffix = tail ? (url ? tail + 1 : 4) : 0;
|
|
1241
|
+
if (groups > (SIZE_MAX - suffix) / 4) scr_bytes_oom();
|
|
1242
|
+
size_t outlen = groups * 4 + suffix;
|
|
1243
|
+
ScrStr *s = scr_str_alloc_raw(outlen, outlen);
|
|
1244
|
+
char *out = s->data;
|
|
1245
|
+
size_t i = 0, o = 0;
|
|
1246
|
+
for (; i < groups * 3; i += 3) {
|
|
1247
|
+
unsigned v = ((unsigned)in[i] << 16) | ((unsigned)in[i + 1] << 8) | in[i + 2];
|
|
1248
|
+
out[o++] = abc[v >> 18];
|
|
1249
|
+
out[o++] = abc[(v >> 12) & 63];
|
|
1250
|
+
out[o++] = abc[(v >> 6) & 63];
|
|
1251
|
+
out[o++] = abc[v & 63];
|
|
1252
|
+
}
|
|
1253
|
+
if (tail) {
|
|
1117
1254
|
unsigned v = (unsigned)in[i] << 16;
|
|
1118
|
-
if (
|
|
1119
|
-
|
|
1120
|
-
out[o++] = abc[(v >> 18) & 63];
|
|
1255
|
+
if (tail == 2) v |= (unsigned)in[i + 1] << 8;
|
|
1256
|
+
out[o++] = abc[v >> 18];
|
|
1121
1257
|
out[o++] = abc[(v >> 12) & 63];
|
|
1122
|
-
if (
|
|
1123
|
-
else if (!url) out[o++] = '=';
|
|
1124
|
-
if (i + 2 < n) out[o++] = abc[v & 63];
|
|
1258
|
+
if (tail == 2) out[o++] = abc[(v >> 6) & 63];
|
|
1125
1259
|
else if (!url) out[o++] = '=';
|
|
1260
|
+
if (!url) out[o++] = '=';
|
|
1126
1261
|
}
|
|
1127
|
-
|
|
1128
|
-
free(out);
|
|
1262
|
+
out[outlen] = '\0';
|
|
1129
1263
|
return s;
|
|
1130
1264
|
}
|
|
1131
1265
|
|
|
@@ -1817,7 +1951,12 @@ ScrDyn *scr_text_encode_into(const ScrDyn *source, const ScrDyn *destination) {
|
|
|
1817
1951
|
const ScrStr *text = source->v.str;
|
|
1818
1952
|
ScrBytes *dest = destination->v.bytes;
|
|
1819
1953
|
size_t read = 0, written = 0;
|
|
1820
|
-
|
|
1954
|
+
size_t limit = text->len < dest->len ? text->len : dest->len;
|
|
1955
|
+
while (written < limit) {
|
|
1956
|
+
size_t ascii = scr_bytes_ascii_prefix((const uint8_t *)text->data + written, limit - written);
|
|
1957
|
+
written += ascii;
|
|
1958
|
+
read += ascii;
|
|
1959
|
+
if (written == limit) break;
|
|
1821
1960
|
size_t end = written;
|
|
1822
1961
|
uint32_t cp = scr_bytes_next_cp((const uint8_t *)text->data, &end);
|
|
1823
1962
|
if (end > dest->len) break;
|
|
@@ -1840,33 +1979,14 @@ static ScrBytes *scr_buffer_validation_input(const ScrDyn *input) {
|
|
|
1840
1979
|
}
|
|
1841
1980
|
|
|
1842
1981
|
static bool scr_buffer_utf8_valid(const uint8_t *data, size_t len) {
|
|
1843
|
-
size_t
|
|
1844
|
-
|
|
1845
|
-
unsigned byte = data[i++], count;
|
|
1846
|
-
unsigned low = 0x80, high = 0xbf;
|
|
1847
|
-
if (byte < 0x80) continue;
|
|
1848
|
-
if (byte >= 0xc2 && byte <= 0xdf) count = 1;
|
|
1849
|
-
else if (byte >= 0xe0 && byte <= 0xef) {
|
|
1850
|
-
count = 2;
|
|
1851
|
-
if (byte == 0xe0) low = 0xa0;
|
|
1852
|
-
if (byte == 0xed) high = 0x9f;
|
|
1853
|
-
} else if (byte >= 0xf0 && byte <= 0xf4) {
|
|
1854
|
-
count = 3;
|
|
1855
|
-
if (byte == 0xf0) low = 0x90;
|
|
1856
|
-
if (byte == 0xf4) high = 0x8f;
|
|
1857
|
-
} else return false;
|
|
1858
|
-
if (count > len - i || data[i] < low || data[i] > high) return false;
|
|
1859
|
-
i++;
|
|
1860
|
-
for (unsigned j = 1; j < count; j++, i++) if (data[i] < 0x80 || data[i] > 0xbf) return false;
|
|
1861
|
-
}
|
|
1862
|
-
return true;
|
|
1982
|
+
size_t next;
|
|
1983
|
+
return scr_bytes_utf8_prefix(data, len, &next) == len;
|
|
1863
1984
|
}
|
|
1864
1985
|
|
|
1865
1986
|
bool scr_buffer_is_ascii(const ScrDyn *input) {
|
|
1866
1987
|
ScrBytes *bytes = scr_buffer_validation_input(input);
|
|
1867
1988
|
if (!bytes) return false;
|
|
1868
|
-
bool result =
|
|
1869
|
-
for (size_t i = 0; i < bytes->len; i++) if (bytes->data[i] > 0x7f) { result = false; break; }
|
|
1989
|
+
bool result = scr_bytes_ascii_prefix(bytes->data, bytes->len) == bytes->len;
|
|
1870
1990
|
scr_bytes_release(bytes);
|
|
1871
1991
|
return result;
|
|
1872
1992
|
}
|
|
@@ -2021,25 +2141,28 @@ static bool scr_enc_is(const ScrStr *enc, const char *name) {
|
|
|
2021
2141
|
* surrogate becomes U+FFFD — Node keeps it as a lone UTF-16 unit, which
|
|
2022
2142
|
* UTF-8 string storage cannot hold (SEMANTICS.md divergence; stdout
|
|
2023
2143
|
* agrees byte-for-byte because Node's own write replaces it there too). */
|
|
2144
|
+
/* Consume one scalar, replacing an unpaired surrogate at the storage boundary. */
|
|
2145
|
+
static uint32_t scr_bytes_utf16le_cp(const uint8_t *in, size_t units, size_t *u) {
|
|
2146
|
+
uint32_t cu = (uint32_t)in[*u * 2] | ((uint32_t)in[*u * 2 + 1] << 8);
|
|
2147
|
+
(*u)++;
|
|
2148
|
+
if (cu >= 0xd800 && cu <= 0xdbff && *u < units) {
|
|
2149
|
+
uint32_t lo = (uint32_t)in[*u * 2] | ((uint32_t)in[*u * 2 + 1] << 8);
|
|
2150
|
+
if (lo >= 0xdc00 && lo <= 0xdfff) {
|
|
2151
|
+
(*u)++;
|
|
2152
|
+
return 0x10000 + ((cu - 0xd800) << 10) + (lo - 0xdc00);
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
return cu >= 0xd800 && cu <= 0xdfff ? 0xfffd : cu;
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2024
2158
|
static ScrStr *scr_bytes_decode_utf16le(const uint8_t *in, size_t n) {
|
|
2025
2159
|
size_t units = n / 2;
|
|
2026
|
-
|
|
2027
|
-
|
|
2160
|
+
if (units > SIZE_MAX / 3) scr_bytes_oom();
|
|
2161
|
+
ScrStr *s = scr_str_alloc_raw(0, units * 3);
|
|
2028
2162
|
size_t o = 0;
|
|
2029
|
-
for (size_t u = 0; u < units; u
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
uint32_t lo = (uint32_t)in[(u + 1) * 2] | ((uint32_t)in[(u + 1) * 2 + 1] << 8);
|
|
2033
|
-
if (lo >= 0xdc00 && lo <= 0xdfff) {
|
|
2034
|
-
o = scr_bytes_put_cp(out, o, 0x10000 + ((cu - 0xd800) << 10) + (lo - 0xdc00));
|
|
2035
|
-
u++;
|
|
2036
|
-
continue;
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
o = scr_bytes_put_cp(out, o, cu >= 0xd800 && cu <= 0xdfff ? 0xfffd : cu);
|
|
2040
|
-
}
|
|
2041
|
-
ScrStr *s = scr_str_new(out, o);
|
|
2042
|
-
free(out);
|
|
2163
|
+
for (size_t u = 0; u < units;) o = scr_bytes_put_cp(s->data, o, scr_bytes_utf16le_cp(in, units, &u));
|
|
2164
|
+
s->len = o;
|
|
2165
|
+
s->data[o] = '\0';
|
|
2043
2166
|
return s;
|
|
2044
2167
|
}
|
|
2045
2168
|
|
|
@@ -2049,35 +2172,34 @@ ScrStr *scr_bytes_to_str(const ScrBytes *b, const ScrStr *enc) {
|
|
|
2049
2172
|
/* Implicit native string/number coercions have no encoding argument. */
|
|
2050
2173
|
if (!enc) return scr_bytes_decode_utf8(in, n);
|
|
2051
2174
|
if (scr_enc_is(enc, "hex")) {
|
|
2052
|
-
|
|
2053
|
-
|
|
2175
|
+
if (n > SIZE_MAX / 2) scr_bytes_oom();
|
|
2176
|
+
ScrStr *s = scr_str_alloc_raw(n * 2, n * 2);
|
|
2177
|
+
char *out = s->data;
|
|
2054
2178
|
for (size_t i = 0; i < n; i++) {
|
|
2055
2179
|
out[i * 2] = scr_hex_digits[in[i] >> 4];
|
|
2056
2180
|
out[i * 2 + 1] = scr_hex_digits[in[i] & 0xf];
|
|
2057
2181
|
}
|
|
2058
|
-
|
|
2059
|
-
free(out);
|
|
2182
|
+
out[n * 2] = '\0';
|
|
2060
2183
|
return s;
|
|
2061
2184
|
}
|
|
2062
2185
|
if (scr_enc_is(enc, "base64")) return scr_bytes_encode_b64(in, n, false);
|
|
2063
2186
|
if (scr_enc_is(enc, "base64url")) return scr_bytes_encode_b64(in, n, true);
|
|
2064
2187
|
if (scr_enc_is(enc, "latin1")) {
|
|
2065
2188
|
/* Each byte is U+00XX ("binary" normalizes here upstream). */
|
|
2066
|
-
|
|
2067
|
-
|
|
2189
|
+
size_t high = 0;
|
|
2190
|
+
for (size_t i = 0; i < n; i++) high += in[i] >> 7;
|
|
2191
|
+
if (n > SIZE_MAX - high) scr_bytes_oom();
|
|
2192
|
+
ScrStr *s = scr_str_alloc_raw(n + high, n + high);
|
|
2068
2193
|
size_t o = 0;
|
|
2069
|
-
for (size_t i = 0; i < n; i++) o = scr_bytes_put_cp(
|
|
2070
|
-
|
|
2071
|
-
free(out);
|
|
2194
|
+
for (size_t i = 0; i < n; i++) o = scr_bytes_put_cp(s->data, o, in[i]);
|
|
2195
|
+
s->data[o] = '\0';
|
|
2072
2196
|
return s;
|
|
2073
2197
|
}
|
|
2074
2198
|
if (scr_enc_is(enc, "ascii")) {
|
|
2075
2199
|
/* Node's ascii decode masks the high bit: byte & 0x7f. */
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
ScrStr *s = scr_str_new(out, n);
|
|
2080
|
-
free(out);
|
|
2200
|
+
ScrStr *s = scr_str_alloc_raw(n, n);
|
|
2201
|
+
for (size_t i = 0; i < n; i++) s->data[i] = (char)(in[i] & 0x7f);
|
|
2202
|
+
s->data[n] = '\0';
|
|
2081
2203
|
return s;
|
|
2082
2204
|
}
|
|
2083
2205
|
if (scr_enc_is(enc, "utf16le")) return scr_bytes_decode_utf16le(in, n);
|
|
@@ -2158,13 +2280,72 @@ static int scr_hex_val(uint8_t c) {
|
|
|
2158
2280
|
return -1;
|
|
2159
2281
|
}
|
|
2160
2282
|
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2283
|
+
/* Both alphabets are accepted by both Buffer base64 encoding names. */
|
|
2284
|
+
static const int8_t scr_b64_values[256] = {
|
|
2285
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2286
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2287
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63,
|
|
2288
|
+
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
|
|
2289
|
+
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
2290
|
+
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
|
|
2291
|
+
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
2292
|
+
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
|
|
2293
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2294
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2295
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2296
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2297
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2298
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2299
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2300
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
2301
|
+
};
|
|
2302
|
+
|
|
2303
|
+
/* Conversion destinations are private until their initialized length is set.
|
|
2304
|
+
* General typed-array allocation must remain zero-filled. */
|
|
2305
|
+
static ScrBytes *scr_bytes_conversion_storage(size_t capacity) {
|
|
2306
|
+
uint8_t *data = malloc(capacity ? capacity : 1);
|
|
2307
|
+
if (!data) scr_bytes_oom();
|
|
2308
|
+
return scr_bytes_take_data(data, 0);
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
static ScrBytes *scr_bytes_decode_b64(const uint8_t *in, size_t n) {
|
|
2312
|
+
ScrBytes *b = scr_bytes_conversion_storage(n / 4 * 3 + 2);
|
|
2313
|
+
size_t i = 0, o = 0;
|
|
2314
|
+
unsigned acc = 0, have = 0;
|
|
2315
|
+
while (i < n) {
|
|
2316
|
+
/* Common complete groups need neither per-character branches nor state. */
|
|
2317
|
+
if (have == 0 && n - i >= 4) {
|
|
2318
|
+
int a = scr_b64_values[in[i]], c = scr_b64_values[in[i + 1]];
|
|
2319
|
+
int d = scr_b64_values[in[i + 2]], e = scr_b64_values[in[i + 3]];
|
|
2320
|
+
if ((a | c | d | e) >= 0) {
|
|
2321
|
+
unsigned v = ((unsigned)a << 18) | ((unsigned)c << 12) | ((unsigned)d << 6) | (unsigned)e;
|
|
2322
|
+
b->data[o++] = (uint8_t)(v >> 16);
|
|
2323
|
+
b->data[o++] = (uint8_t)(v >> 8);
|
|
2324
|
+
b->data[o++] = (uint8_t)v;
|
|
2325
|
+
i += 4;
|
|
2326
|
+
continue;
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
uint8_t byte = in[i++];
|
|
2330
|
+
if (byte == '=') break;
|
|
2331
|
+
int v = scr_b64_values[byte];
|
|
2332
|
+
if (v < 0) continue;
|
|
2333
|
+
acc = (acc << 6) | (unsigned)v;
|
|
2334
|
+
if (++have == 4) {
|
|
2335
|
+
b->data[o++] = (uint8_t)(acc >> 16);
|
|
2336
|
+
b->data[o++] = (uint8_t)(acc >> 8);
|
|
2337
|
+
b->data[o++] = (uint8_t)acc;
|
|
2338
|
+
acc = 0;
|
|
2339
|
+
have = 0;
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
if (have == 2) b->data[o++] = (uint8_t)(acc >> 4);
|
|
2343
|
+
else if (have == 3) {
|
|
2344
|
+
b->data[o++] = (uint8_t)(acc >> 10);
|
|
2345
|
+
b->data[o++] = (uint8_t)(acc >> 2);
|
|
2346
|
+
}
|
|
2347
|
+
b->len = o;
|
|
2348
|
+
return b;
|
|
2168
2349
|
}
|
|
2169
2350
|
|
|
2170
2351
|
ScrBytes *scr_bytes_from_str(const ScrStr *s, const ScrStr *enc) {
|
|
@@ -2173,7 +2354,7 @@ ScrBytes *scr_bytes_from_str(const ScrStr *s, const ScrStr *enc) {
|
|
|
2173
2354
|
if (scr_enc_is(enc, "latin1") || scr_enc_is(enc, "ascii")) {
|
|
2174
2355
|
/* Node writes charCodeAt(i) & 0xFF for BOTH spellings — an astral
|
|
2175
2356
|
* code point contributes its two surrogates' low bytes. */
|
|
2176
|
-
ScrBytes *b =
|
|
2357
|
+
ScrBytes *b = scr_bytes_conversion_storage(n);
|
|
2177
2358
|
size_t o = 0, i = 0;
|
|
2178
2359
|
while (i < n) {
|
|
2179
2360
|
uint32_t cp = scr_bytes_next_cp(in, &i);
|
|
@@ -2189,7 +2370,8 @@ ScrBytes *scr_bytes_from_str(const ScrStr *s, const ScrStr *enc) {
|
|
|
2189
2370
|
return b;
|
|
2190
2371
|
}
|
|
2191
2372
|
if (scr_enc_is(enc, "utf16le")) {
|
|
2192
|
-
|
|
2373
|
+
if (n > SIZE_MAX / 2) scr_bytes_oom();
|
|
2374
|
+
ScrBytes *b = scr_bytes_conversion_storage(n * 2);
|
|
2193
2375
|
size_t o = 0, i = 0;
|
|
2194
2376
|
while (i < n) {
|
|
2195
2377
|
uint32_t cp = scr_bytes_next_cp(in, &i);
|
|
@@ -2208,61 +2390,70 @@ ScrBytes *scr_bytes_from_str(const ScrStr *s, const ScrStr *enc) {
|
|
|
2208
2390
|
b->len = o;
|
|
2209
2391
|
return b;
|
|
2210
2392
|
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
unsigned acc = 0;
|
|
2233
|
-
int have = 0;
|
|
2234
|
-
for (size_t i = 0; i < n; i++) {
|
|
2235
|
-
int v = scr_b64_val(in[i]);
|
|
2236
|
-
if (v < 0) continue;
|
|
2237
|
-
acc = (acc << 6) | (unsigned)v;
|
|
2238
|
-
if (++have == 4) {
|
|
2239
|
-
b->data[o++] = (uint8_t)(acc >> 16);
|
|
2240
|
-
b->data[o++] = (uint8_t)(acc >> 8);
|
|
2241
|
-
b->data[o++] = (uint8_t)acc;
|
|
2242
|
-
acc = 0;
|
|
2243
|
-
have = 0;
|
|
2393
|
+
bool hex = scr_enc_is(enc, "hex");
|
|
2394
|
+
if (hex || scr_enc_is(enc, "base64") || scr_enc_is(enc, "base64url")) {
|
|
2395
|
+
/* Node interprets encoded text as the low byte of each UTF-16 unit.
|
|
2396
|
+
* ASCII can borrow storage; non-ASCII must preserve that truncation. */
|
|
2397
|
+
ScrBytes *narrowed = NULL;
|
|
2398
|
+
if (scr_bytes_ascii_prefix(in, n) != n) {
|
|
2399
|
+
ScrStr *latin1 = scr_str_new("latin1", 6);
|
|
2400
|
+
narrowed = scr_bytes_from_str(s, latin1);
|
|
2401
|
+
scr_str_release(latin1);
|
|
2402
|
+
in = narrowed->data;
|
|
2403
|
+
n = narrowed->len;
|
|
2404
|
+
}
|
|
2405
|
+
ScrBytes *b;
|
|
2406
|
+
if (hex) {
|
|
2407
|
+
/* Stop at the first invalid pair, discarding an odd tail. */
|
|
2408
|
+
b = scr_bytes_conversion_storage(n / 2);
|
|
2409
|
+
size_t o = 0;
|
|
2410
|
+
for (size_t i = 0; i + 1 < n; i += 2) {
|
|
2411
|
+
int hi = scr_hex_val(in[i]), lo = scr_hex_val(in[i + 1]);
|
|
2412
|
+
if (hi < 0 || lo < 0) break;
|
|
2413
|
+
b->data[o++] = (uint8_t)((hi << 4) | lo);
|
|
2244
2414
|
}
|
|
2415
|
+
b->len = o;
|
|
2416
|
+
} else {
|
|
2417
|
+
b = scr_bytes_decode_b64(in, n);
|
|
2245
2418
|
}
|
|
2246
|
-
|
|
2247
|
-
else if (have == 3) {
|
|
2248
|
-
b->data[o++] = (uint8_t)(acc >> 10);
|
|
2249
|
-
b->data[o++] = (uint8_t)(acc >> 2);
|
|
2250
|
-
}
|
|
2251
|
-
b->len = o;
|
|
2419
|
+
scr_bytes_release(narrowed);
|
|
2252
2420
|
return b;
|
|
2253
2421
|
}
|
|
2254
2422
|
/* utf8: ScrStr storage IS the bytes */
|
|
2255
|
-
ScrBytes *b =
|
|
2423
|
+
ScrBytes *b = scr_bytes_conversion_storage(n);
|
|
2256
2424
|
memcpy(b->data, in, n);
|
|
2425
|
+
b->len = n;
|
|
2257
2426
|
return b;
|
|
2258
2427
|
}
|
|
2259
2428
|
|
|
2429
|
+
/* Runtime encoding variables share the output conversion alias/error table.
|
|
2430
|
+
* Buffer.from treats an empty encoding as utf8, even for an empty source. */
|
|
2431
|
+
ScrBytes *scr_bytes_from_str_checked(const ScrStr *s, const ScrStr *enc) {
|
|
2432
|
+
ScrStr *normalized = enc->len ? scr_bytes_normalize_encoding(enc) : scr_str_new("utf8", 4);
|
|
2433
|
+
if (!normalized) return NULL;
|
|
2434
|
+
ScrBytes *out = scr_bytes_from_str(s, normalized);
|
|
2435
|
+
scr_str_release(normalized);
|
|
2436
|
+
return out;
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2260
2439
|
ScrBytes *scr_bytes_from_arr(ScrBytesElem elem, const ScrArr *arr) {
|
|
2261
|
-
ScrBytes *b =
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2440
|
+
ScrBytes *b = scr_bytes_alloc_private(elem, arr->len);
|
|
2441
|
+
size_t width = scr_bytes_elem_size(elem);
|
|
2442
|
+
double values[128];
|
|
2443
|
+
for (size_t start = 0; start < arr->len;) {
|
|
2444
|
+
size_t count = arr->len - start < 128 ? arr->len - start : 128;
|
|
2445
|
+
for (size_t i = 0; i < count; i++) {
|
|
2446
|
+
size_t index = start + i;
|
|
2447
|
+
/* Sparse tails and explicit undefined retain ordinary iteration
|
|
2448
|
+
* semantics. Numeric array slots own no conversion callbacks. */
|
|
2449
|
+
if (index < arr->cap) {
|
|
2450
|
+
if (arr->present[index] == SCR_ARR_VALUE)
|
|
2451
|
+
memcpy(&values[i], &arr->data[index], sizeof(double));
|
|
2452
|
+
else values[i] = NAN;
|
|
2453
|
+
} else values[i] = scr_arr_get_number(arr, (double)index);
|
|
2454
|
+
}
|
|
2455
|
+
scr_bytes_write_numbers(b->data + start * width, elem, values, count);
|
|
2456
|
+
start += count;
|
|
2266
2457
|
}
|
|
2267
2458
|
return b;
|
|
2268
2459
|
}
|
|
@@ -2487,6 +2678,36 @@ double scr_bytes_write_str(ScrBytes *b, const ScrStr *s, const ScrStr *enc,
|
|
|
2487
2678
|
} else {
|
|
2488
2679
|
budget = remaining;
|
|
2489
2680
|
}
|
|
2681
|
+
/* UTF-8 already has its final representation. Copy only the requested
|
|
2682
|
+
* prefix, backing off when the destination ends inside a scalar. */
|
|
2683
|
+
if (scr_enc_is(enc, "utf8")) {
|
|
2684
|
+
size_t k = s->len < budget ? s->len : budget;
|
|
2685
|
+
if (k < s->len) {
|
|
2686
|
+
while (k > 0 && ((uint8_t)s->data[k] & 0xc0) == 0x80) k--;
|
|
2687
|
+
}
|
|
2688
|
+
if (k) memcpy(b->data + o, s->data, k);
|
|
2689
|
+
return (double)k;
|
|
2690
|
+
}
|
|
2691
|
+
bool utf16 = scr_enc_is(enc, "utf16le");
|
|
2692
|
+
if (utf16 || scr_enc_is(enc, "latin1") || scr_enc_is(enc, "ascii")) {
|
|
2693
|
+
size_t i = 0, written = 0, width = utf16 ? 2 : 1;
|
|
2694
|
+
while (i < s->len && budget - written >= width) {
|
|
2695
|
+
uint32_t cp = scr_bytes_next_cp((const uint8_t *)s->data, &i);
|
|
2696
|
+
uint32_t first = cp, second = 0;
|
|
2697
|
+
if (cp > 0xffff) {
|
|
2698
|
+
cp -= 0x10000;
|
|
2699
|
+
first = 0xd800 + (cp >> 10);
|
|
2700
|
+
second = 0xdc00 + (cp & 0x3ff);
|
|
2701
|
+
}
|
|
2702
|
+
b->data[o + written++] = (uint8_t)first;
|
|
2703
|
+
if (utf16) b->data[o + written++] = (uint8_t)(first >> 8);
|
|
2704
|
+
if (second && budget - written >= width) {
|
|
2705
|
+
b->data[o + written++] = (uint8_t)second;
|
|
2706
|
+
if (utf16) b->data[o + written++] = (uint8_t)(second >> 8);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
return (double)written;
|
|
2710
|
+
}
|
|
2490
2711
|
ScrBytes *encd = scr_bytes_from_str(s, enc);
|
|
2491
2712
|
size_t k = encd->len < budget ? encd->len : budget;
|
|
2492
2713
|
if (k < encd->len) {
|