Files
xterm.js/src/common/SortedList.ts
T

96 lines
2.4 KiB
TypeScript

/**
* Copyright (c) 2022 The xterm.js authors. All rights reserved.
* @license MIT
*/
/**
* A generic list that is maintained in sorted order and allows values with duplicate keys. This
* list is based on binary search and as such locating a key will take O(log n) amortized, this
* includes the by key iterator.
*/
export class SortedList<T> {
private readonly _array: T[] = [];
constructor(
private readonly _getKey: (value: T) => number
) {
}
public clear(): void {
this._array.length = 0;
}
public insert(value: T): void {
if (this._array.length === 0) {
this._array.push(value);
return;
}
const i = this._search(this._getKey(value), 0, this._array.length - 1);
this._array.splice(i, 0, value);
}
public delete(value: T): boolean {
if (this._array.length === 0) {
return false;
}
const key = this._getKey(value);
if (key === undefined) {
return false;
}
let i = this._search(key, 0, this._array.length - 1);
if (i === -1) {
return false;
}
if (this._getKey(this._array[i]) !== key) {
return false;
}
do {
if (this._array[i] === value) {
this._array.splice(i, 1);
return true;
}
} while (++i < this._array.length && this._getKey(this._array[i]) === key);
return false;
}
public *getKeyIterator(key: number): IterableIterator<T> {
if (this._array.length === 0) {
return;
}
let i = this._search(key, 0, this._array.length - 1);
if (i < 0 || i >= this._array.length) {
return;
}
if (this._getKey(this._array[i]) !== key) {
return;
}
do {
yield this._array[i];
} while (++i < this._array.length && this._getKey(this._array[i]) === key);
}
public values(): IterableIterator<T> {
return this._array.values();
}
private _search(key: number, min: number, max: number): number {
if (max < min) {
return min;
}
let mid = Math.floor((min + max) / 2);
const midKey = this._getKey(this._array[mid]);
if (midKey > key) {
return this._search(key, min, mid - 1);
}
if (midKey < key) {
return this._search(key, mid + 1, max);
}
// Value found! Since keys can be duplicates, move the result index back to the lowest index
// that matches the key.
while (mid > 0 && this._getKey(this._array[mid - 1]) === key) {
mid--;
}
return mid;
}
}