Skip to content

Commit e5c1e08

Browse files
MaxGraeydcodeIO
authored andcommitted
Unify Array#join implementation (#881)
1 parent 0710bda commit e5c1e08

File tree

5 files changed

+1620
-1213
lines changed

5 files changed

+1620
-1213
lines changed

std/assembly/array.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { BLOCK_MAXSIZE } from "./rt/common";
44
import { COMPARATOR, SORT } from "./util/sort";
55
import { ArrayBufferView } from "./arraybuffer";
6-
import { joinBooleanArray, joinIntegerArray, joinFloatArray, joinStringArray, joinArrays, joinObjectArray } from "./util/string";
6+
import { joinBooleanArray, joinIntegerArray, joinFloatArray, joinStringArray, joinReferenceArray } from "./util/string";
77
import { idof, isArray as builtin_isArray } from "./builtins";
88
import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_EMPTYARRAY, E_HOLEYARRAY } from "./util/error";
99

@@ -462,12 +462,15 @@ export class Array<T> extends ArrayBufferView {
462462
join(separator: string = ","): string {
463463
var dataStart = this.dataStart;
464464
var length = this.length_;
465-
if (isString<T>()) return joinStringArray(dataStart, length, separator);
466465
if (isBoolean<T>()) return joinBooleanArray(dataStart, length, separator);
467466
if (isInteger<T>()) return joinIntegerArray<T>(dataStart, length, separator);
468467
if (isFloat<T>()) return joinFloatArray<T>(dataStart, length, separator);
469-
if (isArray<T>()) return joinArrays<T>(dataStart, length, separator);
470-
if (isReference<T>()) return joinObjectArray<T>(dataStart, length, separator);
468+
469+
if (ASC_SHRINK_LEVEL < 1) {
470+
if (isString<T>()) return joinStringArray(dataStart, length, separator);
471+
}
472+
// For rest objects and arrays use general join routine
473+
if (isReference<T>()) return joinReferenceArray<T>(dataStart, length, separator);
471474
ERROR("unspported element type");
472475
return <string>unreachable();
473476
}

std/assembly/util/string.ts

Lines changed: 21 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -372,31 +372,34 @@ export function joinFloatArray<T>(dataStart: usize, length: i32, separator: stri
372372
export function joinStringArray(dataStart: usize, length: i32, separator: string): string {
373373
var lastIndex = length - 1;
374374
if (lastIndex < 0) return "";
375-
if (!lastIndex) return load<string>(dataStart);
376-
377-
var sepLen = separator.length;
375+
if (!lastIndex) {
376+
// @ts-ignore: type
377+
return load<string>(dataStart) || "";
378+
}
378379
var estLen = 0;
379-
var value: string | null;
380-
for (let i = 0, len = lastIndex + 1; i < len; ++i) {
380+
var value: string;
381+
for (let i = 0; i < length; ++i) {
381382
value = load<string>(dataStart + (<usize>i << alignof<string>()));
383+
// @ts-ignore: type
382384
if (value !== null) estLen += value.length;
383385
}
384386
var offset = 0;
385-
var result = changetype<string>(__alloc((estLen + sepLen * lastIndex) << 1, idof<string>())); // retains
387+
var sepLen = separator.length;
388+
var result = __alloc((estLen + sepLen * lastIndex) << 1, idof<string>());
386389
for (let i = 0; i < lastIndex; ++i) {
387390
value = load<string>(dataStart + (<usize>i << alignof<string>()));
388391
if (value !== null) {
389-
let valueLen = changetype<string>(value).length;
392+
let valueLen = value.length;
390393
memory.copy(
391-
changetype<usize>(result) + (<usize>offset << 1),
394+
result + (<usize>offset << 1),
392395
changetype<usize>(value),
393396
<usize>valueLen << 1
394397
);
395398
offset += valueLen;
396399
}
397400
if (sepLen) {
398401
memory.copy(
399-
changetype<usize>(result) + (<usize>offset << 1),
402+
result + (<usize>offset << 1),
400403
changetype<usize>(separator),
401404
<usize>sepLen << 1
402405
);
@@ -406,77 +409,34 @@ export function joinStringArray(dataStart: usize, length: i32, separator: string
406409
value = load<string>(dataStart + (<usize>lastIndex << alignof<string>()));
407410
if (value !== null) {
408411
memory.copy(
409-
changetype<usize>(result) + (<usize>offset << 1),
412+
result + (<usize>offset << 1),
410413
changetype<usize>(value),
411-
<usize>changetype<string>(value).length << 1
414+
<usize>value.length << 1
412415
);
413416
}
414-
return result;
417+
return changetype<string>(result); // retains
415418
}
416419

417-
export function joinArrays<T>(dataStart: usize, length: i32, separator: string): string {
420+
export function joinReferenceArray<T>(dataStart: usize, length: i32, separator: string): string {
418421
var lastIndex = length - 1;
419422
if (lastIndex < 0) return "";
420-
421-
var result = "";
422-
var sepLen = separator.length;
423423
var value: T;
424424
if (!lastIndex) {
425425
value = load<T>(dataStart);
426426
// @ts-ignore: type
427-
return value ? value.join(separator) : "";
427+
return value !== null ? value.toString() : "";
428428
}
429+
var result = "";
430+
var sepLen = separator.length;
429431
for (let i = 0; i < lastIndex; ++i) {
430432
value = load<T>(dataStart + (<usize>i << alignof<T>()));
431433
// @ts-ignore: type
432-
if (value) result += value.join(separator);
434+
if (value !== null) result += value.toString();
433435
if (sepLen) result += separator;
434436
}
435437
value = load<T>(dataStart + (<usize>lastIndex << alignof<T>()));
436438
// @ts-ignore: type
437-
if (value) result += value.join(separator);
438-
return result; // registered by concatenation (FIXME: lots of garbage)
439-
}
440-
441-
export function joinObjectArray<T>(dataStart: usize, length: i32, separator: string): string {
442-
var lastIndex = length - 1;
443-
if (lastIndex < 0) return "";
444-
if (!lastIndex) return "[object Object]";
445-
446-
const valueLen = 15; // max possible length of element len("[object Object]")
447-
var sepLen = separator.length;
448-
var estLen = (valueLen + sepLen) * lastIndex + valueLen;
449-
var result = changetype<string>(__alloc(estLen << 1, idof<string>()));
450-
var offset = 0;
451-
var value: T;
452-
for (let i = 0; i < lastIndex; ++i) {
453-
value = load<T>(dataStart + (<usize>i << alignof<T>()));
454-
if (value) {
455-
memory.copy(
456-
changetype<usize>(result) + (<usize>offset << 1),
457-
changetype<usize>("[object Object]"),
458-
<usize>valueLen << 1
459-
);
460-
offset += valueLen;
461-
}
462-
if (sepLen) {
463-
memory.copy(
464-
changetype<usize>(result) + (<usize>offset << 1),
465-
changetype<usize>(separator),
466-
<usize>sepLen << 1
467-
);
468-
offset += sepLen;
469-
}
470-
}
471-
if (load<T>(dataStart + (<usize>lastIndex << alignof<T>()))) {
472-
memory.copy(
473-
changetype<usize>(result) + (<usize>offset << 1),
474-
changetype<usize>("[object Object]"),
475-
<usize>valueLen << 1
476-
);
477-
offset += valueLen;
478-
}
479-
if (estLen > offset) return result.substring(0, offset);
439+
if (value !== null) result += value.toString();
480440
return result;
481441
}
482442

0 commit comments

Comments
 (0)