Files
nage/engine/lib/Dictionary.ts
T
2026-08-26 18:03:33 +02:00

96 lines
2.1 KiB
TypeScript

export type Dictionary<K, V> = {
entries: Array<[K, V]>;
indices: Map<K, number>;
isIterating: boolean;
deleteQueue: Array<K>;
setQueue: Array<[K, V]>;
};
export function createDictionary<K, V>(
iterable?: Iterable<[K, V]>,
): Dictionary<K, V> {
const entries = iterable ? [...iterable] : [];
const indices = new Map(entries.map(([k], i) => [k, i]));
return {
entries,
indices,
isIterating: false,
deleteQueue: [],
setQueue: [],
};
}
export function deleteEntry<K, V>(dict: Dictionary<K, V>, 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<K, V>(dict: Dictionary<K, V>, key: K): void {
if (dict.isIterating) {
dict.deleteQueue.push();
} else {
deleteEntry(dict, key);
}
}
export function setEntry<K, V>(
dict: Dictionary<K, V>,
[key, value]: [K, V],
): void {
const index = dict.indices.get(key);
if (index === undefined) {
dict.indices.set(key, dict.entries.length);
dict.entries.push([key, value]);
} else {
dict.entries[index][1] = value;
}
}
export function setEntrySave<K, V>(
dict: Dictionary<K, V>,
key: K,
value: V,
): void {
if (dict.isIterating) {
dict.setQueue.push([key, value]);
} else {
setEntry(dict, [key, value]);
}
}
export function getEntry<K, V>(dict: Dictionary<K, V>, key: K): V | undefined {
const index = dict.indices.get(key);
return index === undefined ? undefined : dict.entries[index][1];
}
export function forEntry<K, V>(
dict: Dictionary<K, V>,
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()!);
}
}