xbintsc 0.2.9 → 0.3.1
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/README.md +17 -2
- package/README.zh-CN.md +16 -2
- package/bin/xbintsc.js +49 -10
- package/dist/src/ast/expressions.d.ts +2 -0
- package/dist/src/binder/binder.d.ts +24 -98
- package/dist/src/binder/binder.js +13 -559
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/binder/declarations.d.ts +16 -0
- package/dist/src/binder/declarations.js +168 -0
- package/dist/src/binder/declarations.js.map +1 -0
- package/dist/src/binder/helpers.d.ts +11 -0
- package/dist/src/binder/helpers.js +46 -0
- package/dist/src/binder/helpers.js.map +1 -0
- package/dist/src/binder/references.d.ts +21 -0
- package/dist/src/binder/references.js +349 -0
- package/dist/src/binder/references.js.map +1 -0
- package/dist/src/binder/types.d.ts +114 -0
- package/dist/src/binder/types.js +27 -0
- package/dist/src/binder/types.js.map +1 -0
- package/dist/src/cli/main.d.ts +1 -0
- package/dist/src/cli/main.js +40 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.d.ts +13 -0
- package/dist/src/codegen/generator/calls/access.js +115 -0
- package/dist/src/codegen/generator/calls/access.js.map +1 -0
- package/dist/src/codegen/generator/calls/closures.d.ts +11 -0
- package/dist/src/codegen/generator/calls/closures.js +50 -0
- package/dist/src/codegen/generator/calls/closures.js.map +1 -0
- package/dist/src/codegen/generator/calls/invocation.d.ts +18 -0
- package/dist/src/codegen/generator/calls/invocation.js +242 -0
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -0
- package/dist/src/codegen/generator/calls/literals.d.ts +10 -0
- package/dist/src/codegen/generator/calls/literals.js +69 -0
- package/dist/src/codegen/generator/calls/literals.js.map +1 -0
- package/dist/src/codegen/generator/calls/super.d.ts +10 -0
- package/dist/src/codegen/generator/calls/super.js +47 -0
- package/dist/src/codegen/generator/calls/super.js.map +1 -0
- package/dist/src/codegen/generator/calls.d.ts +15 -24
- package/dist/src/codegen/generator/calls.js +15 -482
- package/dist/src/codegen/generator/calls.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +1 -1
- package/dist/src/codegen/generator/context.js +2 -2
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/assignment.d.ts +13 -0
- package/dist/src/codegen/generator/expressions/assignment.js +203 -0
- package/dist/src/codegen/generator/expressions/assignment.js.map +1 -0
- package/dist/src/codegen/generator/expressions/operators.d.ts +14 -0
- package/dist/src/codegen/generator/expressions/operators.js +163 -0
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -0
- package/dist/src/codegen/generator/expressions/primary.d.ts +17 -0
- package/dist/src/codegen/generator/expressions/primary.js +260 -0
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -0
- package/dist/src/codegen/generator/expressions.d.ts +11 -21
- package/dist/src/codegen/generator/expressions.js +11 -494
- package/dist/src/codegen/generator/expressions.js.map +1 -1
- package/dist/src/codegen/generator/module.js +16 -4
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +8 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.d.ts +14 -0
- package/dist/src/codegen/generator/statements/control-flow.js +199 -0
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -0
- package/dist/src/codegen/generator/statements/dispatch.d.ts +12 -0
- package/dist/src/codegen/generator/statements/dispatch.js +100 -0
- package/dist/src/codegen/generator/statements/dispatch.js.map +1 -0
- package/dist/src/codegen/generator/statements/loops.d.ts +13 -0
- package/dist/src/codegen/generator/statements/loops.js +152 -0
- package/dist/src/codegen/generator/statements/loops.js.map +1 -0
- package/dist/src/codegen/generator/statements/variables.d.ts +13 -0
- package/dist/src/codegen/generator/statements/variables.js +146 -0
- package/dist/src/codegen/generator/statements/variables.js.map +1 -0
- package/dist/src/codegen/generator/statements.d.ts +13 -21
- package/dist/src/codegen/generator/statements.js +13 -568
- package/dist/src/codegen/generator/statements.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +7 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/codegen/values.d.ts +17 -17
- package/dist/src/codegen/values.js +21 -57
- package/dist/src/codegen/values.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +1 -0
- package/dist/src/diagnostics/diagnostic.js +1 -0
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/diagnostics/source.d.ts +1 -1
- package/dist/src/diagnostics/source.js +7 -12
- package/dist/src/diagnostics/source.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +4 -0
- package/dist/src/driver/compiler.js +51 -16
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/index.d.ts +5 -2
- package/dist/src/driver/index.js +5 -2
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/paths.d.ts +20 -0
- package/dist/src/driver/paths.js +49 -0
- package/dist/src/driver/paths.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +18 -0
- package/dist/src/driver/runtime-lib.js +31 -0
- package/dist/src/driver/runtime-lib.js.map +1 -0
- package/dist/src/driver/toolchain-download.d.ts +50 -0
- package/dist/src/driver/toolchain-download.js +76 -0
- package/dist/src/driver/toolchain-download.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +33 -0
- package/dist/src/driver/toolchain-provider.js +71 -0
- package/dist/src/driver/toolchain-provider.js.map +1 -0
- package/dist/src/driver/toolchain.d.ts +9 -4
- package/dist/src/driver/toolchain.js +6 -10
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/extensions/node/child_process/index.d.ts +4 -2
- package/dist/src/extensions/node/child_process/index.js +4 -2
- package/dist/src/extensions/node/child_process/index.js.map +1 -1
- package/dist/src/extensions/node/events/index.d.ts +10 -0
- package/dist/src/extensions/node/events/index.js +22 -0
- package/dist/src/extensions/node/events/index.js.map +1 -0
- package/dist/src/extensions/node/index.js +6 -0
- package/dist/src/extensions/node/index.js.map +1 -1
- package/dist/src/extensions/node/querystring/index.d.ts +10 -0
- package/dist/src/extensions/node/querystring/index.js +25 -0
- package/dist/src/extensions/node/querystring/index.js.map +1 -0
- package/dist/src/extensions/node/util/index.d.ts +11 -0
- package/dist/src/extensions/node/util/index.js +41 -0
- package/dist/src/extensions/node/util/index.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +6 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lexer/scanner/identifiers.d.ts +9 -0
- package/dist/src/lexer/scanner/identifiers.js +33 -0
- package/dist/src/lexer/scanner/identifiers.js.map +1 -0
- package/dist/src/lexer/scanner/numbers.d.ts +10 -0
- package/dist/src/lexer/scanner/numbers.js +89 -0
- package/dist/src/lexer/scanner/numbers.js.map +1 -0
- package/dist/src/lexer/scanner/punctuation.d.ts +9 -0
- package/dist/src/lexer/scanner/punctuation.js +151 -0
- package/dist/src/lexer/scanner/punctuation.js.map +1 -0
- package/dist/src/lexer/scanner/regex.d.ts +11 -0
- package/dist/src/lexer/scanner/regex.js +69 -0
- package/dist/src/lexer/scanner/regex.js.map +1 -0
- package/dist/src/lexer/scanner/strings.d.ts +13 -0
- package/dist/src/lexer/scanner/strings.js +118 -0
- package/dist/src/lexer/scanner/strings.js.map +1 -0
- package/dist/src/lexer/scanner.d.ts +20 -27
- package/dist/src/lexer/scanner.js +11 -415
- package/dist/src/lexer/scanner.js.map +1 -1
- package/dist/src/parser/declarations/classes.d.ts +14 -0
- package/dist/src/parser/declarations/classes.js +191 -0
- package/dist/src/parser/declarations/classes.js.map +1 -0
- package/dist/src/parser/declarations/functions.d.ts +17 -0
- package/dist/src/parser/declarations/functions.js +241 -0
- package/dist/src/parser/declarations/functions.js.map +1 -0
- package/dist/src/parser/declarations/type-members.d.ts +16 -0
- package/dist/src/parser/declarations/type-members.js +156 -0
- package/dist/src/parser/declarations/type-members.js.map +1 -0
- package/dist/src/parser/declarations.d.ts +13 -24
- package/dist/src/parser/declarations.js +13 -571
- package/dist/src/parser/declarations.js.map +1 -1
- package/dist/src/parser/helpers.js +13 -4
- package/dist/src/parser/helpers.js.map +1 -1
- package/dist/src/parser/literals.js +10 -1
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +24 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/driver/compiler.test.js +3 -0
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/paths.test.d.ts +1 -0
- package/dist/tests/driver/paths.test.js +26 -0
- package/dist/tests/driver/paths.test.js.map +1 -0
- package/dist/tests/driver/toolchain-download.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-download.test.js +38 -0
- package/dist/tests/driver/toolchain-download.test.js.map +1 -0
- package/dist/tests/driver/toolchain-provider.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-provider.test.js +37 -0
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -0
- package/dist/tests/e2e/compile-node.test.d.ts +7 -0
- package/dist/tests/e2e/compile-node.test.js +123 -0
- package/dist/tests/e2e/compile-node.test.js.map +1 -0
- package/dist/tests/e2e/compile.test.d.ts +4 -1
- package/dist/tests/e2e/compile.test.js +78 -130
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/dist/tests/e2e/harness.d.ts +36 -0
- package/dist/tests/e2e/harness.js +64 -0
- package/dist/tests/e2e/harness.js.map +1 -0
- package/dist/tests/e2e/node-modules.test.js +60 -0
- package/dist/tests/e2e/node-modules.test.js.map +1 -1
- package/dist/tests/extensions/registry.test.js +4 -0
- package/dist/tests/extensions/registry.test.js.map +1 -1
- package/package.json +5 -3
- package/runtime/ext_node/buffer/buffer.c +12 -552
- package/runtime/ext_node/buffer/parts/byte-access.inc +35 -0
- package/runtime/ext_node/buffer/parts/construction.inc +60 -0
- package/runtime/ext_node/buffer/parts/integer-io.inc +119 -0
- package/runtime/ext_node/buffer/parts/methods.inc +135 -0
- package/runtime/ext_node/buffer/parts/prototype.inc +54 -0
- package/runtime/ext_node/buffer/parts/search.inc +86 -0
- package/runtime/ext_node/buffer/parts/static-api.inc +58 -0
- package/runtime/ext_node/child_process/child_process.c +37 -3
- package/runtime/ext_node/events/events.c +285 -0
- package/runtime/ext_node/http/http.c +11 -736
- package/runtime/ext_node/http/parts/client.inc +290 -0
- package/runtime/ext_node/http/parts/helpers.inc +45 -0
- package/runtime/ext_node/http/parts/prototypes.inc +57 -0
- package/runtime/ext_node/http/parts/response.inc +149 -0
- package/runtime/ext_node/http/parts/server.inc +133 -0
- package/runtime/ext_node/http/parts/string-builder.inc +58 -0
- package/runtime/ext_node/net/net.c +12 -504
- package/runtime/ext_node/net/parts/construction.inc +22 -0
- package/runtime/ext_node/net/parts/platform.inc +60 -0
- package/runtime/ext_node/net/parts/prototypes.inc +35 -0
- package/runtime/ext_node/net/parts/read-loop.inc +58 -0
- package/runtime/ext_node/net/parts/server.inc +131 -0
- package/runtime/ext_node/net/parts/socket-methods.inc +100 -0
- package/runtime/ext_node/net/parts/static-api.inc +93 -0
- package/runtime/ext_node/querystring/querystring.c +251 -0
- package/runtime/ext_node/util/util.c +456 -0
- package/runtime/rt.h +8 -2
- package/runtime/rt_internal.h +34 -0
- package/runtime/xt_bigint/arithmetic.inc +135 -0
- package/runtime/xt_bigint/bits.inc +98 -0
- package/runtime/xt_bigint/bitwise.inc +103 -0
- package/runtime/xt_bigint/compare.inc +30 -0
- package/runtime/xt_bigint/conversions.inc +51 -0
- package/runtime/xt_bigint/division.inc +85 -0
- package/runtime/xt_bigint/format.inc +145 -0
- package/runtime/xt_bigint/helpers.inc +92 -0
- package/runtime/xt_bigint/magnitude.inc +88 -0
- package/runtime/xt_bigint/public.inc +59 -0
- package/runtime/xt_bigint/small-arithmetic.inc +58 -0
- package/runtime/xt_bigint.c +42 -0
- package/runtime/xt_builtins.c +1 -0
- package/runtime/xt_io.c +7 -0
- package/runtime/xt_stdlib/arrays.inc +161 -0
- package/runtime/xt_stdlib/dispatch.inc +116 -0
- package/runtime/xt_stdlib/helpers.inc +23 -0
- package/runtime/xt_stdlib/math.inc +72 -0
- package/runtime/xt_stdlib/strings.inc +178 -0
- package/runtime/xt_stdlib.c +10 -549
- package/runtime/xt_stdlib2/array-statics.inc +37 -0
- package/runtime/xt_stdlib2/arrays.inc +189 -0
- package/runtime/xt_stdlib2/container.inc +23 -0
- package/runtime/xt_stdlib2/date.inc +72 -0
- package/runtime/xt_stdlib2/error.inc +22 -0
- package/runtime/xt_stdlib2/helpers.inc +43 -0
- package/runtime/xt_stdlib2/json.inc +213 -0
- package/runtime/xt_stdlib2/map.inc +95 -0
- package/runtime/xt_stdlib2/number-string-statics.inc +73 -0
- package/runtime/xt_stdlib2/numbers.inc +38 -0
- package/runtime/xt_stdlib2/objects.inc +41 -0
- package/runtime/xt_stdlib2/regexp-match.inc +204 -0
- package/runtime/xt_stdlib2/regexp.inc +20 -0
- package/runtime/xt_stdlib2/set.inc +105 -0
- package/runtime/xt_stdlib2/strings.inc +94 -0
- package/runtime/xt_stdlib2.c +19 -1278
- package/runtime/xt_values.c +155 -12
- package/scripts/build-runtime.ts +109 -0
- package/scripts/fetch-toolchain.ts +101 -0
- package/scripts/package-release.ts +192 -0
- package/src/ast/expressions.ts +2 -0
- package/src/binder/binder.ts +40 -725
- package/src/binder/declarations.ts +203 -0
- package/src/binder/helpers.ts +47 -0
- package/src/binder/references.ts +410 -0
- package/src/binder/types.ts +134 -0
- package/src/cli/main.ts +43 -0
- package/src/codegen/generator/calls/access.ts +139 -0
- package/src/codegen/generator/calls/closures.ts +60 -0
- package/src/codegen/generator/calls/invocation.ts +282 -0
- package/src/codegen/generator/calls/literals.ts +77 -0
- package/src/codegen/generator/calls/super.ts +61 -0
- package/src/codegen/generator/calls.ts +30 -552
- package/src/codegen/generator/context.ts +2 -2
- package/src/codegen/generator/expressions/assignment.ts +226 -0
- package/src/codegen/generator/expressions/operators.ts +182 -0
- package/src/codegen/generator/expressions/primary.ts +304 -0
- package/src/codegen/generator/expressions.ts +22 -553
- package/src/codegen/generator/module.ts +14 -4
- package/src/codegen/generator/state.ts +8 -0
- package/src/codegen/generator/statements/control-flow.ts +225 -0
- package/src/codegen/generator/statements/dispatch.ts +122 -0
- package/src/codegen/generator/statements/loops.ts +173 -0
- package/src/codegen/generator/statements/variables.ts +152 -0
- package/src/codegen/generator/statements.ts +26 -612
- package/src/codegen/generator/tables.ts +7 -0
- package/src/codegen/values.ts +22 -57
- package/src/diagnostics/diagnostic.ts +1 -0
- package/src/diagnostics/source.ts +7 -12
- package/src/driver/compiler.ts +61 -18
- package/src/driver/index.ts +17 -2
- package/src/driver/paths.ts +54 -0
- package/src/driver/runtime-lib.ts +32 -0
- package/src/driver/toolchain-download.ts +108 -0
- package/src/driver/toolchain-provider.ts +91 -0
- package/src/driver/toolchain.ts +29 -11
- package/src/extensions/node/child_process/index.ts +4 -2
- package/src/extensions/node/events/index.ts +27 -0
- package/src/extensions/node/index.ts +6 -0
- package/src/extensions/node/querystring/index.ts +29 -0
- package/src/extensions/node/util/index.ts +48 -0
- package/src/extensions/registry.ts +6 -0
- package/src/index.ts +1 -0
- package/src/lexer/scanner/identifiers.ts +37 -0
- package/src/lexer/scanner/numbers.ts +84 -0
- package/src/lexer/scanner/punctuation.ts +132 -0
- package/src/lexer/scanner/regex.ts +79 -0
- package/src/lexer/scanner/strings.ts +128 -0
- package/src/lexer/scanner.ts +35 -401
- package/src/parser/declarations/classes.ts +215 -0
- package/src/parser/declarations/functions.ts +254 -0
- package/src/parser/declarations/type-members.ts +181 -0
- package/src/parser/declarations.ts +32 -609
- package/src/parser/helpers.ts +13 -6
- package/src/parser/literals.ts +10 -1
- package/scripts/build-runtime.mjs +0 -55
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* -- integer readers / writers -------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
static uint64_t xt_buffer_read_le(xt_value buffer, uint32_t offset, int bytes) {
|
|
4
|
+
uint64_t value = 0;
|
|
5
|
+
for (int i = 0; i < bytes; i++) value |= ((uint64_t)xt_buffer_byte(buffer, offset + (uint32_t)i)) << (8 * i);
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static uint64_t xt_buffer_read_be(xt_value buffer, uint32_t offset, int bytes) {
|
|
10
|
+
uint64_t value = 0;
|
|
11
|
+
for (int i = 0; i < bytes; i++) value = (value << 8) | xt_buffer_byte(buffer, offset + (uint32_t)i);
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static void xt_buffer_write_le(xt_value buffer, uint32_t offset, int bytes, uint64_t value) {
|
|
16
|
+
for (int i = 0; i < bytes; i++) xt_buffer_put(buffer, offset + (uint32_t)i, (unsigned char)((value >> (8 * i)) & 0xff));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static void xt_buffer_write_be(xt_value buffer, uint32_t offset, int bytes, uint64_t value) {
|
|
20
|
+
for (int i = 0; i < bytes; i++) xt_buffer_put(buffer, offset + (uint32_t)i, (unsigned char)((value >> (8 * (bytes - 1 - i))) & 0xff));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static xt_value xt_buffer_read_method(xt_value thisValue, int32_t argc, xt_value *argv, int bytes, int little, int signedValue) {
|
|
24
|
+
uint32_t offset = argc > 0 ? (uint32_t)xt_to_number(argv[0]) : 0;
|
|
25
|
+
uint64_t raw = little ? xt_buffer_read_le(thisValue, offset, bytes) : xt_buffer_read_be(thisValue, offset, bytes);
|
|
26
|
+
double result;
|
|
27
|
+
if (signedValue) {
|
|
28
|
+
int64_t signedRaw = (int64_t)raw;
|
|
29
|
+
int bits = bytes * 8;
|
|
30
|
+
if (bits < 64 && (raw & (1ULL << (bits - 1)))) signedRaw = (int64_t)(raw | (~0ULL << bits));
|
|
31
|
+
result = (double)signedRaw;
|
|
32
|
+
} else {
|
|
33
|
+
result = (double)raw;
|
|
34
|
+
}
|
|
35
|
+
return xt_number(result);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static xt_value xt_buffer_write_method(xt_value thisValue, int32_t argc, xt_value *argv, int bytes, int little) {
|
|
39
|
+
uint32_t offset = argc > 1 ? (uint32_t)xt_to_number(argv[1]) : 0;
|
|
40
|
+
uint64_t value = (uint64_t)(int64_t)xt_to_number(xt_arg_at(argc, argv, 0));
|
|
41
|
+
if (little) xt_buffer_write_le(thisValue, offset, bytes, value);
|
|
42
|
+
else xt_buffer_write_be(thisValue, offset, bytes, value);
|
|
43
|
+
return xt_number((double)(offset + (uint32_t)bytes));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#define XT_BUFFER_DEFINE_IO(name, bytes, little, signedValue) \
|
|
47
|
+
static xt_value xt_buffer_read_##name(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) { \
|
|
48
|
+
(void)env; \
|
|
49
|
+
return xt_buffer_read_method(thisValue, argc, argv, bytes, little, signedValue); \
|
|
50
|
+
} \
|
|
51
|
+
static xt_value xt_buffer_write_##name(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) { \
|
|
52
|
+
(void)env; \
|
|
53
|
+
return xt_buffer_write_method(thisValue, argc, argv, bytes, little); \
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#define XT_BUFFER_DEFINE_SIGNED_IO(name, bytes, little) \
|
|
57
|
+
XT_BUFFER_DEFINE_IO(name, bytes, little, 0) \
|
|
58
|
+
static xt_value xt_buffer_read_##name##s(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) { \
|
|
59
|
+
(void)env; \
|
|
60
|
+
return xt_buffer_read_method(thisValue, argc, argv, bytes, little, 1); \
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
XT_BUFFER_DEFINE_SIGNED_IO(u8, 1, 1)
|
|
64
|
+
XT_BUFFER_DEFINE_SIGNED_IO(u16, 2, 1)
|
|
65
|
+
static xt_value xt_buffer_read_u16be(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
66
|
+
(void)env;
|
|
67
|
+
return xt_buffer_read_method(thisValue, argc, argv, 2, 0, 0);
|
|
68
|
+
}
|
|
69
|
+
static xt_value xt_buffer_write_u16be(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
70
|
+
(void)env;
|
|
71
|
+
return xt_buffer_write_method(thisValue, argc, argv, 2, 0);
|
|
72
|
+
}
|
|
73
|
+
static xt_value xt_buffer_read_u16bes(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
74
|
+
(void)env;
|
|
75
|
+
return xt_buffer_read_method(thisValue, argc, argv, 2, 0, 1);
|
|
76
|
+
}
|
|
77
|
+
XT_BUFFER_DEFINE_SIGNED_IO(u32, 4, 1)
|
|
78
|
+
static xt_value xt_buffer_read_u32be(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
79
|
+
(void)env;
|
|
80
|
+
return xt_buffer_read_method(thisValue, argc, argv, 4, 0, 0);
|
|
81
|
+
}
|
|
82
|
+
static xt_value xt_buffer_write_u32be(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
83
|
+
(void)env;
|
|
84
|
+
return xt_buffer_write_method(thisValue, argc, argv, 4, 0);
|
|
85
|
+
}
|
|
86
|
+
static xt_value xt_buffer_read_u32bes(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
87
|
+
(void)env;
|
|
88
|
+
return xt_buffer_read_method(thisValue, argc, argv, 4, 0, 1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static xt_value xt_buffer_read_float(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv, int little, int doublePrecision) {
|
|
92
|
+
(void)env;
|
|
93
|
+
(void)thisValue;
|
|
94
|
+
(void)argc;
|
|
95
|
+
(void)argv;
|
|
96
|
+
(void)little;
|
|
97
|
+
(void)doublePrecision;
|
|
98
|
+
return xt_number(0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static xt_value xt_buffer_method_keys(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
102
|
+
(void)env;
|
|
103
|
+
(void)argc;
|
|
104
|
+
(void)argv;
|
|
105
|
+
xt_value result = xt_array_new(0, NULL);
|
|
106
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
107
|
+
for (uint32_t i = 0; i < length; i++) xt_array_push(result, xt_number((double)i));
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static xt_value xt_buffer_method_values(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
112
|
+
(void)env;
|
|
113
|
+
(void)argc;
|
|
114
|
+
(void)argv;
|
|
115
|
+
xt_value result = xt_array_new(0, NULL);
|
|
116
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
117
|
+
for (uint32_t i = 0; i < length; i++) xt_array_push(result, xt_number((double)xt_buffer_byte(thisValue, i)));
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* -- instance methods ----------------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
static xt_value xt_buffer_method_to_string(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
4
|
+
(void)env;
|
|
5
|
+
const char *encoding = argc > 0 ? xt_node_encoding(argv[0]) : NULL;
|
|
6
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
7
|
+
uint32_t start = argc > 1 ? (uint32_t)xt_to_number(argv[1]) : 0;
|
|
8
|
+
uint32_t end = argc > 2 ? (uint32_t)xt_to_number(argv[2]) : length;
|
|
9
|
+
if (end > length) end = length;
|
|
10
|
+
if (start > end) start = end;
|
|
11
|
+
unsigned char *bytes = (unsigned char *)malloc(end - start + 1);
|
|
12
|
+
for (uint32_t i = start; i < end; i++) bytes[i - start] = xt_buffer_byte(thisValue, i);
|
|
13
|
+
xt_value result = xt_node_encode(bytes, end - start, encoding);
|
|
14
|
+
free(bytes);
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static xt_value xt_buffer_method_to_json(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
19
|
+
(void)env;
|
|
20
|
+
(void)argc;
|
|
21
|
+
(void)argv;
|
|
22
|
+
xt_value object = xt_object_new();
|
|
23
|
+
xt_value type = xt_string_from_cstr("Buffer");
|
|
24
|
+
xt_object_set(object, xt_string_from_cstr("type"), type);
|
|
25
|
+
xt_value data = xt_array_new(0, NULL);
|
|
26
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
27
|
+
for (uint32_t i = 0; i < length; i++) xt_array_push(data, xt_number((double)xt_buffer_byte(thisValue, i)));
|
|
28
|
+
xt_object_set(object, xt_string_from_cstr("data"), data);
|
|
29
|
+
return object;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static xt_value xt_buffer_method_slice(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
33
|
+
(void)env;
|
|
34
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
35
|
+
int32_t start = argc > 0 ? (int32_t)xt_to_number(argv[0]) : 0;
|
|
36
|
+
int32_t end = argc > 1 ? (int32_t)xt_to_number(argv[1]) : (int32_t)length;
|
|
37
|
+
if (start < 0) start += (int32_t)length;
|
|
38
|
+
if (end < 0) end += (int32_t)length;
|
|
39
|
+
if (start < 0) start = 0;
|
|
40
|
+
if (end > (int32_t)length) end = (int32_t)length;
|
|
41
|
+
if (end < start) end = start;
|
|
42
|
+
unsigned char *bytes = (unsigned char *)malloc((size_t)(end - start) + 1);
|
|
43
|
+
for (int32_t i = start; i < end; i++) bytes[i - start] = xt_buffer_byte(thisValue, (uint32_t)i);
|
|
44
|
+
xt_value result = xt_buffer_from_bytes(bytes, (size_t)(end - start));
|
|
45
|
+
free(bytes);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static xt_value xt_buffer_method_equals(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
50
|
+
(void)env;
|
|
51
|
+
xt_value other = xt_arg_at(argc, argv, 0);
|
|
52
|
+
if (!xt_buffer_is(other)) return xt_bool(0);
|
|
53
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
54
|
+
if (length != xt_buffer_length(other)) return xt_bool(0);
|
|
55
|
+
for (uint32_t i = 0; i < length; i++) {
|
|
56
|
+
if (xt_buffer_byte(thisValue, i) != xt_buffer_byte(other, i)) return xt_bool(0);
|
|
57
|
+
}
|
|
58
|
+
return xt_bool(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static xt_value xt_buffer_method_compare(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
62
|
+
(void)env;
|
|
63
|
+
xt_value other = xt_arg_at(argc, argv, 0);
|
|
64
|
+
uint32_t la = xt_buffer_length(thisValue), lb = xt_buffer_length(other);
|
|
65
|
+
uint32_t n = la < lb ? la : lb;
|
|
66
|
+
for (uint32_t i = 0; i < n; i++) {
|
|
67
|
+
unsigned char x = xt_buffer_byte(thisValue, i), y = xt_buffer_byte(other, i);
|
|
68
|
+
if (x != y) return xt_number(x < y ? -1 : 1);
|
|
69
|
+
}
|
|
70
|
+
return xt_number(la < lb ? -1 : la > lb ? 1 : 0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static xt_value xt_buffer_method_copy(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
74
|
+
(void)env;
|
|
75
|
+
xt_value target = xt_arg_at(argc, argv, 0);
|
|
76
|
+
if (!xt_buffer_is(target)) return xt_number(0);
|
|
77
|
+
uint32_t targetStart = argc > 1 ? (uint32_t)xt_to_number(argv[1]) : 0;
|
|
78
|
+
uint32_t sourceStart = argc > 2 ? (uint32_t)xt_to_number(argv[2]) : 0;
|
|
79
|
+
uint32_t sourceEnd = argc > 3 ? (uint32_t)xt_to_number(argv[3]) : xt_buffer_length(thisValue);
|
|
80
|
+
uint32_t targetLength = xt_buffer_length(target);
|
|
81
|
+
uint32_t written = 0;
|
|
82
|
+
for (uint32_t i = sourceStart; i < sourceEnd && targetStart + written < targetLength; i++) {
|
|
83
|
+
xt_buffer_put(target, targetStart + written, xt_buffer_byte(thisValue, i));
|
|
84
|
+
written++;
|
|
85
|
+
}
|
|
86
|
+
return xt_number((double)written);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static xt_value xt_buffer_method_write(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
90
|
+
(void)env;
|
|
91
|
+
xt_value text = xt_to_string(xt_arg_at(argc, argv, 0));
|
|
92
|
+
xt_string *string = xt_as_string(text);
|
|
93
|
+
uint32_t offset = argc > 1 ? (uint32_t)xt_to_number(argv[1]) : 0;
|
|
94
|
+
const char *encoding = argc > 3 ? xt_node_encoding(argv[3]) : NULL;
|
|
95
|
+
size_t decoded = 0;
|
|
96
|
+
unsigned char *bytes = xt_node_decode(string->data, string->length, encoding, &decoded);
|
|
97
|
+
uint32_t available = xt_buffer_length(thisValue);
|
|
98
|
+
uint32_t written = 0;
|
|
99
|
+
for (size_t i = 0; i < decoded && offset + written < available; i++) {
|
|
100
|
+
xt_buffer_put(thisValue, offset + written, bytes[i]);
|
|
101
|
+
written++;
|
|
102
|
+
}
|
|
103
|
+
free(bytes);
|
|
104
|
+
return xt_number((double)written);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static xt_value xt_buffer_method_fill(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
108
|
+
(void)env;
|
|
109
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
110
|
+
uint32_t start = argc > 1 ? (uint32_t)xt_to_number(argv[1]) : 0;
|
|
111
|
+
uint32_t end = argc > 2 ? (uint32_t)xt_to_number(argv[2]) : length;
|
|
112
|
+
if (end > length) end = length;
|
|
113
|
+
unsigned char byte = 0;
|
|
114
|
+
if (XT_IS_STRING(xt_arg_at(argc, argv, 0))) {
|
|
115
|
+
const char *text = xt_string_data(xt_arg_at(argc, argv, 0));
|
|
116
|
+
if (text && text[0]) byte = (unsigned char)text[0];
|
|
117
|
+
} else if (argc > 0) {
|
|
118
|
+
byte = (unsigned char)((int32_t)xt_to_number(argv[0]) & 0xff);
|
|
119
|
+
}
|
|
120
|
+
for (uint32_t i = start; i < end; i++) xt_buffer_put(thisValue, i, byte);
|
|
121
|
+
return thisValue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static xt_value xt_buffer_method_reverse(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
125
|
+
(void)env;
|
|
126
|
+
(void)argc;
|
|
127
|
+
(void)argv;
|
|
128
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
129
|
+
for (uint32_t i = 0; i < length / 2; i++) {
|
|
130
|
+
unsigned char a = xt_buffer_byte(thisValue, i);
|
|
131
|
+
xt_buffer_put(thisValue, i, xt_buffer_byte(thisValue, length - 1 - i));
|
|
132
|
+
xt_buffer_put(thisValue, length - 1 - i, a);
|
|
133
|
+
}
|
|
134
|
+
return thisValue;
|
|
135
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* -- prototype ------------------------------------------------------------ */
|
|
2
|
+
|
|
3
|
+
static xt_value xt_buffer_proto(void) {
|
|
4
|
+
static xt_value proto = 0;
|
|
5
|
+
if (proto) return proto;
|
|
6
|
+
proto = xt_object_new();
|
|
7
|
+
xt_node_define_method(proto, "toString", (void *)xt_buffer_method_to_string);
|
|
8
|
+
xt_node_define_method(proto, "toJSON", (void *)xt_buffer_method_to_json);
|
|
9
|
+
xt_node_define_method(proto, "slice", (void *)xt_buffer_method_slice);
|
|
10
|
+
xt_node_define_method(proto, "subarray", (void *)xt_buffer_method_slice);
|
|
11
|
+
xt_node_define_method(proto, "equals", (void *)xt_buffer_method_equals);
|
|
12
|
+
xt_node_define_method(proto, "compare", (void *)xt_buffer_method_compare);
|
|
13
|
+
xt_node_define_method(proto, "copy", (void *)xt_buffer_method_copy);
|
|
14
|
+
xt_node_define_method(proto, "write", (void *)xt_buffer_method_write);
|
|
15
|
+
xt_node_define_method(proto, "fill", (void *)xt_buffer_method_fill);
|
|
16
|
+
xt_node_define_method(proto, "reverse", (void *)xt_buffer_method_reverse);
|
|
17
|
+
xt_node_define_method(proto, "indexOf", (void *)xt_buffer_method_index_of_fwd);
|
|
18
|
+
xt_node_define_method(proto, "lastIndexOf", (void *)xt_buffer_method_index_of_rev);
|
|
19
|
+
xt_node_define_method(proto, "includes", (void *)xt_buffer_method_includes);
|
|
20
|
+
xt_node_define_method(proto, "keys", (void *)xt_buffer_method_keys);
|
|
21
|
+
xt_node_define_method(proto, "values", (void *)xt_buffer_method_values);
|
|
22
|
+
xt_node_define_method(proto, "readUInt8", (void *)xt_buffer_read_u8);
|
|
23
|
+
xt_node_define_method(proto, "readInt8", (void *)xt_buffer_read_u8s);
|
|
24
|
+
xt_node_define_method(proto, "writeUInt8", (void *)xt_buffer_write_u8);
|
|
25
|
+
xt_node_define_method(proto, "writeInt8", (void *)xt_buffer_write_u8);
|
|
26
|
+
xt_node_define_method(proto, "readUInt16LE", (void *)xt_buffer_read_u16);
|
|
27
|
+
xt_node_define_method(proto, "readUInt16BE", (void *)xt_buffer_read_u16be);
|
|
28
|
+
xt_node_define_method(proto, "readInt16LE", (void *)xt_buffer_read_u16s);
|
|
29
|
+
xt_node_define_method(proto, "readInt16BE", (void *)xt_buffer_read_u16bes);
|
|
30
|
+
xt_node_define_method(proto, "writeUInt16LE", (void *)xt_buffer_write_u16);
|
|
31
|
+
xt_node_define_method(proto, "writeUInt16BE", (void *)xt_buffer_write_u16be);
|
|
32
|
+
xt_node_define_method(proto, "readUInt32LE", (void *)xt_buffer_read_u32);
|
|
33
|
+
xt_node_define_method(proto, "readUInt32BE", (void *)xt_buffer_read_u32be);
|
|
34
|
+
xt_node_define_method(proto, "readInt32LE", (void *)xt_buffer_read_u32s);
|
|
35
|
+
xt_node_define_method(proto, "readInt32BE", (void *)xt_buffer_read_u32bes);
|
|
36
|
+
xt_node_define_method(proto, "writeUInt32LE", (void *)xt_buffer_write_u32);
|
|
37
|
+
xt_node_define_method(proto, "writeUInt32BE", (void *)xt_buffer_write_u32be);
|
|
38
|
+
(void)xt_buffer_read_float;
|
|
39
|
+
return proto;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Enforce prototype creation on first use so `Buffer.from` marks the object. */
|
|
43
|
+
void xt_buffer_ensure_proto(void) { (void)xt_buffer_proto(); }
|
|
44
|
+
|
|
45
|
+
/* Cross-module helpers used by the net/http/dgram modules. */
|
|
46
|
+
int xt_node_is_buffer(xt_value value) { return xt_buffer_is(value); }
|
|
47
|
+
|
|
48
|
+
unsigned char *xt_node_buffer_bytes(xt_value value, size_t *outLength) {
|
|
49
|
+
uint32_t length = xt_buffer_length(value);
|
|
50
|
+
unsigned char *bytes = (unsigned char *)malloc(length ? length : 1);
|
|
51
|
+
for (uint32_t i = 0; i < length; i++) bytes[i] = xt_buffer_byte(value, i);
|
|
52
|
+
*outLength = length;
|
|
53
|
+
return bytes;
|
|
54
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* -- search --------------------------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
static const unsigned char *xt_buffer_search_needle(xt_value value, const char *encoding, size_t *length,
|
|
4
|
+
unsigned char *single) {
|
|
5
|
+
if (XT_IS_NUMBER(value)) {
|
|
6
|
+
*single = (unsigned char)((int32_t)xt_to_number(value) & 0xff);
|
|
7
|
+
*length = 1;
|
|
8
|
+
return single;
|
|
9
|
+
}
|
|
10
|
+
if (xt_buffer_is(value)) {
|
|
11
|
+
uint32_t n = xt_buffer_length(value);
|
|
12
|
+
unsigned char *bytes = (unsigned char *)malloc(n ? n : 1);
|
|
13
|
+
for (uint32_t i = 0; i < n; i++) bytes[i] = xt_buffer_byte(value, i);
|
|
14
|
+
*length = n;
|
|
15
|
+
return bytes;
|
|
16
|
+
}
|
|
17
|
+
xt_value text = xt_to_string(value);
|
|
18
|
+
xt_string *string = xt_as_string(text);
|
|
19
|
+
size_t decoded = 0;
|
|
20
|
+
unsigned char *bytes = xt_node_decode(string->data, string->length, encoding, &decoded);
|
|
21
|
+
*length = decoded;
|
|
22
|
+
return bytes;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static xt_value xt_buffer_method_index_of(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv,
|
|
26
|
+
int reverse) {
|
|
27
|
+
(void)env;
|
|
28
|
+
const char *encoding = argc > 2 ? xt_node_encoding(argv[2]) : NULL;
|
|
29
|
+
size_t needleLength = 0;
|
|
30
|
+
unsigned char single = 0;
|
|
31
|
+
const unsigned char *needle = xt_buffer_search_needle(xt_arg_at(argc, argv, 0), encoding, &needleLength, &single);
|
|
32
|
+
uint32_t length = xt_buffer_length(thisValue);
|
|
33
|
+
int32_t start = argc > 1 ? (int32_t)xt_to_number(argv[1]) : (reverse ? (int32_t)length - 1 : 0);
|
|
34
|
+
if (start < 0) start += (int32_t)length;
|
|
35
|
+
if (start < 0) start = 0;
|
|
36
|
+
if (needleLength == 0 || needleLength > length) {
|
|
37
|
+
if (!xt_buffer_is(xt_arg_at(argc, argv, 0))) free((void *)needle);
|
|
38
|
+
return xt_number(-1);
|
|
39
|
+
}
|
|
40
|
+
int found = -1;
|
|
41
|
+
if (reverse) {
|
|
42
|
+
if (start > (int32_t)length - 1) start = (int32_t)length - 1;
|
|
43
|
+
for (int32_t i = start; i >= 0; i--) {
|
|
44
|
+
int match = 1;
|
|
45
|
+
for (size_t j = 0; j < needleLength; j++) {
|
|
46
|
+
if ((uint32_t)(i + (int32_t)j) >= length || xt_buffer_byte(thisValue, (uint32_t)(i + (int32_t)j)) != needle[j]) {
|
|
47
|
+
match = 0;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (match) {
|
|
52
|
+
found = i;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
for (uint32_t i = (uint32_t)start; i + needleLength <= length; i++) {
|
|
58
|
+
int match = 1;
|
|
59
|
+
for (size_t j = 0; j < needleLength; j++) {
|
|
60
|
+
if (xt_buffer_byte(thisValue, i + (uint32_t)j) != needle[j]) {
|
|
61
|
+
match = 0;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (match) {
|
|
66
|
+
found = (int)i;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!xt_buffer_is(xt_arg_at(argc, argv, 0))) free((void *)needle);
|
|
72
|
+
return xt_number((double)found);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static xt_value xt_buffer_method_index_of_fwd(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
76
|
+
return xt_buffer_method_index_of(thisValue, env, argc, argv, 0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static xt_value xt_buffer_method_index_of_rev(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
80
|
+
return xt_buffer_method_index_of(thisValue, env, argc, argv, 1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static xt_value xt_buffer_method_includes(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
84
|
+
xt_value result = xt_buffer_method_index_of(thisValue, env, argc, argv, 0);
|
|
85
|
+
return xt_bool(xt_to_number(result) >= 0);
|
|
86
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* -- static API ----------------------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
xt_value xt_buffer_ctor(int32_t argc, xt_value *argv) {
|
|
4
|
+
if (argc == 0) return xt_buffer_new(0, NULL);
|
|
5
|
+
if (XT_IS_NUMBER(argv[0])) {
|
|
6
|
+
return xt_buffer_alloc((uint32_t)xt_to_number(argv[0]), XT_UNDEFINED, NULL);
|
|
7
|
+
}
|
|
8
|
+
return xt_buffer_from_args(argc, argv);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
xt_value xt_buffer_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
12
|
+
const char *fn = xt_string_data(name);
|
|
13
|
+
if (!fn) return xt_undefined();
|
|
14
|
+
if (strcmp(fn, "from") == 0 || strcmp(fn, "of") == 0) return xt_buffer_from_args(argc, argv);
|
|
15
|
+
if (strcmp(fn, "alloc") == 0 || strcmp(fn, "allocUnsafe") == 0 || strcmp(fn, "allocUnsafeSlow") == 0) {
|
|
16
|
+
uint32_t size = argc > 0 ? (uint32_t)xt_to_number(argv[0]) : 0;
|
|
17
|
+
const char *encoding = argc > 2 ? xt_node_encoding(argv[2]) : NULL;
|
|
18
|
+
return xt_buffer_alloc(size, argc > 1 ? argv[1] : XT_UNDEFINED, encoding);
|
|
19
|
+
}
|
|
20
|
+
if (strcmp(fn, "isBuffer") == 0) return xt_bool(xt_buffer_is(xt_arg_at(argc, argv, 0)));
|
|
21
|
+
if (strcmp(fn, "byteLength") == 0) {
|
|
22
|
+
xt_value value = xt_arg_at(argc, argv, 0);
|
|
23
|
+
if (xt_buffer_is(value)) return xt_number((double)xt_buffer_length(value));
|
|
24
|
+
const char *encoding = argc > 1 ? xt_node_encoding(argv[1]) : NULL;
|
|
25
|
+
xt_value text = xt_to_string(value);
|
|
26
|
+
xt_string *string = xt_as_string(text);
|
|
27
|
+
if (encoding && strcmp(encoding, "hex") == 0) return xt_number((double)(string->length / 2));
|
|
28
|
+
if (encoding && strcmp(encoding, "base64") == 0) return xt_number((double)(string->length / 4 * 3));
|
|
29
|
+
return xt_number((double)string->length);
|
|
30
|
+
}
|
|
31
|
+
if (strcmp(fn, "concat") == 0) {
|
|
32
|
+
xt_value list = xt_arg_at(argc, argv, 0);
|
|
33
|
+
uint32_t total = 0;
|
|
34
|
+
uint32_t count = XT_IS_ARRAY(list) ? (uint32_t)xt_to_number(xt_array_length(list)) : 0;
|
|
35
|
+
for (uint32_t i = 0; i < count; i++) total += xt_buffer_length(xt_array_get(list, xt_number((double)i)));
|
|
36
|
+
if (argc > 1 && XT_IS_NUMBER(argv[1])) total = (uint32_t)xt_to_number(argv[1]);
|
|
37
|
+
xt_value result = xt_buffer_new(total, NULL);
|
|
38
|
+
uint32_t offset = 0;
|
|
39
|
+
for (uint32_t i = 0; i < count && offset < total; i++) {
|
|
40
|
+
xt_value item = xt_array_get(list, xt_number((double)i));
|
|
41
|
+
uint32_t length = xt_buffer_length(item);
|
|
42
|
+
for (uint32_t j = 0; j < length && offset < total; j++) xt_buffer_put(result, offset++, xt_buffer_byte(item, j));
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
if (strcmp(fn, "compare") == 0) {
|
|
47
|
+
xt_value a = xt_arg_at(argc, argv, 0);
|
|
48
|
+
xt_value b = xt_arg_at(argc, argv, 1);
|
|
49
|
+
uint32_t la = xt_buffer_length(a), lb = xt_buffer_length(b);
|
|
50
|
+
uint32_t n = la < lb ? la : lb;
|
|
51
|
+
for (uint32_t i = 0; i < n; i++) {
|
|
52
|
+
unsigned char x = xt_buffer_byte(a, i), y = xt_buffer_byte(b, i);
|
|
53
|
+
if (x != y) return xt_number(x < y ? -1 : 1);
|
|
54
|
+
}
|
|
55
|
+
return xt_number(la < lb ? -1 : la > lb ? 1 : 0);
|
|
56
|
+
}
|
|
57
|
+
return xt_undefined();
|
|
58
|
+
}
|
|
@@ -51,6 +51,14 @@ static const char *option_cwd(xt_value options) {
|
|
|
51
51
|
return xt_string_data(cwd);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/* `stdio: "inherit"` hands the child the parent's stdout/stderr instead of
|
|
55
|
+
* capturing them. Used by `xbintsc run` so a program's output streams live. */
|
|
56
|
+
static int option_stdio_inherit(xt_value options) {
|
|
57
|
+
if (!XT_IS_OBJECT(options)) return 0;
|
|
58
|
+
xt_value stdio = xt_object_get(options, xt_string_from_cstr("stdio"));
|
|
59
|
+
return stdio && XT_IS_STRING(stdio) && strcmp(xt_string_data(stdio), "inherit") == 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
static xt_value make_result(double status, const char *out, const char *err) {
|
|
55
63
|
xt_value result = xt_object_new();
|
|
56
64
|
xt_set(result, xt_string_from_cstr("status"), xt_number(status));
|
|
@@ -84,6 +92,17 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
84
92
|
char **child_argv = (char **)build_argv(command, args, &count);
|
|
85
93
|
if (!child_argv) return make_result(-1, "", "out of memory");
|
|
86
94
|
|
|
95
|
+
char previous[4096];
|
|
96
|
+
int had_cwd = cwd && _getcwd(previous, sizeof(previous)) != NULL;
|
|
97
|
+
|
|
98
|
+
if (option_stdio_inherit(argc > 2 ? argv[2] : XT_UNDEFINED)) {
|
|
99
|
+
if (cwd) _chdir(cwd);
|
|
100
|
+
intptr_t inherit_rc = _spawnvp(_P_WAIT, command, (const char *const *)child_argv);
|
|
101
|
+
if (had_cwd) _chdir(previous);
|
|
102
|
+
free(child_argv);
|
|
103
|
+
return make_result(inherit_rc < 0 ? -1 : (double)inherit_rc, "", "");
|
|
104
|
+
}
|
|
105
|
+
|
|
87
106
|
FILE *out_file = tmpfile();
|
|
88
107
|
FILE *err_file = tmpfile();
|
|
89
108
|
if (!out_file || !err_file) {
|
|
@@ -98,12 +117,9 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
98
117
|
_dup2(_fileno(out_file), _fileno(stdout));
|
|
99
118
|
_dup2(_fileno(err_file), _fileno(stderr));
|
|
100
119
|
|
|
101
|
-
char previous[4096];
|
|
102
|
-
int had_cwd = cwd && _getcwd(previous, sizeof(previous)) != NULL;
|
|
103
120
|
if (cwd) _chdir(cwd);
|
|
104
121
|
intptr_t rc = _spawnvp(_P_WAIT, command, (const char *const *)child_argv);
|
|
105
122
|
if (had_cwd) _chdir(previous);
|
|
106
|
-
|
|
107
123
|
fflush(stdout);
|
|
108
124
|
fflush(stderr);
|
|
109
125
|
_dup2(saved_out, _fileno(stdout));
|
|
@@ -149,6 +165,24 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
149
165
|
char **child_argv = (char **)build_argv(command, args, &count);
|
|
150
166
|
if (!child_argv) return make_result(-1, "", "out of memory");
|
|
151
167
|
|
|
168
|
+
if (option_stdio_inherit(argc > 2 ? argv[2] : XT_UNDEFINED)) {
|
|
169
|
+
pid_t inherit_pid = fork();
|
|
170
|
+
if (inherit_pid < 0) {
|
|
171
|
+
free(child_argv);
|
|
172
|
+
return make_result(-1, "", "failed to fork");
|
|
173
|
+
}
|
|
174
|
+
if (inherit_pid == 0) {
|
|
175
|
+
if (cwd) chdir(cwd);
|
|
176
|
+
execvp(command, child_argv);
|
|
177
|
+
_exit(127);
|
|
178
|
+
}
|
|
179
|
+
int inherit_status = 0;
|
|
180
|
+
waitpid(inherit_pid, &inherit_status, 0);
|
|
181
|
+
free(child_argv);
|
|
182
|
+
return make_result(
|
|
183
|
+
WIFEXITED(inherit_status) ? (double)WEXITSTATUS(inherit_status) : -1.0, "", "");
|
|
184
|
+
}
|
|
185
|
+
|
|
152
186
|
int out_pipe[2];
|
|
153
187
|
int err_pipe[2];
|
|
154
188
|
if (pipe(out_pipe) != 0 || pipe(err_pipe) != 0) {
|