2022-06-25 00:23:03 +08:00

187 lines
3.6 KiB
JavaScript

export class OptimizedArray {
/**
* Initialize this array with specified capacity.
* @param {Number} [size] The size.
*/
constructor(size = 0) {
this._size = size;
this._data = new Array(size);
}
/**
* Size of this array.
* @return {Number}
*/
get size() {
return this._size;
}
/**
* The underlying Array of this array.
* @return {Array}
*/
get data() {
return this._data;
}
/**
* Capacity of this array.
*/
get capacity() {
return this._data.length;
}
/**
* Push a value to back of this array.
* @param {any} value
*/
push(value) {
if (this._size > this._data.length)
this._extends(this._data.length);
this._data[this._size] = value;
++this._size;
}
/**
* Remove the last element and return it, if exists.
*/
pop() {
if (this._size == 0)
return;
--this._size;
let ret = this._data[this._size];
this._data[this._size] = undefined;
return ret;
}
/**
* Remove all elements.
*/
clear() {
for (let i = 0; i < this._data.length; ++i)
this._data[i] = undefined;
this._size = 0;
}
/**
* @ignore
* @param {Number} size
*/
_extends(size) {
let finalSize = this._data.length + size;
for (let i = this._data.length; i < finalSize; ++i)
this._data[i] = undefined;
}
}
export class OptimizedValueArray {
/**
* Initialize this array with specified capacity.
* @param {any} ctor The constructor to create the value.
* @param {Number} [size] The size.
*/
constructor(ctor, dtor, size = 0) {
this._size = size;
this._data = new Array();
this._ctor = ctor;
this._dtor = dtor;
this._extends(size);
}
/**
* Size of this array.
* @return {Number}
*/
get size() {
return this._size;
}
/**
* The underlying Array of this array.
* @return {Array}
*/
get data() {
return this._data;
}
/**
* Capacity of this array.
*/
get capacity() {
return this._data.length;
}
/**
* Push a value to back of this array.
*/
push() {
if (this._size >= this._data.length)
this._extends(this._data.length + 1);
let retval = this._data[this._size];
++this._size;
return retval;
}
/**
* Remove the last element, if exists.
* Since that element is not erased, so we cannot return it.
*/
pop() {
if (this._size == 0)
return;
--this._size;
this._dtor(this._data[this._size]);
}
/**
* Remove all elements.
*/
clear() {
this._size = 0;
for (let i = 0; i < this._data.length; ++i)
this._dtor(this._data[i]);
}
splice(from, number) {
if (number == 0)
return;
if (from >= this.size)
return; // throw
number = Math.min(this.size - from, number);
let originalSize = this._size;
this._size -= number;
for (let i = 0, moveStart = from + number, moveNumber = originalSize - moveStart; i < moveNumber; ++i) {
let temp = this._data[from + i];
this._data[from + i] = this._data[moveStart + i];
this._data[moveStart + i] = temp;
}
for (let i = this._size; i != originalSize; ++i)
this._dtor(this._data[i]);
}
forEach(fx) {
for (let i = 0; i < this.size; ++i)
fx(this.data[i], i, this);
}
map(fx) {
let result = new Array();
for (let i = 0; i < this.size; ++i)
result.push(fx(this.data[i], i, this));
return result;
}
/**
* @ignore
* @param {Number} size
*/
_extends(size) {
let finalSize = this._data.length + size;
for (let i = this._data.length; i < finalSize; ++i)
this._data[i] = this._ctor();
}
}