UNPKG

@rimbu/sorted

Version:

Immutable SortedMap and SortedSet implementations for TypeScript

151 lines 5.54 kB
import { Stream } from '@rimbu/stream'; import { SortedIndex, SortedBuilder } from '@rimbu/sorted/common'; export class SortedSetBuilder extends SortedBuilder { constructor(context, source, _entries, _children, size = source?.size ?? 0) { super(); this.context = context; this.source = source; this._entries = _entries; this._children = _children; this.size = size; // prettier-ignore this.has = (value) => { if (!this.context.comp.isComparable(value)) return false; if (undefined !== this.source) return this.source.has(value); const index = this.context.findIndex(value, this.entries); if (index >= 0) return true; if (!this.hasChildren) return false; const childIndex = SortedIndex.next(index); const child = this.children[childIndex]; return child.has(value); }; this.add = (value) => { this.checkLock(); const result = this.addInternal(value); this.normalize(); return result; }; this.addAll = (source) => { this.checkLock(); return Stream.from(source).filterPure({ pred: this.add }).count() > 0; }; // prettier-ignore this.remove = (value) => { this.checkLock(); if (!this.context.comp.isComparable(value)) return false; const result = this.removeInternal(value); this.normalize(); return result; }; // prettier-ignore this.removeAll = (values) => { this.checkLock(); return Stream.from(values).filterPure({ pred: this.remove }).count() > 0; }; this.build = () => { if (undefined !== this.source) return this.source; if (this.size === 0) return this.context.empty(); if (!this.hasChildren) { return this.context.leaf(this.entries.slice()); } return this.context.inner(this.entries.slice(), this.children.map((child) => child.build()), this.size); }; } createNew(source, entries, children, size) { return new SortedSetBuilder(this.context, source, entries, children, size); } prepareMutate() { if (undefined === this._entries) { if (undefined !== this.source) { if (this.context.isSortedSetEmpty(this.source)) { this._entries = []; this._children = []; } else if (this.context.isSortedSetLeaf(this.source)) { this._entries = this.source.entries.slice(); } else if (this.context.isSortedSetInner(this.source)) { this._entries = this.source.entries.slice(); this._children = this.source.children.map((child) => this.createNew(child)); } } if (undefined === this._entries) this._entries = []; } } get children() { this.prepareMutate(); return this._children; } set children(value) { this.prepareMutate(); this.source = undefined; this._children = value; } addInternal(value) { const entryIndex = this.context.findIndex(value, this.entries); if (entryIndex >= 0) { return false; } const childIndex = SortedIndex.next(entryIndex); if (!this.hasChildren) { this.source = undefined; this.size++; this.entries.splice(childIndex, 0, value); return true; } const child = this.children[childIndex]; const preSize = child.size; const changed = child.addInternal(value); if (!changed) return false; this.source = undefined; this.size += child.size - preSize; this.normalizeChildDecrease(childIndex); return changed; } removeInternal(value) { if (this.size === 0) return false; const entryIndex = this.context.findIndex(value, this.entries); if (entryIndex >= 0) { this.source = undefined; this.size--; if (!this.hasChildren) { this.entries.splice(entryIndex, 1); return true; } const leftChild = this.children[entryIndex]; const rightChild = this.children[entryIndex + 1]; if (leftChild.size >= rightChild.size) { this.entries[entryIndex] = leftChild.deleteMax(); this.normalizeChildIncrease(entryIndex); } else { this.entries[entryIndex] = rightChild.deleteMin(); this.normalizeChildIncrease(entryIndex + 1); } return true; } if (!this.hasChildren) return false; const childIndex = SortedIndex.next(entryIndex); const child = this.children[childIndex]; const preSize = child.size; const changed = child.removeInternal(value); if (!changed) return false; this.source = undefined; this.size += child.size - preSize; this.normalizeChildIncrease(childIndex); return true; } } //# sourceMappingURL=builder.mjs.map