File size: 1,801 Bytes
2a1c46d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// entityTries.js
// Builds integer-keyed tries so the decoder never allocates a string object
// during lookup β€” every key is a plain charCode number.
//
// trie1: Map<code0, entity>
// trie2: Map<code0, Map<code1, entity>>
// trie3: Map<code0, Map<code1, Map<code2, entity>>>

import { ALL_ENTITIES } from './entities.js';

// Reverse map: character sequence β†’ "&name;"
const CHAR_TO_ENTITY = new Map();
for (const [name, chars] of Object.entries(ALL_ENTITIES)) {
  CHAR_TO_ENTITY.set(chars, `&${name};`);
}

export const trie1 = new Map();   // code0          β†’ entity string
export const trie2 = new Map();   // code0 β†’ Map    β†’ entity string
export const trie3 = new Map();   // code0 β†’ Map β†’ Map β†’ entity string

for (const [chars, entity] of CHAR_TO_ENTITY) {
  const len = chars.length;

  if (len === 1) {
    const c0 = chars.charCodeAt(0);
    // Keep shortest match only if no longer match already claimed this code
    // (longer matches are inserted in the same pass so we just overwrite β€”
    //  trie1 is only consulted after trie2/trie3 both miss, so no conflict)
    trie1.set(c0, entity);

  } else if (len === 2) {
    const c0 = chars.charCodeAt(0);
    const c1 = chars.charCodeAt(1);
    let inner = trie2.get(c0);
    if (inner === undefined) { inner = new Map(); trie2.set(c0, inner); }
    inner.set(c1, entity);

  } else if (len === 3) {
    const c0 = chars.charCodeAt(0);
    const c1 = chars.charCodeAt(1);
    const c2 = chars.charCodeAt(2);
    let mid = trie3.get(c0);
    if (mid === undefined) { mid = new Map(); trie3.set(c0, mid); }
    let inner = mid.get(c1);
    if (inner === undefined) { inner = new Map(); mid.set(c1, inner); }
    inner.set(c2, entity);
  }
  // HTML5 has no named entity whose character sequence is longer than 3 chars
}