toilscript 0.0.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/LICENSE +201 -0
- package/NOTICE +94 -0
- package/README.md +114 -0
- package/bin/asc.js +35 -0
- package/bin/asinit.js +468 -0
- package/dist/asc.d.ts +4 -0
- package/dist/toilscript.d.ts +4 -0
- package/dist/transform.cjs +1 -0
- package/dist/transform.d.ts +1 -0
- package/dist/transform.js +1 -0
- package/lib/binaryen.d.ts +2 -0
- package/lib/binaryen.js +2 -0
- package/package.json +114 -0
- package/std/README.md +6 -0
- package/std/assembly/array.ts +550 -0
- package/std/assembly/arraybuffer.ts +77 -0
- package/std/assembly/atomics.ts +127 -0
- package/std/assembly/bindings/asyncify.ts +16 -0
- package/std/assembly/bindings/dom.ts +291 -0
- package/std/assembly/bindings/node.ts +6 -0
- package/std/assembly/bitflags.ts +53 -0
- package/std/assembly/builtins.ts +2650 -0
- package/std/assembly/byteslice.ts +177 -0
- package/std/assembly/compat.ts +2 -0
- package/std/assembly/console.ts +42 -0
- package/std/assembly/crypto.ts +9 -0
- package/std/assembly/dataview.ts +181 -0
- package/std/assembly/date.ts +375 -0
- package/std/assembly/diagnostics.ts +11 -0
- package/std/assembly/encoding.ts +151 -0
- package/std/assembly/endian.ts +45 -0
- package/std/assembly/error.ts +44 -0
- package/std/assembly/fixedarray.ts +173 -0
- package/std/assembly/fixedmap.ts +326 -0
- package/std/assembly/fixedset.ts +275 -0
- package/std/assembly/function.ts +42 -0
- package/std/assembly/index.d.ts +2891 -0
- package/std/assembly/iterator.ts +35 -0
- package/std/assembly/map.ts +269 -0
- package/std/assembly/math.ts +3289 -0
- package/std/assembly/memory.ts +123 -0
- package/std/assembly/number.ts +388 -0
- package/std/assembly/object.ts +36 -0
- package/std/assembly/performance.ts +9 -0
- package/std/assembly/pointer.ts +80 -0
- package/std/assembly/polyfills.ts +27 -0
- package/std/assembly/process.ts +50 -0
- package/std/assembly/reference.ts +48 -0
- package/std/assembly/regexp.ts +12 -0
- package/std/assembly/rt/README.md +83 -0
- package/std/assembly/rt/common.ts +81 -0
- package/std/assembly/rt/index-incremental.ts +2 -0
- package/std/assembly/rt/index-memory.ts +1 -0
- package/std/assembly/rt/index-minimal.ts +2 -0
- package/std/assembly/rt/index-stub.ts +1 -0
- package/std/assembly/rt/index.d.ts +37 -0
- package/std/assembly/rt/itcms.ts +419 -0
- package/std/assembly/rt/memory-runtime.ts +94 -0
- package/std/assembly/rt/rtrace.ts +15 -0
- package/std/assembly/rt/stub.ts +133 -0
- package/std/assembly/rt/tcms.ts +254 -0
- package/std/assembly/rt/tlsf.ts +592 -0
- package/std/assembly/rt.ts +90 -0
- package/std/assembly/set.ts +225 -0
- package/std/assembly/shared/feature.ts +68 -0
- package/std/assembly/shared/runtime.ts +13 -0
- package/std/assembly/shared/target.ts +11 -0
- package/std/assembly/shared/tsconfig.json +11 -0
- package/std/assembly/shared/typeinfo.ts +72 -0
- package/std/assembly/staticarray.ts +423 -0
- package/std/assembly/string.ts +850 -0
- package/std/assembly/symbol.ts +114 -0
- package/std/assembly/table.ts +16 -0
- package/std/assembly/tsconfig.json +6 -0
- package/std/assembly/typedarray.ts +1954 -0
- package/std/assembly/uri.ts +17 -0
- package/std/assembly/util/bytes.ts +107 -0
- package/std/assembly/util/casemap.ts +497 -0
- package/std/assembly/util/error.ts +58 -0
- package/std/assembly/util/hash.ts +117 -0
- package/std/assembly/util/math.ts +1922 -0
- package/std/assembly/util/memory.ts +290 -0
- package/std/assembly/util/number.ts +873 -0
- package/std/assembly/util/sort.ts +313 -0
- package/std/assembly/util/string.ts +1202 -0
- package/std/assembly/util/uri.ts +275 -0
- package/std/assembly/vector.ts +4 -0
- package/std/assembly.json +16 -0
- package/std/portable/index.d.ts +461 -0
- package/std/portable/index.js +416 -0
- package/std/portable.json +11 -0
- package/std/types/assembly/index.d.ts +1 -0
- package/std/types/assembly/package.json +3 -0
- package/std/types/portable/index.d.ts +1 -0
- package/std/types/portable/package.json +3 -0
- package/tsconfig-base.json +13 -0
- package/util/README.md +23 -0
- package/util/browser/fs.js +1 -0
- package/util/browser/module.js +5 -0
- package/util/browser/path.js +520 -0
- package/util/browser/process.js +59 -0
- package/util/browser/url.js +23 -0
- package/util/cpu.d.ts +9 -0
- package/util/cpu.js +42 -0
- package/util/find.d.ts +6 -0
- package/util/find.js +20 -0
- package/util/node.d.ts +21 -0
- package/util/node.js +34 -0
- package/util/options.d.ts +70 -0
- package/util/options.js +262 -0
- package/util/terminal.d.ts +52 -0
- package/util/terminal.js +35 -0
- package/util/text.d.ts +26 -0
- package/util/text.js +114 -0
- package/util/tsconfig.json +9 -0
- package/util/web.d.ts +11 -0
- package/util/web.js +33 -0
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
/// <reference path="./rt/index.d.ts" />
|
|
2
|
+
|
|
3
|
+
import { OBJECT, BLOCK_MAXSIZE, TOTAL_OVERHEAD } from "./rt/common";
|
|
4
|
+
import { Runtime } from "shared/runtime";
|
|
5
|
+
import { compareImpl, strtol, strtod, isSpace, isAscii, isFinalSigma, toLower8, toUpper8 } from "./util/string";
|
|
6
|
+
import { SPECIALS_UPPER, casemap, bsearch } from "./util/casemap";
|
|
7
|
+
import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_UNPAIRED_SURROGATE } from "./util/error";
|
|
8
|
+
import { idof } from "./builtins";
|
|
9
|
+
import { Array } from "./array";
|
|
10
|
+
|
|
11
|
+
@final export abstract class String {
|
|
12
|
+
|
|
13
|
+
@lazy static readonly MAX_LENGTH: i32 = <i32>(BLOCK_MAXSIZE >>> alignof<u16>());
|
|
14
|
+
|
|
15
|
+
static fromCharCode(unit: i32, surr: i32 = -1): String {
|
|
16
|
+
let hasSur = surr > 0;
|
|
17
|
+
let out = changetype<String>(__new(2 << i32(hasSur), idof<String>()));
|
|
18
|
+
store<u16>(changetype<usize>(out), <u16>unit);
|
|
19
|
+
if (hasSur) store<u16>(changetype<usize>(out), <u16>surr, 2);
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static fromCharCodes(units: Array<i32>): String {
|
|
24
|
+
let length = units.length;
|
|
25
|
+
let out = changetype<String>(__new(<usize>length << 1, idof<String>()));
|
|
26
|
+
let ptr = units.dataStart;
|
|
27
|
+
for (let i = 0; i < length; ++i) {
|
|
28
|
+
store<u16>(changetype<usize>(out) + (<usize>i << 1), load<i32>(ptr + (<usize>i << 2)));
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static fromCodePoint(code: i32): String {
|
|
34
|
+
let hasSur = <u32>code > 0xFFFF;
|
|
35
|
+
let out = changetype<String>(__new(2 << i32(hasSur), idof<String>()));
|
|
36
|
+
if (!hasSur) {
|
|
37
|
+
store<u16>(changetype<usize>(out), <u16>code);
|
|
38
|
+
} else {
|
|
39
|
+
// Checks valid code point range
|
|
40
|
+
assert(<u32>code <= 0x10FFFF);
|
|
41
|
+
code -= 0x10000;
|
|
42
|
+
let hi = (code & 0x03FF) | 0xDC00;
|
|
43
|
+
let lo = code >>> 10 | 0xD800;
|
|
44
|
+
store<u32>(changetype<usize>(out), lo | hi << 16);
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@builtin static raw(parts: TemplateStringsArray, ...args: unknown[]): string { return unreachable(); }
|
|
50
|
+
|
|
51
|
+
get length(): i32 {
|
|
52
|
+
return changetype<OBJECT>(changetype<usize>(this) - TOTAL_OVERHEAD).rtSize >> 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
at(pos: i32): String {
|
|
56
|
+
let len = this.length;
|
|
57
|
+
pos += select(0, len, pos >= 0);
|
|
58
|
+
if (<u32>pos >= <u32>len) throw new RangeError(E_INDEXOUTOFRANGE);
|
|
59
|
+
let out = __new(2, idof<String>());
|
|
60
|
+
store<u16>(out, load<u16>(changetype<usize>(this) + (<usize>pos << 1)));
|
|
61
|
+
return changetype<String>(out); // retains
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@operator("[]") charAt(pos: i32): String {
|
|
65
|
+
if (<u32>pos >= <u32>this.length) return changetype<String>("");
|
|
66
|
+
let out = changetype<String>(__new(2, idof<String>()));
|
|
67
|
+
store<u16>(changetype<usize>(out), load<u16>(changetype<usize>(this) + (<usize>pos << 1)));
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
charCodeAt(pos: i32): i32 {
|
|
72
|
+
if (<u32>pos >= <u32>this.length) return -1; // (NaN)
|
|
73
|
+
return load<u16>(changetype<usize>(this) + (<usize>pos << 1));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
codePointAt(pos: i32): i32 {
|
|
77
|
+
let len = this.length;
|
|
78
|
+
if (<u32>pos >= <u32>len) return -1; // (undefined)
|
|
79
|
+
let first = <i32>load<u16>(changetype<usize>(this) + (<usize>pos << 1));
|
|
80
|
+
if ((first & 0xFC00) != 0xD800 || pos + 1 == len) return first;
|
|
81
|
+
let second = <i32>load<u16>(changetype<usize>(this) + (<usize>pos << 1), 2);
|
|
82
|
+
if ((second & 0xFC00) != 0xDC00) return first;
|
|
83
|
+
return (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@operator("+") private static __concat(left: String, right: String): String {
|
|
87
|
+
return left.concat(right);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
concat(other: String): String {
|
|
91
|
+
let thisSize: isize = this.length << 1;
|
|
92
|
+
let otherSize: isize = other.length << 1;
|
|
93
|
+
let outSize: usize = thisSize + otherSize;
|
|
94
|
+
if (outSize == 0) return changetype<String>("");
|
|
95
|
+
let out = changetype<String>(__new(outSize, idof<String>()));
|
|
96
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this), thisSize);
|
|
97
|
+
memory.copy(changetype<usize>(out) + thisSize, changetype<usize>(other), otherSize);
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
endsWith(search: String, end: i32 = String.MAX_LENGTH): bool {
|
|
102
|
+
end = min(max(end, 0), this.length);
|
|
103
|
+
let searchLength = <isize>search.length;
|
|
104
|
+
let searchStart = <isize>end - searchLength;
|
|
105
|
+
if (searchStart < 0) return false;
|
|
106
|
+
// @ts-ignore: string <-> String
|
|
107
|
+
return !compareImpl(this, searchStart, search, 0, searchLength);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@operator("==") private static __eq(left: String | null, right: String | null): bool {
|
|
111
|
+
if (changetype<usize>(left) == changetype<usize>(right)) return true;
|
|
112
|
+
if (changetype<usize>(left) == 0 || changetype<usize>(right) == 0) return false;
|
|
113
|
+
let leftLength = changetype<string>(left).length;
|
|
114
|
+
if (leftLength != changetype<string>(right).length) return false;
|
|
115
|
+
// @ts-ignore: string <-> String
|
|
116
|
+
return !compareImpl(left, 0, right, 0, leftLength);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@operator.prefix("!")
|
|
120
|
+
private static __not(str: String | null): bool {
|
|
121
|
+
return changetype<usize>(str) == 0 || !changetype<string>(str).length;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@operator("!=")
|
|
125
|
+
private static __ne(left: String | null, right: String | null): bool {
|
|
126
|
+
return !this.__eq(left, right);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@operator(">") private static __gt(left: String, right: String): bool {
|
|
130
|
+
if (changetype<usize>(left) == changetype<usize>(right)) return false;
|
|
131
|
+
let leftLength = left.length;
|
|
132
|
+
if (!leftLength) return false;
|
|
133
|
+
let rightLength = right.length;
|
|
134
|
+
if (!rightLength) return true;
|
|
135
|
+
// @ts-ignore: string <-> String
|
|
136
|
+
let res = compareImpl(left, 0, right, 0, min(leftLength, rightLength));
|
|
137
|
+
return res ? res > 0 : leftLength > rightLength;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@operator(">=") private static __gte(left: String, right: String): bool {
|
|
141
|
+
return !this.__lt(left, right);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@operator("<") private static __lt(left: String, right: String): bool {
|
|
145
|
+
if (changetype<usize>(left) == changetype<usize>(right)) return false;
|
|
146
|
+
let rightLength = right.length;
|
|
147
|
+
if (!rightLength) return false;
|
|
148
|
+
let leftLength = left.length;
|
|
149
|
+
if (!leftLength) return true;
|
|
150
|
+
// @ts-ignore: string <-> String
|
|
151
|
+
let res = compareImpl(left, 0, right, 0, min(leftLength, rightLength));
|
|
152
|
+
return res ? res < 0 : leftLength < rightLength;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@operator("<=") private static __lte(left: String, right: String): bool {
|
|
156
|
+
return !this.__gt(left, right);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
includes(search: String, start: i32 = 0): bool {
|
|
160
|
+
return this.indexOf(search, start) != -1;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
indexOf(search: String, start: i32 = 0): i32 {
|
|
164
|
+
let searchLen = <isize>search.length;
|
|
165
|
+
if (!searchLen) return 0;
|
|
166
|
+
let len = <isize>this.length;
|
|
167
|
+
if (!len) return -1;
|
|
168
|
+
let searchStart = min(max(<isize>start, 0), len);
|
|
169
|
+
for (len -= searchLen; searchStart <= len; ++searchStart) {
|
|
170
|
+
// @ts-ignore: string <-> String
|
|
171
|
+
if (!compareImpl(this, searchStart, search, 0, searchLen)) return <i32>searchStart;
|
|
172
|
+
}
|
|
173
|
+
return -1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
lastIndexOf(search: String, start: i32 = i32.MAX_VALUE): i32 {
|
|
177
|
+
let searchLen = <isize>search.length;
|
|
178
|
+
if (!searchLen) return this.length;
|
|
179
|
+
let len = this.length;
|
|
180
|
+
if (!len) return -1;
|
|
181
|
+
let searchStart = min(max(<isize>start, 0), <isize>len - searchLen);
|
|
182
|
+
for (; searchStart >= 0; --searchStart) {
|
|
183
|
+
// @ts-ignore: string <-> String
|
|
184
|
+
if (!compareImpl(this, searchStart, search, 0, searchLen)) return <i32>searchStart;
|
|
185
|
+
}
|
|
186
|
+
return -1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// TODO: implement full locale comparison with locales and Collator options
|
|
190
|
+
localeCompare(other: String): i32 {
|
|
191
|
+
if (changetype<usize>(other) == changetype<usize>(this)) return 0;
|
|
192
|
+
let alen = this.length;
|
|
193
|
+
let blen = other.length;
|
|
194
|
+
// @ts-ignore: string <-> String
|
|
195
|
+
let res = compareImpl(this, 0, other, 0, <usize>min(alen, blen));
|
|
196
|
+
res = res ? res : alen - blen;
|
|
197
|
+
// normalize to [-1, 1] range
|
|
198
|
+
return i32(res > 0) - i32(res < 0);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
startsWith(search: String, start: i32 = 0): bool {
|
|
202
|
+
let len = <isize>this.length;
|
|
203
|
+
let searchStart = min(max(<isize>start, 0), len);
|
|
204
|
+
let searchLength = <isize>search.length;
|
|
205
|
+
if (searchLength + searchStart > len) return false;
|
|
206
|
+
// @ts-ignore: string <-> String
|
|
207
|
+
return !compareImpl(this, searchStart, search, 0, searchLength);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
substr(start: i32, length: i32 = i32.MAX_VALUE): String { // legacy
|
|
211
|
+
let intStart: isize = start;
|
|
212
|
+
let end: isize = length;
|
|
213
|
+
let len: isize = this.length;
|
|
214
|
+
if (intStart < 0) intStart = max(len + intStart, 0);
|
|
215
|
+
let size = min(max(end, 0), len - intStart) << 1;
|
|
216
|
+
if (size <= 0) return changetype<String>("");
|
|
217
|
+
let out = changetype<String>(__new(size, idof<String>()));
|
|
218
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this) + (intStart << 1), size);
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
substring(start: i32, end: i32 = i32.MAX_VALUE): String {
|
|
223
|
+
let len: isize = this.length;
|
|
224
|
+
let finalStart = min<isize>(max(start, 0), len);
|
|
225
|
+
let finalEnd = min<isize>(max(end, 0), len);
|
|
226
|
+
let fromPos = min<isize>(finalStart, finalEnd) << 1;
|
|
227
|
+
let toPos = max<isize>(finalStart, finalEnd) << 1;
|
|
228
|
+
let size = toPos - fromPos;
|
|
229
|
+
if (!size) return changetype<String>("");
|
|
230
|
+
if (!fromPos && toPos == len << 1) return this;
|
|
231
|
+
let out = changetype<String>(__new(size, idof<String>()));
|
|
232
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this) + fromPos, size);
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
trim(): String {
|
|
237
|
+
let len = this.length;
|
|
238
|
+
let size: usize = len << 1;
|
|
239
|
+
while (size && isSpace(load<u16>(changetype<usize>(this) + size - 2))) {
|
|
240
|
+
size -= 2;
|
|
241
|
+
}
|
|
242
|
+
let offset: usize = 0;
|
|
243
|
+
while (offset < size && isSpace(load<u16>(changetype<usize>(this) + offset))) {
|
|
244
|
+
offset += 2; size -= 2;
|
|
245
|
+
}
|
|
246
|
+
if (!size) return changetype<String>("");
|
|
247
|
+
if (!offset && size == len << 1) return this;
|
|
248
|
+
let out = changetype<String>(__new(size, idof<String>()));
|
|
249
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this) + offset, size);
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@inline
|
|
254
|
+
trimLeft(): String {
|
|
255
|
+
return this.trimStart();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@inline
|
|
259
|
+
trimRight(): String {
|
|
260
|
+
return this.trimEnd();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
trimStart(): String {
|
|
264
|
+
let size = <usize>this.length << 1;
|
|
265
|
+
let offset: usize = 0;
|
|
266
|
+
while (offset < size && isSpace(load<u16>(changetype<usize>(this) + offset))) {
|
|
267
|
+
offset += 2;
|
|
268
|
+
}
|
|
269
|
+
if (!offset) return this;
|
|
270
|
+
size -= offset;
|
|
271
|
+
if (!size) return changetype<String>("");
|
|
272
|
+
let out = changetype<String>(__new(size, idof<String>()));
|
|
273
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this) + offset, size);
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
trimEnd(): String {
|
|
278
|
+
let originalSize = <usize>this.length << 1;
|
|
279
|
+
let size = originalSize;
|
|
280
|
+
while (size && isSpace(load<u16>(changetype<usize>(this) + size - 2))) {
|
|
281
|
+
size -= 2;
|
|
282
|
+
}
|
|
283
|
+
if (!size) return changetype<String>("");
|
|
284
|
+
if (size == originalSize) return this;
|
|
285
|
+
let out = changetype<String>(__new(size, idof<String>()));
|
|
286
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this), size);
|
|
287
|
+
return out;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
padStart(length: i32, pad: string = " "): String {
|
|
291
|
+
let thisSize = <usize>this.length << 1;
|
|
292
|
+
let targetSize = <usize>length << 1;
|
|
293
|
+
let padSize = <usize>pad.length << 1;
|
|
294
|
+
if (targetSize < thisSize || !padSize) return this;
|
|
295
|
+
let prependSize = targetSize - thisSize;
|
|
296
|
+
let out = changetype<String>(__new(targetSize, idof<String>()));
|
|
297
|
+
if (prependSize > padSize) {
|
|
298
|
+
let repeatCount = (prependSize - 2) / padSize;
|
|
299
|
+
let restBase = repeatCount * padSize;
|
|
300
|
+
let restSize = prependSize - restBase;
|
|
301
|
+
memory.repeat(changetype<usize>(out), changetype<usize>(pad), padSize, repeatCount);
|
|
302
|
+
memory.copy(changetype<usize>(out) + restBase, changetype<usize>(pad), restSize);
|
|
303
|
+
} else {
|
|
304
|
+
memory.copy(changetype<usize>(out), changetype<usize>(pad), prependSize);
|
|
305
|
+
}
|
|
306
|
+
memory.copy(changetype<usize>(out) + prependSize, changetype<usize>(this), thisSize);
|
|
307
|
+
return out;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
padEnd(length: i32, pad: string = " "): String {
|
|
311
|
+
let thisSize = <usize>this.length << 1;
|
|
312
|
+
let targetSize = <usize>length << 1;
|
|
313
|
+
let padSize = <usize>pad.length << 1;
|
|
314
|
+
if (targetSize < thisSize || !padSize) return this;
|
|
315
|
+
let appendSize = targetSize - thisSize;
|
|
316
|
+
let out = changetype<String>(__new(targetSize, idof<String>()));
|
|
317
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this), thisSize);
|
|
318
|
+
if (appendSize > padSize) {
|
|
319
|
+
let repeatCount = (appendSize - 2) / padSize;
|
|
320
|
+
let restBase = repeatCount * padSize;
|
|
321
|
+
let restSize = appendSize - restBase;
|
|
322
|
+
memory.repeat(changetype<usize>(out) + thisSize, changetype<usize>(pad), padSize, repeatCount);
|
|
323
|
+
memory.copy(changetype<usize>(out) + thisSize + restBase, changetype<usize>(pad), restSize);
|
|
324
|
+
} else {
|
|
325
|
+
memory.copy(changetype<usize>(out) + thisSize, changetype<usize>(pad), appendSize);
|
|
326
|
+
}
|
|
327
|
+
return out;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
repeat(count: i32 = 0): String {
|
|
331
|
+
let length = this.length;
|
|
332
|
+
|
|
333
|
+
// Most browsers can't handle strings 1 << 28 chars or longer
|
|
334
|
+
if (count < 0 || <u64>length * count > (1 << 28)) {
|
|
335
|
+
throw new RangeError(E_INVALIDLENGTH);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (count == 0 || !length) return changetype<String>("");
|
|
339
|
+
if (count == 1) return this;
|
|
340
|
+
let out = changetype<String>(__new((length * count) << 1, idof<String>()));
|
|
341
|
+
memory.repeat(changetype<usize>(out), changetype<usize>(this), <usize>length << 1, count);
|
|
342
|
+
return out;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
replace(search: String, replacement: String): String {
|
|
346
|
+
let len: usize = this.length;
|
|
347
|
+
let slen: usize = search.length;
|
|
348
|
+
if (len <= slen) {
|
|
349
|
+
return len < slen ? this : select<String>(replacement, this, search == this);
|
|
350
|
+
}
|
|
351
|
+
let index: isize = this.indexOf(search);
|
|
352
|
+
if (~index) {
|
|
353
|
+
let rlen: usize = replacement.length;
|
|
354
|
+
len -= slen;
|
|
355
|
+
let olen = len + rlen;
|
|
356
|
+
if (olen) {
|
|
357
|
+
let out = changetype<String>(__new(olen << 1, idof<String>()));
|
|
358
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this), index << 1);
|
|
359
|
+
memory.copy(
|
|
360
|
+
changetype<usize>(out) + (index << 1),
|
|
361
|
+
changetype<usize>(replacement),
|
|
362
|
+
rlen << 1
|
|
363
|
+
);
|
|
364
|
+
memory.copy(
|
|
365
|
+
changetype<usize>(out) + ((index + rlen) << 1),
|
|
366
|
+
changetype<usize>(this) + ((index + slen) << 1),
|
|
367
|
+
(len - index) << 1
|
|
368
|
+
);
|
|
369
|
+
return out;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return this;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
replaceAll(search: String, replacement: String): String {
|
|
376
|
+
let thisLen: usize = this.length;
|
|
377
|
+
let searchLen: usize = search.length;
|
|
378
|
+
if (thisLen <= searchLen) {
|
|
379
|
+
return thisLen < searchLen
|
|
380
|
+
? this
|
|
381
|
+
: select<String>(replacement, this, search == this);
|
|
382
|
+
}
|
|
383
|
+
let replaceLen: usize = replacement.length;
|
|
384
|
+
if (!searchLen) {
|
|
385
|
+
if (!replaceLen) return this;
|
|
386
|
+
// Special case: 'abc'.replaceAll('', '-') -> '-a-b-c-'
|
|
387
|
+
let out = changetype<String>(__new((thisLen + (thisLen + 1) * replaceLen) << 1, idof<String>()));
|
|
388
|
+
memory.copy(changetype<usize>(out), changetype<usize>(replacement), replaceLen << 1);
|
|
389
|
+
let offset = replaceLen;
|
|
390
|
+
for (let i: usize = 0; i < thisLen; ++i) {
|
|
391
|
+
store<u16>(
|
|
392
|
+
changetype<usize>(out) + (offset++ << 1),
|
|
393
|
+
load<u16>(changetype<usize>(this) + (i << 1))
|
|
394
|
+
);
|
|
395
|
+
memory.copy(
|
|
396
|
+
changetype<usize>(out) + (offset << 1),
|
|
397
|
+
changetype<usize>(replacement),
|
|
398
|
+
replaceLen << 1
|
|
399
|
+
);
|
|
400
|
+
offset += replaceLen;
|
|
401
|
+
}
|
|
402
|
+
return out;
|
|
403
|
+
}
|
|
404
|
+
let prev: isize = 0, next: isize = 0;
|
|
405
|
+
if (searchLen == replaceLen) {
|
|
406
|
+
// Fast path when search and replacement have same length
|
|
407
|
+
let outSize = thisLen << 1;
|
|
408
|
+
let out = changetype<String>(__new(outSize, idof<String>()));
|
|
409
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this), outSize);
|
|
410
|
+
while (~(next = <isize>this.indexOf(search, <i32>prev))) {
|
|
411
|
+
memory.copy(changetype<usize>(out) + (next << 1), changetype<usize>(replacement), replaceLen << 1);
|
|
412
|
+
prev = next + searchLen;
|
|
413
|
+
}
|
|
414
|
+
return out;
|
|
415
|
+
}
|
|
416
|
+
let out: String | null = null, offset: usize = 0, outSize = thisLen;
|
|
417
|
+
while (~(next = <isize>this.indexOf(search, <i32>prev))) {
|
|
418
|
+
if (!out) out = changetype<String>(__new(thisLen << 1, idof<String>()));
|
|
419
|
+
let chunk = next - prev;
|
|
420
|
+
if (offset + chunk + replaceLen > outSize) {
|
|
421
|
+
outSize <<= 1;
|
|
422
|
+
out = changetype<String>(__renew(changetype<usize>(out), outSize << 1));
|
|
423
|
+
}
|
|
424
|
+
memory.copy(
|
|
425
|
+
changetype<usize>(out) + (offset << 1),
|
|
426
|
+
changetype<usize>(this) + (prev << 1),
|
|
427
|
+
chunk << 1
|
|
428
|
+
);
|
|
429
|
+
offset += chunk;
|
|
430
|
+
memory.copy(
|
|
431
|
+
changetype<usize>(out) + (offset << 1),
|
|
432
|
+
changetype<usize>(replacement),
|
|
433
|
+
replaceLen << 1
|
|
434
|
+
);
|
|
435
|
+
offset += replaceLen;
|
|
436
|
+
prev = next + searchLen;
|
|
437
|
+
}
|
|
438
|
+
if (out) {
|
|
439
|
+
let rest = thisLen - prev;
|
|
440
|
+
if (offset + rest > outSize) {
|
|
441
|
+
outSize <<= 1;
|
|
442
|
+
out = changetype<String>(__renew(changetype<usize>(out), outSize << 1));
|
|
443
|
+
}
|
|
444
|
+
if (rest) {
|
|
445
|
+
memory.copy(
|
|
446
|
+
changetype<usize>(out) + (offset << 1),
|
|
447
|
+
changetype<usize>(this) + (prev << 1),
|
|
448
|
+
rest << 1
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
rest += offset;
|
|
452
|
+
if (outSize > rest) {
|
|
453
|
+
out = changetype<String>(__renew(changetype<usize>(out), rest << 1));
|
|
454
|
+
}
|
|
455
|
+
return out;
|
|
456
|
+
}
|
|
457
|
+
return this;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
slice(start: i32, end: i32 = i32.MAX_VALUE): String {
|
|
461
|
+
let len = this.length;
|
|
462
|
+
start = start < 0 ? max(start + len, 0) : min(start, len);
|
|
463
|
+
end = end < 0 ? max(end + len, 0) : min(end, len);
|
|
464
|
+
len = end - start;
|
|
465
|
+
if (len <= 0) return changetype<String>("");
|
|
466
|
+
let out = changetype<String>(__new(len << 1, idof<String>()));
|
|
467
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this) + (<usize>start << 1), <usize>len << 1);
|
|
468
|
+
return out;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
split(separator: String | null = null, limit: i32 = i32.MAX_VALUE): String[] {
|
|
472
|
+
if (!limit) return changetype<String[]>(__newArray(0, alignof<String>(), idof<Array<String>>()));
|
|
473
|
+
if (changetype<usize>(separator) == 0) return [ this ];
|
|
474
|
+
let length: isize = this.length;
|
|
475
|
+
let sepLen = changetype<string>(separator).length;
|
|
476
|
+
if (limit < 0) limit = i32.MAX_VALUE;
|
|
477
|
+
if (!sepLen) {
|
|
478
|
+
if (!length) return changetype<String[]>(__newArray(0, alignof<String>(), idof<Array<String>>()));
|
|
479
|
+
// split by chars
|
|
480
|
+
length = min<isize>(length, <isize>limit);
|
|
481
|
+
let result = changetype<String[]>(__newArray(<i32>length, alignof<String>(), idof<Array<String>>()));
|
|
482
|
+
// @ts-ignore: cast
|
|
483
|
+
let resultStart = result.dataStart as usize;
|
|
484
|
+
for (let i: isize = 0; i < length; ++i) {
|
|
485
|
+
let charStr = changetype<String>(__new(2, idof<String>()));
|
|
486
|
+
store<u16>(changetype<usize>(charStr), load<u16>(changetype<usize>(this) + (<usize>i << 1)));
|
|
487
|
+
store<usize>(resultStart + (<usize>i << alignof<usize>()), changetype<usize>(charStr)); // result[i] = charStr
|
|
488
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
489
|
+
__link(changetype<usize>(result), changetype<usize>(charStr), true);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return result;
|
|
493
|
+
} else if (!length) {
|
|
494
|
+
let result = changetype<String[]>(__newArray(1, alignof<String>(), idof<Array<String>>()));
|
|
495
|
+
// @ts-ignore: cast
|
|
496
|
+
store<usize>(result.dataStart as usize, changetype<usize>("")); // static ""
|
|
497
|
+
return result;
|
|
498
|
+
}
|
|
499
|
+
let result = changetype<String[]>(__newArray(0, alignof<String>(), idof<Array<String>>()));
|
|
500
|
+
let end = 0, start = 0, i = 0;
|
|
501
|
+
while (~(end = this.indexOf(changetype<string>(separator), start))) {
|
|
502
|
+
let len = end - start;
|
|
503
|
+
if (len > 0) {
|
|
504
|
+
let out = changetype<String>(__new(<usize>len << 1, idof<String>()));
|
|
505
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this) + (<usize>start << 1), <usize>len << 1);
|
|
506
|
+
result.push(out);
|
|
507
|
+
} else {
|
|
508
|
+
result.push(changetype<String>(""));
|
|
509
|
+
}
|
|
510
|
+
if (++i == limit) return result;
|
|
511
|
+
start = end + sepLen;
|
|
512
|
+
}
|
|
513
|
+
if (!start) { // also means: loop above didn't do anything
|
|
514
|
+
result.push(this);
|
|
515
|
+
return result;
|
|
516
|
+
}
|
|
517
|
+
let len = length - start;
|
|
518
|
+
if (len > 0) {
|
|
519
|
+
let out = changetype<String>(__new(<usize>len << 1, idof<String>()));
|
|
520
|
+
memory.copy(changetype<usize>(out), changetype<usize>(this) + (<usize>start << 1), <usize>len << 1);
|
|
521
|
+
result.push(out);
|
|
522
|
+
} else {
|
|
523
|
+
result.push(changetype<String>("")); // static ""
|
|
524
|
+
}
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
toLowerCase(): String {
|
|
529
|
+
let len = <usize>this.length;
|
|
530
|
+
if (!len) return this;
|
|
531
|
+
let codes = changetype<String>(__new(len * 2 * 2, idof<String>()));
|
|
532
|
+
let j: usize = 0;
|
|
533
|
+
for (let i: usize = 0; i < len; ++i, ++j) {
|
|
534
|
+
let c = <u32>load<u16>(changetype<usize>(this) + (i << 1));
|
|
535
|
+
if (isAscii(c)) {
|
|
536
|
+
store<u16>(changetype<usize>(codes) + (j << 1), toLower8(c));
|
|
537
|
+
} else {
|
|
538
|
+
// check and read surrogate pair
|
|
539
|
+
if ((c - 0xD7FF < 0xDC00 - 0xD7FF) && i < len - 1) {
|
|
540
|
+
let c1 = <u32>load<u16>(changetype<usize>(this) + (i << 1), 2);
|
|
541
|
+
if (c1 - 0xDBFF < 0xE000 - 0xDBFF) {
|
|
542
|
+
let c0 = c;
|
|
543
|
+
c = (((c & 0x03FF) << 10) | (c1 & 0x03FF)) + 0x10000;
|
|
544
|
+
++i;
|
|
545
|
+
if (c >= 0x20000) {
|
|
546
|
+
store<u32>(changetype<usize>(codes) + (j << 1), c0 | (c1 << 16));
|
|
547
|
+
++j;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
// check special casing for lower table. It has one ently so instead lookup we just inline this.
|
|
553
|
+
if (c == 0x0130) {
|
|
554
|
+
// 0x0130 -> [0x0069, 0x0307]
|
|
555
|
+
store<u32>(changetype<usize>(codes) + (j << 1), (0x0307 << 16) | 0x0069);
|
|
556
|
+
++j;
|
|
557
|
+
} else if (c == 0x03A3) { // 'Σ'
|
|
558
|
+
// Σ maps to σ but except at the end of a word where it maps to ς
|
|
559
|
+
let sigma = 0x03C3; // σ
|
|
560
|
+
if (len > 1 && isFinalSigma(changetype<usize>(this), i, len)) {
|
|
561
|
+
sigma = 0x03C2; // ς
|
|
562
|
+
}
|
|
563
|
+
store<u16>(changetype<usize>(codes) + (j << 1), sigma);
|
|
564
|
+
} else if (c - 0x24B6 <= 0x24CF - 0x24B6) {
|
|
565
|
+
// Range 0x24B6 <= c <= 0x24CF not covered by casemap and require special early handling
|
|
566
|
+
store<u16>(changetype<usize>(codes) + (j << 1), c + 26);
|
|
567
|
+
} else {
|
|
568
|
+
let code = casemap(c, 0) & 0x1FFFFF;
|
|
569
|
+
if (code < 0x10000) {
|
|
570
|
+
store<u16>(changetype<usize>(codes) + (j << 1), code);
|
|
571
|
+
} else {
|
|
572
|
+
// store as surrogare pair
|
|
573
|
+
code -= 0x10000;
|
|
574
|
+
let lo = (code >>> 10) | 0xD800;
|
|
575
|
+
let hi = (code & 0x03FF) | 0xDC00;
|
|
576
|
+
store<u32>(changetype<usize>(codes) + (j << 1), lo | (hi << 16));
|
|
577
|
+
++j;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return changetype<String>(__renew(changetype<usize>(codes), j << 1));
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
toUpperCase(): String {
|
|
586
|
+
let len = <usize>this.length;
|
|
587
|
+
if (!len) return this;
|
|
588
|
+
let codes = changetype<String>(__new(len * 3 * 2, idof<String>()));
|
|
589
|
+
let specialsPtr = changetype<usize>(SPECIALS_UPPER);
|
|
590
|
+
let specialsLen = SPECIALS_UPPER.length;
|
|
591
|
+
let j: usize = 0;
|
|
592
|
+
for (let i: usize = 0; i < len; ++i, ++j) {
|
|
593
|
+
let c = <u32>load<u16>(changetype<usize>(this) + (i << 1));
|
|
594
|
+
if (isAscii(c)) {
|
|
595
|
+
store<u16>(changetype<usize>(codes) + (j << 1), toUpper8(c));
|
|
596
|
+
} else {
|
|
597
|
+
// check and read surrogate pair
|
|
598
|
+
if ((c - 0xD7FF < 0xDC00 - 0xD7FF) && i < len - 1) {
|
|
599
|
+
let c1 = <u32>load<u16>(changetype<usize>(this) + (i << 1), 2);
|
|
600
|
+
if (c1 - 0xDBFF < 0xE000 - 0xDBFF) {
|
|
601
|
+
let c0 = c;
|
|
602
|
+
c = (((c & 0x03FF) << 10) | (c1 & 0x03FF)) + 0x10000;
|
|
603
|
+
++i;
|
|
604
|
+
if (c >= 0x20000) {
|
|
605
|
+
store<u32>(changetype<usize>(codes) + (j << 1), c0 | (c1 << 16));
|
|
606
|
+
++j;
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
// Range 0x24D0 <= c <= 0x24E9 not covered by casemap and require special early handling
|
|
612
|
+
if (c - 0x24D0 <= 0x24E9 - 0x24D0) {
|
|
613
|
+
// monkey patch
|
|
614
|
+
store<u16>(changetype<usize>(codes) + (j << 1), c - 26);
|
|
615
|
+
} else {
|
|
616
|
+
let index: usize = -1;
|
|
617
|
+
// Fast range check. See first and last rows in specialsUpper table
|
|
618
|
+
if (c - 0x00DF <= 0xFB17 - 0x00DF) {
|
|
619
|
+
index = <usize>bsearch(c, specialsPtr, specialsLen);
|
|
620
|
+
}
|
|
621
|
+
if (~index) {
|
|
622
|
+
// load next 3 code points from row with `index` offset for specialsUpper table
|
|
623
|
+
let ab = load<u32>(specialsPtr + (index << 1), 2);
|
|
624
|
+
let cc = load<u16>(specialsPtr + (index << 1), 6);
|
|
625
|
+
store<u32>(changetype<usize>(codes) + (j << 1), ab, 0);
|
|
626
|
+
store<u16>(changetype<usize>(codes) + (j << 1), cc, 4);
|
|
627
|
+
j += 1 + usize(cc != 0);
|
|
628
|
+
} else {
|
|
629
|
+
let code = casemap(c, 1) & 0x1FFFFF;
|
|
630
|
+
if (code < 0x10000) {
|
|
631
|
+
store<u16>(changetype<usize>(codes) + (j << 1), code);
|
|
632
|
+
} else {
|
|
633
|
+
// store as surrogare pair
|
|
634
|
+
code -= 0x10000;
|
|
635
|
+
let lo = (code >>> 10) | 0xD800;
|
|
636
|
+
let hi = (code & 0x03FF) | 0xDC00;
|
|
637
|
+
store<u32>(changetype<usize>(codes) + (j << 1), lo | (hi << 16));
|
|
638
|
+
++j;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return changetype<String>(__renew(changetype<usize>(codes), j << 1));
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
toString(): String {
|
|
648
|
+
return this;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// @ts-ignore: nolib
|
|
653
|
+
export type string = String;
|
|
654
|
+
|
|
655
|
+
export function parseInt(str: string, radix: i32 = 0): f64 {
|
|
656
|
+
return strtol<f64>(str, radix);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export function parseFloat(str: string): f64 {
|
|
660
|
+
return strtod(str);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Encoding helpers
|
|
664
|
+
export namespace String {
|
|
665
|
+
|
|
666
|
+
export namespace UTF8 {
|
|
667
|
+
|
|
668
|
+
export const enum ErrorMode {
|
|
669
|
+
WTF8,
|
|
670
|
+
REPLACE,
|
|
671
|
+
ERROR
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
export function byteLength(str: string, nullTerminated: bool = false): i32 {
|
|
675
|
+
let strOff = changetype<usize>(str);
|
|
676
|
+
let strEnd = strOff + <usize>changetype<OBJECT>(changetype<usize>(str) - TOTAL_OVERHEAD).rtSize;
|
|
677
|
+
let bufLen = i32(nullTerminated);
|
|
678
|
+
while (strOff < strEnd) {
|
|
679
|
+
let c1 = <u32>load<u16>(strOff);
|
|
680
|
+
if (c1 < 128) {
|
|
681
|
+
// @ts-ignore: cast
|
|
682
|
+
if (nullTerminated & !c1) break;
|
|
683
|
+
bufLen += 1;
|
|
684
|
+
} else if (c1 < 2048) {
|
|
685
|
+
bufLen += 2;
|
|
686
|
+
} else {
|
|
687
|
+
if ((c1 & 0xFC00) == 0xD800 && strOff + 2 < strEnd) {
|
|
688
|
+
if ((<u32>load<u16>(strOff, 2) & 0xFC00) == 0xDC00) {
|
|
689
|
+
bufLen += 4; strOff += 4;
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
bufLen += 3;
|
|
694
|
+
}
|
|
695
|
+
strOff += 2;
|
|
696
|
+
}
|
|
697
|
+
return bufLen;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
export function encode(str: string, nullTerminated: bool = false, errorMode: ErrorMode = ErrorMode.WTF8): ArrayBuffer {
|
|
701
|
+
let buf = changetype<ArrayBuffer>(__new(<usize>byteLength(str, nullTerminated), idof<ArrayBuffer>()));
|
|
702
|
+
encodeUnsafe(changetype<usize>(str), str.length, changetype<usize>(buf), nullTerminated, errorMode);
|
|
703
|
+
return buf;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// @ts-ignore: decorator
|
|
707
|
+
@unsafe
|
|
708
|
+
export function encodeUnsafe(str: usize, len: i32, buf: usize, nullTerminated: bool = false, errorMode: ErrorMode = ErrorMode.WTF8): usize {
|
|
709
|
+
let strEnd = str + (<usize>len << 1);
|
|
710
|
+
let bufOff = buf;
|
|
711
|
+
while (str < strEnd) {
|
|
712
|
+
let c1 = <u32>load<u16>(str);
|
|
713
|
+
if (c1 < 128) {
|
|
714
|
+
store<u8>(bufOff, c1);
|
|
715
|
+
bufOff++;
|
|
716
|
+
// @ts-ignore: cast
|
|
717
|
+
if (nullTerminated & !c1) return bufOff - buf;
|
|
718
|
+
} else if (c1 < 2048) {
|
|
719
|
+
let b0 = c1 >> 6 | 192;
|
|
720
|
+
let b1 = c1 & 63 | 128;
|
|
721
|
+
store<u16>(bufOff, b1 << 8 | b0);
|
|
722
|
+
bufOff += 2;
|
|
723
|
+
} else {
|
|
724
|
+
// D800: 11011 0 0000000000 Lead
|
|
725
|
+
// DBFF: 11011 0 1111111111
|
|
726
|
+
// DC00: 11011 1 0000000000 Trail
|
|
727
|
+
// DFFF: 11011 1 1111111111
|
|
728
|
+
// F800: 11111 0 0000000000 Mask
|
|
729
|
+
// FC00: 11111 1 0000000000
|
|
730
|
+
if ((c1 & 0xF800) == 0xD800) {
|
|
731
|
+
if (c1 < 0xDC00 && str + 2 < strEnd) {
|
|
732
|
+
let c2 = <u32>load<u16>(str, 2);
|
|
733
|
+
if ((c2 & 0xFC00) == 0xDC00) {
|
|
734
|
+
c1 = 0x10000 + ((c1 & 0x03FF) << 10) | (c2 & 0x03FF);
|
|
735
|
+
let b0 = c1 >> 18 | 240;
|
|
736
|
+
let b1 = c1 >> 12 & 63 | 128;
|
|
737
|
+
let b2 = c1 >> 6 & 63 | 128;
|
|
738
|
+
let b3 = c1 & 63 | 128;
|
|
739
|
+
store<u32>(bufOff, b3 << 24 | b2 << 16 | b1 << 8 | b0);
|
|
740
|
+
bufOff += 4; str += 4;
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
if (errorMode != ErrorMode.WTF8) { // unlikely
|
|
745
|
+
if (errorMode == ErrorMode.ERROR) throw new Error(E_UNPAIRED_SURROGATE);
|
|
746
|
+
c1 = 0xFFFD;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
let b0 = c1 >> 12 | 224;
|
|
750
|
+
let b1 = c1 >> 6 & 63 | 128;
|
|
751
|
+
let b2 = c1 & 63 | 128;
|
|
752
|
+
store<u16>(bufOff, b1 << 8 | b0);
|
|
753
|
+
store<u8>(bufOff, b2, 2);
|
|
754
|
+
bufOff += 3;
|
|
755
|
+
}
|
|
756
|
+
str += 2;
|
|
757
|
+
}
|
|
758
|
+
if (nullTerminated) {
|
|
759
|
+
store<u8>(bufOff++, 0);
|
|
760
|
+
}
|
|
761
|
+
return bufOff - buf;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
export function decode(buf: ArrayBuffer, nullTerminated: bool = false): String {
|
|
765
|
+
return decodeUnsafe(changetype<usize>(buf), buf.byteLength, nullTerminated);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// @ts-ignore: decorator
|
|
769
|
+
@unsafe
|
|
770
|
+
export function decodeUnsafe(buf: usize, len: usize, nullTerminated: bool = false): String {
|
|
771
|
+
let bufOff = buf;
|
|
772
|
+
let bufEnd = buf + len;
|
|
773
|
+
assert(bufEnd >= bufOff); // guard wraparound
|
|
774
|
+
let str = changetype<String>(__new(len << 1, idof<String>())); // max is one u16 char per u8 byte
|
|
775
|
+
let strOff = changetype<usize>(str);
|
|
776
|
+
while (bufOff < bufEnd) {
|
|
777
|
+
let u0 = <u32>load<u8>(bufOff); ++bufOff;
|
|
778
|
+
if (!(u0 & 128)) {
|
|
779
|
+
// @ts-ignore: cast
|
|
780
|
+
if (nullTerminated & !u0) break;
|
|
781
|
+
store<u16>(strOff, u0);
|
|
782
|
+
} else {
|
|
783
|
+
if (bufEnd == bufOff) break;
|
|
784
|
+
let u1 = <u32>load<u8>(bufOff) & 63; ++bufOff;
|
|
785
|
+
if ((u0 & 224) == 192) {
|
|
786
|
+
store<u16>(strOff, (u0 & 31) << 6 | u1);
|
|
787
|
+
} else {
|
|
788
|
+
if (bufEnd == bufOff) break;
|
|
789
|
+
let u2 = <u32>load<u8>(bufOff) & 63; ++bufOff;
|
|
790
|
+
if ((u0 & 240) == 224) {
|
|
791
|
+
u0 = (u0 & 15) << 12 | u1 << 6 | u2;
|
|
792
|
+
} else {
|
|
793
|
+
if (bufEnd == bufOff) break;
|
|
794
|
+
u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | <u32>load<u8>(bufOff) & 63;
|
|
795
|
+
++bufOff;
|
|
796
|
+
}
|
|
797
|
+
if (u0 < 0x10000) {
|
|
798
|
+
store<u16>(strOff, u0);
|
|
799
|
+
} else {
|
|
800
|
+
u0 -= 0x10000;
|
|
801
|
+
let lo = u0 >> 10 | 0xD800;
|
|
802
|
+
let hi = (u0 & 0x03FF) | 0xDC00;
|
|
803
|
+
store<u32>(strOff, lo | (hi << 16));
|
|
804
|
+
strOff += 2;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
strOff += 2;
|
|
809
|
+
}
|
|
810
|
+
return changetype<String>(__renew(changetype<usize>(str), strOff - changetype<usize>(str)));
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
export namespace UTF16 {
|
|
815
|
+
|
|
816
|
+
export function byteLength(str: string): i32 {
|
|
817
|
+
return changetype<OBJECT>(changetype<usize>(str) - TOTAL_OVERHEAD).rtSize;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
export function encode(str: string): ArrayBuffer {
|
|
821
|
+
let buf = changetype<ArrayBuffer>(__new(<usize>byteLength(str), idof<ArrayBuffer>()));
|
|
822
|
+
encodeUnsafe(changetype<usize>(str), str.length, changetype<usize>(buf));
|
|
823
|
+
return buf;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// @ts-ignore: decorator
|
|
827
|
+
@unsafe
|
|
828
|
+
export function encodeUnsafe(str: usize, len: i32, buf: usize): usize {
|
|
829
|
+
let size = <usize>len << 1;
|
|
830
|
+
memory.copy(buf, changetype<usize>(str), size);
|
|
831
|
+
return size;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
export function decode(buf: ArrayBuffer): String {
|
|
835
|
+
return decodeUnsafe(changetype<usize>(buf), buf.byteLength);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// @ts-ignore: decorator
|
|
839
|
+
@unsafe
|
|
840
|
+
export function decodeUnsafe(buf: usize, len: usize): String {
|
|
841
|
+
let str = changetype<String>(__new(len &= ~1, idof<String>()));
|
|
842
|
+
memory.copy(changetype<usize>(str), buf, len);
|
|
843
|
+
return str;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
export class TemplateStringsArray extends Array<string> {
|
|
849
|
+
readonly raw: string[];
|
|
850
|
+
}
|