forked from CringeStudios/gamja
lib/irc: add case-mapping primitives
irc.CaseMapping contains the basic canonicalization functions for the three supported case-mappings. irc.CaseMapMap is a Map-like class that supports case-mapped keys.
This commit is contained in:
parent
d880b23d32
commit
3110a9e2df
165
lib/irc.js
165
lib/irc.js
@ -320,6 +320,7 @@ export function parseCTCP(msg) {
|
||||
}
|
||||
|
||||
export function parseISUPPORT(tokens, params) {
|
||||
var changed = [];
|
||||
tokens.forEach((tok) => {
|
||||
if (tok.startsWith("-")) {
|
||||
var k = tok.slice(1);
|
||||
@ -333,6 +334,168 @@ export function parseISUPPORT(tokens, params) {
|
||||
k = tok.slice(0, i);
|
||||
v = tok.slice(i + 1);
|
||||
}
|
||||
params.set(k.toUpperCase(), v);
|
||||
|
||||
k = k.toUpperCase();
|
||||
|
||||
params.set(k, v);
|
||||
changed.push(k);
|
||||
});
|
||||
return changed;
|
||||
}
|
||||
|
||||
export const CaseMapping = {
|
||||
ASCII(str) {
|
||||
var out = "";
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var ch = str[i];
|
||||
if ("A" <= ch && ch <= "Z") {
|
||||
ch = ch.toLowerCase();
|
||||
}
|
||||
out += ch;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
RFC1459(str) {
|
||||
var out = "";
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var ch = str[i];
|
||||
if ("A" <= ch && ch <= "Z") {
|
||||
ch = ch.toLowerCase();
|
||||
} else if (ch == "{") {
|
||||
ch = "[";
|
||||
} else if (ch == "}") {
|
||||
ch = "]";
|
||||
} else if (ch == "\\") {
|
||||
ch = "|";
|
||||
} else if (ch == "~") {
|
||||
ch = "^";
|
||||
}
|
||||
out += ch;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
RFC1459Strict(str) {
|
||||
var out = "";
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var ch = str[i];
|
||||
if ("A" <= ch && ch <= "Z") {
|
||||
ch = ch.toLowerCase();
|
||||
} else if (ch == "{") {
|
||||
ch = "[";
|
||||
} else if (ch == "}") {
|
||||
ch = "]";
|
||||
} else if (ch == "\\") {
|
||||
ch = "|";
|
||||
}
|
||||
out += ch;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
byName(name) {
|
||||
switch (name) {
|
||||
case "ascii":
|
||||
return CaseMapping.ASCII;
|
||||
case "rfc1459":
|
||||
return CaseMapping.RFC1459;
|
||||
case "rfc1459-strict":
|
||||
return CaseMapping.RFC1459Strict;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
function createIterator(next) {
|
||||
var it = { next };
|
||||
// Not defining this can lead to surprises when feeding the iterator
|
||||
// to e.g. Array.from
|
||||
it[Symbol.iterator] = () => it;
|
||||
return it;
|
||||
}
|
||||
|
||||
function mapIterator(it, f) {
|
||||
return createIterator(() => {
|
||||
var { value, done } = it.next();
|
||||
if (done) {
|
||||
return { done: true };
|
||||
}
|
||||
return { value: f(value), done: false };
|
||||
});
|
||||
}
|
||||
|
||||
export class CaseMapMap {
|
||||
caseMap = null;
|
||||
map = null;
|
||||
|
||||
constructor(iterable, cm) {
|
||||
if ((iterable instanceof CaseMapMap) && (iterable.caseMap === cm || !cm)) {
|
||||
// Fast-path if we're just cloning another CaseMapMap
|
||||
this.caseMap = iterable.caseMap;
|
||||
this.map = new Map(iterable.map);
|
||||
} else {
|
||||
if (!cm) {
|
||||
throw new Error("Missing case-mapping when creating CaseMapMap");
|
||||
}
|
||||
|
||||
this.caseMap = cm;
|
||||
this.map = new Map();
|
||||
|
||||
if (iterable) {
|
||||
for (var [key, value] of iterable) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.map.size;
|
||||
}
|
||||
|
||||
has(key) {
|
||||
return this.map.has(this.caseMap(key));
|
||||
}
|
||||
|
||||
get(key) {
|
||||
var kv = this.map.get(this.caseMap(key));
|
||||
if (kv) {
|
||||
return kv.value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this.map.set(this.caseMap(key), { key, value });
|
||||
}
|
||||
|
||||
delete(key) {
|
||||
this.map.delete(this.caseMap(key));
|
||||
}
|
||||
|
||||
entries() {
|
||||
var it = this.map.values();
|
||||
return mapIterator(it, (kv) => {
|
||||
return [kv.key, kv.value];
|
||||
});
|
||||
}
|
||||
|
||||
keys() {
|
||||
var it = this.map.values();
|
||||
return mapIterator(it, (kv) => {
|
||||
return kv.key;
|
||||
});
|
||||
}
|
||||
|
||||
values() {
|
||||
var it = this.map.values();
|
||||
return mapIterator(it, (kv) => {
|
||||
return kv.value;
|
||||
});
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.entries();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user