Skip to content

Commit 671121b

Browse files
MaxGraeydcodeIO
authored andcommitted
Implement String#padStart/padEnd; Refactor internal string copy, compare and repeat (AssemblyScript#171)
1 parent 298a8f1 commit 671121b

15 files changed

+9061
-6659
lines changed

std/assembly/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,8 @@ declare class String {
489489
trim(): string;
490490
trimLeft(): string;
491491
trimRight(): string;
492+
padStart(targetLength: i32, padString?: string): string;
493+
padEnd(targetLength: i32, padString?: string): string;
492494
repeat(count?: i32): string;
493495
toString(): string;
494496
toUTF8(): usize;

std/assembly/internal/string.ts

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const EMPTY = changetype<String>(""); // TODO: is this a bad idea with '=
1717

1818
@inline
1919
export function clamp<T>(val: T, lo: T, hi: T): T {
20-
return max<T>(min<T>(val, hi), lo);
20+
return min<T>(max<T>(val, lo), hi);
2121
}
2222

2323
/** Allocates a raw String with uninitialized contents. */
@@ -28,6 +28,15 @@ export function allocate(length: i32): String {
2828
return changetype<String>(buffer);
2929
}
3030

31+
@inline
32+
export function copyUnsafe(dest: String, destOffset: usize, src: String, srcOffset: usize, len: usize): void {
33+
memory.copy(
34+
changetype<usize>(dest) + (destOffset << 1) + HEADER_SIZE,
35+
changetype<usize>(src) + (srcOffset << 1) + HEADER_SIZE,
36+
len << 1
37+
);
38+
}
39+
3140
export function isWhiteSpaceOrLineTerminator(c: u16): bool {
3241
switch (c) {
3342
case 10: // <LF>
@@ -76,24 +85,19 @@ export const enum CharCode {
7685

7786
export function parse<T>(str: String, radix: i32 = 0): T {
7887
var len: i32 = str.length;
79-
if (!len) {
80-
return <T>NaN;
81-
}
88+
if (!len) return <T>NaN;
89+
8290
var ptr = changetype<usize>(str) /* + HEAD -> offset */;
8391
var code = <i32>load<u16>(ptr, HEADER_SIZE);
8492

8593
// determine sign
8694
var sign: T;
8795
if (code == CharCode.MINUS) {
88-
if (!--len) {
89-
return <T>NaN;
90-
}
96+
if (!--len) return <T>NaN;
9197
code = <i32>load<u16>(ptr += 2, HEADER_SIZE);
9298
sign = -1;
9399
} else if (code == CharCode.PLUS) {
94-
if (!--len) {
95-
return <T>NaN;
96-
}
100+
if (!--len) return <T>NaN;
97101
code = <i32>load<u16>(ptr += 2, HEADER_SIZE);
98102
sign = 1;
99103
} else {
@@ -122,9 +126,7 @@ export function parse<T>(str: String, radix: i32 = 0): T {
122126
radix = 16;
123127
break;
124128
}
125-
default: {
126-
radix = 10;
127-
}
129+
default: radix = 10;
128130
}
129131
} else radix = 10;
130132
} else if (radix < 2 || radix > 36) {
@@ -141,22 +143,79 @@ export function parse<T>(str: String, radix: i32 = 0): T {
141143
code -= CharCode.A - 10;
142144
} else if (code >= CharCode.a && code <= CharCode.z) {
143145
code -= CharCode.a - 10;
144-
} else {
145-
break;
146-
}
147-
if (code >= radix) {
148-
break;
149-
}
146+
} else break;
147+
if (code >= radix) break;
150148
num = (num * radix) + code;
151149
ptr += 2;
152150
}
153151
return sign * num;
154152
}
155153

156-
export function compareUTF16(ptr1: usize, ptr2: usize, len: usize): i32 {
154+
export function compareUnsafe(str1: String, offset1: usize, str2: String, offset2: usize, len: usize): i32 {
157155
var cmp: i32 = 0;
156+
var ptr1 = changetype<usize>(str1) + (offset1 << 1);
157+
var ptr2 = changetype<usize>(str2) + (offset2 << 1);
158158
while (len && !(cmp = <i32>load<u16>(ptr1, HEADER_SIZE) - <i32>load<u16>(ptr2, HEADER_SIZE))) {
159159
--len, ++ptr1, ++ptr2;
160160
}
161161
return cmp;
162162
}
163+
164+
export function repeatUnsafe(dest: String, destOffset: usize, src: String, count: i32): void {
165+
var length = src.length;
166+
if (ASC_SHRINK_LEVEL > 1) {
167+
let strLen = length << 1;
168+
let to = changetype<usize>(dest) + HEADER_SIZE + (destOffset << 1);
169+
let from = changetype<usize>(src) + HEADER_SIZE;
170+
for (let i = 0, len = strLen * count; i < len; i += strLen) {
171+
memory.copy(to + i, from, strLen);
172+
}
173+
} else {
174+
switch (length) {
175+
case 0: break;
176+
case 1: {
177+
let cc = load<u16>(changetype<usize>(src), HEADER_SIZE);
178+
let out = changetype<usize>(dest) + (destOffset << 1);
179+
for (let i = 0; i < count; ++i) {
180+
store<u16>(out + (i << 1), cc, HEADER_SIZE);
181+
}
182+
break;
183+
}
184+
case 2: {
185+
let cc = load<u32>(changetype<usize>(src), HEADER_SIZE);
186+
let out = changetype<usize>(dest) + (destOffset << 1);
187+
for (let i = 0; i < count; ++i) {
188+
store<u32>(out + (i << 2), cc, HEADER_SIZE);
189+
}
190+
break;
191+
}
192+
case 3: {
193+
let cc1 = load<u32>(changetype<usize>(src), HEADER_SIZE + 0);
194+
let cc2 = load<u16>(changetype<usize>(src), HEADER_SIZE + 4);
195+
let out = changetype<usize>(dest) + (destOffset << 1);
196+
for (let i = 0; i < count; ++i) {
197+
store<u32>(out + (i << 2), cc1, HEADER_SIZE + 0);
198+
store<u16>(out + (i << 1), cc2, HEADER_SIZE + 4);
199+
}
200+
break;
201+
}
202+
case 4: {
203+
let cc = load<u64>(changetype<usize>(src), HEADER_SIZE);
204+
let out = changetype<usize>(dest) + (destOffset << 1);
205+
for (let i = 0; i < count; ++i) {
206+
store<u64>(out + (i << 3), cc, HEADER_SIZE);
207+
}
208+
break;
209+
}
210+
default: {
211+
let strLen = length << 1;
212+
let to = changetype<usize>(dest) + HEADER_SIZE + (destOffset << 1);
213+
let from = changetype<usize>(src) + HEADER_SIZE;
214+
for (let i = 0, len = strLen * count; i < len; i += strLen) {
215+
memory.copy(to + i, from, strLen);
216+
}
217+
break;
218+
}
219+
}
220+
}
221+
}

0 commit comments

Comments
 (0)