goscript 0.0.38 → 0.0.39
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/compiler/expr-call.go +12 -0
- package/compiler/lit.go +17 -6
- package/dist/gs/builtin/builtin.d.ts +45 -0
- package/dist/gs/builtin/builtin.js +197 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.d.ts +56 -0
- package/dist/gs/bytes/buffer.gs.js +611 -0
- package/dist/gs/bytes/buffer.gs.js.map +1 -0
- package/dist/gs/bytes/bytes.gs.d.ts +78 -0
- package/dist/gs/bytes/bytes.gs.js +1011 -0
- package/dist/gs/bytes/bytes.gs.js.map +1 -0
- package/dist/gs/bytes/index.d.ts +4 -0
- package/dist/gs/bytes/index.js +5 -0
- package/dist/gs/bytes/index.js.map +1 -0
- package/dist/gs/bytes/iter.gs.d.ts +9 -0
- package/dist/gs/bytes/iter.gs.js +143 -0
- package/dist/gs/bytes/iter.gs.js.map +1 -0
- package/dist/gs/bytes/reader.gs.d.ts +34 -0
- package/dist/gs/bytes/reader.gs.js +198 -0
- package/dist/gs/bytes/reader.gs.js.map +1 -0
- package/dist/gs/internal/bytealg/index.d.ts +14 -2
- package/dist/gs/internal/bytealg/index.js +114 -8
- package/dist/gs/internal/bytealg/index.js.map +1 -1
- package/dist/gs/reflect/deepequal.d.ts +2 -1
- package/dist/gs/reflect/deepequal.js +5 -53
- package/dist/gs/reflect/deepequal.js.map +1 -1
- package/dist/gs/reflect/map.d.ts +14 -8
- package/dist/gs/reflect/map.js +15 -11
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +17 -9
- package/dist/gs/reflect/type.js +1 -1
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/value.js +2 -1
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +18 -12
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/unicode/utf8/utf8.d.ts +1 -1
- package/dist/gs/unicode/utf8/utf8.js +4 -2
- package/dist/gs/unicode/utf8/utf8.js.map +1 -1
- package/gs/builtin/builtin.ts +219 -0
- package/gs/bytes/buffer.gs.ts +614 -0
- package/gs/bytes/bytes.gs.ts +1180 -0
- package/gs/bytes/godoc.txt +69 -0
- package/gs/bytes/index.ts +69 -0
- package/gs/bytes/iter.gs.ts +149 -0
- package/gs/bytes/reader.gs.ts +230 -0
- package/gs/internal/bytealg/index.ts +125 -10
- package/gs/reflect/deepequal.test.ts +41 -0
- package/gs/reflect/deepequal.ts +19 -4
- package/gs/reflect/map.test.ts +30 -0
- package/gs/reflect/map.ts +22 -18
- package/gs/reflect/type.ts +19 -15
- package/gs/reflect/value.ts +8 -2
- package/gs/reflect/visiblefields.ts +17 -13
- package/gs/unicode/utf8/utf8.ts +8 -5
- package/package.json +1 -1
- package/dist/gs/internal/testlog/index.d.ts +0 -1
- package/dist/gs/internal/testlog/index.js +0 -5
- package/dist/gs/internal/testlog/index.js.map +0 -1
- package/dist/gs/maps/iter.gs.d.ts +0 -7
- package/dist/gs/maps/iter.gs.js +0 -65
- package/dist/gs/maps/iter.gs.js.map +0 -1
- package/dist/gs/maps/maps.gs.d.ts +0 -7
- package/dist/gs/maps/maps.gs.js +0 -79
- package/dist/gs/maps/maps.gs.js.map +0 -1
- package/dist/gs/reflect/abi.d.ts +0 -59
- package/dist/gs/reflect/abi.gs.d.ts +0 -59
- package/dist/gs/reflect/abi.gs.js +0 -79
- package/dist/gs/reflect/abi.gs.js.map +0 -1
- package/dist/gs/reflect/abi.js +0 -79
- package/dist/gs/reflect/abi.js.map +0 -1
- package/dist/gs/reflect/badlinkname.d.ts +0 -52
- package/dist/gs/reflect/badlinkname.gs.d.ts +0 -52
- package/dist/gs/reflect/badlinkname.gs.js +0 -72
- package/dist/gs/reflect/badlinkname.gs.js.map +0 -1
- package/dist/gs/reflect/badlinkname.js +0 -72
- package/dist/gs/reflect/badlinkname.js.map +0 -1
- package/dist/gs/reflect/deepequal.gs.d.ts +0 -25
- package/dist/gs/reflect/deepequal.gs.js +0 -308
- package/dist/gs/reflect/deepequal.gs.js.map +0 -1
- package/dist/gs/reflect/float32reg_generic.gs.d.ts +0 -2
- package/dist/gs/reflect/float32reg_generic.gs.js +0 -10
- package/dist/gs/reflect/float32reg_generic.gs.js.map +0 -1
- package/dist/gs/reflect/index.gs.d.ts +0 -1
- package/dist/gs/reflect/index.gs.js +0 -3
- package/dist/gs/reflect/index.gs.js.map +0 -1
- package/dist/gs/reflect/iter.gs.d.ts +0 -3
- package/dist/gs/reflect/iter.gs.js +0 -24
- package/dist/gs/reflect/iter.gs.js.map +0 -1
- package/dist/gs/reflect/makefunc.gs.d.ts +0 -34
- package/dist/gs/reflect/makefunc.gs.js +0 -288
- package/dist/gs/reflect/makefunc.gs.js.map +0 -1
- package/dist/gs/reflect/map_swiss.gs.d.ts +0 -14
- package/dist/gs/reflect/map_swiss.gs.js +0 -70
- package/dist/gs/reflect/map_swiss.gs.js.map +0 -1
- package/dist/gs/reflect/reflect.gs.d.ts +0 -132
- package/dist/gs/reflect/reflect.gs.js +0 -437
- package/dist/gs/reflect/reflect.gs.js.map +0 -1
- package/dist/gs/reflect/swapper.gs.d.ts +0 -1
- package/dist/gs/reflect/swapper.gs.js +0 -32
- package/dist/gs/reflect/swapper.gs.js.map +0 -1
- package/dist/gs/reflect/type.gs.d.ts +0 -4
- package/dist/gs/reflect/type.gs.js +0 -21
- package/dist/gs/reflect/type.gs.js.map +0 -1
- package/dist/gs/reflect/value.gs.d.ts +0 -4
- package/dist/gs/reflect/value.gs.js +0 -12
- package/dist/gs/reflect/value.gs.js.map +0 -1
- package/dist/gs/reflect/visiblefields.gs.d.ts +0 -3
- package/dist/gs/reflect/visiblefields.gs.js +0 -123
- package/dist/gs/reflect/visiblefields.gs.js.map +0 -1
- package/dist/gs/stringslite/index.d.ts +0 -1
- package/dist/gs/stringslite/index.js +0 -2
- package/dist/gs/stringslite/index.js.map +0 -1
- package/dist/gs/stringslite/strings.d.ts +0 -11
- package/dist/gs/stringslite/strings.js +0 -67
- package/dist/gs/stringslite/strings.js.map +0 -1
|
@@ -0,0 +1,1011 @@
|
|
|
1
|
+
import * as $ from "@goscript/builtin/builtin.js";
|
|
2
|
+
import * as unicode from "@goscript/unicode/index.js";
|
|
3
|
+
import * as utf8 from "@goscript/unicode/utf8/index.js";
|
|
4
|
+
// Equal reports whether a and b
|
|
5
|
+
// are the same length and contain the same bytes.
|
|
6
|
+
// A nil argument is equivalent to an empty slice.
|
|
7
|
+
export function Equal(a, b) {
|
|
8
|
+
return $.bytesEqual(a, b);
|
|
9
|
+
}
|
|
10
|
+
// Compare returns an integer comparing two byte slices lexicographically.
|
|
11
|
+
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
|
|
12
|
+
// A nil argument is equivalent to an empty slice.
|
|
13
|
+
export function Compare(a, b) {
|
|
14
|
+
return $.bytesCompare(a, b);
|
|
15
|
+
}
|
|
16
|
+
// explode splits s into a slice of UTF-8 sequences, one per Unicode code point (still slices of bytes),
|
|
17
|
+
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
|
|
18
|
+
export function explode(s, n) {
|
|
19
|
+
if (n === 0) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
if (s === null || $.len(s) === 0) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const result = [];
|
|
26
|
+
let i = 0;
|
|
27
|
+
while (i < $.len(s) && (n < 0 || result.length < n)) {
|
|
28
|
+
const [, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
29
|
+
if (size <= 0) {
|
|
30
|
+
// Invalid UTF-8, take single byte
|
|
31
|
+
result.push($.goSlice(s, i, i + 1));
|
|
32
|
+
i++;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
result.push($.goSlice(s, i, i + size));
|
|
36
|
+
i += size;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// If we have remaining bytes and haven't reached n limit, add the rest
|
|
40
|
+
if (i < $.len(s) && (n < 0 || result.length < n)) {
|
|
41
|
+
result.push($.goSlice(s, i, undefined));
|
|
42
|
+
}
|
|
43
|
+
return $.arrayToSlice(result);
|
|
44
|
+
}
|
|
45
|
+
// Count counts the number of non-overlapping instances of sep in s.
|
|
46
|
+
// If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded code points in s.
|
|
47
|
+
export function Count(s, sep) {
|
|
48
|
+
// Special case for empty separator
|
|
49
|
+
if (sep === null || $.len(sep) === 0) {
|
|
50
|
+
if (s === null)
|
|
51
|
+
return 1;
|
|
52
|
+
// For now, use simple byte count + 1 (TODO: proper UTF-8 rune counting)
|
|
53
|
+
return $.len(s) + 1;
|
|
54
|
+
}
|
|
55
|
+
// Single byte separator - optimized path
|
|
56
|
+
if ($.len(sep) === 1) {
|
|
57
|
+
return $.bytesCount(s, sep);
|
|
58
|
+
}
|
|
59
|
+
return $.bytesCount(s, sep);
|
|
60
|
+
}
|
|
61
|
+
// Contains reports whether subslice is within b.
|
|
62
|
+
export function Contains(b, subslice) {
|
|
63
|
+
return Index(b, subslice) !== -1;
|
|
64
|
+
}
|
|
65
|
+
// ContainsAny reports whether any of the UTF-8-encoded code points in chars are within b.
|
|
66
|
+
export function ContainsAny(b, chars) {
|
|
67
|
+
return IndexAny(b, chars) >= 0;
|
|
68
|
+
}
|
|
69
|
+
// ContainsRune reports whether the rune is contained in the UTF-8-encoded byte slice b.
|
|
70
|
+
export function ContainsRune(b, r) {
|
|
71
|
+
return IndexRune(b, r) >= 0;
|
|
72
|
+
}
|
|
73
|
+
// ContainsFunc reports whether any of the UTF-8-encoded code points r within b satisfy f(r).
|
|
74
|
+
export function ContainsFunc(b, f) {
|
|
75
|
+
return IndexFunc(b, f) >= 0;
|
|
76
|
+
}
|
|
77
|
+
// IndexByte returns the index of the first instance of c in b, or -1 if c is not present in b.
|
|
78
|
+
export function IndexByte(b, c) {
|
|
79
|
+
return $.bytesIndexByte(b, c);
|
|
80
|
+
}
|
|
81
|
+
export function indexBytePortable(s, c) {
|
|
82
|
+
if (s === null)
|
|
83
|
+
return -1;
|
|
84
|
+
const arr = $.bytesToArray(s);
|
|
85
|
+
return arr.indexOf(c);
|
|
86
|
+
}
|
|
87
|
+
// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
|
|
88
|
+
export function LastIndex(s, sep) {
|
|
89
|
+
if (sep === null || $.len(sep) === 0) {
|
|
90
|
+
return s === null ? 0 : $.len(s);
|
|
91
|
+
}
|
|
92
|
+
if ($.len(sep) === 1) {
|
|
93
|
+
return $.bytesLastIndexByte(s, sep[0]);
|
|
94
|
+
}
|
|
95
|
+
return $.bytesLastIndexOf(s, sep);
|
|
96
|
+
}
|
|
97
|
+
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
|
|
98
|
+
export function LastIndexByte(s, c) {
|
|
99
|
+
return $.bytesLastIndexByte(s, c);
|
|
100
|
+
}
|
|
101
|
+
// IndexRune interprets s as a sequence of UTF-8-encoded code points.
|
|
102
|
+
// It returns the byte index of the first occurrence in s of the given rune.
|
|
103
|
+
// It returns -1 if rune is not present in s.
|
|
104
|
+
// If r is [utf8.RuneError], it returns the first instance of any
|
|
105
|
+
// invalid UTF-8 byte sequence.
|
|
106
|
+
export function IndexRune(s, r) {
|
|
107
|
+
if (s === null) {
|
|
108
|
+
return -1;
|
|
109
|
+
}
|
|
110
|
+
if (r < utf8.RuneSelf) {
|
|
111
|
+
// ASCII case - use IndexByte for efficiency
|
|
112
|
+
return IndexByte(s, r);
|
|
113
|
+
}
|
|
114
|
+
if (r === utf8.RuneError) {
|
|
115
|
+
// Look for invalid UTF-8 sequences
|
|
116
|
+
for (let i = 0; i < $.len(s);) {
|
|
117
|
+
const [r1, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
118
|
+
if (r1 === utf8.RuneError && size === 1) {
|
|
119
|
+
return i;
|
|
120
|
+
}
|
|
121
|
+
if (size <= 0) {
|
|
122
|
+
return i;
|
|
123
|
+
}
|
|
124
|
+
i += size;
|
|
125
|
+
}
|
|
126
|
+
return -1;
|
|
127
|
+
}
|
|
128
|
+
// Encode the rune to bytes and search for it
|
|
129
|
+
const runeBytes = new Uint8Array(4);
|
|
130
|
+
const n = utf8.EncodeRune(runeBytes, r);
|
|
131
|
+
const needle = $.goSlice(runeBytes, 0, n);
|
|
132
|
+
return Index(s, needle);
|
|
133
|
+
}
|
|
134
|
+
// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
|
|
135
|
+
// It returns the byte index of the first occurrence in s of any of the Unicode
|
|
136
|
+
// code points in chars. It returns -1 if chars is empty or if there is no code
|
|
137
|
+
// point in common.
|
|
138
|
+
export function IndexAny(s, chars) {
|
|
139
|
+
if (s === null || chars.length === 0) {
|
|
140
|
+
return -1;
|
|
141
|
+
}
|
|
142
|
+
// Check if all chars are ASCII for optimization
|
|
143
|
+
let allASCII = true;
|
|
144
|
+
for (let i = 0; i < chars.length; i++) {
|
|
145
|
+
if (chars.charCodeAt(i) >= utf8.RuneSelf) {
|
|
146
|
+
allASCII = false;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (allASCII) {
|
|
151
|
+
// ASCII optimization
|
|
152
|
+
for (let i = 0; i < $.len(s); i++) {
|
|
153
|
+
const b = s[i];
|
|
154
|
+
if (b < utf8.RuneSelf && chars.indexOf(String.fromCharCode(b)) >= 0) {
|
|
155
|
+
return i;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return -1;
|
|
159
|
+
}
|
|
160
|
+
// Full UTF-8 handling
|
|
161
|
+
for (let i = 0; i < $.len(s);) {
|
|
162
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
163
|
+
if (size <= 0) {
|
|
164
|
+
i++;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
// Check if this rune is in chars
|
|
168
|
+
if (containsRune(chars, r)) {
|
|
169
|
+
return i;
|
|
170
|
+
}
|
|
171
|
+
i += size;
|
|
172
|
+
}
|
|
173
|
+
return -1;
|
|
174
|
+
}
|
|
175
|
+
// LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code
|
|
176
|
+
// points. It returns the byte index of the last occurrence in s of any of
|
|
177
|
+
// the Unicode code points in chars. It returns -1 if chars is empty or if
|
|
178
|
+
// there is no code point in common.
|
|
179
|
+
export function LastIndexAny(s, chars) {
|
|
180
|
+
if (s === null || chars.length === 0) {
|
|
181
|
+
return -1;
|
|
182
|
+
}
|
|
183
|
+
// Check if all chars are ASCII for optimization
|
|
184
|
+
let allASCII = true;
|
|
185
|
+
for (let i = 0; i < chars.length; i++) {
|
|
186
|
+
if (chars.charCodeAt(i) >= utf8.RuneSelf) {
|
|
187
|
+
allASCII = false;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (allASCII) {
|
|
192
|
+
// ASCII optimization - search backwards
|
|
193
|
+
for (let i = $.len(s) - 1; i >= 0; i--) {
|
|
194
|
+
const b = s[i];
|
|
195
|
+
if (b < utf8.RuneSelf && chars.indexOf(String.fromCharCode(b)) >= 0) {
|
|
196
|
+
return i;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return -1;
|
|
200
|
+
}
|
|
201
|
+
// Full UTF-8 handling - need to scan forward to find rune boundaries
|
|
202
|
+
let lastIndex = -1;
|
|
203
|
+
for (let i = 0; i < $.len(s);) {
|
|
204
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
205
|
+
if (size <= 0) {
|
|
206
|
+
i++;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
// Check if this rune is in chars
|
|
210
|
+
if (containsRune(chars, r)) {
|
|
211
|
+
lastIndex = i;
|
|
212
|
+
}
|
|
213
|
+
i += size;
|
|
214
|
+
}
|
|
215
|
+
return lastIndex;
|
|
216
|
+
}
|
|
217
|
+
// Generic split: splits after each instance of sep,
|
|
218
|
+
// including sepSave bytes of sep in the subslices.
|
|
219
|
+
export function genSplit(s, sep, sepSave, n) {
|
|
220
|
+
if (n === 0) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
if (sep === null || $.len(sep) === 0) {
|
|
224
|
+
return explode(s, n);
|
|
225
|
+
}
|
|
226
|
+
if (n < 0) {
|
|
227
|
+
n = Count(s, sep) + 1;
|
|
228
|
+
}
|
|
229
|
+
if (n > Count(s, sep) + 1) {
|
|
230
|
+
n = Count(s, sep) + 1;
|
|
231
|
+
}
|
|
232
|
+
const result = [];
|
|
233
|
+
let start = 0;
|
|
234
|
+
for (let i = 0; i < n - 1; i++) {
|
|
235
|
+
const m = Index($.goSlice(s, start, undefined), sep);
|
|
236
|
+
if (m < 0) {
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
const end = start + m + sepSave;
|
|
240
|
+
result.push($.goSlice(s, start, end));
|
|
241
|
+
start += m + $.len(sep);
|
|
242
|
+
}
|
|
243
|
+
// Add the remaining part
|
|
244
|
+
result.push($.goSlice(s, start, undefined));
|
|
245
|
+
return $.arrayToSlice(result);
|
|
246
|
+
}
|
|
247
|
+
// SplitN slices s into subslices separated by sep and returns a slice of
|
|
248
|
+
// the subslices between those separators.
|
|
249
|
+
// If sep is empty, SplitN splits after each UTF-8 sequence.
|
|
250
|
+
// The count determines the number of subslices to return:
|
|
251
|
+
// - n > 0: at most n subslices; the last subslice will be the unsplit remainder;
|
|
252
|
+
// - n == 0: the result is nil (zero subslices);
|
|
253
|
+
// - n < 0: all subslices.
|
|
254
|
+
//
|
|
255
|
+
// To split around the first instance of a separator, see [Cut].
|
|
256
|
+
export function SplitN(s, sep, n) {
|
|
257
|
+
return genSplit(s, sep, 0, n);
|
|
258
|
+
}
|
|
259
|
+
// SplitAfterN slices s into subslices after each instance of sep and
|
|
260
|
+
// returns a slice of those subslices.
|
|
261
|
+
// If sep is empty, SplitAfterN splits after each UTF-8 sequence.
|
|
262
|
+
// The count determines the number of subslices to return:
|
|
263
|
+
// - n > 0: at most n subslices; the last subslice will be the unsplit remainder;
|
|
264
|
+
// - n == 0: the result is nil (zero subslices);
|
|
265
|
+
// - n < 0: all subslices.
|
|
266
|
+
export function SplitAfterN(s, sep, n) {
|
|
267
|
+
return genSplit(s, sep, $.len(sep), n);
|
|
268
|
+
}
|
|
269
|
+
// Split slices s into all subslices separated by sep and returns a slice of
|
|
270
|
+
// the subslices between those separators.
|
|
271
|
+
// If sep is empty, Split splits after each UTF-8 sequence.
|
|
272
|
+
// It is equivalent to SplitN with a count of -1.
|
|
273
|
+
//
|
|
274
|
+
// To split around the first instance of a separator, see [Cut].
|
|
275
|
+
export function Split(s, sep) {
|
|
276
|
+
return genSplit(s, sep, 0, -1);
|
|
277
|
+
}
|
|
278
|
+
// SplitAfter slices s into all subslices after each instance of sep and
|
|
279
|
+
// returns a slice of those subslices.
|
|
280
|
+
// If sep is empty, SplitAfter splits after each UTF-8 sequence.
|
|
281
|
+
// It is equivalent to SplitAfterN with a count of -1.
|
|
282
|
+
export function SplitAfter(s, sep) {
|
|
283
|
+
return genSplit(s, sep, $.len(sep), -1);
|
|
284
|
+
}
|
|
285
|
+
export let asciiSpace = $.arrayToSlice([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
286
|
+
// Fields interprets s as a sequence of UTF-8-encoded code points.
|
|
287
|
+
// It splits the slice s around each instance of one or more consecutive white space
|
|
288
|
+
// characters, as defined by [unicode.IsSpace], returning a slice of subslices of s or an
|
|
289
|
+
// empty slice if s contains only white space.
|
|
290
|
+
export function Fields(s) {
|
|
291
|
+
// Use FieldsFunc with unicode.IsSpace
|
|
292
|
+
return FieldsFunc(s, unicode.IsSpace);
|
|
293
|
+
}
|
|
294
|
+
// FieldsFunc interprets s as a sequence of UTF-8-encoded code points.
|
|
295
|
+
// It splits the slice s at each run of code points c satisfying f(c) and
|
|
296
|
+
// returns a slice of subslices of s. If all code points in s satisfy f(c), or
|
|
297
|
+
// len(s) == 0, an empty slice is returned.
|
|
298
|
+
//
|
|
299
|
+
// FieldsFunc makes no guarantees about the order in which it calls f(c)
|
|
300
|
+
// and assumes that f always returns the same value for a given c.
|
|
301
|
+
export function FieldsFunc(s, f) {
|
|
302
|
+
if (s === null || f === null) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
const result = [];
|
|
306
|
+
let start = -1;
|
|
307
|
+
for (let i = 0; i < $.len(s);) {
|
|
308
|
+
let size = 1;
|
|
309
|
+
let r = s[i];
|
|
310
|
+
if (r >= utf8.RuneSelf) {
|
|
311
|
+
const [rune, runeSize] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
312
|
+
r = rune;
|
|
313
|
+
size = runeSize;
|
|
314
|
+
}
|
|
315
|
+
if (f(r)) {
|
|
316
|
+
// Found separator
|
|
317
|
+
if (start >= 0) {
|
|
318
|
+
result.push($.goSlice(s, start, i));
|
|
319
|
+
start = -1;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else if (start < 0) {
|
|
323
|
+
// Start of new field
|
|
324
|
+
start = i;
|
|
325
|
+
}
|
|
326
|
+
i += size;
|
|
327
|
+
}
|
|
328
|
+
// Add final field if any
|
|
329
|
+
if (start >= 0) {
|
|
330
|
+
result.push($.goSlice(s, start, undefined));
|
|
331
|
+
}
|
|
332
|
+
return result.length === 0 ? null : $.arrayToSlice(result);
|
|
333
|
+
}
|
|
334
|
+
// Join concatenates the elements of s to create a new byte slice. The separator
|
|
335
|
+
// sep is placed between elements in the resulting slice.
|
|
336
|
+
export function Join(s, sep) {
|
|
337
|
+
if (s === null || $.len(s) === 0) {
|
|
338
|
+
return new Uint8Array(0);
|
|
339
|
+
}
|
|
340
|
+
// Just return a copy for single element
|
|
341
|
+
if ($.len(s) === 1) {
|
|
342
|
+
if (s[0] === null)
|
|
343
|
+
return new Uint8Array(0);
|
|
344
|
+
return new Uint8Array($.bytesToArray(s[0]));
|
|
345
|
+
}
|
|
346
|
+
// Calculate total length needed
|
|
347
|
+
let totalLen = 0;
|
|
348
|
+
const sepLen = sep === null ? 0 : $.len(sep);
|
|
349
|
+
for (let i = 0; i < $.len(s); i++) {
|
|
350
|
+
const elem = s[i];
|
|
351
|
+
if (elem !== null) {
|
|
352
|
+
totalLen += $.len(elem);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (sepLen > 0) {
|
|
356
|
+
totalLen += sepLen * ($.len(s) - 1);
|
|
357
|
+
}
|
|
358
|
+
// Build result
|
|
359
|
+
const result = new Uint8Array(totalLen);
|
|
360
|
+
let pos = 0;
|
|
361
|
+
for (let i = 0; i < $.len(s); i++) {
|
|
362
|
+
if (i > 0 && sepLen > 0) {
|
|
363
|
+
const sepArr = $.bytesToArray(sep);
|
|
364
|
+
for (let j = 0; j < sepArr.length; j++) {
|
|
365
|
+
result[pos++] = sepArr[j];
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const elem = s[i];
|
|
369
|
+
if (elem !== null) {
|
|
370
|
+
const elemArr = $.bytesToArray(elem);
|
|
371
|
+
for (let j = 0; j < elemArr.length; j++) {
|
|
372
|
+
result[pos++] = elemArr[j];
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return result;
|
|
377
|
+
}
|
|
378
|
+
// HasPrefix reports whether the byte slice s begins with prefix.
|
|
379
|
+
export function HasPrefix(s, prefix) {
|
|
380
|
+
if (s === null)
|
|
381
|
+
s = new Uint8Array(0);
|
|
382
|
+
if (prefix === null)
|
|
383
|
+
prefix = new Uint8Array(0);
|
|
384
|
+
if ($.len(s) < $.len(prefix))
|
|
385
|
+
return false;
|
|
386
|
+
const sArr = $.bytesToArray(s);
|
|
387
|
+
const prefixArr = $.bytesToArray(prefix);
|
|
388
|
+
for (let i = 0; i < prefixArr.length; i++) {
|
|
389
|
+
if (sArr[i] !== prefixArr[i])
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
// HasSuffix reports whether the byte slice s ends with suffix.
|
|
395
|
+
export function HasSuffix(s, suffix) {
|
|
396
|
+
if (s === null)
|
|
397
|
+
s = new Uint8Array(0);
|
|
398
|
+
if (suffix === null)
|
|
399
|
+
suffix = new Uint8Array(0);
|
|
400
|
+
if ($.len(s) < $.len(suffix))
|
|
401
|
+
return false;
|
|
402
|
+
const sArr = $.bytesToArray(s);
|
|
403
|
+
const suffixArr = $.bytesToArray(suffix);
|
|
404
|
+
const offset = sArr.length - suffixArr.length;
|
|
405
|
+
for (let i = 0; i < suffixArr.length; i++) {
|
|
406
|
+
if (sArr[offset + i] !== suffixArr[i])
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
// Map returns a copy of the byte slice s with all its characters modified
|
|
412
|
+
// according to the mapping function. If mapping returns a negative value, the character is
|
|
413
|
+
// dropped from the byte slice with no replacement. The characters in s and the
|
|
414
|
+
// output are interpreted as UTF-8-encoded code points.
|
|
415
|
+
export function Map(mapping, s) {
|
|
416
|
+
// TODO: Implement Map function with proper UTF-8 handling
|
|
417
|
+
throw new Error("Map: not implemented");
|
|
418
|
+
}
|
|
419
|
+
// Repeat returns a new byte slice consisting of count copies of b.
|
|
420
|
+
//
|
|
421
|
+
// It panics if count is negative or if the result of (len(b) * count)
|
|
422
|
+
// overflows.
|
|
423
|
+
export function Repeat(b, count) {
|
|
424
|
+
if (count === 0) {
|
|
425
|
+
return new Uint8Array(0);
|
|
426
|
+
}
|
|
427
|
+
if (count < 0) {
|
|
428
|
+
$.panic("bytes: negative Repeat count");
|
|
429
|
+
}
|
|
430
|
+
if (b === null || $.len(b) === 0) {
|
|
431
|
+
return new Uint8Array(0);
|
|
432
|
+
}
|
|
433
|
+
const bArr = $.bytesToArray(b);
|
|
434
|
+
const totalLen = bArr.length * count;
|
|
435
|
+
// Check for overflow
|
|
436
|
+
if (totalLen / count !== bArr.length) {
|
|
437
|
+
$.panic("bytes: Repeat output length overflow");
|
|
438
|
+
}
|
|
439
|
+
const result = new Uint8Array(totalLen);
|
|
440
|
+
let pos = 0;
|
|
441
|
+
for (let i = 0; i < count; i++) {
|
|
442
|
+
for (let j = 0; j < bArr.length; j++) {
|
|
443
|
+
result[pos++] = bArr[j];
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return result;
|
|
447
|
+
}
|
|
448
|
+
// ToUpper returns a copy of the byte slice s with all Unicode letters mapped to
|
|
449
|
+
// their upper case.
|
|
450
|
+
export function ToUpper(s) {
|
|
451
|
+
if (s === null || $.len(s) === 0) {
|
|
452
|
+
return new Uint8Array(0);
|
|
453
|
+
}
|
|
454
|
+
const result = [];
|
|
455
|
+
for (let i = 0; i < $.len(s);) {
|
|
456
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
457
|
+
if (size <= 0) {
|
|
458
|
+
// Invalid UTF-8, copy the byte as-is
|
|
459
|
+
result.push(s[i]);
|
|
460
|
+
i++;
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
// Convert rune to uppercase
|
|
464
|
+
const upperR = unicode.ToUpper(r);
|
|
465
|
+
// Encode the uppercase rune back to bytes
|
|
466
|
+
const runeBytes = new Uint8Array(utf8.UTFMax);
|
|
467
|
+
const n = utf8.EncodeRune(runeBytes, upperR);
|
|
468
|
+
// Add the encoded bytes to result
|
|
469
|
+
for (let j = 0; j < n; j++) {
|
|
470
|
+
result.push(runeBytes[j]);
|
|
471
|
+
}
|
|
472
|
+
i += size;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return new Uint8Array(result);
|
|
476
|
+
}
|
|
477
|
+
// ToLower returns a copy of the byte slice s with all Unicode letters mapped to
|
|
478
|
+
// their lower case.
|
|
479
|
+
export function ToLower(s) {
|
|
480
|
+
if (s === null || $.len(s) === 0) {
|
|
481
|
+
return new Uint8Array(0);
|
|
482
|
+
}
|
|
483
|
+
const result = [];
|
|
484
|
+
for (let i = 0; i < $.len(s);) {
|
|
485
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
486
|
+
if (size <= 0) {
|
|
487
|
+
// Invalid UTF-8, copy the byte as-is
|
|
488
|
+
result.push(s[i]);
|
|
489
|
+
i++;
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
// Convert rune to lowercase
|
|
493
|
+
const lowerR = unicode.ToLower(r);
|
|
494
|
+
// Encode the lowercase rune back to bytes
|
|
495
|
+
const runeBytes = new Uint8Array(utf8.UTFMax);
|
|
496
|
+
const n = utf8.EncodeRune(runeBytes, lowerR);
|
|
497
|
+
// Add the encoded bytes to result
|
|
498
|
+
for (let j = 0; j < n; j++) {
|
|
499
|
+
result.push(runeBytes[j]);
|
|
500
|
+
}
|
|
501
|
+
i += size;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return new Uint8Array(result);
|
|
505
|
+
}
|
|
506
|
+
// ToTitle treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their title case.
|
|
507
|
+
export function ToTitle(s) {
|
|
508
|
+
return Map(unicode.ToTitle, s);
|
|
509
|
+
}
|
|
510
|
+
// ToUpperSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
|
511
|
+
// upper case, giving priority to the special casing rules.
|
|
512
|
+
export function ToUpperSpecial(c, s) {
|
|
513
|
+
// TODO: Fix SpecialCase method calls
|
|
514
|
+
throw new Error("ToUpperSpecial: not implemented");
|
|
515
|
+
}
|
|
516
|
+
// ToLowerSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
|
517
|
+
// lower case, giving priority to the special casing rules.
|
|
518
|
+
export function ToLowerSpecial(c, s) {
|
|
519
|
+
// TODO: Fix SpecialCase method calls
|
|
520
|
+
throw new Error("ToLowerSpecial: not implemented");
|
|
521
|
+
}
|
|
522
|
+
// ToTitleSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
|
523
|
+
// title case, giving priority to the special casing rules.
|
|
524
|
+
export function ToTitleSpecial(c, s) {
|
|
525
|
+
// TODO: Fix SpecialCase method calls
|
|
526
|
+
throw new Error("ToTitleSpecial: not implemented");
|
|
527
|
+
}
|
|
528
|
+
// ToValidUTF8 treats s as UTF-8-encoded bytes and returns a copy with each run of bytes
|
|
529
|
+
// representing invalid UTF-8 replaced with the bytes in replacement, which may be empty.
|
|
530
|
+
export function ToValidUTF8(s, replacement) {
|
|
531
|
+
// TODO: Implement ToValidUTF8 with proper UTF-8 validation
|
|
532
|
+
throw new Error("ToValidUTF8: not implemented");
|
|
533
|
+
}
|
|
534
|
+
// isSeparator reports whether the rune could mark a word boundary.
|
|
535
|
+
// TODO: update when package unicode captures more of the properties.
|
|
536
|
+
export function isSeparator(r) {
|
|
537
|
+
// ASCII alphanumerics and underscore are not separators
|
|
538
|
+
if (r <= 0x7F) {
|
|
539
|
+
if ((48 <= r && r <= 57) || // 0-9
|
|
540
|
+
(97 <= r && r <= 122) || // a-z
|
|
541
|
+
(65 <= r && r <= 90) || // A-Z
|
|
542
|
+
r === 95) { // _
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
// Letters and digits are not separators
|
|
548
|
+
if (unicode.IsLetter(r) || unicode.IsDigit(r)) {
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
// Otherwise, all we can do for now is treat spaces as separators.
|
|
552
|
+
return unicode.IsSpace(r);
|
|
553
|
+
}
|
|
554
|
+
// Title treats s as UTF-8-encoded bytes and returns a copy with all Unicode letters that begin
|
|
555
|
+
// words mapped to their title case.
|
|
556
|
+
//
|
|
557
|
+
// Deprecated: The rule Title uses for word boundaries does not handle Unicode
|
|
558
|
+
// punctuation properly. Use golang.org/x/text/cases instead.
|
|
559
|
+
export function Title(s) {
|
|
560
|
+
// TODO: Implement Title function properly
|
|
561
|
+
throw new Error("Title: not implemented");
|
|
562
|
+
}
|
|
563
|
+
// TrimLeftFunc treats s as UTF-8-encoded bytes and returns a subslice of s by slicing off
|
|
564
|
+
// all leading UTF-8-encoded code points c that satisfy f(c).
|
|
565
|
+
export function TrimLeftFunc(s, f) {
|
|
566
|
+
const i = indexFunc(s, f, false);
|
|
567
|
+
if (i === -1) {
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
return $.goSlice(s, i, undefined);
|
|
571
|
+
}
|
|
572
|
+
// TrimRightFunc returns a subslice of s by slicing off all trailing
|
|
573
|
+
// UTF-8-encoded code points c that satisfy f(c).
|
|
574
|
+
export function TrimRightFunc(s, f) {
|
|
575
|
+
const i = lastIndexFunc(s, f, false);
|
|
576
|
+
if (i >= 0 && $.len(s) > i) {
|
|
577
|
+
const [, wid] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
578
|
+
return $.goSlice(s, undefined, i + wid);
|
|
579
|
+
}
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
// TrimFunc returns a subslice of s by slicing off all leading and trailing
|
|
583
|
+
// UTF-8-encoded code points c that satisfy f(c).
|
|
584
|
+
export function TrimFunc(s, f) {
|
|
585
|
+
return TrimRightFunc(TrimLeftFunc(s, f), f);
|
|
586
|
+
}
|
|
587
|
+
// TrimPrefix returns s without the provided leading prefix string.
|
|
588
|
+
// If s doesn't start with prefix, s is returned unchanged.
|
|
589
|
+
export function TrimPrefix(s, prefix) {
|
|
590
|
+
if (HasPrefix(s, prefix)) {
|
|
591
|
+
return $.goSlice(s, $.len(prefix), undefined);
|
|
592
|
+
}
|
|
593
|
+
return s;
|
|
594
|
+
}
|
|
595
|
+
// TrimSuffix returns s without the provided trailing suffix string.
|
|
596
|
+
// If s doesn't end with suffix, s is returned unchanged.
|
|
597
|
+
export function TrimSuffix(s, suffix) {
|
|
598
|
+
if (HasSuffix(s, suffix)) {
|
|
599
|
+
return $.goSlice(s, undefined, $.len(s) - $.len(suffix));
|
|
600
|
+
}
|
|
601
|
+
return s;
|
|
602
|
+
}
|
|
603
|
+
// IndexFunc interprets s as a sequence of UTF-8-encoded code points.
|
|
604
|
+
// It returns the byte index in s of the first Unicode
|
|
605
|
+
// code point satisfying f(c), or -1 if none do.
|
|
606
|
+
export function IndexFunc(s, f) {
|
|
607
|
+
return indexFunc(s, f, true);
|
|
608
|
+
}
|
|
609
|
+
// LastIndexFunc interprets s as a sequence of UTF-8-encoded code points.
|
|
610
|
+
// It returns the byte index in s of the last Unicode
|
|
611
|
+
// code point satisfying f(c), or -1 if none do.
|
|
612
|
+
export function LastIndexFunc(s, f) {
|
|
613
|
+
return lastIndexFunc(s, f, true);
|
|
614
|
+
}
|
|
615
|
+
// indexFunc is the same as IndexFunc except that if
|
|
616
|
+
// truth==false, the sense of the predicate function is
|
|
617
|
+
// inverted.
|
|
618
|
+
export function indexFunc(s, f, truth) {
|
|
619
|
+
if (s === null || f === null) {
|
|
620
|
+
return -1;
|
|
621
|
+
}
|
|
622
|
+
for (let i = 0; i < $.len(s);) {
|
|
623
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
624
|
+
if (size <= 0) {
|
|
625
|
+
// Invalid UTF-8
|
|
626
|
+
if (f(utf8.RuneError) === truth) {
|
|
627
|
+
return i;
|
|
628
|
+
}
|
|
629
|
+
i++;
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
if (f(r) === truth) {
|
|
633
|
+
return i;
|
|
634
|
+
}
|
|
635
|
+
i += size;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return -1;
|
|
639
|
+
}
|
|
640
|
+
// lastIndexFunc is the same as LastIndexFunc except that if
|
|
641
|
+
// truth==false, the sense of the predicate function is
|
|
642
|
+
// inverted.
|
|
643
|
+
export function lastIndexFunc(s, f, truth) {
|
|
644
|
+
if (s === null || f === null) {
|
|
645
|
+
return -1;
|
|
646
|
+
}
|
|
647
|
+
let lastIndex = -1;
|
|
648
|
+
for (let i = 0; i < $.len(s);) {
|
|
649
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
650
|
+
if (size <= 0) {
|
|
651
|
+
// Invalid UTF-8
|
|
652
|
+
if (f(utf8.RuneError) === truth) {
|
|
653
|
+
lastIndex = i;
|
|
654
|
+
}
|
|
655
|
+
i++;
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
if (f(r) === truth) {
|
|
659
|
+
lastIndex = i;
|
|
660
|
+
}
|
|
661
|
+
i += size;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return lastIndex;
|
|
665
|
+
}
|
|
666
|
+
class asciiSet {
|
|
667
|
+
_value;
|
|
668
|
+
constructor(_value) {
|
|
669
|
+
this._value = _value;
|
|
670
|
+
}
|
|
671
|
+
valueOf() {
|
|
672
|
+
return this._value;
|
|
673
|
+
}
|
|
674
|
+
toString() {
|
|
675
|
+
return String(this._value);
|
|
676
|
+
}
|
|
677
|
+
static from(value) {
|
|
678
|
+
return new asciiSet(value);
|
|
679
|
+
}
|
|
680
|
+
// contains reports whether c is inside the set.
|
|
681
|
+
contains(c) {
|
|
682
|
+
const _as = this._value;
|
|
683
|
+
return ((_as[c >> 5] & (1 << (c & 31)))) !== 0;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
// makeASCIISet creates a set of ASCII characters and reports whether all
|
|
687
|
+
// characters in chars are ASCII.
|
|
688
|
+
export function makeASCIISet(chars) {
|
|
689
|
+
const _as = new asciiSet([0, 0, 0, 0, 0, 0, 0, 0]);
|
|
690
|
+
for (let i = 0; i < chars.length; i++) {
|
|
691
|
+
const c = chars.charCodeAt(i);
|
|
692
|
+
if (c >= utf8.RuneSelf) {
|
|
693
|
+
return [_as, false];
|
|
694
|
+
}
|
|
695
|
+
_as._value[c >> 5] |= (1 << (c & 31));
|
|
696
|
+
}
|
|
697
|
+
return [_as, true];
|
|
698
|
+
}
|
|
699
|
+
// containsRune is a simplified version of strings.ContainsRune
|
|
700
|
+
// to avoid importing the strings package.
|
|
701
|
+
// We avoid bytes.ContainsRune to avoid allocating a temporary copy of s.
|
|
702
|
+
export function containsRune(s, r) {
|
|
703
|
+
for (let i = 0; i < s.length;) {
|
|
704
|
+
const c = s.codePointAt(i);
|
|
705
|
+
if (c === r)
|
|
706
|
+
return true;
|
|
707
|
+
i += c > 0xFFFF ? 2 : 1;
|
|
708
|
+
}
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
// Trim returns a subslice of s by slicing off all leading and
|
|
712
|
+
// trailing UTF-8-encoded code points contained in cutset.
|
|
713
|
+
export function Trim(s, cutset) {
|
|
714
|
+
if (s === null || cutset.length === 0) {
|
|
715
|
+
return s;
|
|
716
|
+
}
|
|
717
|
+
if (cutset.length === 1 && cutset.charCodeAt(0) < utf8.RuneSelf) {
|
|
718
|
+
// Single ASCII character optimization
|
|
719
|
+
return trimRightByte(trimLeftByte(s, cutset.charCodeAt(0)), cutset.charCodeAt(0));
|
|
720
|
+
}
|
|
721
|
+
const [as, allASCII] = makeASCIISet(cutset);
|
|
722
|
+
if (allASCII) {
|
|
723
|
+
return trimRightASCII(trimLeftASCII(s, as), as);
|
|
724
|
+
}
|
|
725
|
+
return trimRightUnicode(trimLeftUnicode(s, cutset), cutset);
|
|
726
|
+
}
|
|
727
|
+
// TrimLeft returns a subslice of s by slicing off all leading
|
|
728
|
+
// UTF-8-encoded code points contained in cutset.
|
|
729
|
+
export function TrimLeft(s, cutset) {
|
|
730
|
+
if (s === null || cutset.length === 0) {
|
|
731
|
+
return s;
|
|
732
|
+
}
|
|
733
|
+
if (cutset.length === 1 && cutset.charCodeAt(0) < utf8.RuneSelf) {
|
|
734
|
+
// Single ASCII character optimization
|
|
735
|
+
return trimLeftByte(s, cutset.charCodeAt(0));
|
|
736
|
+
}
|
|
737
|
+
const [as, allASCII] = makeASCIISet(cutset);
|
|
738
|
+
if (allASCII) {
|
|
739
|
+
return trimLeftASCII(s, as);
|
|
740
|
+
}
|
|
741
|
+
return trimLeftUnicode(s, cutset);
|
|
742
|
+
}
|
|
743
|
+
export function trimLeftByte(s, c) {
|
|
744
|
+
if (s === null)
|
|
745
|
+
return null;
|
|
746
|
+
for (let i = 0; i < $.len(s); i++) {
|
|
747
|
+
if (s[i] !== c) {
|
|
748
|
+
return $.goSlice(s, i, undefined);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return null;
|
|
752
|
+
}
|
|
753
|
+
export function trimLeftASCII(s, _as) {
|
|
754
|
+
if (s === null)
|
|
755
|
+
return null;
|
|
756
|
+
for (let i = 0; i < $.len(s); i++) {
|
|
757
|
+
const b = s[i];
|
|
758
|
+
if (b >= utf8.RuneSelf || !_as.contains(b)) {
|
|
759
|
+
return $.goSlice(s, i, undefined);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
764
|
+
export function trimLeftUnicode(s, cutset) {
|
|
765
|
+
if (s === null)
|
|
766
|
+
return null;
|
|
767
|
+
for (let i = 0; i < $.len(s);) {
|
|
768
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
769
|
+
if (size <= 0) {
|
|
770
|
+
// Invalid UTF-8, keep it
|
|
771
|
+
return $.goSlice(s, i, undefined);
|
|
772
|
+
}
|
|
773
|
+
if (!containsRune(cutset, r)) {
|
|
774
|
+
return $.goSlice(s, i, undefined);
|
|
775
|
+
}
|
|
776
|
+
i += size;
|
|
777
|
+
}
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
// TrimRight returns a subslice of s by slicing off all trailing
|
|
781
|
+
// UTF-8-encoded code points that are contained in cutset.
|
|
782
|
+
export function TrimRight(s, cutset) {
|
|
783
|
+
if (s === null || cutset.length === 0) {
|
|
784
|
+
return s;
|
|
785
|
+
}
|
|
786
|
+
if (cutset.length === 1 && cutset.charCodeAt(0) < utf8.RuneSelf) {
|
|
787
|
+
// Single ASCII character optimization
|
|
788
|
+
return trimRightByte(s, cutset.charCodeAt(0));
|
|
789
|
+
}
|
|
790
|
+
const [as, allASCII] = makeASCIISet(cutset);
|
|
791
|
+
if (allASCII) {
|
|
792
|
+
return trimRightASCII(s, as);
|
|
793
|
+
}
|
|
794
|
+
return trimRightUnicode(s, cutset);
|
|
795
|
+
}
|
|
796
|
+
export function trimRightByte(s, c) {
|
|
797
|
+
if (s === null)
|
|
798
|
+
return null;
|
|
799
|
+
for (let i = $.len(s) - 1; i >= 0; i--) {
|
|
800
|
+
if (s[i] !== c) {
|
|
801
|
+
return $.goSlice(s, undefined, i + 1);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
export function trimRightASCII(s, _as) {
|
|
807
|
+
if (s === null)
|
|
808
|
+
return null;
|
|
809
|
+
for (let i = $.len(s) - 1; i >= 0; i--) {
|
|
810
|
+
const b = s[i];
|
|
811
|
+
if (b >= utf8.RuneSelf || !_as.contains(b)) {
|
|
812
|
+
return $.goSlice(s, undefined, i + 1);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
return null;
|
|
816
|
+
}
|
|
817
|
+
export function trimRightUnicode(s, cutset) {
|
|
818
|
+
if (s === null)
|
|
819
|
+
return null;
|
|
820
|
+
// Need to scan from left to find rune boundaries, but track the last non-cutset position
|
|
821
|
+
let lastKeep = -1;
|
|
822
|
+
for (let i = 0; i < $.len(s);) {
|
|
823
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
824
|
+
if (size <= 0) {
|
|
825
|
+
// Invalid UTF-8, keep everything up to here
|
|
826
|
+
return $.goSlice(s, undefined, i + 1);
|
|
827
|
+
}
|
|
828
|
+
if (!containsRune(cutset, r)) {
|
|
829
|
+
lastKeep = i + size;
|
|
830
|
+
}
|
|
831
|
+
i += size;
|
|
832
|
+
}
|
|
833
|
+
if (lastKeep < 0) {
|
|
834
|
+
return null;
|
|
835
|
+
}
|
|
836
|
+
return $.goSlice(s, undefined, lastKeep);
|
|
837
|
+
}
|
|
838
|
+
// TrimSpace returns a subslice of s by slicing off all leading and
|
|
839
|
+
// trailing white space, as defined by Unicode.
|
|
840
|
+
export function TrimSpace(s) {
|
|
841
|
+
return TrimFunc(s, unicode.IsSpace);
|
|
842
|
+
}
|
|
843
|
+
// Runes interprets s as a sequence of UTF-8-encoded code points.
|
|
844
|
+
// It returns a slice of runes (Unicode code points) equivalent to s.
|
|
845
|
+
export function Runes(s) {
|
|
846
|
+
if (s === null || $.len(s) === 0) {
|
|
847
|
+
return null;
|
|
848
|
+
}
|
|
849
|
+
const result = [];
|
|
850
|
+
for (let i = 0; i < $.len(s);) {
|
|
851
|
+
const [r, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
852
|
+
if (size <= 0) {
|
|
853
|
+
// Invalid UTF-8, add replacement character
|
|
854
|
+
result.push(utf8.RuneError);
|
|
855
|
+
i++;
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
result.push(r);
|
|
859
|
+
i += size;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return $.arrayToSlice(result);
|
|
863
|
+
}
|
|
864
|
+
// Replace returns a copy of the slice s with the first n
|
|
865
|
+
// non-overlapping instances of old replaced by new.
|
|
866
|
+
// If old is empty, it matches at the beginning of the slice
|
|
867
|
+
// and after each UTF-8 sequence, yielding up to k+1 replacements
|
|
868
|
+
// for a k-rune slice.
|
|
869
|
+
// If n < 0, there is no limit on the number of replacements.
|
|
870
|
+
export function Replace(s, old, _new, n) {
|
|
871
|
+
if (s === null) {
|
|
872
|
+
return new Uint8Array(0);
|
|
873
|
+
}
|
|
874
|
+
if (n === 0) {
|
|
875
|
+
// Make a copy without any replacements
|
|
876
|
+
return new Uint8Array($.bytesToArray(s));
|
|
877
|
+
}
|
|
878
|
+
// Handle empty old pattern - replace at beginning and after each UTF-8 sequence
|
|
879
|
+
if (old === null || $.len(old) === 0) {
|
|
880
|
+
const result = [];
|
|
881
|
+
const newBytes = _new === null ? [] : $.bytesToArray(_new);
|
|
882
|
+
// Add replacement at beginning
|
|
883
|
+
if (n !== 0) {
|
|
884
|
+
result.push(...newBytes);
|
|
885
|
+
if (n > 0)
|
|
886
|
+
n--;
|
|
887
|
+
}
|
|
888
|
+
// Add replacement after each UTF-8 sequence
|
|
889
|
+
for (let i = 0; i < $.len(s) && n !== 0;) {
|
|
890
|
+
const [, size] = utf8.DecodeRune($.goSlice(s, i, undefined));
|
|
891
|
+
if (size <= 0) {
|
|
892
|
+
result.push(s[i]);
|
|
893
|
+
i++;
|
|
894
|
+
}
|
|
895
|
+
else {
|
|
896
|
+
// Add the rune bytes
|
|
897
|
+
for (let j = 0; j < size; j++) {
|
|
898
|
+
result.push(s[i + j]);
|
|
899
|
+
}
|
|
900
|
+
i += size;
|
|
901
|
+
}
|
|
902
|
+
// Add replacement after this rune
|
|
903
|
+
if (n !== 0) {
|
|
904
|
+
result.push(...newBytes);
|
|
905
|
+
if (n > 0)
|
|
906
|
+
n--;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
return new Uint8Array(result);
|
|
910
|
+
}
|
|
911
|
+
// Normal case - replace occurrences of old with new
|
|
912
|
+
const result = [];
|
|
913
|
+
const sBytes = $.bytesToArray(s);
|
|
914
|
+
const oldBytes = $.bytesToArray(old);
|
|
915
|
+
const newBytes = _new === null ? [] : $.bytesToArray(_new);
|
|
916
|
+
let i = 0;
|
|
917
|
+
let replacements = 0;
|
|
918
|
+
while (i <= sBytes.length - oldBytes.length && (n < 0 || replacements < n)) {
|
|
919
|
+
// Check if old pattern matches at current position
|
|
920
|
+
let matches = true;
|
|
921
|
+
for (let j = 0; j < oldBytes.length; j++) {
|
|
922
|
+
if (sBytes[i + j] !== oldBytes[j]) {
|
|
923
|
+
matches = false;
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
if (matches) {
|
|
928
|
+
// Replace with new bytes
|
|
929
|
+
result.push(...newBytes);
|
|
930
|
+
i += oldBytes.length;
|
|
931
|
+
replacements++;
|
|
932
|
+
}
|
|
933
|
+
else {
|
|
934
|
+
// Copy one byte and advance
|
|
935
|
+
result.push(sBytes[i]);
|
|
936
|
+
i++;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
// Copy remaining bytes
|
|
940
|
+
while (i < sBytes.length) {
|
|
941
|
+
result.push(sBytes[i]);
|
|
942
|
+
i++;
|
|
943
|
+
}
|
|
944
|
+
return new Uint8Array(result);
|
|
945
|
+
}
|
|
946
|
+
// ReplaceAll returns a copy of the slice s with all
|
|
947
|
+
// non-overlapping instances of old replaced by new.
|
|
948
|
+
// If old is empty, it matches at the beginning of the slice
|
|
949
|
+
// and after each UTF-8 sequence, yielding up to k+1 replacements
|
|
950
|
+
// for a k-rune slice.
|
|
951
|
+
export function ReplaceAll(s, old, _new) {
|
|
952
|
+
return Replace(s, old, _new, -1);
|
|
953
|
+
}
|
|
954
|
+
// EqualFold reports whether s and t, interpreted as UTF-8 strings,
|
|
955
|
+
// are equal under simple Unicode case-folding, which is a more general
|
|
956
|
+
// form of case-insensitivity.
|
|
957
|
+
export function EqualFold(s, t) {
|
|
958
|
+
// TODO: Implement EqualFold function properly (complex Unicode folding logic)
|
|
959
|
+
throw new Error("EqualFold: not implemented");
|
|
960
|
+
}
|
|
961
|
+
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
|
962
|
+
export function Index(s, sep) {
|
|
963
|
+
return $.bytesIndexOf(s, sep);
|
|
964
|
+
}
|
|
965
|
+
// Cut slices s around the first instance of sep,
|
|
966
|
+
// returning the text before and after sep.
|
|
967
|
+
// The found result reports whether sep appears in s.
|
|
968
|
+
// If sep does not appear in s, cut returns s, nil, false.
|
|
969
|
+
//
|
|
970
|
+
// Cut returns slices of the original slice s, not copies.
|
|
971
|
+
export function Cut(s, sep) {
|
|
972
|
+
const i = Index(s, sep);
|
|
973
|
+
if (i >= 0) {
|
|
974
|
+
return [$.goSlice(s, undefined, i), $.goSlice(s, i + $.len(sep), undefined), true];
|
|
975
|
+
}
|
|
976
|
+
return [s, null, false];
|
|
977
|
+
}
|
|
978
|
+
// Clone returns a copy of b[:len(b)].
|
|
979
|
+
// The result may have additional unused capacity.
|
|
980
|
+
// Clone(nil) returns nil.
|
|
981
|
+
export function Clone(b) {
|
|
982
|
+
if (b === null) {
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
return new Uint8Array($.bytesToArray(b));
|
|
986
|
+
}
|
|
987
|
+
// CutPrefix returns s without the provided leading prefix byte slice
|
|
988
|
+
// and reports whether it found the prefix.
|
|
989
|
+
// If s doesn't start with prefix, CutPrefix returns s, false.
|
|
990
|
+
// If prefix is the empty byte slice, CutPrefix returns s, true.
|
|
991
|
+
//
|
|
992
|
+
// CutPrefix returns slices of the original slice s, not copies.
|
|
993
|
+
export function CutPrefix(s, prefix) {
|
|
994
|
+
if (!HasPrefix(s, prefix)) {
|
|
995
|
+
return [s, false];
|
|
996
|
+
}
|
|
997
|
+
return [$.goSlice(s, $.len(prefix), undefined), true];
|
|
998
|
+
}
|
|
999
|
+
// CutSuffix returns s without the provided ending suffix byte slice
|
|
1000
|
+
// and reports whether it found the suffix.
|
|
1001
|
+
// If s doesn't end with suffix, CutSuffix returns s, false.
|
|
1002
|
+
// If suffix is the empty byte slice, CutSuffix returns s, true.
|
|
1003
|
+
//
|
|
1004
|
+
// CutSuffix returns slices of the original slice s, not copies.
|
|
1005
|
+
export function CutSuffix(s, suffix) {
|
|
1006
|
+
if (!HasSuffix(s, suffix)) {
|
|
1007
|
+
return [s, false];
|
|
1008
|
+
}
|
|
1009
|
+
return [$.goSlice(s, undefined, $.len(s) - $.len(suffix)), true];
|
|
1010
|
+
}
|
|
1011
|
+
//# sourceMappingURL=bytes.gs.js.map
|