diff --git a/engine/lib/Dictionary.ts b/engine/lib/Dictionary.ts new file mode 100644 index 0000000..0fc0e2d --- /dev/null +++ b/engine/lib/Dictionary.ts @@ -0,0 +1,90 @@ +export type Dictionary = { + entries: Array<[K, V]>; + indices: Map; + isIterating: boolean; + deleteQueue: Array; + setQueue: Array<[K, V]>; +}; + +export function createDictionary(): Dictionary { + return { + entries: [], + indices: new Map(), + isIterating: false, + deleteQueue: [], + setQueue: [], + }; +} + +export function deleteEntry(dict: Dictionary, key: K): void { + const index = dict.indices.get(key); + if (index === undefined) { + return; + } + + const last = dict.entries.length - 1; + if (index !== last) { + dict.entries[index] = dict.entries[last]; + dict.indices.set(dict.entries[index][0], index); + } + + dict.entries.pop(); + dict.indices.delete(key); +} + +export function deleteEntrySave(dict: Dictionary, key: K): void { + if (dict.isIterating) { + dict.deleteQueue.push(); + } else { + deleteEntry(dict, key); + } +} + +export function setEntry( + dict: Dictionary, + [key, value]: [K, V], +): void { + const index = dict.indices.get(key); + if (index === undefined) { + dict.entries.push([key, value]); + dict.indices.set(key, dict.entries.length); + } else { + dict.entries[index][1] = value; + } +} + +export function setEntrySave( + dict: Dictionary, + key: K, + value: V, +): void { + if (dict.isIterating) { + dict.setQueue.push([key, value]); + } else { + setEntry(dict, [key, value]); + } +} + +export function getEntry(dict: Dictionary, key: K): V | undefined { + const index = dict.indices.get(key); + return index === undefined ? undefined : dict.entries[index][1]; +} + +export function forEntry( + dict: Dictionary, + callback: (value: V, key: K, index: number) => void, +): void { + dict.isIterating = true; + for (let i = 0; i < dict.entries.length; i++) { + callback(dict.entries[i][1], dict.entries[i][0], i); + } + dict.isIterating = false; + + while (dict.deleteQueue.length > 0) { + deleteEntry(dict, dict.deleteQueue.pop()!); + } + + while (dict.setQueue.length > 0) { + setEntry(dict, dict.setQueue.pop()!); + } +}