(mapper: (codePoint: number) => string)
| 82 | } |
| 83 | |
| 84 | export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: string) => string { |
| 85 | const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); |
| 86 | |
| 87 | return function stringConcatMap_inner(s: string): string { |
| 88 | let cs: string[] | null = null; |
| 89 | let start = 0; |
| 90 | let i = 0; |
| 91 | while (i < s.length) { |
| 92 | let cc = s.charCodeAt(i); |
| 93 | if (!charNoEscapeMap[cc]) { |
| 94 | if (cs === null) cs = []; |
| 95 | cs.push(s.substring(start, i)); |
| 96 | |
| 97 | if (isHighSurrogate(cc)) { |
| 98 | const highSurrogate = cc; |
| 99 | i++; |
| 100 | const lowSurrogate = s.charCodeAt(i); |
| 101 | assert(isLowSurrogate(lowSurrogate), "High surrogate not followed by low surrogate"); |
| 102 | const highBits = highSurrogate - 0xd800; |
| 103 | const lowBits = lowSurrogate - 0xdc00; |
| 104 | cc = 0x10000 + lowBits + (highBits << 10); |
| 105 | } |
| 106 | |
| 107 | const str = charStringMap[cc]; |
| 108 | if (str === undefined) { |
| 109 | cs.push(mapper(cc)); |
| 110 | } else { |
| 111 | cs.push(str); |
| 112 | } |
| 113 | |
| 114 | start = i + 1; |
| 115 | } |
| 116 | i++; |
| 117 | } |
| 118 | |
| 119 | if (cs === null) return s; |
| 120 | |
| 121 | cs.push(s.substring(start, i)); |
| 122 | |
| 123 | return cs.join(""); |
| 124 | }; |
| 125 | } |
| 126 | |
| 127 | export function utf16LegalizeCharacters(isLegal: (utf16Unit: number) => boolean): (s: string) => string { |
| 128 | return utf16ConcatMap(u => (isLegal(u) ? String.fromCharCode(u) : "")); |
no test coverage detected
searching dependent graphs…