Files
ueblueprint/js/selection/OrderedIndexArray.js
2022-10-09 11:43:28 +02:00

119 lines
3.3 KiB
JavaScript
Executable File

export default class OrderedIndexArray {
/**
* @param {(arrayElement: number) => number} comparisonValueSupplier
* @param {number} value
*/
constructor(comparisonValueSupplier = v => v, value = null) {
this.array = new Uint32Array(value)
this.comparisonValueSupplier = comparisonValueSupplier
this.length = 0
this.currentPosition = 0
}
/** @param {number} index */
get(index) {
if (index >= 0 && index < this.length) {
return this.array[index]
}
return null
}
getArray() {
return this.array
}
/** @param {number} value */
getPosition(value) {
let l = 0
let r = this.length
while (l < r) {
let m = Math.floor((l + r) / 2)
if (this.comparisonValueSupplier(this.array[m]) < value) {
l = m + 1
} else {
r = m
}
}
return l
}
reserve(length) {
if (this.array.length < length) {
let newArray = new Uint32Array(length)
newArray.set(this.array)
this.array = newArray
}
}
/** @param {number} element */
insert(element, comparisonValue = null) {
let position = this.getPosition(this.comparisonValueSupplier(element))
if (
position < this.currentPosition
|| comparisonValue != null && position == this.currentPosition && this.comparisonValueSupplier(element) < comparisonValue) {
++this.currentPosition
}
this.shiftRight(position)
this.array[position] = element
++this.length
return position
}
/** @param {number} element */
remove(element) {
let position = this.getPosition(this.comparisonValueSupplier(element))
if (this.array[position] == element) {
this.removeAt(position)
}
}
/** @param {number} position */
removeAt(position) {
if (position < this.currentPosition) {
--this.currentPosition
}
this.shiftLeft(position)
--this.length
return position
}
getNext() {
if (this.currentPosition >= 0 && this.currentPosition < this.length) {
return this.get(this.currentPosition)
}
return null
}
getNextValue() {
if (this.currentPosition >= 0 && this.currentPosition < this.length) {
return this.comparisonValueSupplier(this.get(this.currentPosition))
} else {
return Number.MAX_SAFE_INTEGER
}
}
getPrev() {
if (this.currentPosition > 0) {
return this.get(this.currentPosition - 1)
}
return null
}
getPrevValue() {
if (this.currentPosition > 0) {
return this.comparisonValueSupplier(this.get(this.currentPosition - 1))
} else {
return Number.MIN_SAFE_INTEGER
}
}
shiftLeft(leftLimit, steps = 1) {
this.array.set(this.array.subarray(leftLimit + steps), leftLimit)
}
shiftRight(leftLimit, steps = 1) {
this.array.set(this.array.subarray(leftLimit, -steps), leftLimit + steps)
}
}