mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-26 15:32:16 +00:00
Add String#lastIndexOf and improve tests (#163)
This commit is contained in:
parent
c4199673ef
commit
365884ff73
3
std/assembly/index.d.ts
vendored
3
std/assembly/index.d.ts
vendored
@ -431,7 +431,8 @@ declare class String {
|
||||
charCodeAt(index: u32): u16;
|
||||
concat(other: string): string;
|
||||
endsWith(other: string): bool;
|
||||
indexOf(other: string): u32;
|
||||
indexOf(other: string, fromIndex?: i32): u32;
|
||||
lastIndexOf(other: string, fromIndex?: i32): i32;
|
||||
includes(other: string): bool;
|
||||
startsWith(other: string): bool;
|
||||
substr(start: u32, length?: u32): string;
|
||||
|
@ -15,6 +15,11 @@ export const MAX_LENGTH = (<i32>MAX_SIZE_32 - HEADER_SIZE) >>> 1;
|
||||
/** Singleton empty String. */
|
||||
export const EMPTY = changetype<String>(""); // TODO: is this a bad idea with '===' in place?
|
||||
|
||||
@inline
|
||||
export function clamp<T>(val: T, lo: T, hi: T): T {
|
||||
return max<T>(min<T>(val, hi), lo);
|
||||
}
|
||||
|
||||
/** Allocates a raw String with uninitialized contents. */
|
||||
export function allocate(length: i32): String {
|
||||
assert(length > 0 && length <= MAX_LENGTH);
|
||||
|
@ -2,6 +2,7 @@ import {
|
||||
HEADER_SIZE,
|
||||
MAX_LENGTH,
|
||||
EMPTY,
|
||||
clamp,
|
||||
allocate,
|
||||
isWhiteSpaceOrLineTerminator,
|
||||
CharCode,
|
||||
@ -97,7 +98,7 @@ export class String {
|
||||
endsWith(searchString: String, endPosition: i32 = MAX_LENGTH): bool {
|
||||
assert(this !== null);
|
||||
if (searchString === null) return false;
|
||||
var end: isize = <isize>min(max(endPosition, 0), this.length);
|
||||
var end = clamp<isize>(endPosition, 0, this.length);
|
||||
var searchLength: isize = searchString.length;
|
||||
var start: isize = end - searchLength;
|
||||
if (start < 0) return false;
|
||||
@ -206,21 +207,44 @@ export class String {
|
||||
return this.indexOf(searchString, position) != -1;
|
||||
}
|
||||
|
||||
indexOf(searchString: String, position: i32 = 0): i32 {
|
||||
indexOf(searchString: String, fromIndex: i32 = 0): i32 {
|
||||
assert(this !== null);
|
||||
if (searchString === null) searchString = changetype<String>("null");
|
||||
var pos: isize = position;
|
||||
var searchLen: isize = searchString.length;
|
||||
if (!searchLen) return 0;
|
||||
var len: isize = this.length;
|
||||
var start: isize = min<isize>(max<isize>(pos, 0), len);
|
||||
var searchLen: isize = <isize>searchString.length;
|
||||
|
||||
// TODO: two-way, multiple char codes
|
||||
for (let k: usize = start; <isize>k + searchLen <= len; ++k) {
|
||||
if (!len) return -1;
|
||||
var start = clamp<isize>(fromIndex, 0, len);
|
||||
len -= searchLen;
|
||||
// TODO: multiple char codes
|
||||
for (let k: isize = start; k <= len; ++k) {
|
||||
if (!compare_memory(
|
||||
changetype<usize>(this) + HEADER_SIZE + (k << 1),
|
||||
changetype<usize>(searchString) + HEADER_SIZE,
|
||||
searchLen << 1)
|
||||
) {
|
||||
searchLen << 1
|
||||
)) {
|
||||
return <i32>k;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
lastIndexOf(searchString: String, fromIndex: i32 = 0): i32 {
|
||||
assert(this !== null);
|
||||
if (searchString === null) searchString = changetype<String>("null");
|
||||
var len: isize = this.length;
|
||||
var searchLen: isize = searchString.length;
|
||||
if (!searchLen) return len;
|
||||
if (!len) return -1;
|
||||
var start = clamp<isize>(fromIndex - searchLen, 0, len);
|
||||
|
||||
// TODO: multiple char codes
|
||||
for (let k: isize = len - 1; k >= start; --k) {
|
||||
if (!compare_memory(
|
||||
changetype<usize>(this) + HEADER_SIZE + (k << 1),
|
||||
changetype<usize>(searchString) + HEADER_SIZE,
|
||||
searchLen << 1
|
||||
)) {
|
||||
return <i32>k;
|
||||
}
|
||||
}
|
||||
@ -233,8 +257,8 @@ export class String {
|
||||
|
||||
var pos: isize = position;
|
||||
var len: isize = this.length;
|
||||
var start: isize = min<isize>(max<isize>(pos, 0), len);
|
||||
var searchLength: isize = <isize>searchString.length;
|
||||
var start = clamp<isize>(pos, 0, len);
|
||||
var searchLength: isize = searchString.length;
|
||||
if (searchLength + start > len) {
|
||||
return false;
|
||||
}
|
||||
@ -253,7 +277,7 @@ export class String {
|
||||
if (intStart < 0) {
|
||||
intStart = max<isize>(size + intStart, 0);
|
||||
}
|
||||
var resultLength: isize = min<isize>(max<isize>(end, 0), size - intStart);
|
||||
var resultLength = clamp<isize>(end, 0, size - intStart);
|
||||
if (resultLength <= 0) {
|
||||
return EMPTY;
|
||||
}
|
||||
@ -269,8 +293,8 @@ export class String {
|
||||
substring(start: i32, end: i32 = i32.MAX_VALUE): String {
|
||||
assert(this !== null);
|
||||
var len = this.length;
|
||||
var finalStart = min<i32>(max<i32>(start, 0), len);
|
||||
var finalEnd = min<i32>(max<i32>(end, 0), len);
|
||||
var finalStart = clamp<isize>(start, 0, len);
|
||||
var finalEnd = clamp<isize>(end, 0, len);
|
||||
var from = min<i32>(finalStart, finalEnd);
|
||||
var to = max<i32>(finalStart, finalEnd);
|
||||
len = to - from;
|
||||
|
8
std/portable/index.d.ts
vendored
8
std/portable/index.d.ts
vendored
@ -280,14 +280,14 @@ declare class String {
|
||||
|
||||
private constructor();
|
||||
|
||||
indexOf(subject: string, position?: i32): i32;
|
||||
indexOf(other: string, fromIndex?: i32): i32;
|
||||
lastIndexOf(other: string, fromIndex?: i32): i32;
|
||||
includes(other: string): bool;
|
||||
lastIndexOf(subject: string, position?: i32): i32;
|
||||
charAt(index: i32): string;
|
||||
charCodeAt(index: i32): i32;
|
||||
substring(from: i32, to?: i32): string;
|
||||
startsWith(subject: string): bool;
|
||||
endsWith(subject: string): bool;
|
||||
startsWith(other: string): bool;
|
||||
endsWith(other: string): bool;
|
||||
replace(search: string, replacement: string): string;
|
||||
repeat(count?: i32): string;
|
||||
toString(): string;
|
||||
|
@ -132,7 +132,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 12)
|
||||
(i32.const 231)
|
||||
(i32.const 255)
|
||||
(i32.const 4)
|
||||
)
|
||||
(unreachable)
|
||||
@ -154,31 +154,31 @@
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(tee_local $3
|
||||
(tee_local $2
|
||||
(select
|
||||
(tee_local $3
|
||||
(tee_local $2
|
||||
(select
|
||||
(get_local $2)
|
||||
(i32.const 0)
|
||||
(i32.gt_s
|
||||
(tee_local $3
|
||||
(i32.load
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(i32.lt_s
|
||||
(get_local $2)
|
||||
(i32.const 0)
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(tee_local $2
|
||||
(i32.load
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(i32.lt_s
|
||||
(get_local $3)
|
||||
(i32.const 0)
|
||||
(i32.gt_s
|
||||
(get_local $2)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $2)
|
||||
(get_local $3)
|
||||
)
|
||||
(return
|
||||
(i32.const 0)
|
||||
@ -192,7 +192,7 @@
|
||||
(i32.const 4)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $3)
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
|
@ -201,6 +201,7 @@
|
||||
(local $6 i32)
|
||||
(local $7 i32)
|
||||
(local $8 i32)
|
||||
(local $9 i32)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.ne
|
||||
@ -212,7 +213,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 12)
|
||||
(i32.const 231)
|
||||
(i32.const 255)
|
||||
(i32.const 4)
|
||||
)
|
||||
(unreachable)
|
||||
@ -235,32 +236,37 @@
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(set_local $7
|
||||
(select
|
||||
(tee_local $5
|
||||
(select
|
||||
(tee_local $5
|
||||
(get_local $3)
|
||||
)
|
||||
(tee_local $6
|
||||
(i32.const 0)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $5)
|
||||
(get_local $6)
|
||||
(set_local $8
|
||||
(block $~lib/internal/string/clamp<isize>|inlined.0 (result i32)
|
||||
(set_local $5
|
||||
(i32.const 0)
|
||||
)
|
||||
(select
|
||||
(tee_local $6
|
||||
(select
|
||||
(tee_local $6
|
||||
(get_local $3)
|
||||
)
|
||||
(tee_local $7
|
||||
(get_local $4)
|
||||
)
|
||||
(i32.lt_s
|
||||
(get_local $6)
|
||||
(get_local $7)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(tee_local $6
|
||||
(get_local $4)
|
||||
)
|
||||
(i32.lt_s
|
||||
(get_local $5)
|
||||
(get_local $6)
|
||||
(tee_local $7
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $6)
|
||||
(get_local $7)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $8
|
||||
(set_local $9
|
||||
(i32.load
|
||||
(get_local $1)
|
||||
)
|
||||
@ -268,8 +274,8 @@
|
||||
(if
|
||||
(i32.gt_s
|
||||
(i32.add
|
||||
(get_local $9)
|
||||
(get_local $8)
|
||||
(get_local $7)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
@ -285,7 +291,7 @@
|
||||
(i32.const 4)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $7)
|
||||
(get_local $8)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
@ -294,7 +300,7 @@
|
||||
(i32.const 4)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $8)
|
||||
(get_local $9)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
|
@ -5823,7 +5823,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 728)
|
||||
(i32.const 20)
|
||||
(i32.const 25)
|
||||
(i32.const 2)
|
||||
)
|
||||
(unreachable)
|
||||
@ -5855,7 +5855,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 696)
|
||||
(i32.const 18)
|
||||
(i32.const 19)
|
||||
(i32.const 4)
|
||||
)
|
||||
(unreachable)
|
||||
@ -5903,7 +5903,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 696)
|
||||
(i32.const 74)
|
||||
(i32.const 75)
|
||||
(i32.const 4)
|
||||
)
|
||||
(unreachable)
|
||||
|
@ -8611,7 +8611,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 728)
|
||||
(i32.const 20)
|
||||
(i32.const 25)
|
||||
(i32.const 2)
|
||||
)
|
||||
(unreachable)
|
||||
@ -8647,7 +8647,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 696)
|
||||
(i32.const 18)
|
||||
(i32.const 19)
|
||||
(i32.const 4)
|
||||
)
|
||||
(unreachable)
|
||||
@ -8699,7 +8699,7 @@
|
||||
(call $~lib/env/abort
|
||||
(i32.const 0)
|
||||
(i32.const 696)
|
||||
(i32.const 74)
|
||||
(i32.const 75)
|
||||
(i32.const 4)
|
||||
)
|
||||
(unreachable)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,8 +13,24 @@ assert(str.charCodeAt(0) == 0x68);
|
||||
assert(str.startsWith("hi"));
|
||||
assert(str.endsWith("string"));
|
||||
assert(str.includes("I'm"));
|
||||
|
||||
assert("".indexOf("") == 0);
|
||||
assert("".indexOf("hi") == -1);
|
||||
assert(str.indexOf("") == 0);
|
||||
assert(str.indexOf(",") == 2);
|
||||
assert(str.indexOf("x") == -1);
|
||||
assert(str.indexOf(",", 2) == 2);
|
||||
assert(str.indexOf(",", 3) == -1);
|
||||
assert(str.indexOf(", I", -1) == 2);
|
||||
|
||||
assert("".lastIndexOf("") == 0);
|
||||
assert("".lastIndexOf("hi") == -1);
|
||||
assert(str.lastIndexOf("") == str.length);
|
||||
assert(str.lastIndexOf(",") == 2);
|
||||
assert(str.lastIndexOf("x") == -1);
|
||||
assert(str.lastIndexOf(",", 2) == 2);
|
||||
assert(str.lastIndexOf(",", 3) == 2);
|
||||
assert(str.lastIndexOf(", I", -1) == 2);
|
||||
|
||||
export function getString(): string {
|
||||
return str;
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user