@grain/stdlib 0.5.2 → 0.5.4
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/CHANGELOG.md +59 -0
- package/array.gr +61 -1
- package/array.md +113 -0
- package/bigint.md +30 -30
- package/buffer.gr +24 -22
- package/char.gr +2 -2
- package/float32.md +3 -3
- package/float64.md +3 -3
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +360 -0
- package/immutablepriorityqueue.md +291 -0
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/list.gr +75 -2
- package/list.md +110 -0
- package/map.gr +1 -2
- package/marshal.gr +1058 -0
- package/marshal.md +76 -0
- package/number.gr +689 -23
- package/number.md +362 -27
- package/package.json +1 -1
- package/pervasives.gr +16 -5
- package/pervasives.md +28 -0
- package/priorityqueue.gr +261 -0
- package/priorityqueue.md +309 -0
- package/queue.gr +14 -1
- package/queue.md +16 -1
- package/regex.gr +90 -67
- package/runtime/bigint.gr +4 -4
- package/runtime/compare.gr +179 -0
- package/runtime/compare.md +6 -0
- package/runtime/equal.gr +3 -3
- package/runtime/exception.gr +9 -5
- package/runtime/exception.md +8 -2
- package/runtime/gc.gr +2 -1
- package/runtime/malloc.gr +1 -3
- package/runtime/numberUtils.gr +11 -11
- package/runtime/numbers.gr +423 -100
- package/runtime/numbers.md +50 -0
- package/runtime/string.gr +4 -2
- package/set.gr +26 -27
- package/stack.gr +12 -0
- package/stack.md +15 -0
- package/string.gr +409 -53
- package/string.md +164 -1
- package/sys/file.gr +4 -4
- package/sys/file.md +3 -3
- package/sys/process.gr +3 -3
- package/sys/process.md +3 -3
- package/sys/random.gr +2 -2
- package/sys/random.md +2 -2
- package/sys/time.gr +2 -2
- package/sys/time.md +2 -2
package/string.gr
CHANGED
|
@@ -11,6 +11,7 @@ import Memory from "runtime/unsafe/memory"
|
|
|
11
11
|
import Exception from "runtime/exception"
|
|
12
12
|
import Conv from "runtime/unsafe/conv"
|
|
13
13
|
import {
|
|
14
|
+
untagSimpleNumber,
|
|
14
15
|
tagSimpleNumber,
|
|
15
16
|
tagChar,
|
|
16
17
|
untagChar,
|
|
@@ -100,7 +101,7 @@ export let byteLength = (string: String) => {
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
/**
|
|
103
|
-
* Finds the position of a substring in the input string.
|
|
104
|
+
* Finds the first position of a substring in the input string.
|
|
104
105
|
*
|
|
105
106
|
* @param search: The substring to find
|
|
106
107
|
* @param string: The string to inspect
|
|
@@ -161,6 +162,65 @@ export let indexOf = (search: String, string: String) => {
|
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Finds the last position of a substring in the input string.
|
|
167
|
+
*
|
|
168
|
+
* @param search: The substring to find
|
|
169
|
+
* @param string: The string to inspect
|
|
170
|
+
* @returns `Some(position)` containing the starting position of the substring if found or `None` otherwise
|
|
171
|
+
*
|
|
172
|
+
* @example String.lastIndexOf("world", "Hello world world") == Some(12)
|
|
173
|
+
*
|
|
174
|
+
* @since v0.5.3
|
|
175
|
+
*/
|
|
176
|
+
@unsafe
|
|
177
|
+
export let lastIndexOf = (search: String, string: String) => {
|
|
178
|
+
// The last possible index in the string given the length of the search
|
|
179
|
+
let lastIndex = length(string) - length(search)
|
|
180
|
+
|
|
181
|
+
let (>) = WasmI32.gtU
|
|
182
|
+
let (>=) = WasmI32.geU
|
|
183
|
+
let (==) = WasmI32.eq
|
|
184
|
+
let (!=) = WasmI32.ne
|
|
185
|
+
let (+) = WasmI32.add
|
|
186
|
+
let (-) = WasmI32.sub
|
|
187
|
+
let (&) = WasmI32.and
|
|
188
|
+
|
|
189
|
+
let search = WasmI32.fromGrain(search)
|
|
190
|
+
let string = WasmI32.fromGrain(string)
|
|
191
|
+
let searchSize = WasmI32.load(search, 4n)
|
|
192
|
+
let stringSize = WasmI32.load(string, 4n)
|
|
193
|
+
if (searchSize > stringSize) {
|
|
194
|
+
None
|
|
195
|
+
} else {
|
|
196
|
+
let mut matchIndex = -1n
|
|
197
|
+
let mut stringIndex = untagSimpleNumber(lastIndex)
|
|
198
|
+
let searchPtr = search + 8n
|
|
199
|
+
let stringStartPtr = string + 8n
|
|
200
|
+
for (
|
|
201
|
+
let mut stringPtr = stringStartPtr + stringSize - searchSize;
|
|
202
|
+
stringPtr >= stringStartPtr;
|
|
203
|
+
stringPtr -= 1n
|
|
204
|
+
) {
|
|
205
|
+
let byte = WasmI32.load8U(stringPtr, 0n)
|
|
206
|
+
if ((byte & 0xC0n) == 0x80n) {
|
|
207
|
+
// We're not at the start of a codepoint, so move on
|
|
208
|
+
continue
|
|
209
|
+
}
|
|
210
|
+
if (Memory.compare(stringPtr, searchPtr, searchSize) == 0n) {
|
|
211
|
+
matchIndex = stringIndex
|
|
212
|
+
break
|
|
213
|
+
}
|
|
214
|
+
stringIndex -= 1n
|
|
215
|
+
}
|
|
216
|
+
if (matchIndex == -1n) {
|
|
217
|
+
None
|
|
218
|
+
} else {
|
|
219
|
+
Some(tagSimpleNumber(matchIndex))
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
164
224
|
@disableGC
|
|
165
225
|
let getCodePoint = (ptr: WasmI32) => {
|
|
166
226
|
// Algorithm from https://encoding.spec.whatwg.org/#utf-8-decoder
|
|
@@ -221,19 +281,9 @@ let getCodePoint = (ptr: WasmI32) => {
|
|
|
221
281
|
}
|
|
222
282
|
result
|
|
223
283
|
}
|
|
224
|
-
|
|
225
|
-
* Get the character at the position in the input string.
|
|
226
|
-
*
|
|
227
|
-
* @param position: The position to check
|
|
228
|
-
* @param string: The string to search
|
|
229
|
-
* @returns The character at the provided position
|
|
230
|
-
*
|
|
231
|
-
* @example String.charAt(5, "Hello world") == ' '
|
|
232
|
-
*
|
|
233
|
-
* @since v0.4.0
|
|
234
|
-
*/
|
|
284
|
+
|
|
235
285
|
@unsafe
|
|
236
|
-
|
|
286
|
+
let charAtHelp = (position, string: String) => {
|
|
237
287
|
if (length(string) <= position || position < 0) {
|
|
238
288
|
fail "Invalid offset: " ++ toString(position)
|
|
239
289
|
}
|
|
@@ -249,10 +299,10 @@ export let charAt = (position, string: String) => {
|
|
|
249
299
|
let mut ptr = string + 8n
|
|
250
300
|
let end = ptr + size
|
|
251
301
|
let mut counter = 0n
|
|
252
|
-
let mut result =
|
|
302
|
+
let mut result = 0n
|
|
253
303
|
while (ptr < end) {
|
|
254
304
|
if (counter == position) {
|
|
255
|
-
result =
|
|
305
|
+
result = getCodePoint(ptr)
|
|
256
306
|
break
|
|
257
307
|
}
|
|
258
308
|
let byte = WasmI32.load8U(ptr, 0n)
|
|
@@ -274,6 +324,38 @@ export let charAt = (position, string: String) => {
|
|
|
274
324
|
result
|
|
275
325
|
}
|
|
276
326
|
|
|
327
|
+
/**
|
|
328
|
+
* Get the Unicode code point at the position in the input string.
|
|
329
|
+
*
|
|
330
|
+
* @param position: The position to check
|
|
331
|
+
* @param string: The string to search
|
|
332
|
+
* @returns The character code at the provided position
|
|
333
|
+
*
|
|
334
|
+
* @example String.charCodeAt(5, "Hello world") == 32
|
|
335
|
+
*
|
|
336
|
+
* @since v0.5.3
|
|
337
|
+
*/
|
|
338
|
+
@unsafe
|
|
339
|
+
export let charCodeAt = (position, string: String) => {
|
|
340
|
+
tagSimpleNumber(charAtHelp(position, string))
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Get the character at the position in the input string.
|
|
345
|
+
*
|
|
346
|
+
* @param position: The position to check
|
|
347
|
+
* @param string: The string to search
|
|
348
|
+
* @returns The character at the provided position
|
|
349
|
+
*
|
|
350
|
+
* @example String.charAt(5, "Hello world") == ' '
|
|
351
|
+
*
|
|
352
|
+
* @since v0.4.0
|
|
353
|
+
*/
|
|
354
|
+
@unsafe
|
|
355
|
+
export let charAt = (position, string: String) => {
|
|
356
|
+
tagChar(charAtHelp(position, string))
|
|
357
|
+
}
|
|
358
|
+
|
|
277
359
|
@unsafe
|
|
278
360
|
let explodeHelp = (s: String, chars) => {
|
|
279
361
|
let (>>>) = WasmI32.shrU
|
|
@@ -790,6 +872,239 @@ export let endsWith = (search: String, string: String) => {
|
|
|
790
872
|
}
|
|
791
873
|
}
|
|
792
874
|
|
|
875
|
+
/**
|
|
876
|
+
* Replaces the first appearance of the search pattern in the string with the replacement value.
|
|
877
|
+
*
|
|
878
|
+
* @param searchPattern: The string to replace
|
|
879
|
+
* @param replacement: The replacement
|
|
880
|
+
* @param string: The string to change
|
|
881
|
+
* @returns A new string with the first occurrence of the search pattern replaced
|
|
882
|
+
*
|
|
883
|
+
* @example String.replaceFirst("🌾", "🌎", "Hello 🌾🌾") == "Hello 🌎🌾"
|
|
884
|
+
*
|
|
885
|
+
* @since v0.5.4
|
|
886
|
+
*/
|
|
887
|
+
@unsafe
|
|
888
|
+
export let replaceFirst =
|
|
889
|
+
(
|
|
890
|
+
searchPattern: String,
|
|
891
|
+
replacement: String,
|
|
892
|
+
string: String,
|
|
893
|
+
) => {
|
|
894
|
+
let (+) = WasmI32.add
|
|
895
|
+
let (-) = WasmI32.sub
|
|
896
|
+
let (>) = WasmI32.gtU
|
|
897
|
+
let (<) = WasmI32.ltU
|
|
898
|
+
let (==) = WasmI32.eq
|
|
899
|
+
|
|
900
|
+
let mut patternPtr = WasmI32.fromGrain(searchPattern)
|
|
901
|
+
let mut stringPtr = WasmI32.fromGrain(string)
|
|
902
|
+
let mut replacementPtr = WasmI32.fromGrain(replacement)
|
|
903
|
+
|
|
904
|
+
let patternLen = WasmI32.load(patternPtr, 4n)
|
|
905
|
+
let stringLen = WasmI32.load(stringPtr, 4n)
|
|
906
|
+
let replacementLen = WasmI32.load(replacementPtr, 4n)
|
|
907
|
+
// Bail if search str is longer than the string
|
|
908
|
+
if (stringLen < patternLen) {
|
|
909
|
+
string
|
|
910
|
+
} else {
|
|
911
|
+
patternPtr += 8n
|
|
912
|
+
stringPtr += 8n
|
|
913
|
+
replacementPtr += 8n
|
|
914
|
+
|
|
915
|
+
let mut found = false
|
|
916
|
+
// Search for an instance of the string
|
|
917
|
+
let mut foundIndex = -1n
|
|
918
|
+
let stringEndPtr = stringPtr + stringLen - patternLen + 1n
|
|
919
|
+
for (let mut i = stringPtr; i < stringEndPtr; i += 1n) {
|
|
920
|
+
// check for match
|
|
921
|
+
foundIndex += 1n
|
|
922
|
+
if (Memory.compare(i, patternPtr, patternLen) == 0n) {
|
|
923
|
+
found = true
|
|
924
|
+
break
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
if (found) {
|
|
928
|
+
// Create the new string
|
|
929
|
+
let str = allocateString(stringLen - patternLen + replacementLen)
|
|
930
|
+
let strPtr = str + 8n
|
|
931
|
+
Memory.copy(strPtr, stringPtr, foundIndex)
|
|
932
|
+
Memory.copy(strPtr + foundIndex, replacementPtr, replacementLen)
|
|
933
|
+
Memory.copy(
|
|
934
|
+
strPtr + foundIndex + replacementLen,
|
|
935
|
+
stringPtr + foundIndex + patternLen,
|
|
936
|
+
stringLen - foundIndex
|
|
937
|
+
)
|
|
938
|
+
// Copy over the str
|
|
939
|
+
WasmI32.toGrain(str): String
|
|
940
|
+
} else {
|
|
941
|
+
string
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Replaces the last appearance of the search pattern in the string with the replacement value.
|
|
948
|
+
*
|
|
949
|
+
* @param searchPattern: The string to replace
|
|
950
|
+
* @param replacement: The replacement
|
|
951
|
+
* @param string: The string to change
|
|
952
|
+
* @returns A new string with the last occurrence of the search pattern replaced
|
|
953
|
+
*
|
|
954
|
+
* @example String.replaceLast("🌾", "🌎", "Hello 🌾🌾") == "Hello 🌾🌎"
|
|
955
|
+
*
|
|
956
|
+
* @since v0.5.4
|
|
957
|
+
*/
|
|
958
|
+
@unsafe
|
|
959
|
+
export let replaceLast =
|
|
960
|
+
(
|
|
961
|
+
searchPattern: String,
|
|
962
|
+
replacement: String,
|
|
963
|
+
string: String,
|
|
964
|
+
) => {
|
|
965
|
+
let (+) = WasmI32.add
|
|
966
|
+
let (-) = WasmI32.sub
|
|
967
|
+
let (>) = WasmI32.gtU
|
|
968
|
+
let (<) = WasmI32.ltU
|
|
969
|
+
let (==) = WasmI32.eq
|
|
970
|
+
|
|
971
|
+
let mut patternPtr = WasmI32.fromGrain(searchPattern)
|
|
972
|
+
let mut stringPtr = WasmI32.fromGrain(string)
|
|
973
|
+
let mut replacementPtr = WasmI32.fromGrain(replacement)
|
|
974
|
+
|
|
975
|
+
let patternLen = WasmI32.load(patternPtr, 4n)
|
|
976
|
+
let stringLen = WasmI32.load(stringPtr, 4n)
|
|
977
|
+
let replacementLen = WasmI32.load(replacementPtr, 4n)
|
|
978
|
+
|
|
979
|
+
// Bail if search str is longer than the string
|
|
980
|
+
if (stringLen < patternLen) {
|
|
981
|
+
string
|
|
982
|
+
} else {
|
|
983
|
+
patternPtr += 8n
|
|
984
|
+
stringPtr += 8n
|
|
985
|
+
replacementPtr += 8n
|
|
986
|
+
|
|
987
|
+
let mut found = false
|
|
988
|
+
// Search for an instance of the string
|
|
989
|
+
let stringEndPtr = stringPtr + stringLen - patternLen
|
|
990
|
+
let mut foundIndex = stringLen - patternLen + 1n
|
|
991
|
+
for (let mut i = stringEndPtr; i > stringPtr - 1n; i -= 1n) {
|
|
992
|
+
// check for match
|
|
993
|
+
foundIndex -= 1n
|
|
994
|
+
if (Memory.compare(i, patternPtr, patternLen) == 0n) {
|
|
995
|
+
found = true
|
|
996
|
+
break
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (found) {
|
|
1000
|
+
// Create the new string
|
|
1001
|
+
let str = allocateString(stringLen - patternLen + replacementLen)
|
|
1002
|
+
let strPtr = str + 8n
|
|
1003
|
+
Memory.copy(strPtr, stringPtr, foundIndex)
|
|
1004
|
+
Memory.copy(strPtr + foundIndex, replacementPtr, replacementLen)
|
|
1005
|
+
Memory.copy(
|
|
1006
|
+
strPtr + foundIndex + replacementLen,
|
|
1007
|
+
stringPtr + foundIndex + patternLen,
|
|
1008
|
+
stringLen - foundIndex
|
|
1009
|
+
)
|
|
1010
|
+
// Copy over the str
|
|
1011
|
+
WasmI32.toGrain(str): String
|
|
1012
|
+
} else {
|
|
1013
|
+
string
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* Replaces every appearance of the search pattern in the string with the replacement value.
|
|
1020
|
+
*
|
|
1021
|
+
* @param searchPattern: The string to replace
|
|
1022
|
+
* @param replacement: The replacement
|
|
1023
|
+
* @param string: The string to change
|
|
1024
|
+
* @returns A new string with each occurrence of the search pattern replaced
|
|
1025
|
+
*
|
|
1026
|
+
* @example String.replaceAll("🌾", "🌎", "Hello 🌾🌾") == "Hello 🌎🌎"
|
|
1027
|
+
*
|
|
1028
|
+
* @since v0.5.4
|
|
1029
|
+
*/
|
|
1030
|
+
@unsafe
|
|
1031
|
+
export let replaceAll =
|
|
1032
|
+
(
|
|
1033
|
+
searchPattern: String,
|
|
1034
|
+
replacement: String,
|
|
1035
|
+
string: String,
|
|
1036
|
+
) => {
|
|
1037
|
+
let (*) = WasmI32.mul
|
|
1038
|
+
let (+) = WasmI32.add
|
|
1039
|
+
let (-) = WasmI32.sub
|
|
1040
|
+
let (>) = WasmI32.gtU
|
|
1041
|
+
let (<) = WasmI32.ltU
|
|
1042
|
+
let (==) = WasmI32.eq
|
|
1043
|
+
let (>>) = WasmI32.shrS
|
|
1044
|
+
|
|
1045
|
+
let mut patternPtr = WasmI32.fromGrain(searchPattern)
|
|
1046
|
+
let mut stringPtr = WasmI32.fromGrain(string)
|
|
1047
|
+
let mut replacementPtr = WasmI32.fromGrain(replacement)
|
|
1048
|
+
|
|
1049
|
+
let patternLen = WasmI32.load(patternPtr, 4n)
|
|
1050
|
+
let stringLen = WasmI32.load(stringPtr, 4n)
|
|
1051
|
+
let replacementLen = WasmI32.load(replacementPtr, 4n)
|
|
1052
|
+
|
|
1053
|
+
// Bail if search str is longer than the string
|
|
1054
|
+
if (stringLen < patternLen) {
|
|
1055
|
+
string
|
|
1056
|
+
} else {
|
|
1057
|
+
patternPtr += 8n
|
|
1058
|
+
stringPtr += 8n
|
|
1059
|
+
replacementPtr += 8n
|
|
1060
|
+
|
|
1061
|
+
let mut found = false
|
|
1062
|
+
// Search for an instance of the string
|
|
1063
|
+
let stringEndPtr = stringPtr + stringLen - patternLen
|
|
1064
|
+
let mut foundIndex = stringLen - patternLen + 1n
|
|
1065
|
+
let mut foundIndexes = []
|
|
1066
|
+
let mut foundCount = 0n
|
|
1067
|
+
for (let mut i = stringEndPtr; i > stringPtr - 1n; i -= 1n) {
|
|
1068
|
+
// check for match
|
|
1069
|
+
foundIndex -= 1n
|
|
1070
|
+
if (Memory.compare(i, patternPtr, patternLen) == 0n) {
|
|
1071
|
+
found = true
|
|
1072
|
+
foundCount += 1n
|
|
1073
|
+
foundIndexes = [tagSimpleNumber(foundIndex), ...foundIndexes]
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if (found) {
|
|
1077
|
+
// Create the new string
|
|
1078
|
+
let str = allocateString(
|
|
1079
|
+
stringLen - (patternLen - replacementLen) * foundCount
|
|
1080
|
+
)
|
|
1081
|
+
let mut strPtr = str + 8n
|
|
1082
|
+
let mut lastIndex = 0n
|
|
1083
|
+
while (true) {
|
|
1084
|
+
match (foundIndexes) {
|
|
1085
|
+
[idx, ...rest] => {
|
|
1086
|
+
let index = untagSimpleNumber(idx)
|
|
1087
|
+
// Copy the part before
|
|
1088
|
+
Memory.copy(strPtr, stringPtr + lastIndex, index - lastIndex)
|
|
1089
|
+
strPtr += index - lastIndex
|
|
1090
|
+
// Copy the part after
|
|
1091
|
+
Memory.copy(strPtr, replacementPtr, replacementLen)
|
|
1092
|
+
strPtr += replacementLen
|
|
1093
|
+
lastIndex = index + patternLen
|
|
1094
|
+
foundIndexes = rest
|
|
1095
|
+
},
|
|
1096
|
+
[] => break,
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
// Copy remaining string
|
|
1100
|
+
Memory.copy(strPtr, stringPtr + lastIndex, stringLen - lastIndex)
|
|
1101
|
+
WasmI32.toGrain(str): String
|
|
1102
|
+
} else {
|
|
1103
|
+
string
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
793
1108
|
// String->Byte encoding and helper functions:
|
|
794
1109
|
|
|
795
1110
|
// these are globals to avoid memory leaks
|
|
@@ -1267,33 +1582,33 @@ let bytesHaveBom = (bytes: Bytes, encoding: Encoding, start: WasmI32) => {
|
|
|
1267
1582
|
match (encoding) {
|
|
1268
1583
|
UTF8 => {
|
|
1269
1584
|
bytesSize >= 3n &&
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1585
|
+
WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xEFn &&
|
|
1586
|
+
WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xBBn &&
|
|
1587
|
+
WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0xBFn
|
|
1273
1588
|
},
|
|
1274
1589
|
UTF16_BE => {
|
|
1275
1590
|
bytesSize >= 2n &&
|
|
1276
|
-
|
|
1277
|
-
|
|
1591
|
+
WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFEn &&
|
|
1592
|
+
WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFFn
|
|
1278
1593
|
},
|
|
1279
1594
|
UTF16_LE => {
|
|
1280
1595
|
bytesSize >= 2n &&
|
|
1281
|
-
|
|
1282
|
-
|
|
1596
|
+
WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFFn &&
|
|
1597
|
+
WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFEn
|
|
1283
1598
|
},
|
|
1284
1599
|
UTF32_BE => {
|
|
1285
1600
|
bytesSize >= 4n &&
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1601
|
+
WasmI32.load8U(ptr, _BYTES_OFFSET) == 0x00n &&
|
|
1602
|
+
WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0x00n &&
|
|
1603
|
+
WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0xFEn &&
|
|
1604
|
+
WasmI32.load8U(ptr + 3n, _BYTES_OFFSET) == 0xFFn
|
|
1290
1605
|
},
|
|
1291
1606
|
UTF32_LE => {
|
|
1292
1607
|
bytesSize >= 4n &&
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1608
|
+
WasmI32.load8U(ptr, _BYTES_OFFSET) == 0xFFn &&
|
|
1609
|
+
WasmI32.load8U(ptr + 1n, _BYTES_OFFSET) == 0xFEn &&
|
|
1610
|
+
WasmI32.load8U(ptr + 2n, _BYTES_OFFSET) == 0x00n &&
|
|
1611
|
+
WasmI32.load8U(ptr + 3n, _BYTES_OFFSET) == 0x00n
|
|
1297
1612
|
},
|
|
1298
1613
|
}
|
|
1299
1614
|
}
|
|
@@ -1530,7 +1845,7 @@ let decodeRangeHelp =
|
|
|
1530
1845
|
// high surrogate. next character is low srurrogate
|
|
1531
1846
|
let w1 = (w1 & 0x03FFn) << 10n
|
|
1532
1847
|
let w2 = (WasmI32.load8U(bytesPtr, 2n) << 8n |
|
|
1533
|
-
|
|
1848
|
+
WasmI32.load8U(bytesPtr, 3n)) &
|
|
1534
1849
|
0x03FFn
|
|
1535
1850
|
let codeWord = w1 + w2 + 0x10000n
|
|
1536
1851
|
// no problems, so go past both code words
|
|
@@ -1553,7 +1868,7 @@ let decodeRangeHelp =
|
|
|
1553
1868
|
// high surrogate. next character is low srurrogate
|
|
1554
1869
|
let w1 = (w1 & 0x03FFn) << 10n
|
|
1555
1870
|
let w2 = (WasmI32.load8U(bytesPtr, 3n) << 8n |
|
|
1556
|
-
|
|
1871
|
+
WasmI32.load8U(bytesPtr, 2n)) &
|
|
1557
1872
|
0x03FFn
|
|
1558
1873
|
//let uPrime = codePoint - 0x10000n
|
|
1559
1874
|
//let w1 = ((uPrime & 0b11111111110000000000n) >>> 10n) + 0xD800n // High surrogate
|
|
@@ -1785,30 +2100,71 @@ export let forEachCodePointi = (fn: (Number, Number) -> Void, str: String) => {
|
|
|
1785
2100
|
void
|
|
1786
2101
|
}
|
|
1787
2102
|
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
let
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
2103
|
+
@unsafe
|
|
2104
|
+
let trimString = (str: String, fromEnd: Bool) => {
|
|
2105
|
+
let (>>>) = WasmI32.shrU
|
|
2106
|
+
let (+) = WasmI32.add
|
|
2107
|
+
let (*) = WasmI32.mul
|
|
2108
|
+
let (-) = WasmI32.sub
|
|
2109
|
+
let (<) = WasmI32.ltU
|
|
2110
|
+
let (==) = WasmI32.eq
|
|
2111
|
+
let (!=) = WasmI32.ne
|
|
2112
|
+
|
|
2113
|
+
let mut stringPtr = WasmI32.fromGrain(str)
|
|
2114
|
+
let byteLength = WasmI32.load(stringPtr, 4n)
|
|
2115
|
+
stringPtr += 8n
|
|
2116
|
+
let mut i = 0n, offset = 1n
|
|
2117
|
+
if (fromEnd) {
|
|
2118
|
+
i = byteLength - 1n
|
|
2119
|
+
offset = -1n
|
|
1794
2120
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
//
|
|
2121
|
+
let mut count = 0n
|
|
2122
|
+
for (; i < byteLength; i += offset) {
|
|
2123
|
+
// Get the byte, not necessarily a full UTF-8 codepoint
|
|
2124
|
+
let byte = WasmI32.load8U(stringPtr, i)
|
|
2125
|
+
// TODO(#661): Use unicode whitespace property and unicode line terminator
|
|
2126
|
+
if (!fromEnd) {
|
|
2127
|
+
if (
|
|
2128
|
+
byte == 0xEFn && // Check for the first BOM byte
|
|
2129
|
+
// Check for the full BOM codepoint, 0xEFBBBF. Bytes are reversed because wasm is little-endian
|
|
2130
|
+
WasmI32.load(stringPtr, i - 1n) >>> 8n == 0xBFBBEFn
|
|
2131
|
+
) {
|
|
2132
|
+
i += 2n
|
|
2133
|
+
count += 3n
|
|
2134
|
+
continue
|
|
2135
|
+
}
|
|
2136
|
+
} else {
|
|
2137
|
+
if (
|
|
2138
|
+
byte == 0xBFn && // Check for the last BOM byte
|
|
2139
|
+
// Check for the full BOM codepoint, 0xEFBBBF. Bytes are reversed because wasm is little-endian
|
|
2140
|
+
WasmI32.load(stringPtr, i - 3n) >>> 8n == 0xBFBBEFn
|
|
2141
|
+
) {
|
|
2142
|
+
i -= 2n
|
|
2143
|
+
count += 3n
|
|
2144
|
+
continue
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
1798
2147
|
if (
|
|
1799
|
-
//
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
2148
|
+
byte != 0x20n && // Space
|
|
2149
|
+
byte != 0x0Dn && // LF
|
|
2150
|
+
byte != 0x0An && // CR
|
|
2151
|
+
byte != 0x09n && // Tab
|
|
2152
|
+
byte != 0x0Bn && // LINE TABULATION
|
|
2153
|
+
byte != 0x0Cn && // FORM FEED (FF)
|
|
2154
|
+
byte != 0xA0n // No Break Space
|
|
2155
|
+
) {
|
|
2156
|
+
break
|
|
2157
|
+
}
|
|
2158
|
+
count += 1n
|
|
1810
2159
|
}
|
|
1811
|
-
|
|
2160
|
+
let str = allocateString(byteLength - count)
|
|
2161
|
+
// Copy the string
|
|
2162
|
+
if (fromEnd) {
|
|
2163
|
+
Memory.copy(str + 8n, stringPtr, byteLength - count)
|
|
2164
|
+
} else {
|
|
2165
|
+
Memory.copy(str + 8n, stringPtr + count, byteLength - count)
|
|
2166
|
+
}
|
|
2167
|
+
WasmI32.toGrain(str): String
|
|
1812
2168
|
}
|
|
1813
2169
|
/**
|
|
1814
2170
|
* Trims the beginning of a string—removing any leading whitespace characters.
|