111 lines
3.6 KiB
TypeScript
Raw Normal View History

2017-12-16 17:54:53 +01:00
export class Array<T> {
private __memory: usize;
private __capacity: i32;
length: i32;
constructor(capacity: i32 = 0) {
2017-12-16 17:54:53 +01:00
if (capacity < 0)
throw new RangeError("invalid array length");
this.__capacity = this.length = capacity;
this.__memory = capacity > 0 ? allocate_memory(<usize>capacity * sizeof<T>()) : 0;
}
@operator("[]")
2018-01-06 10:20:38 +01:00
private __get(index: i32): T {
if (<u32>index >= this.__capacity)
throw new RangeError("index out of range");
return load<T>(this.__memory + <usize>index * sizeof<T>());
}
@operator("[]=")
2018-01-06 10:20:38 +01:00
private __set(index: i32, value: T): void {
if (<u32>index >= this.__capacity)
throw new RangeError("index out of range");
store<T>(this.__memory + <usize>index * sizeof<T>(), value);
}
indexOf(searchElement: T, fromIndex: i32 = 0): i32 {
if (<u32>fromIndex >= this.__capacity)
throw new RangeError("fromIndex out of range");
for (var index: usize = <usize>fromIndex, length: usize = min<u32>(this.length, this.__capacity); index < length; ++index)
if (load<T>(this.__memory + index * sizeof<T>()) == searchElement)
return index;
return -1;
}
private __grow(newCapacity: i32): void {
assert(newCapacity > this.__capacity);
var newMemory = allocate_memory(<usize>newCapacity * sizeof<T>());
if (this.__memory) {
move_memory(newMemory, this.__memory, this.__capacity * sizeof<T>());
free_memory(this.__memory);
}
this.__memory = newMemory;
this.__capacity = newCapacity;
}
push(element: T): i32 {
if (<u32>this.length >= this.__capacity)
this.__grow(max(this.length + 1, this.__capacity << 1));
store<T>(this.__memory + <usize>this.length * sizeof<T>(), element);
return ++this.length;
}
pop(): T {
if (this.length < 1 || <u32>this.length > this.__capacity)
throw new RangeError("index out of range");
--this.length;
return load<T>(this.__memory + <usize>this.length * sizeof<T>());
}
2017-12-16 02:27:39 +01:00
shift(): T {
if (this.length < 1 || <u32>this.length > this.__capacity)
throw new RangeError("index out of range");
var element = load<T>(this.__memory);
move_memory(this.__memory, this.__memory + sizeof<T>(), (this.__capacity - 1) * sizeof<T>());
set_memory(this.__memory + (this.__capacity - 1) * sizeof<T>(), 0, sizeof<T>());
--this.length;
return element;
}
unshift(element: T): i32 {
var oldCapacity = this.__capacity;
2018-01-14 02:41:13 +01:00
if (<u32>this.length >= oldCapacity) {
// inlined `this.__grow(max(this.length + 1, oldCapacity * 2))` (avoids moving twice)
var newCapacity = max(this.length + 1, oldCapacity * 2);
assert(newCapacity > this.__capacity);
var newMemory = allocate_memory(<usize>newCapacity * sizeof<T>());
if (this.__memory) {
move_memory(newMemory + sizeof<T>(), this.__memory, oldCapacity * sizeof<T>());
free_memory(this.__memory);
}
this.__memory = newMemory;
this.__capacity = newCapacity;
} else
move_memory(this.__memory + sizeof<T>(), this.__memory, oldCapacity * sizeof<T>());
store<T>(this.__memory, element);
return ++this.length;
}
}
2018-01-05 01:55:59 +01:00
@explicit
2018-01-05 01:55:59 +01:00
export class CArray<T> {
private constructor() {}
@operator("[]")
private __get(index: i32): T {
if (index < 0)
throw new RangeError("index out of range");
return load<T>(changetype<usize>(this) + <usize>index * sizeof<T>());
2018-01-05 01:55:59 +01:00
}
@operator("[]=")
private __set(index: i32, value: T): void {
if (index < 0)
throw new RangeError("index out of range");
store<T>(changetype<usize>(this) + <usize>index * sizeof<T>(), value);
2018-01-05 01:55:59 +01:00
}
}