UNPKG

monaco-editor

Version:
105 lines (104 loc) 3.73 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ const emptyArr = []; /** * Represents an immutable set that works best for a small number of elements (less than 32). * It uses bits to encode element membership efficiently. */ export class SmallImmutableSet { static create(items, additionalItems) { if (items <= 128 && additionalItems.length === 0) { // We create a cache of 128=2^7 elements to cover all sets with up to 7 (dense) elements. let cached = SmallImmutableSet.cache[items]; if (!cached) { cached = new SmallImmutableSet(items, additionalItems); SmallImmutableSet.cache[items] = cached; } return cached; } return new SmallImmutableSet(items, additionalItems); } static getEmpty() { return this.empty; } constructor(items, additionalItems) { this.items = items; this.additionalItems = additionalItems; } add(value, keyProvider) { const key = keyProvider.getKey(value); let idx = key >> 5; // divided by 32 if (idx === 0) { // fast path const newItem = (1 << key) | this.items; if (newItem === this.items) { return this; } return SmallImmutableSet.create(newItem, this.additionalItems); } idx--; const newItems = this.additionalItems.slice(0); while (newItems.length < idx) { newItems.push(0); } newItems[idx] |= 1 << (key & 31); return SmallImmutableSet.create(this.items, newItems); } merge(other) { const merged = this.items | other.items; if (this.additionalItems === emptyArr && other.additionalItems === emptyArr) { // fast path if (merged === this.items) { return this; } if (merged === other.items) { return other; } return SmallImmutableSet.create(merged, emptyArr); } // This can be optimized, but it's not a common case const newItems = []; for (let i = 0; i < Math.max(this.additionalItems.length, other.additionalItems.length); i++) { const item1 = this.additionalItems[i] || 0; const item2 = other.additionalItems[i] || 0; newItems.push(item1 | item2); } return SmallImmutableSet.create(merged, newItems); } intersects(other) { if ((this.items & other.items) !== 0) { return true; } for (let i = 0; i < Math.min(this.additionalItems.length, other.additionalItems.length); i++) { if ((this.additionalItems[i] & other.additionalItems[i]) !== 0) { return true; } } return false; } } SmallImmutableSet.cache = new Array(129); SmallImmutableSet.empty = SmallImmutableSet.create(0, emptyArr); export const identityKeyProvider = { getKey(value) { return value; } }; /** * Assigns values a unique incrementing key. */ export class DenseKeyProvider { constructor() { this.items = new Map(); } getKey(value) { let existing = this.items.get(value); if (existing === undefined) { existing = this.items.size; this.items.set(value, existing); } return existing; } }