import { printTree } from "./utils.mjs" /** * Child { * char: 'a', * children: [Child, Child], * path: null / 'full/path', * count: 0 * } */ function Child(char) { this.char = char this.children = [] this.path = null this.count = 0 } function buildChild(i, arr) { let letter = new Child(arr[0][i]) let consume = [] if (arr[0].length === i + 1) { letter.path = arr[0] letter.count += 1 } else { consume = [arr[0]] } for (let y = 1; y < arr.length; y++) { if (arr[y][i] !== letter.char) break consume.push(arr[y]) } letter.count += consume.length while (consume.length) { letter.children.push(buildChild(i + 1, consume)) consume.splice(0, letter.children[letter.children.length - 1].count) } return letter } export function buildTree(all) { let paths = Array.from(new Set(all)).sort() let builder = [] while (paths.length) { builder.push(buildChild(0, paths)) paths.splice(0, builder[builder.length - 1].count) } printTree(builder) return builder } function IfTreeBranch(branches, indent = 0) { let output = '' let indentation = ''.padStart(indent * 2) for (let i = 0; i < branches.length; i++) { let branch = branches[i] output += `${i > 0 ? 'else ': ''}if (str.charCodeAt(${indent}) === ${branch.char.charCodeAt(0)}) { // ${branch.char}` if (branch.path) { output += '\n' + indentation + ` if (str.length === ${branch.path.length}) {` output += '\n' + indentation + ` return "${branch.path}"` output += '\n' + indentation + ` }` } if (branch.children.length) { if (branch.path) { output += ' else ' } else { output += '\n' + indentation + ' ' } output += IfTreeBranch(branch.children, indent + 1) } output += '\n' + indentation + '} ' } return output } export function compileTreeIntoIfs(tree) { let output = IfTreeBranch(tree) output += '\nreturn null' return new Function('str', output) } function IfTreeBranchBuffer(branches, indent = 0) { let output = '' let indentation = ''.padStart(indent * 2) for (let i = 0; i < branches.length; i++) { let branch = branches[i] output += `${i > 0 ? 'else ': ''}if (uint[${indent}] === ${branch.char.charCodeAt(0)}) { // ${branch.char}` if (branch.path) { output += '\n' + indentation + ` if (uint.length === ${branch.path.length}) {` output += '\n' + indentation + ` return "${branch.path}"` output += '\n' + indentation + ` }` } if (branch.children.length) { if (branch.path) { output += ' else ' } else { output += '\n' + indentation + ' ' } output += IfTreeBranchBuffer(branch.children, indent + 1) } output += '\n' + indentation + '} ' } return output } export function compileTreeIntoIfsWithBuffer(tree) { let output = `var uint = Buffer.from(str)\n` output += IfTreeBranchBuffer(tree) output += '\nreturn null' return new Function('str', output) }