[79a0317] | 1 | "use strict";
|
---|
| 2 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
| 3 | exports.serializeBase64 = exports.TrieBuilder = exports.BITS_32 = exports.BITS_16 = void 0;
|
---|
| 4 | var Trie_1 = require("./Trie");
|
---|
| 5 | var base64_arraybuffer_1 = require("base64-arraybuffer");
|
---|
| 6 | /**
|
---|
| 7 | * Trie2 constants, defining shift widths, index array lengths, etc.
|
---|
| 8 | *
|
---|
| 9 | * These are needed for the runtime macros but users can treat these as
|
---|
| 10 | * implementation details and skip to the actual public API further below.
|
---|
| 11 | */
|
---|
| 12 | // const UTRIE2_OPTIONS_VALUE_BITS_MASK = 0x000f;
|
---|
| 13 | /** Number of code points per index-1 table entry. 2048=0x800 */
|
---|
| 14 | var UTRIE2_CP_PER_INDEX_1_ENTRY = 1 << Trie_1.UTRIE2_SHIFT_1;
|
---|
| 15 | /** The alignment size of a data block. Also the granularity for compaction. */
|
---|
| 16 | var UTRIE2_DATA_GRANULARITY = 1 << Trie_1.UTRIE2_INDEX_SHIFT;
|
---|
| 17 | /* Fixed layout of the first part of the index array. ------------------- */
|
---|
| 18 | /**
|
---|
| 19 | * The BMP part of the index-2 table is fixed and linear and starts at offset 0.
|
---|
| 20 | * Length=2048=0x800=0x10000>>UTRIE2_SHIFT_2.
|
---|
| 21 | */
|
---|
| 22 | var UTRIE2_INDEX_2_OFFSET = 0;
|
---|
| 23 | var UTRIE2_MAX_INDEX_1_LENGTH = 0x100000 >> Trie_1.UTRIE2_SHIFT_1;
|
---|
| 24 | /*
|
---|
| 25 | * Fixed layout of the first part of the data array. -----------------------
|
---|
| 26 | * Starts with 4 blocks (128=0x80 entries) for ASCII.
|
---|
| 27 | */
|
---|
| 28 | /**
|
---|
| 29 | * The illegal-UTF-8 data block follows the ASCII block, at offset 128=0x80.
|
---|
| 30 | * Used with linear access for single bytes 0..0xbf for simple error handling.
|
---|
| 31 | * Length 64=0x40, not UTRIE2_DATA_BLOCK_LENGTH.
|
---|
| 32 | */
|
---|
| 33 | var UTRIE2_BAD_UTF8_DATA_OFFSET = 0x80;
|
---|
| 34 | /** The start of non-linear-ASCII data blocks, at offset 192=0xc0. */
|
---|
| 35 | var UTRIE2_DATA_START_OFFSET = 0xc0;
|
---|
| 36 | /* Building a Trie2 ---------------------------------------------------------- */
|
---|
| 37 | /*
|
---|
| 38 | * These definitions are mostly needed by utrie2_builder.c, but also by
|
---|
| 39 | * utrie2_get32() and utrie2_enum().
|
---|
| 40 | */
|
---|
| 41 | /*
|
---|
| 42 | * At build time, leave a gap in the index-2 table,
|
---|
| 43 | * at least as long as the maximum lengths of the 2-byte UTF-8 index-2 table
|
---|
| 44 | * and the supplementary index-1 table.
|
---|
| 45 | * Round up to UTRIE2_INDEX_2_BLOCK_LENGTH for proper compacting.
|
---|
| 46 | */
|
---|
| 47 | var UNEWTRIE2_INDEX_GAP_OFFSET = Trie_1.UTRIE2_INDEX_2_BMP_LENGTH;
|
---|
| 48 | var UNEWTRIE2_INDEX_GAP_LENGTH = (Trie_1.UTRIE2_UTF8_2B_INDEX_2_LENGTH + UTRIE2_MAX_INDEX_1_LENGTH + Trie_1.UTRIE2_INDEX_2_MASK) & ~Trie_1.UTRIE2_INDEX_2_MASK;
|
---|
| 49 | /**
|
---|
| 50 | * Maximum length of the build-time index-2 array.
|
---|
| 51 | * Maximum number of Unicode code points (0x110000) shifted right by UTRIE2_SHIFT_2,
|
---|
| 52 | * plus the part of the index-2 table for lead surrogate code points,
|
---|
| 53 | * plus the build-time index gap,
|
---|
| 54 | * plus the null index-2 block.
|
---|
| 55 | */
|
---|
| 56 | var UNEWTRIE2_MAX_INDEX_2_LENGTH = (0x110000 >> Trie_1.UTRIE2_SHIFT_2) +
|
---|
| 57 | Trie_1.UTRIE2_LSCP_INDEX_2_LENGTH +
|
---|
| 58 | UNEWTRIE2_INDEX_GAP_LENGTH +
|
---|
| 59 | Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH;
|
---|
| 60 | var UNEWTRIE2_INDEX_1_LENGTH = 0x110000 >> Trie_1.UTRIE2_SHIFT_1;
|
---|
| 61 | /**
|
---|
| 62 | * Maximum length of the build-time data array.
|
---|
| 63 | * One entry per 0x110000 code points, plus the illegal-UTF-8 block and the null block,
|
---|
| 64 | * plus values for the 0x400 surrogate code units.
|
---|
| 65 | */
|
---|
| 66 | var UNEWTRIE2_MAX_DATA_LENGTH = 0x110000 + 0x40 + 0x40 + 0x400;
|
---|
| 67 | /* Start with allocation of 16k data entries. */
|
---|
| 68 | var UNEWTRIE2_INITIAL_DATA_LENGTH = 1 << 14;
|
---|
| 69 | /* Grow about 8x each time. */
|
---|
| 70 | var UNEWTRIE2_MEDIUM_DATA_LENGTH = 1 << 17;
|
---|
| 71 | /** The null index-2 block, following the gap in the index-2 table. */
|
---|
| 72 | var UNEWTRIE2_INDEX_2_NULL_OFFSET = UNEWTRIE2_INDEX_GAP_OFFSET + UNEWTRIE2_INDEX_GAP_LENGTH;
|
---|
| 73 | /** The start of allocated index-2 blocks. */
|
---|
| 74 | var UNEWTRIE2_INDEX_2_START_OFFSET = UNEWTRIE2_INDEX_2_NULL_OFFSET + Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH;
|
---|
| 75 | /**
|
---|
| 76 | * The null data block.
|
---|
| 77 | * Length 64=0x40 even if UTRIE2_DATA_BLOCK_LENGTH is smaller,
|
---|
| 78 | * to work with 6-bit trail bytes from 2-byte UTF-8.
|
---|
| 79 | */
|
---|
| 80 | var UNEWTRIE2_DATA_NULL_OFFSET = UTRIE2_DATA_START_OFFSET;
|
---|
| 81 | /** The start of allocated data blocks. */
|
---|
| 82 | var UNEWTRIE2_DATA_START_OFFSET = UNEWTRIE2_DATA_NULL_OFFSET + 0x40;
|
---|
| 83 | /**
|
---|
| 84 | * The start of data blocks for U+0800 and above.
|
---|
| 85 | * Below, compaction uses a block length of 64 for 2-byte UTF-8.
|
---|
| 86 | * From here on, compaction uses UTRIE2_DATA_BLOCK_LENGTH.
|
---|
| 87 | * Data values for 0x780 code points beyond ASCII.
|
---|
| 88 | */
|
---|
| 89 | var UNEWTRIE2_DATA_0800_OFFSET = UNEWTRIE2_DATA_START_OFFSET + 0x780;
|
---|
| 90 | /**
|
---|
| 91 | * Maximum length of the runtime index array.
|
---|
| 92 | * Limited by its own 16-bit index values, and by uint16_t UTrie2Header.indexLength.
|
---|
| 93 | * (The actual maximum length is lower,
|
---|
| 94 | * (0x110000>>UTRIE2_SHIFT_2)+UTRIE2_UTF8_2B_INDEX_2_LENGTH+UTRIE2_MAX_INDEX_1_LENGTH.)
|
---|
| 95 | */
|
---|
| 96 | var UTRIE2_MAX_INDEX_LENGTH = 0xffff;
|
---|
| 97 | /**
|
---|
| 98 | * Maximum length of the runtime data array.
|
---|
| 99 | * Limited by 16-bit index values that are left-shifted by UTRIE2_INDEX_SHIFT,
|
---|
| 100 | * and by uint16_t UTrie2Header.shiftedDataLength.
|
---|
| 101 | */
|
---|
| 102 | var UTRIE2_MAX_DATA_LENGTH = 0xffff << Trie_1.UTRIE2_INDEX_SHIFT;
|
---|
| 103 | exports.BITS_16 = 16;
|
---|
| 104 | exports.BITS_32 = 32;
|
---|
| 105 | var isHighSurrogate = function (c) { return c >= 0xd800 && c <= 0xdbff; };
|
---|
| 106 | var equalInt = function (a, s, t, length) {
|
---|
| 107 | for (var i = 0; i < length; i++) {
|
---|
| 108 | if (a[s + i] !== a[t + i]) {
|
---|
| 109 | return false;
|
---|
| 110 | }
|
---|
| 111 | }
|
---|
| 112 | return true;
|
---|
| 113 | };
|
---|
| 114 | var TrieBuilder = /** @class */ (function () {
|
---|
| 115 | function TrieBuilder(initialValue, errorValue) {
|
---|
| 116 | if (initialValue === void 0) { initialValue = 0; }
|
---|
| 117 | if (errorValue === void 0) { errorValue = 0; }
|
---|
| 118 | this.initialValue = initialValue;
|
---|
| 119 | this.errorValue = errorValue;
|
---|
| 120 | this.highStart = 0x110000;
|
---|
| 121 | this.data = new Uint32Array(UNEWTRIE2_INITIAL_DATA_LENGTH);
|
---|
| 122 | this.dataCapacity = UNEWTRIE2_INITIAL_DATA_LENGTH;
|
---|
| 123 | this.highStart = 0x110000;
|
---|
| 124 | this.firstFreeBlock = 0; /* no free block in the list */
|
---|
| 125 | this.isCompacted = false;
|
---|
| 126 | this.index1 = new Uint32Array(UNEWTRIE2_INDEX_1_LENGTH);
|
---|
| 127 | this.index2 = new Uint32Array(UNEWTRIE2_MAX_INDEX_2_LENGTH);
|
---|
| 128 | /*
|
---|
| 129 | * Multi-purpose per-data-block table.
|
---|
| 130 | *
|
---|
| 131 | * Before compacting:
|
---|
| 132 | *
|
---|
| 133 | * Per-data-block reference counters/free-block list.
|
---|
| 134 | * 0: unused
|
---|
| 135 | * >0: reference counter (number of index-2 entries pointing here)
|
---|
| 136 | * <0: next free data block in free-block list
|
---|
| 137 | *
|
---|
| 138 | * While compacting:
|
---|
| 139 | *
|
---|
| 140 | * Map of adjusted indexes, used in compactData() and compactIndex2().
|
---|
| 141 | * Maps from original indexes to new ones.
|
---|
| 142 | */
|
---|
| 143 | this.map = new Uint32Array(UNEWTRIE2_MAX_DATA_LENGTH >> Trie_1.UTRIE2_SHIFT_2);
|
---|
| 144 | /*
|
---|
| 145 | * preallocate and reset
|
---|
| 146 | * - ASCII
|
---|
| 147 | * - the bad-UTF-8-data block
|
---|
| 148 | * - the null data block
|
---|
| 149 | */
|
---|
| 150 | var i, j;
|
---|
| 151 | for (i = 0; i < 0x80; ++i) {
|
---|
| 152 | this.data[i] = initialValue;
|
---|
| 153 | }
|
---|
| 154 | for (; i < 0xc0; ++i) {
|
---|
| 155 | this.data[i] = errorValue;
|
---|
| 156 | }
|
---|
| 157 | for (i = UNEWTRIE2_DATA_NULL_OFFSET; i < UNEWTRIE2_DATA_START_OFFSET; ++i) {
|
---|
| 158 | this.data[i] = initialValue;
|
---|
| 159 | }
|
---|
| 160 | this.dataNullOffset = UNEWTRIE2_DATA_NULL_OFFSET;
|
---|
| 161 | this.dataLength = UNEWTRIE2_DATA_START_OFFSET;
|
---|
| 162 | /* set the index-2 indexes for the 2=0x80>>UTRIE2_SHIFT_2 ASCII data blocks */
|
---|
| 163 | for (i = 0, j = 0; j < 0x80; ++i, j += Trie_1.UTRIE2_DATA_BLOCK_LENGTH) {
|
---|
| 164 | this.index2[i] = j;
|
---|
| 165 | this.map[i] = 1;
|
---|
| 166 | }
|
---|
| 167 | /* reference counts for the bad-UTF-8-data block */
|
---|
| 168 | for (; j < 0xc0; ++i, j += Trie_1.UTRIE2_DATA_BLOCK_LENGTH) {
|
---|
| 169 | this.map[i] = 0;
|
---|
| 170 | }
|
---|
| 171 | /*
|
---|
| 172 | * Reference counts for the null data block: all blocks except for the ASCII blocks.
|
---|
| 173 | * Plus 1 so that we don't drop this block during compaction.
|
---|
| 174 | * Plus as many as needed for lead surrogate code points.
|
---|
| 175 | */
|
---|
| 176 | /* i==newTrie->dataNullOffset */
|
---|
| 177 | this.map[i++] = (0x110000 >> Trie_1.UTRIE2_SHIFT_2) - (0x80 >> Trie_1.UTRIE2_SHIFT_2) + 1 + Trie_1.UTRIE2_LSCP_INDEX_2_LENGTH;
|
---|
| 178 | j += Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 179 | for (; j < UNEWTRIE2_DATA_START_OFFSET; ++i, j += Trie_1.UTRIE2_DATA_BLOCK_LENGTH) {
|
---|
| 180 | this.map[i] = 0;
|
---|
| 181 | }
|
---|
| 182 | /*
|
---|
| 183 | * set the remaining indexes in the BMP index-2 block
|
---|
| 184 | * to the null data block
|
---|
| 185 | */
|
---|
| 186 | for (i = 0x80 >> Trie_1.UTRIE2_SHIFT_2; i < Trie_1.UTRIE2_INDEX_2_BMP_LENGTH; ++i) {
|
---|
| 187 | this.index2[i] = UNEWTRIE2_DATA_NULL_OFFSET;
|
---|
| 188 | }
|
---|
| 189 | /*
|
---|
| 190 | * Fill the index gap with impossible values so that compaction
|
---|
| 191 | * does not overlap other index-2 blocks with the gap.
|
---|
| 192 | */
|
---|
| 193 | for (i = 0; i < UNEWTRIE2_INDEX_GAP_LENGTH; ++i) {
|
---|
| 194 | this.index2[UNEWTRIE2_INDEX_GAP_OFFSET + i] = -1;
|
---|
| 195 | }
|
---|
| 196 | /* set the indexes in the null index-2 block */
|
---|
| 197 | for (i = 0; i < Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH; ++i) {
|
---|
| 198 | this.index2[UNEWTRIE2_INDEX_2_NULL_OFFSET + i] = UNEWTRIE2_DATA_NULL_OFFSET;
|
---|
| 199 | }
|
---|
| 200 | this.index2NullOffset = UNEWTRIE2_INDEX_2_NULL_OFFSET;
|
---|
| 201 | this.index2Length = UNEWTRIE2_INDEX_2_START_OFFSET;
|
---|
| 202 | /* set the index-1 indexes for the linear index-2 block */
|
---|
| 203 | for (i = 0, j = 0; i < Trie_1.UTRIE2_OMITTED_BMP_INDEX_1_LENGTH; ++i, j += Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH) {
|
---|
| 204 | this.index1[i] = j;
|
---|
| 205 | }
|
---|
| 206 | /* set the remaining index-1 indexes to the null index-2 block */
|
---|
| 207 | for (; i < UNEWTRIE2_INDEX_1_LENGTH; ++i) {
|
---|
| 208 | this.index1[i] = UNEWTRIE2_INDEX_2_NULL_OFFSET;
|
---|
| 209 | }
|
---|
| 210 | /*
|
---|
| 211 | * Preallocate and reset data for U+0080..U+07ff,
|
---|
| 212 | * for 2-byte UTF-8 which will be compacted in 64-blocks
|
---|
| 213 | * even if UTRIE2_DATA_BLOCK_LENGTH is smaller.
|
---|
| 214 | */
|
---|
| 215 | for (i = 0x80; i < 0x800; i += Trie_1.UTRIE2_DATA_BLOCK_LENGTH) {
|
---|
| 216 | this.set(i, initialValue);
|
---|
| 217 | }
|
---|
| 218 | }
|
---|
| 219 | /**
|
---|
| 220 | * Set a value for a code point.
|
---|
| 221 | *
|
---|
| 222 | * @param c the code point
|
---|
| 223 | * @param value the value
|
---|
| 224 | */
|
---|
| 225 | TrieBuilder.prototype.set = function (c, value) {
|
---|
| 226 | if (c < 0 || c > 0x10ffff) {
|
---|
| 227 | throw new Error('Invalid code point.');
|
---|
| 228 | }
|
---|
| 229 | this._set(c, true, value);
|
---|
| 230 | return this;
|
---|
| 231 | };
|
---|
| 232 | /**
|
---|
| 233 | * Set a value in a range of code points [start..end].
|
---|
| 234 | * All code points c with start<=c<=end will get the value if
|
---|
| 235 | * overwrite is TRUE or if the old value is the initial value.
|
---|
| 236 | *
|
---|
| 237 | * @param start the first code point to get the value
|
---|
| 238 | * @param end the last code point to get the value (inclusive)
|
---|
| 239 | * @param value the value
|
---|
| 240 | * @param overwrite flag for whether old non-initial values are to be overwritten
|
---|
| 241 | */
|
---|
| 242 | TrieBuilder.prototype.setRange = function (start, end, value, overwrite) {
|
---|
| 243 | if (overwrite === void 0) { overwrite = false; }
|
---|
| 244 | /*
|
---|
| 245 | * repeat value in [start..end]
|
---|
| 246 | * mark index values for repeat-data blocks by setting bit 31 of the index values
|
---|
| 247 | * fill around existing values if any, if(overwrite)
|
---|
| 248 | */
|
---|
| 249 | var block, rest, repeatBlock;
|
---|
| 250 | if (start > 0x10ffff || start < 0 || end > 0x10ffff || end < 0 || start > end) {
|
---|
| 251 | throw new Error('Invalid code point range.');
|
---|
| 252 | }
|
---|
| 253 | if (!overwrite && value === this.initialValue) {
|
---|
| 254 | return this; /* nothing to do */
|
---|
| 255 | }
|
---|
| 256 | if (this.isCompacted) {
|
---|
| 257 | throw new Error('Trie was already compacted');
|
---|
| 258 | }
|
---|
| 259 | var limit = end + 1;
|
---|
| 260 | if ((start & Trie_1.UTRIE2_DATA_MASK) !== 0) {
|
---|
| 261 | /* set partial block at [start..following block boundary[ */
|
---|
| 262 | block = this.getDataBlock(start, true);
|
---|
| 263 | var nextStart = (start + Trie_1.UTRIE2_DATA_BLOCK_LENGTH) & ~Trie_1.UTRIE2_DATA_MASK;
|
---|
| 264 | if (nextStart <= limit) {
|
---|
| 265 | this.fillBlock(block, start & Trie_1.UTRIE2_DATA_MASK, Trie_1.UTRIE2_DATA_BLOCK_LENGTH, value, this.initialValue, overwrite);
|
---|
| 266 | start = nextStart;
|
---|
| 267 | }
|
---|
| 268 | else {
|
---|
| 269 | this.fillBlock(block, start & Trie_1.UTRIE2_DATA_MASK, limit & Trie_1.UTRIE2_DATA_MASK, value, this.initialValue, overwrite);
|
---|
| 270 | return this;
|
---|
| 271 | }
|
---|
| 272 | }
|
---|
| 273 | /* number of positions in the last, partial block */
|
---|
| 274 | rest = limit & Trie_1.UTRIE2_DATA_MASK;
|
---|
| 275 | /* round down limit to a block boundary */
|
---|
| 276 | limit &= ~Trie_1.UTRIE2_DATA_MASK;
|
---|
| 277 | /* iterate over all-value blocks */
|
---|
| 278 | repeatBlock = value === this.initialValue ? this.dataNullOffset : -1;
|
---|
| 279 | while (start < limit) {
|
---|
| 280 | var i2 = void 0;
|
---|
| 281 | var setRepeatBlock = false;
|
---|
| 282 | if (value === this.initialValue && this.isInNullBlock(start, true)) {
|
---|
| 283 | start += Trie_1.UTRIE2_DATA_BLOCK_LENGTH; /* nothing to do */
|
---|
| 284 | continue;
|
---|
| 285 | }
|
---|
| 286 | /* get index value */
|
---|
| 287 | i2 = this.getIndex2Block(start, true);
|
---|
| 288 | i2 += (start >> Trie_1.UTRIE2_SHIFT_2) & Trie_1.UTRIE2_INDEX_2_MASK;
|
---|
| 289 | block = this.index2[i2];
|
---|
| 290 | if (this.isWritableBlock(block)) {
|
---|
| 291 | /* already allocated */
|
---|
| 292 | if (overwrite && block >= UNEWTRIE2_DATA_0800_OFFSET) {
|
---|
| 293 | /*
|
---|
| 294 | * We overwrite all values, and it's not a
|
---|
| 295 | * protected (ASCII-linear or 2-byte UTF-8) block:
|
---|
| 296 | * replace with the repeatBlock.
|
---|
| 297 | */
|
---|
| 298 | setRepeatBlock = true;
|
---|
| 299 | }
|
---|
| 300 | else {
|
---|
| 301 | /* !overwrite, or protected block: just write the values into this block */
|
---|
| 302 | this.fillBlock(block, 0, Trie_1.UTRIE2_DATA_BLOCK_LENGTH, value, this.initialValue, overwrite);
|
---|
| 303 | }
|
---|
| 304 | }
|
---|
| 305 | else if (this.data[block] !== value && (overwrite || block === this.dataNullOffset)) {
|
---|
| 306 | /*
|
---|
| 307 | * Set the repeatBlock instead of the null block or previous repeat block:
|
---|
| 308 | *
|
---|
| 309 | * If !isWritableBlock() then all entries in the block have the same value
|
---|
| 310 | * because it's the null block or a range block (the repeatBlock from a previous
|
---|
| 311 | * call to utrie2_setRange32()).
|
---|
| 312 | * No other blocks are used multiple times before compacting.
|
---|
| 313 | *
|
---|
| 314 | * The null block is the only non-writable block with the initialValue because
|
---|
| 315 | * of the repeatBlock initialization above. (If value==initialValue, then
|
---|
| 316 | * the repeatBlock will be the null data block.)
|
---|
| 317 | *
|
---|
| 318 | * We set our repeatBlock if the desired value differs from the block's value,
|
---|
| 319 | * and if we overwrite any data or if the data is all initial values
|
---|
| 320 | * (which is the same as the block being the null block, see above).
|
---|
| 321 | */
|
---|
| 322 | setRepeatBlock = true;
|
---|
| 323 | }
|
---|
| 324 | if (setRepeatBlock) {
|
---|
| 325 | if (repeatBlock >= 0) {
|
---|
| 326 | this.setIndex2Entry(i2, repeatBlock);
|
---|
| 327 | }
|
---|
| 328 | else {
|
---|
| 329 | /* create and set and fill the repeatBlock */
|
---|
| 330 | repeatBlock = this.getDataBlock(start, true);
|
---|
| 331 | this.writeBlock(repeatBlock, value);
|
---|
| 332 | }
|
---|
| 333 | }
|
---|
| 334 | start += Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 335 | }
|
---|
| 336 | if (rest > 0) {
|
---|
| 337 | /* set partial block at [last block boundary..limit[ */
|
---|
| 338 | block = this.getDataBlock(start, true);
|
---|
| 339 | this.fillBlock(block, 0, rest, value, this.initialValue, overwrite);
|
---|
| 340 | }
|
---|
| 341 | return this;
|
---|
| 342 | };
|
---|
| 343 | /**
|
---|
| 344 | * Get the value for a code point as stored in the Trie2.
|
---|
| 345 | *
|
---|
| 346 | * @param codePoint the code point
|
---|
| 347 | * @return the value
|
---|
| 348 | */
|
---|
| 349 | TrieBuilder.prototype.get = function (codePoint) {
|
---|
| 350 | if (codePoint < 0 || codePoint > 0x10ffff) {
|
---|
| 351 | return this.errorValue;
|
---|
| 352 | }
|
---|
| 353 | else {
|
---|
| 354 | return this._get(codePoint, true);
|
---|
| 355 | }
|
---|
| 356 | };
|
---|
| 357 | TrieBuilder.prototype._get = function (c, fromLSCP) {
|
---|
| 358 | var i2;
|
---|
| 359 | if (c >= this.highStart && (!(c >= 0xd800 && c < 0xdc00) || fromLSCP)) {
|
---|
| 360 | return this.data[this.dataLength - UTRIE2_DATA_GRANULARITY];
|
---|
| 361 | }
|
---|
| 362 | if (c >= 0xd800 && c < 0xdc00 && fromLSCP) {
|
---|
| 363 | i2 = Trie_1.UTRIE2_LSCP_INDEX_2_OFFSET - (0xd800 >> Trie_1.UTRIE2_SHIFT_2) + (c >> Trie_1.UTRIE2_SHIFT_2);
|
---|
| 364 | }
|
---|
| 365 | else {
|
---|
| 366 | i2 = this.index1[c >> Trie_1.UTRIE2_SHIFT_1] + ((c >> Trie_1.UTRIE2_SHIFT_2) & Trie_1.UTRIE2_INDEX_2_MASK);
|
---|
| 367 | }
|
---|
| 368 | var block = this.index2[i2];
|
---|
| 369 | return this.data[block + (c & Trie_1.UTRIE2_DATA_MASK)];
|
---|
| 370 | };
|
---|
| 371 | TrieBuilder.prototype.freeze = function (valueBits) {
|
---|
| 372 | if (valueBits === void 0) { valueBits = exports.BITS_32; }
|
---|
| 373 | var i;
|
---|
| 374 | var allIndexesLength;
|
---|
| 375 | var dataMove; /* >0 if the data is moved to the end of the index array */
|
---|
| 376 | /* compact if necessary */
|
---|
| 377 | if (!this.isCompacted) {
|
---|
| 378 | this.compactTrie();
|
---|
| 379 | }
|
---|
| 380 | allIndexesLength = this.highStart <= 0x10000 ? Trie_1.UTRIE2_INDEX_1_OFFSET : this.index2Length;
|
---|
| 381 | if (valueBits === exports.BITS_16) {
|
---|
| 382 | // dataMove = allIndexesLength;
|
---|
| 383 | dataMove = 0;
|
---|
| 384 | }
|
---|
| 385 | else {
|
---|
| 386 | dataMove = 0;
|
---|
| 387 | }
|
---|
| 388 | /* are indexLength and dataLength within limits? */
|
---|
| 389 | if (
|
---|
| 390 | /* for unshifted indexLength */
|
---|
| 391 | allIndexesLength > UTRIE2_MAX_INDEX_LENGTH ||
|
---|
| 392 | /* for unshifted dataNullOffset */
|
---|
| 393 | dataMove + this.dataNullOffset > 0xffff ||
|
---|
| 394 | /* for unshifted 2-byte UTF-8 index-2 values */
|
---|
| 395 | dataMove + UNEWTRIE2_DATA_0800_OFFSET > 0xffff ||
|
---|
| 396 | /* for shiftedDataLength */
|
---|
| 397 | dataMove + this.dataLength > UTRIE2_MAX_DATA_LENGTH) {
|
---|
| 398 | throw new Error('Trie data is too large.');
|
---|
| 399 | }
|
---|
| 400 | var index = new Uint16Array(allIndexesLength);
|
---|
| 401 | /* write the index-2 array values shifted right by UTRIE2_INDEX_SHIFT, after adding dataMove */
|
---|
| 402 | var destIdx = 0;
|
---|
| 403 | for (i = 0; i < Trie_1.UTRIE2_INDEX_2_BMP_LENGTH; i++) {
|
---|
| 404 | index[destIdx++] = (this.index2[i] + dataMove) >> Trie_1.UTRIE2_INDEX_SHIFT;
|
---|
| 405 | }
|
---|
| 406 | /* write UTF-8 2-byte index-2 values, not right-shifted */
|
---|
| 407 | for (i = 0; i < 0xc2 - 0xc0; ++i) {
|
---|
| 408 | /* C0..C1 */
|
---|
| 409 | index[destIdx++] = dataMove + UTRIE2_BAD_UTF8_DATA_OFFSET;
|
---|
| 410 | }
|
---|
| 411 | for (; i < 0xe0 - 0xc0; ++i) {
|
---|
| 412 | /* C2..DF */
|
---|
| 413 | index[destIdx++] = dataMove + this.index2[i << (6 - Trie_1.UTRIE2_SHIFT_2)];
|
---|
| 414 | }
|
---|
| 415 | if (this.highStart > 0x10000) {
|
---|
| 416 | var index1Length = (this.highStart - 0x10000) >> Trie_1.UTRIE2_SHIFT_1;
|
---|
| 417 | var index2Offset = Trie_1.UTRIE2_INDEX_2_BMP_LENGTH + Trie_1.UTRIE2_UTF8_2B_INDEX_2_LENGTH + index1Length;
|
---|
| 418 | /* write 16-bit index-1 values for supplementary code points */
|
---|
| 419 | for (i = 0; i < index1Length; i++) {
|
---|
| 420 | index[destIdx++] = UTRIE2_INDEX_2_OFFSET + this.index1[i + Trie_1.UTRIE2_OMITTED_BMP_INDEX_1_LENGTH];
|
---|
| 421 | }
|
---|
| 422 | /*
|
---|
| 423 | * write the index-2 array values for supplementary code points,
|
---|
| 424 | * shifted right by UTRIE2_INDEX_SHIFT, after adding dataMove
|
---|
| 425 | */
|
---|
| 426 | for (i = 0; i < this.index2Length - index2Offset; i++) {
|
---|
| 427 | index[destIdx++] = (dataMove + this.index2[index2Offset + i]) >> Trie_1.UTRIE2_INDEX_SHIFT;
|
---|
| 428 | }
|
---|
| 429 | }
|
---|
| 430 | /* write the 16/32-bit data array */
|
---|
| 431 | switch (valueBits) {
|
---|
| 432 | case exports.BITS_16:
|
---|
| 433 | /* write 16-bit data values */
|
---|
| 434 | var data16 = new Uint16Array(this.dataLength);
|
---|
| 435 | for (i = 0; i < this.dataLength; i++) {
|
---|
| 436 | data16[i] = this.data[i];
|
---|
| 437 | }
|
---|
| 438 | return new Trie_1.Trie(this.initialValue, this.errorValue, this.highStart, dataMove + this.dataLength - UTRIE2_DATA_GRANULARITY, index, data16);
|
---|
| 439 | case exports.BITS_32:
|
---|
| 440 | /* write 32-bit data values */
|
---|
| 441 | var data32 = new Uint32Array(this.dataLength);
|
---|
| 442 | for (i = 0; i < this.dataLength; i++) {
|
---|
| 443 | data32[i] = this.data[i];
|
---|
| 444 | }
|
---|
| 445 | return new Trie_1.Trie(this.initialValue, this.errorValue, this.highStart, dataMove + this.dataLength - UTRIE2_DATA_GRANULARITY, index, data32);
|
---|
| 446 | default:
|
---|
| 447 | throw new Error('Bits should be either 16 or 32');
|
---|
| 448 | }
|
---|
| 449 | };
|
---|
| 450 | /*
|
---|
| 451 | * Find the start of the last range in the trie by enumerating backward.
|
---|
| 452 | * Indexes for supplementary code points higher than this will be omitted.
|
---|
| 453 | */
|
---|
| 454 | TrieBuilder.prototype.findHighStart = function (highValue) {
|
---|
| 455 | var value;
|
---|
| 456 | var i2, j, i2Block, prevI2Block, block, prevBlock;
|
---|
| 457 | /* set variables for previous range */
|
---|
| 458 | if (highValue === this.initialValue) {
|
---|
| 459 | prevI2Block = this.index2NullOffset;
|
---|
| 460 | prevBlock = this.dataNullOffset;
|
---|
| 461 | }
|
---|
| 462 | else {
|
---|
| 463 | prevI2Block = -1;
|
---|
| 464 | prevBlock = -1;
|
---|
| 465 | }
|
---|
| 466 | var prev = 0x110000;
|
---|
| 467 | /* enumerate index-2 blocks */
|
---|
| 468 | var i1 = UNEWTRIE2_INDEX_1_LENGTH;
|
---|
| 469 | var c = prev;
|
---|
| 470 | while (c > 0) {
|
---|
| 471 | i2Block = this.index1[--i1];
|
---|
| 472 | if (i2Block === prevI2Block) {
|
---|
| 473 | /* the index-2 block is the same as the previous one, and filled with highValue */
|
---|
| 474 | c -= UTRIE2_CP_PER_INDEX_1_ENTRY;
|
---|
| 475 | continue;
|
---|
| 476 | }
|
---|
| 477 | prevI2Block = i2Block;
|
---|
| 478 | if (i2Block === this.index2NullOffset) {
|
---|
| 479 | /* this is the null index-2 block */
|
---|
| 480 | if (highValue !== this.initialValue) {
|
---|
| 481 | return c;
|
---|
| 482 | }
|
---|
| 483 | c -= UTRIE2_CP_PER_INDEX_1_ENTRY;
|
---|
| 484 | }
|
---|
| 485 | else {
|
---|
| 486 | /* enumerate data blocks for one index-2 block */
|
---|
| 487 | for (i2 = Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH; i2 > 0;) {
|
---|
| 488 | block = this.index2[i2Block + --i2];
|
---|
| 489 | if (block === prevBlock) {
|
---|
| 490 | /* the block is the same as the previous one, and filled with highValue */
|
---|
| 491 | c -= Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 492 | continue;
|
---|
| 493 | }
|
---|
| 494 | prevBlock = block;
|
---|
| 495 | if (block === this.dataNullOffset) {
|
---|
| 496 | /* this is the null data block */
|
---|
| 497 | if (highValue !== this.initialValue) {
|
---|
| 498 | return c;
|
---|
| 499 | }
|
---|
| 500 | c -= Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 501 | }
|
---|
| 502 | else {
|
---|
| 503 | for (j = Trie_1.UTRIE2_DATA_BLOCK_LENGTH; j > 0;) {
|
---|
| 504 | value = this.data[block + --j];
|
---|
| 505 | if (value !== highValue) {
|
---|
| 506 | return c;
|
---|
| 507 | }
|
---|
| 508 | --c;
|
---|
| 509 | }
|
---|
| 510 | }
|
---|
| 511 | }
|
---|
| 512 | }
|
---|
| 513 | }
|
---|
| 514 | /* deliver last range */
|
---|
| 515 | return 0;
|
---|
| 516 | };
|
---|
| 517 | /*
|
---|
| 518 | * Compact a build-time trie.
|
---|
| 519 | *
|
---|
| 520 | * The compaction
|
---|
| 521 | * - removes blocks that are identical with earlier ones
|
---|
| 522 | * - overlaps adjacent blocks as much as possible (if overlap==TRUE)
|
---|
| 523 | * - moves blocks in steps of the data granularity
|
---|
| 524 | * - moves and overlaps blocks that overlap with multiple values in the overlap region
|
---|
| 525 | *
|
---|
| 526 | * It does not
|
---|
| 527 | * - try to move and overlap blocks that are not already adjacent
|
---|
| 528 | */
|
---|
| 529 | TrieBuilder.prototype.compactData = function () {
|
---|
| 530 | var start, movedStart;
|
---|
| 531 | var blockLength, overlap;
|
---|
| 532 | var i, mapIndex, blockCount;
|
---|
| 533 | /* do not compact linear-ASCII data */
|
---|
| 534 | var newStart = UTRIE2_DATA_START_OFFSET;
|
---|
| 535 | for (start = 0, i = 0; start < newStart; start += Trie_1.UTRIE2_DATA_BLOCK_LENGTH, ++i) {
|
---|
| 536 | this.map[i] = start;
|
---|
| 537 | }
|
---|
| 538 | /*
|
---|
| 539 | * Start with a block length of 64 for 2-byte UTF-8,
|
---|
| 540 | * then switch to UTRIE2_DATA_BLOCK_LENGTH.
|
---|
| 541 | */
|
---|
| 542 | blockLength = 64;
|
---|
| 543 | blockCount = blockLength >> Trie_1.UTRIE2_SHIFT_2;
|
---|
| 544 | for (start = newStart; start < this.dataLength;) {
|
---|
| 545 | /*
|
---|
| 546 | * start: index of first entry of current block
|
---|
| 547 | * newStart: index where the current block is to be moved
|
---|
| 548 | * (right after current end of already-compacted data)
|
---|
| 549 | */
|
---|
| 550 | if (start === UNEWTRIE2_DATA_0800_OFFSET) {
|
---|
| 551 | blockLength = Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 552 | blockCount = 1;
|
---|
| 553 | }
|
---|
| 554 | /* skip blocks that are not used */
|
---|
| 555 | if (this.map[start >> Trie_1.UTRIE2_SHIFT_2] <= 0) {
|
---|
| 556 | /* advance start to the next block */
|
---|
| 557 | start += blockLength;
|
---|
| 558 | /* leave newStart with the previous block! */
|
---|
| 559 | continue;
|
---|
| 560 | }
|
---|
| 561 | /* search for an identical block */
|
---|
| 562 | movedStart = this.findSameDataBlock(newStart, start, blockLength);
|
---|
| 563 | if (movedStart >= 0) {
|
---|
| 564 | /* found an identical block, set the other block's index value for the current block */
|
---|
| 565 | for (i = blockCount, mapIndex = start >> Trie_1.UTRIE2_SHIFT_2; i > 0; --i) {
|
---|
| 566 | this.map[mapIndex++] = movedStart;
|
---|
| 567 | movedStart += Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 568 | }
|
---|
| 569 | /* advance start to the next block */
|
---|
| 570 | start += blockLength;
|
---|
| 571 | /* leave newStart with the previous block! */
|
---|
| 572 | continue;
|
---|
| 573 | }
|
---|
| 574 | /* see if the beginning of this block can be overlapped with the end of the previous block */
|
---|
| 575 | /* look for maximum overlap (modulo granularity) with the previous, adjacent block */
|
---|
| 576 | for (overlap = blockLength - UTRIE2_DATA_GRANULARITY; overlap > 0 && !equalInt(this.data, newStart - overlap, start, overlap); overlap -= UTRIE2_DATA_GRANULARITY) { }
|
---|
| 577 | if (overlap > 0 || newStart < start) {
|
---|
| 578 | /* some overlap, or just move the whole block */
|
---|
| 579 | movedStart = newStart - overlap;
|
---|
| 580 | for (i = blockCount, mapIndex = start >> Trie_1.UTRIE2_SHIFT_2; i > 0; --i) {
|
---|
| 581 | this.map[mapIndex++] = movedStart;
|
---|
| 582 | movedStart += Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 583 | }
|
---|
| 584 | /* move the non-overlapping indexes to their new positions */
|
---|
| 585 | start += overlap;
|
---|
| 586 | for (i = blockLength - overlap; i > 0; --i) {
|
---|
| 587 | this.data[newStart++] = this.data[start++];
|
---|
| 588 | }
|
---|
| 589 | }
|
---|
| 590 | else {
|
---|
| 591 | /* no overlap && newStart==start */
|
---|
| 592 | for (i = blockCount, mapIndex = start >> Trie_1.UTRIE2_SHIFT_2; i > 0; --i) {
|
---|
| 593 | this.map[mapIndex++] = start;
|
---|
| 594 | start += Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 595 | }
|
---|
| 596 | newStart = start;
|
---|
| 597 | }
|
---|
| 598 | }
|
---|
| 599 | /* now adjust the index-2 table */
|
---|
| 600 | for (i = 0; i < this.index2Length; ++i) {
|
---|
| 601 | if (i === UNEWTRIE2_INDEX_GAP_OFFSET) {
|
---|
| 602 | /* Gap indexes are invalid (-1). Skip over the gap. */
|
---|
| 603 | i += UNEWTRIE2_INDEX_GAP_LENGTH;
|
---|
| 604 | }
|
---|
| 605 | this.index2[i] = this.map[this.index2[i] >> Trie_1.UTRIE2_SHIFT_2];
|
---|
| 606 | }
|
---|
| 607 | this.dataNullOffset = this.map[this.dataNullOffset >> Trie_1.UTRIE2_SHIFT_2];
|
---|
| 608 | /* ensure dataLength alignment */
|
---|
| 609 | while ((newStart & (UTRIE2_DATA_GRANULARITY - 1)) !== 0) {
|
---|
| 610 | this.data[newStart++] = this.initialValue;
|
---|
| 611 | }
|
---|
| 612 | this.dataLength = newStart;
|
---|
| 613 | };
|
---|
| 614 | TrieBuilder.prototype.findSameDataBlock = function (dataLength, otherBlock, blockLength) {
|
---|
| 615 | var block = 0;
|
---|
| 616 | /* ensure that we do not even partially get past dataLength */
|
---|
| 617 | dataLength -= blockLength;
|
---|
| 618 | for (; block <= dataLength; block += UTRIE2_DATA_GRANULARITY) {
|
---|
| 619 | if (equalInt(this.data, block, otherBlock, blockLength)) {
|
---|
| 620 | return block;
|
---|
| 621 | }
|
---|
| 622 | }
|
---|
| 623 | return -1;
|
---|
| 624 | };
|
---|
| 625 | TrieBuilder.prototype.compactTrie = function () {
|
---|
| 626 | var highValue = this.get(0x10ffff);
|
---|
| 627 | /* find highStart and round it up */
|
---|
| 628 | var localHighStart = this.findHighStart(highValue);
|
---|
| 629 | localHighStart = (localHighStart + (UTRIE2_CP_PER_INDEX_1_ENTRY - 1)) & ~(UTRIE2_CP_PER_INDEX_1_ENTRY - 1);
|
---|
| 630 | if (localHighStart === 0x110000) {
|
---|
| 631 | highValue = this.errorValue;
|
---|
| 632 | }
|
---|
| 633 | /*
|
---|
| 634 | * Set trie->highStart only after utrie2_get32(trie, highStart).
|
---|
| 635 | * Otherwise utrie2_get32(trie, highStart) would try to read the highValue.
|
---|
| 636 | */
|
---|
| 637 | this.highStart = localHighStart;
|
---|
| 638 | if (this.highStart < 0x110000) {
|
---|
| 639 | /* Blank out [highStart..10ffff] to release associated data blocks. */
|
---|
| 640 | var suppHighStart = this.highStart <= 0x10000 ? 0x10000 : this.highStart;
|
---|
| 641 | this.setRange(suppHighStart, 0x10ffff, this.initialValue, true);
|
---|
| 642 | }
|
---|
| 643 | this.compactData();
|
---|
| 644 | if (this.highStart > 0x10000) {
|
---|
| 645 | this.compactIndex2();
|
---|
| 646 | }
|
---|
| 647 | /*
|
---|
| 648 | * Store the highValue in the data array and round up the dataLength.
|
---|
| 649 | * Must be done after compactData() because that assumes that dataLength
|
---|
| 650 | * is a multiple of UTRIE2_DATA_BLOCK_LENGTH.
|
---|
| 651 | */
|
---|
| 652 | this.data[this.dataLength++] = highValue;
|
---|
| 653 | while ((this.dataLength & (UTRIE2_DATA_GRANULARITY - 1)) !== 0) {
|
---|
| 654 | this.data[this.dataLength++] = this.initialValue;
|
---|
| 655 | }
|
---|
| 656 | this.isCompacted = true;
|
---|
| 657 | };
|
---|
| 658 | TrieBuilder.prototype.compactIndex2 = function () {
|
---|
| 659 | var i, start, movedStart, overlap;
|
---|
| 660 | /* do not compact linear-BMP index-2 blocks */
|
---|
| 661 | var newStart = Trie_1.UTRIE2_INDEX_2_BMP_LENGTH;
|
---|
| 662 | for (start = 0, i = 0; start < newStart; start += Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH, ++i) {
|
---|
| 663 | this.map[i] = start;
|
---|
| 664 | }
|
---|
| 665 | /* Reduce the index table gap to what will be needed at runtime. */
|
---|
| 666 | newStart += Trie_1.UTRIE2_UTF8_2B_INDEX_2_LENGTH + ((this.highStart - 0x10000) >> Trie_1.UTRIE2_SHIFT_1);
|
---|
| 667 | for (start = UNEWTRIE2_INDEX_2_NULL_OFFSET; start < this.index2Length;) {
|
---|
| 668 | /*
|
---|
| 669 | * start: index of first entry of current block
|
---|
| 670 | * newStart: index where the current block is to be moved
|
---|
| 671 | * (right after current end of already-compacted data)
|
---|
| 672 | */
|
---|
| 673 | /* search for an identical block */
|
---|
| 674 | if ((movedStart = this.findSameIndex2Block(newStart, start)) >= 0) {
|
---|
| 675 | /* found an identical block, set the other block's index value for the current block */
|
---|
| 676 | this.map[start >> Trie_1.UTRIE2_SHIFT_1_2] = movedStart;
|
---|
| 677 | /* advance start to the next block */
|
---|
| 678 | start += Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH;
|
---|
| 679 | /* leave newStart with the previous block! */
|
---|
| 680 | continue;
|
---|
| 681 | }
|
---|
| 682 | /* see if the beginning of this block can be overlapped with the end of the previous block */
|
---|
| 683 | /* look for maximum overlap with the previous, adjacent block */
|
---|
| 684 | for (overlap = Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH - 1; overlap > 0 && !equalInt(this.index2, newStart - overlap, start, overlap); --overlap) { }
|
---|
| 685 | if (overlap > 0 || newStart < start) {
|
---|
| 686 | /* some overlap, or just move the whole block */
|
---|
| 687 | this.map[start >> Trie_1.UTRIE2_SHIFT_1_2] = newStart - overlap;
|
---|
| 688 | /* move the non-overlapping indexes to their new positions */
|
---|
| 689 | start += overlap;
|
---|
| 690 | for (i = Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH - overlap; i > 0; --i) {
|
---|
| 691 | this.index2[newStart++] = this.index2[start++];
|
---|
| 692 | }
|
---|
| 693 | }
|
---|
| 694 | else {
|
---|
| 695 | /* no overlap && newStart==start */ this.map[start >> Trie_1.UTRIE2_SHIFT_1_2] = start;
|
---|
| 696 | start += Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH;
|
---|
| 697 | newStart = start;
|
---|
| 698 | }
|
---|
| 699 | }
|
---|
| 700 | /* now adjust the index-1 table */
|
---|
| 701 | for (i = 0; i < UNEWTRIE2_INDEX_1_LENGTH; ++i) {
|
---|
| 702 | this.index1[i] = this.map[this.index1[i] >> Trie_1.UTRIE2_SHIFT_1_2];
|
---|
| 703 | }
|
---|
| 704 | this.index2NullOffset = this.map[this.index2NullOffset >> Trie_1.UTRIE2_SHIFT_1_2];
|
---|
| 705 | /*
|
---|
| 706 | * Ensure data table alignment:
|
---|
| 707 | * Needs to be granularity-aligned for 16-bit trie
|
---|
| 708 | * (so that dataMove will be down-shiftable),
|
---|
| 709 | * and 2-aligned for uint32_t data.
|
---|
| 710 | */
|
---|
| 711 | while ((newStart & ((UTRIE2_DATA_GRANULARITY - 1) | 1)) !== 0) {
|
---|
| 712 | /* Arbitrary value: 0x3fffc not possible for real data. */
|
---|
| 713 | this.index2[newStart++] = 0x0000ffff << Trie_1.UTRIE2_INDEX_SHIFT;
|
---|
| 714 | }
|
---|
| 715 | this.index2Length = newStart;
|
---|
| 716 | };
|
---|
| 717 | TrieBuilder.prototype.findSameIndex2Block = function (index2Length, otherBlock) {
|
---|
| 718 | /* ensure that we do not even partially get past index2Length */
|
---|
| 719 | index2Length -= Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH;
|
---|
| 720 | for (var block = 0; block <= index2Length; ++block) {
|
---|
| 721 | if (equalInt(this.index2, block, otherBlock, Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH)) {
|
---|
| 722 | return block;
|
---|
| 723 | }
|
---|
| 724 | }
|
---|
| 725 | return -1;
|
---|
| 726 | };
|
---|
| 727 | TrieBuilder.prototype._set = function (c, forLSCP, value) {
|
---|
| 728 | if (this.isCompacted) {
|
---|
| 729 | throw new Error('Trie was already compacted');
|
---|
| 730 | }
|
---|
| 731 | var block = this.getDataBlock(c, forLSCP);
|
---|
| 732 | this.data[block + (c & Trie_1.UTRIE2_DATA_MASK)] = value;
|
---|
| 733 | return this;
|
---|
| 734 | };
|
---|
| 735 | TrieBuilder.prototype.writeBlock = function (block, value) {
|
---|
| 736 | var limit = block + Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 737 | while (block < limit) {
|
---|
| 738 | this.data[block++] = value;
|
---|
| 739 | }
|
---|
| 740 | };
|
---|
| 741 | TrieBuilder.prototype.isInNullBlock = function (c, forLSCP) {
|
---|
| 742 | var i2 = isHighSurrogate(c) && forLSCP
|
---|
| 743 | ? Trie_1.UTRIE2_LSCP_INDEX_2_OFFSET - (0xd800 >> Trie_1.UTRIE2_SHIFT_2) + (c >> Trie_1.UTRIE2_SHIFT_2)
|
---|
| 744 | : this.index1[c >> Trie_1.UTRIE2_SHIFT_1] + ((c >> Trie_1.UTRIE2_SHIFT_2) & Trie_1.UTRIE2_INDEX_2_MASK);
|
---|
| 745 | var block = this.index2[i2];
|
---|
| 746 | return block === this.dataNullOffset;
|
---|
| 747 | };
|
---|
| 748 | TrieBuilder.prototype.fillBlock = function (block, start, limit, value, initialValue, overwrite) {
|
---|
| 749 | var pLimit = block + limit;
|
---|
| 750 | if (overwrite) {
|
---|
| 751 | for (var i = block + start; i < pLimit; i++) {
|
---|
| 752 | this.data[i] = value;
|
---|
| 753 | }
|
---|
| 754 | }
|
---|
| 755 | else {
|
---|
| 756 | for (var i = block + start; i < pLimit; i++) {
|
---|
| 757 | if (this.data[i] === initialValue) {
|
---|
| 758 | this.data[i] = value;
|
---|
| 759 | }
|
---|
| 760 | }
|
---|
| 761 | }
|
---|
| 762 | };
|
---|
| 763 | TrieBuilder.prototype.setIndex2Entry = function (i2, block) {
|
---|
| 764 | ++this.map[block >> Trie_1.UTRIE2_SHIFT_2]; /* increment first, in case block==oldBlock! */
|
---|
| 765 | var oldBlock = this.index2[i2];
|
---|
| 766 | if (0 === --this.map[oldBlock >> Trie_1.UTRIE2_SHIFT_2]) {
|
---|
| 767 | this.releaseDataBlock(oldBlock);
|
---|
| 768 | }
|
---|
| 769 | this.index2[i2] = block;
|
---|
| 770 | };
|
---|
| 771 | TrieBuilder.prototype.releaseDataBlock = function (block) {
|
---|
| 772 | /* put this block at the front of the free-block chain */
|
---|
| 773 | this.map[block >> Trie_1.UTRIE2_SHIFT_2] = -this.firstFreeBlock;
|
---|
| 774 | this.firstFreeBlock = block;
|
---|
| 775 | };
|
---|
| 776 | TrieBuilder.prototype.getDataBlock = function (c, forLSCP) {
|
---|
| 777 | var i2 = this.getIndex2Block(c, forLSCP);
|
---|
| 778 | i2 += (c >> Trie_1.UTRIE2_SHIFT_2) & Trie_1.UTRIE2_INDEX_2_MASK;
|
---|
| 779 | var oldBlock = this.index2[i2];
|
---|
| 780 | if (this.isWritableBlock(oldBlock)) {
|
---|
| 781 | return oldBlock;
|
---|
| 782 | }
|
---|
| 783 | /* allocate a new data block */
|
---|
| 784 | var newBlock = this.allocDataBlock(oldBlock);
|
---|
| 785 | this.setIndex2Entry(i2, newBlock);
|
---|
| 786 | return newBlock;
|
---|
| 787 | };
|
---|
| 788 | TrieBuilder.prototype.isWritableBlock = function (block) {
|
---|
| 789 | return block !== this.dataNullOffset && 1 === this.map[block >> Trie_1.UTRIE2_SHIFT_2];
|
---|
| 790 | };
|
---|
| 791 | TrieBuilder.prototype.getIndex2Block = function (c, forLSCP) {
|
---|
| 792 | if (c >= 0xd800 && c < 0xdc00 && forLSCP) {
|
---|
| 793 | return Trie_1.UTRIE2_LSCP_INDEX_2_OFFSET;
|
---|
| 794 | }
|
---|
| 795 | var i1 = c >> Trie_1.UTRIE2_SHIFT_1;
|
---|
| 796 | var i2 = this.index1[i1];
|
---|
| 797 | if (i2 === this.index2NullOffset) {
|
---|
| 798 | i2 = this.allocIndex2Block();
|
---|
| 799 | this.index1[i1] = i2;
|
---|
| 800 | }
|
---|
| 801 | return i2;
|
---|
| 802 | };
|
---|
| 803 | TrieBuilder.prototype.allocDataBlock = function (copyBlock) {
|
---|
| 804 | var newBlock;
|
---|
| 805 | if (this.firstFreeBlock !== 0) {
|
---|
| 806 | /* get the first free block */
|
---|
| 807 | newBlock = this.firstFreeBlock;
|
---|
| 808 | this.firstFreeBlock = -this.map[newBlock >> Trie_1.UTRIE2_SHIFT_2];
|
---|
| 809 | }
|
---|
| 810 | else {
|
---|
| 811 | /* get a new block from the high end */
|
---|
| 812 | newBlock = this.dataLength;
|
---|
| 813 | var newTop = newBlock + Trie_1.UTRIE2_DATA_BLOCK_LENGTH;
|
---|
| 814 | if (newTop > this.dataCapacity) {
|
---|
| 815 | var capacity = void 0;
|
---|
| 816 | /* out of memory in the data array */
|
---|
| 817 | if (this.dataCapacity < UNEWTRIE2_MEDIUM_DATA_LENGTH) {
|
---|
| 818 | capacity = UNEWTRIE2_MEDIUM_DATA_LENGTH;
|
---|
| 819 | }
|
---|
| 820 | else if (this.dataCapacity < UNEWTRIE2_MAX_DATA_LENGTH) {
|
---|
| 821 | capacity = UNEWTRIE2_MAX_DATA_LENGTH;
|
---|
| 822 | }
|
---|
| 823 | else {
|
---|
| 824 | /*
|
---|
| 825 | * Should never occur.
|
---|
| 826 | * Either UNEWTRIE2_MAX_DATA_LENGTH is incorrect,
|
---|
| 827 | * or the code writes more values than should be possible.
|
---|
| 828 | */
|
---|
| 829 | throw new Error('Internal error in Trie creation.');
|
---|
| 830 | }
|
---|
| 831 | var newData = new Uint32Array(capacity);
|
---|
| 832 | newData.set(this.data.subarray(0, this.dataLength));
|
---|
| 833 | this.data = newData;
|
---|
| 834 | this.dataCapacity = capacity;
|
---|
| 835 | }
|
---|
| 836 | this.dataLength = newTop;
|
---|
| 837 | }
|
---|
| 838 | this.data.set(this.data.subarray(copyBlock, copyBlock + Trie_1.UTRIE2_DATA_BLOCK_LENGTH), newBlock);
|
---|
| 839 | this.map[newBlock >> Trie_1.UTRIE2_SHIFT_2] = 0;
|
---|
| 840 | return newBlock;
|
---|
| 841 | };
|
---|
| 842 | TrieBuilder.prototype.allocIndex2Block = function () {
|
---|
| 843 | var newBlock = this.index2Length;
|
---|
| 844 | var newTop = newBlock + Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH;
|
---|
| 845 | if (newTop > this.index2.length) {
|
---|
| 846 | throw new Error('Internal error in Trie creation.');
|
---|
| 847 | /*
|
---|
| 848 | * Should never occur.
|
---|
| 849 | * Either UTRIE2_MAX_BUILD_TIME_INDEX_LENGTH is incorrect,
|
---|
| 850 | * or the code writes more values than should be possible.
|
---|
| 851 | */
|
---|
| 852 | }
|
---|
| 853 | this.index2Length = newTop;
|
---|
| 854 | this.index2.set(this.index2.subarray(this.index2NullOffset, this.index2NullOffset + Trie_1.UTRIE2_INDEX_2_BLOCK_LENGTH), newBlock);
|
---|
| 855 | return newBlock;
|
---|
| 856 | };
|
---|
| 857 | return TrieBuilder;
|
---|
| 858 | }());
|
---|
| 859 | exports.TrieBuilder = TrieBuilder;
|
---|
| 860 | var serializeBase64 = function (trie) {
|
---|
| 861 | var index = trie.index;
|
---|
| 862 | var data = trie.data;
|
---|
| 863 | if (!(index instanceof Uint16Array) || !(data instanceof Uint16Array || data instanceof Uint32Array)) {
|
---|
| 864 | throw new Error('TrieBuilder serializer only support TypedArrays');
|
---|
| 865 | }
|
---|
| 866 | var headerLength = Uint32Array.BYTES_PER_ELEMENT * 6;
|
---|
| 867 | var bufferLength = headerLength + index.byteLength + data.byteLength;
|
---|
| 868 | var buffer = new ArrayBuffer(Math.ceil(bufferLength / 4) * 4);
|
---|
| 869 | var view32 = new Uint32Array(buffer);
|
---|
| 870 | var view16 = new Uint16Array(buffer);
|
---|
| 871 | view32[0] = trie.initialValue;
|
---|
| 872 | view32[1] = trie.errorValue;
|
---|
| 873 | view32[2] = trie.highStart;
|
---|
| 874 | view32[3] = trie.highValueIndex;
|
---|
| 875 | view32[4] = index.byteLength;
|
---|
| 876 | // $FlowFixMe
|
---|
| 877 | view32[5] = data.BYTES_PER_ELEMENT;
|
---|
| 878 | view16.set(index, headerLength / Uint16Array.BYTES_PER_ELEMENT);
|
---|
| 879 | if (data.BYTES_PER_ELEMENT === Uint16Array.BYTES_PER_ELEMENT) {
|
---|
| 880 | view16.set(data, (headerLength + index.byteLength) / Uint16Array.BYTES_PER_ELEMENT);
|
---|
| 881 | }
|
---|
| 882 | else {
|
---|
| 883 | view32.set(data, Math.ceil((headerLength + index.byteLength) / Uint32Array.BYTES_PER_ELEMENT));
|
---|
| 884 | }
|
---|
| 885 | return [base64_arraybuffer_1.encode(new Uint8Array(buffer)), buffer.byteLength];
|
---|
| 886 | };
|
---|
| 887 | exports.serializeBase64 = serializeBase64;
|
---|
| 888 | //# sourceMappingURL=TrieBuilder.js.map |
---|