2019-12-26 15:34:17 +01:00
|
|
|
/*
|
|
|
|
Use this class to manage keys where you don't care
|
|
|
|
about case (i.e. case-insensitive).
|
|
|
|
|
|
|
|
Keys for FoldDict should be strings. We "fold" all
|
|
|
|
casings of "alice" (e.g. "ALICE", "Alice", "ALIce", etc.)
|
|
|
|
to "alice" as the key.
|
|
|
|
|
|
|
|
Examples of case-insensitive data in Zulip are:
|
|
|
|
- emails
|
|
|
|
- stream names
|
|
|
|
- topics
|
|
|
|
- etc.
|
|
|
|
*/
|
|
|
|
type KeyValue<V> = { k: string; v: V };
|
|
|
|
|
|
|
|
export class FoldDict<V> {
|
2020-01-31 08:49:03 +01:00
|
|
|
private _items: Map<string, KeyValue<V>> = new Map();
|
2019-12-26 15:34:17 +01:00
|
|
|
|
|
|
|
get(key: string): V | undefined {
|
2020-01-31 08:49:03 +01:00
|
|
|
const mapping = this._items.get(this._munge(key));
|
2019-12-26 15:34:17 +01:00
|
|
|
if (mapping === undefined) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
return mapping.v;
|
|
|
|
}
|
|
|
|
|
2020-02-03 07:18:13 +01:00
|
|
|
set(key: string, value: V): FoldDict<V> {
|
2020-01-31 08:49:03 +01:00
|
|
|
this._items.set(this._munge(key), {k: key, v: value});
|
2020-02-03 07:18:13 +01:00
|
|
|
return this;
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
has(key: string): boolean {
|
2020-01-31 08:49:03 +01:00
|
|
|
return this._items.has(this._munge(key));
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
2020-02-03 07:41:38 +01:00
|
|
|
delete(key: string): boolean {
|
|
|
|
return this._items.delete(this._munge(key));
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
keys(): string[] {
|
2020-01-31 08:49:03 +01:00
|
|
|
return [...this._items.values()].map(({k}) => k);
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
values(): V[] {
|
2020-01-31 08:49:03 +01:00
|
|
|
return [...this._items.values()].map(({v}) => v);
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
items(): [string, V][] {
|
2020-01-31 08:49:03 +01:00
|
|
|
return [...this._items.values()].map(({k, v}) => [k, v]);
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
num_items(): number {
|
2020-01-31 08:49:03 +01:00
|
|
|
return this._items.size;
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
is_empty(): boolean {
|
2020-01-31 08:49:03 +01:00
|
|
|
return this._items.size === 0;
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
each(f: (v: V, k?: string) => void): void {
|
2020-01-31 08:49:03 +01:00
|
|
|
this._items.forEach(({k, v}) => f(v, k));
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
clear(): void {
|
2020-01-31 08:49:03 +01:00
|
|
|
this._items.clear();
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle case-folding of keys and the empty string.
|
|
|
|
private _munge(key: string): string | undefined {
|
|
|
|
if (key === undefined) {
|
|
|
|
blueslip.error("Tried to call a FoldDict method with an undefined key.");
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
2020-01-31 08:49:03 +01:00
|
|
|
return key.toString().toLowerCase();
|
2019-12-26 15:34:17 +01:00
|
|
|
}
|
|
|
|
}
|