Maintain decorations sorted by line

This commit is contained in:
Daniel Imms
2022-05-11 09:34:51 -07:00
parent c0b4edaf31
commit 931ee9e89e
3 changed files with 207 additions and 25 deletions
+80
View File
@@ -0,0 +1,80 @@
/**
* Copyright (c) 2022 The xterm.js authors. All rights reserved.
* @license MIT
*/
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);
let i = this._search(key, 0, this._array.length - 1);
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 (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);
if (this._getKey(this._array[mid]) > key) {
return this._search(key, min, mid - 1);
}
if (this._getKey(this._array[mid]) < 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;
}
}