You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.6 KiB
117 lines
3.6 KiB
"use strict"; |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
exports.flattenToTrieRefNodeArray = exports.flattenToTrieRefNodeIterable = exports.flattenToTrieRefNode = void 0; |
|
function flattenToTrieRefNode(root, nodes) { |
|
const signatures = new Map(); |
|
const cached = new Set([0]); // The end of word is always a 0 and is always cached. |
|
function canCache(n) { |
|
if (!n.r) |
|
return true; |
|
for (const v of n.r) { |
|
if (!cached.has(v[1])) |
|
return false; |
|
} |
|
return true; |
|
} |
|
function convert(n) { |
|
const r = copy(n); |
|
if (n.c) { |
|
const children = [...n.c].sort((a, b) => (a[0] < b[0] ? -1 : 1)); |
|
r.r = children.map((c) => [c[0], convert(c[1])]); |
|
} |
|
if (!canCache(r)) { |
|
return nodes.push(r) - 1; |
|
} |
|
const sig = signature(r); |
|
const ref = signatures.get(sig); |
|
if (ref !== undefined) { |
|
cached.add(ref); |
|
return ref; |
|
} |
|
const idx = nodes.push(r) - 1; |
|
signatures.set(sig, idx); |
|
return idx; |
|
} |
|
return convert(root); |
|
} |
|
exports.flattenToTrieRefNode = flattenToTrieRefNode; |
|
function flattenToTrieRefNodeIterable(root) { |
|
const signatures = new Map(); |
|
const cached = new Set([0]); // The end of word is always a 0 and is always cached. |
|
function canCache(n) { |
|
if (!n.r) |
|
return true; |
|
for (const v of n.r) { |
|
if (!cached.has(v[1])) |
|
return false; |
|
} |
|
return true; |
|
} |
|
function* convert(root) { |
|
const stack = []; |
|
function addToStack(c, p) { |
|
if (!c) |
|
return; |
|
const children = [...c.entries()] |
|
.map(([k, n]) => ({ k, n, p, r: undefined })) |
|
.sort((a, b) => (a.k < b.k ? 1 : -1)); |
|
stack.push(...children); |
|
} |
|
const r = copy(root); |
|
addToStack(root.c, r); |
|
let t; |
|
let count = 0; |
|
function calcRef(r) { |
|
if (!canCache(r)) { |
|
return { ref: count++, emit: true }; |
|
} |
|
const sig = signature(r); |
|
const ref = signatures.get(sig); |
|
if (ref !== undefined) { |
|
cached.add(ref); |
|
return { ref, emit: false }; |
|
} |
|
const idx = count++; |
|
signatures.set(sig, idx); |
|
return { ref: idx, emit: true }; |
|
} |
|
while ((t = stack.pop())) { |
|
if (t.r) { |
|
// We are on the way out. |
|
const ref = calcRef(t.r); |
|
t.p.r = t.p.r || []; |
|
t.p.r.push([t.k, ref.ref]); |
|
if (ref.emit) { |
|
yield t.r; |
|
} |
|
} |
|
else { |
|
// Going deeper |
|
t.r = copy(t.n); |
|
stack.push(t); |
|
addToStack(t.n.c, t.r); |
|
} |
|
} |
|
const ref = calcRef(r); |
|
if (ref.emit) { |
|
yield r; |
|
} |
|
} |
|
return convert(root); |
|
} |
|
exports.flattenToTrieRefNodeIterable = flattenToTrieRefNodeIterable; |
|
function flattenToTrieRefNodeArray(root) { |
|
const nodes = []; |
|
flattenToTrieRefNode(root, nodes); |
|
return nodes; |
|
} |
|
exports.flattenToTrieRefNodeArray = flattenToTrieRefNodeArray; |
|
function signature(n) { |
|
const refs = n.r ? JSON.stringify(n.r) : ''; |
|
const isWord = n.f ? '*' : ''; |
|
return isWord + refs; |
|
} |
|
function copy(n) { |
|
return n.f ? { f: n.f, r: undefined } : { f: undefined, r: undefined }; |
|
} |
|
//# sourceMappingURL=flatten.js.map
|