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.
Files changed (117) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +94 -0
  3. package/README.md +114 -0
  4. package/bin/asc.js +35 -0
  5. package/bin/asinit.js +468 -0
  6. package/dist/asc.d.ts +4 -0
  7. package/dist/toilscript.d.ts +4 -0
  8. package/dist/transform.cjs +1 -0
  9. package/dist/transform.d.ts +1 -0
  10. package/dist/transform.js +1 -0
  11. package/lib/binaryen.d.ts +2 -0
  12. package/lib/binaryen.js +2 -0
  13. package/package.json +114 -0
  14. package/std/README.md +6 -0
  15. package/std/assembly/array.ts +550 -0
  16. package/std/assembly/arraybuffer.ts +77 -0
  17. package/std/assembly/atomics.ts +127 -0
  18. package/std/assembly/bindings/asyncify.ts +16 -0
  19. package/std/assembly/bindings/dom.ts +291 -0
  20. package/std/assembly/bindings/node.ts +6 -0
  21. package/std/assembly/bitflags.ts +53 -0
  22. package/std/assembly/builtins.ts +2650 -0
  23. package/std/assembly/byteslice.ts +177 -0
  24. package/std/assembly/compat.ts +2 -0
  25. package/std/assembly/console.ts +42 -0
  26. package/std/assembly/crypto.ts +9 -0
  27. package/std/assembly/dataview.ts +181 -0
  28. package/std/assembly/date.ts +375 -0
  29. package/std/assembly/diagnostics.ts +11 -0
  30. package/std/assembly/encoding.ts +151 -0
  31. package/std/assembly/endian.ts +45 -0
  32. package/std/assembly/error.ts +44 -0
  33. package/std/assembly/fixedarray.ts +173 -0
  34. package/std/assembly/fixedmap.ts +326 -0
  35. package/std/assembly/fixedset.ts +275 -0
  36. package/std/assembly/function.ts +42 -0
  37. package/std/assembly/index.d.ts +2891 -0
  38. package/std/assembly/iterator.ts +35 -0
  39. package/std/assembly/map.ts +269 -0
  40. package/std/assembly/math.ts +3289 -0
  41. package/std/assembly/memory.ts +123 -0
  42. package/std/assembly/number.ts +388 -0
  43. package/std/assembly/object.ts +36 -0
  44. package/std/assembly/performance.ts +9 -0
  45. package/std/assembly/pointer.ts +80 -0
  46. package/std/assembly/polyfills.ts +27 -0
  47. package/std/assembly/process.ts +50 -0
  48. package/std/assembly/reference.ts +48 -0
  49. package/std/assembly/regexp.ts +12 -0
  50. package/std/assembly/rt/README.md +83 -0
  51. package/std/assembly/rt/common.ts +81 -0
  52. package/std/assembly/rt/index-incremental.ts +2 -0
  53. package/std/assembly/rt/index-memory.ts +1 -0
  54. package/std/assembly/rt/index-minimal.ts +2 -0
  55. package/std/assembly/rt/index-stub.ts +1 -0
  56. package/std/assembly/rt/index.d.ts +37 -0
  57. package/std/assembly/rt/itcms.ts +419 -0
  58. package/std/assembly/rt/memory-runtime.ts +94 -0
  59. package/std/assembly/rt/rtrace.ts +15 -0
  60. package/std/assembly/rt/stub.ts +133 -0
  61. package/std/assembly/rt/tcms.ts +254 -0
  62. package/std/assembly/rt/tlsf.ts +592 -0
  63. package/std/assembly/rt.ts +90 -0
  64. package/std/assembly/set.ts +225 -0
  65. package/std/assembly/shared/feature.ts +68 -0
  66. package/std/assembly/shared/runtime.ts +13 -0
  67. package/std/assembly/shared/target.ts +11 -0
  68. package/std/assembly/shared/tsconfig.json +11 -0
  69. package/std/assembly/shared/typeinfo.ts +72 -0
  70. package/std/assembly/staticarray.ts +423 -0
  71. package/std/assembly/string.ts +850 -0
  72. package/std/assembly/symbol.ts +114 -0
  73. package/std/assembly/table.ts +16 -0
  74. package/std/assembly/tsconfig.json +6 -0
  75. package/std/assembly/typedarray.ts +1954 -0
  76. package/std/assembly/uri.ts +17 -0
  77. package/std/assembly/util/bytes.ts +107 -0
  78. package/std/assembly/util/casemap.ts +497 -0
  79. package/std/assembly/util/error.ts +58 -0
  80. package/std/assembly/util/hash.ts +117 -0
  81. package/std/assembly/util/math.ts +1922 -0
  82. package/std/assembly/util/memory.ts +290 -0
  83. package/std/assembly/util/number.ts +873 -0
  84. package/std/assembly/util/sort.ts +313 -0
  85. package/std/assembly/util/string.ts +1202 -0
  86. package/std/assembly/util/uri.ts +275 -0
  87. package/std/assembly/vector.ts +4 -0
  88. package/std/assembly.json +16 -0
  89. package/std/portable/index.d.ts +461 -0
  90. package/std/portable/index.js +416 -0
  91. package/std/portable.json +11 -0
  92. package/std/types/assembly/index.d.ts +1 -0
  93. package/std/types/assembly/package.json +3 -0
  94. package/std/types/portable/index.d.ts +1 -0
  95. package/std/types/portable/package.json +3 -0
  96. package/tsconfig-base.json +13 -0
  97. package/util/README.md +23 -0
  98. package/util/browser/fs.js +1 -0
  99. package/util/browser/module.js +5 -0
  100. package/util/browser/path.js +520 -0
  101. package/util/browser/process.js +59 -0
  102. package/util/browser/url.js +23 -0
  103. package/util/cpu.d.ts +9 -0
  104. package/util/cpu.js +42 -0
  105. package/util/find.d.ts +6 -0
  106. package/util/find.js +20 -0
  107. package/util/node.d.ts +21 -0
  108. package/util/node.js +34 -0
  109. package/util/options.d.ts +70 -0
  110. package/util/options.js +262 -0
  111. package/util/terminal.d.ts +52 -0
  112. package/util/terminal.js +35 -0
  113. package/util/text.d.ts +26 -0
  114. package/util/text.js +114 -0
  115. package/util/tsconfig.json +9 -0
  116. package/util/web.d.ts +11 -0
  117. 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
+ }