PageSourceSearch

https://www.mot.be/assets/base/core/scripts/bbor62.js?etag=LygHa0LJ4IP

js mot.be collected 2026-10-02 10:50:15 UTC 54,478 bytes, 1,568 lines download raw bytes

1/*
2 * Copyright (c) 2024 Republic of Reinvention BV <[email protected]>. All Rights Reserved.
3 * This file is part of project "cinematek-filmout-site" and can not be copied and/or distributed without
4 * the express permission and written consent of the legal responsible of Republic of Reinvention BV.
5 */
6
7/**
8 * Created by bram on 7/28/15.
9 */
10base.plugin("base.core.Bbor62", ["constants.base.core", function (BaseConstants)
11{
12    // ----- ByteStream.java -----
13    class ByteStream
14    {
15        constructor()
16        {
17            // use Uint8Array instead of byte[] for more efficient byte storage
18            this.buffer = new Uint8Array(8);
19            this.readPos = 0;
20            this.readBitPos = 0;
21            this.writePos = 0;
22            this.writeBitPos = 0;
23            this.writeBuf = 0;
24        }
25
26        read(numBits)
27        {
28            if (numBits <= 0 || numBits > 32) {
29                throw new Error("Number of bits must be between 1 and 32");
30            }
31
32            var result = 0;
33            var bitsRemaining = numBits;
34
35            while (bitsRemaining > 0) {
36                var currentValue = this.buffer[this.readPos];
37                var bitsAvailable = 8 - this.readBitPos;
38                var bitsToRead = Math.min(bitsRemaining, bitsAvailable);
39                var mask = (1 << bitsToRead) - 1;
40                var shift = bitsAvailable - bitsToRead;
41                var extractedBits = (currentValue >>> shift) & mask;
42
43                result = (result << bitsToRead) | extractedBits;
44                bitsRemaining -= bitsToRead;
45                this.readBitPos += bitsToRead;
46
47                if (this.readBitPos >= 8) {
48                    this.readPos++;
49                    this.readBitPos -= 8;
50                }
51            }
52
53            return result;
54        }
55
56        hasNext(numBits)
57        {
58            return (this.readPos * 8 + this.readBitPos + numBits) <= this.writePos * 8;
59        }
60
61        write(value, numBits)
62        {
63            if (numBits <= 0 || numBits > 32) {
64                throw new Error("Number of bits must be between 1 and 32");
65            }
66            if (value >= (1 << numBits)) {
67                throw new Error("Value is too large for the specified number of bits");
68            }
69
70            while (numBits > 0) {
71                var bitsAvailable = 8 - this.writeBitPos;
72                var bitsToWrite = Math.min(numBits, bitsAvailable);
73                var remainingBits = numBits - bitsToWrite;
74
75                var mask = (1 << bitsToWrite) - 1;
76                var val = (value >>> remainingBits) & mask;
77
78                this.writeBuf = (this.writeBuf << bitsToWrite) | val;
79                this.writeBitPos += bitsToWrite;
80
81                if (this.writeBitPos === 8) {
82                    this._assertSpaceFor(1);
83                    this.buffer[this.writePos++] = this.writeBuf;
84                    this.writeBuf = 0;
85                    this.writeBitPos = 0;
86                }
87
88                numBits = remainingBits;
89            }
90        }
91
92        flush()
93        {
94            if (this.writeBitPos > 0) {
95                throw new Error("Remaining bits left in the byte stream, this shouldn't happen; " + this.writeBitPos);
96            }
97        }
98
99        length()
100        {
101            return this.writePos;
102        }
103
104        _assertSpaceFor(numBytes)
105        {
106            if (this.readPos > 0) {
107                var newBuffer = new Uint8Array(this.buffer.length);
108                // JS for arraycopy
109                newBuffer.set(this.buffer.subarray(this.readPos, this.buffer.length), 0);
110                this.buffer = newBuffer;
111                this.writePos -= this.readPos;
112                this.readPos = 0;
113            }
114
115            if (this.writePos + numBytes > this.buffer.length) {
116                var newBuffer = new Uint8Array(this.buffer.length * 2);
117                newBuffer.set(this.buffer);
118                this.buffer = newBuffer;
119            }
120        }
121    }
122
123    // ----- WrappedByteReader.java -----
124    class WrappedByteReader
125    {
126        constructor(stream, byteNum)
127        {
128            this.stream = stream;
129            this.byteNum = byteNum;
130            this.bitsRead = 0;
131            this.bytesRead = 0;
132        }
133
134        read(numBits)
135        {
136            var retVal = this.stream.read(numBits);
137
138            this.bitsRead += numBits;
139            // note that in JS, Math.floor() is the same as Math.floorDiv()
140            this.bytesRead += Math.floor(this.bitsRead / 8);
141            this.bitsRead = this.bitsRead % 8;
142
143            return retVal;
144        }
145
146        hasNext(numBits)
147        {
148            var newBitsRead = this.bitsRead + numBits;
149            // note that in JS, Math.floor() is the same as Math.floorDiv()
150            var newBytesRead = this.bytesRead + Math.floor(newBitsRead / 8);
151            newBitsRead = newBitsRead % 8;
152
153            return newBytesRead < this.byteNum || (newBytesRead === this.byteNum && newBitsRead === 0);
154        }
155    }
156
157    // ----- FlexDict.java -----
158    class FlexDict
159    {
160        // Note: used Number.MAX_SAFE_INTEGER instead of Integer.MAX_VALUE
161        constructor(staticDict, enableDynamic = true, maxSize = Number.MAX_SAFE_INTEGER)
162        {
163            this.staticDict = staticDict;
164            // note that we use a Map, because plain objects (eg. {}):
165            // - didn't guarantee property order before ES2015 (now they do for string keys)
166            // - don't keep size
167            // - behave differently for string keys as for int keys
168            this.dynamicDict = new Map();
169            this.enableDynamic = enableDynamic;
170            this.maxSize = maxSize;
171        }
172
173        get(key)
174        {
175            return this.staticDict.has(key) ? this.staticDict.get(key) : this.dynamicDict.get(key);
176        }
177
178        hasKey(key)
179        {
180            return this.staticDict.has(key) || this.dynamicDict.has(key);
181        }
182
183        add(key, val)
184        {
185            if (this.enableDynamic && this.size() < this.maxSize && !this.hasKey(key)) {
186                this.dynamicDict.set(key, val);
187            }
188        }
189
190        size()
191        {
192            return this.staticDict.size + this.dynamicDict.size;
193        }
194
195        reset()
196        {
197            this.dynamicDict.clear();
198        }
199    }
200
201    // ----- BaseXStream.java -----
202    class BaseXStream
203    {
204        // Note that this is a static getter property
205        // (methods that look like properties but actually execute code when accessed)
206        static get BITS_PER_BYTE()
207        {
208            return 8;
209        }
210
211        static log2ceil(x)
212        {
213            return 32 - Math.clz32(x - 1);
214        }
215    }
216
217    class BaseXStreamEncoder
218    {
219        constructor(consumer, config)
220        {
221            this.consumer = consumer || function ()
222            {
223            };
224            this.config = config || BaseXStream.DEFAULT_CONFIG;
225            this.buffer = 0;
226            this.bitsInBuffer = 0;
227            this.byteModulo = 0;
228        }
229
230        write(value, numBits)
231        {
232            if (numBits <= 0 || numBits > 32) {
233                throw new Error("Number of bits must be between 1 and 32");
234            }
235            // note that 1 << numBits returns 1, because bits shifts in JS only have 32 bit precision
236            if (numBits === 32) {
237                if (value >= 4294967296) {
238                    throw new Error("Value is too large for the specified number of bits");
239                }
240            }
241            // numBits is guaranteed < 32
242            else if (value >= (1 << numBits)) {
243                throw new Error("Value is too large for the specified number of bits");
244            }
245
246            while (numBits > 0) {
247                var bitsAvailable = this.config.bitsPerBlock - this.bitsInBuffer;
248                var bitsToWrite = Math.min(numBits, bitsAvailable);
249                var remainingBits = numBits - bitsToWrite;
250
251                var mask = (1 << bitsToWrite) - 1;
252                var val = (value >>> remainingBits) & mask;
253
254                this.buffer = (this.buffer << bitsToWrite) | val;
255                this.bitsInBuffer += bitsToWrite;
256                this.byteModulo = (this.byteModulo + bitsToWrite) % BaseXStream.BITS_PER_BYTE;
257
258                if (this.bitsInBuffer === this.config.bitsPerBlock) {
259                    if (this.config.enableBitSqueezing) {
260                        while (remainingBits > 0) {
261                            var extraBitVal = (value >>> (remainingBits - 1)) & 1;
262                            var tryBuffer = (this.buffer << 1) | extraBitVal;
263
264                            if (tryBuffer > this.config.maxBlockValue && tryBuffer < this.config.maxBlockCapacity) {
265                                this.buffer = tryBuffer;
266                                this.bitsInBuffer++;
267                                this.byteModulo = (this.byteModulo + 1) % BaseXStream.BITS_PER_BYTE;
268                                remainingBits--;
269                            }
270                            else {
271                                break;
272                            }
273                        }
274                    }
275
276                    this.consumer(this.encode(this.buffer, false));
277                    this.buffer = 0;
278                    this.bitsInBuffer = 0;
279                }
280
281                numBits = remainingBits;
282            }
283        }
284
285        flush()
286        {
287            if (this.bitsInBuffer > 0) {
288                if (this.byteModulo === 0) {
289                    var mask = (1 << this.bitsInBuffer) - 1;
290                    var valueToEncode = this.buffer & mask;
291                    var lastCode = this.encode(valueToEncode, true);
292                    this.consumer(lastCode);
293                }
294                else {
295                    throw new Error("Stream is not byte aligned");
296                }
297            }
298
299            this.buffer = 0;
300            this.bitsInBuffer = 0;
301        }
302
303        encode(valueToEncode, finalBlock)
304        {
305            var result = '';
306
307            do {
308                var remainder = valueToEncode % this.config.radix;
309                valueToEncode = Math.floor(valueToEncode / this.config.radix);
310                result = this.config.dict.charAt(remainder) + result;
311            } while (valueToEncode !== 0);
312
313            if (!finalBlock) {
314                while (result.length < this.config.charsPerBlock) {
315                    result = this.config.dict.charAt(0) + result;
316                }
317            }
318            else {
319                while (BaseXStream.log2ceil(Math.pow(this.config.radix, result.length) - 1) < this.bitsInBuffer) {
320                    result = this.config.dict.charAt(0) + result;
321                }
322            }
323
324            return result;
325        }
326    }
327
328    BaseXStream.Encoder = BaseXStreamEncoder;
329
330    class BaseXStreamDecoder
331    {
332        constructor(input, config)
333        {
334            this.config = config || BaseXStream.DEFAULT_CONFIG;
335            this.buffer = 0;
336            this.bitsInBuffer = 0;
337            this.byteModulo = 0;
338            this.currentBlock = '';
339            this.blockVal = 0;
340            this.blockPos = this.config.charsPerBlock - 1;
341            this.finalBlockLut = this.buildFinalBlockLut();
342
343            this.inputPos = 0;
344            this.readBuffer = new ByteStream();
345            this.input = input;
346        }
347
348        read(numBits)
349        {
350            return this.assertBits(numBits).read(numBits);
351        }
352
353        hasNext(numBits)
354        {
355            return this.readBuffer.hasNext(numBits) || this.inputPos < this.input.length;
356        }
357
358        assertBits(numBits)
359        {
360            while (!this.readBuffer.hasNext(numBits) && this.inputPos < this.input.length) {
361                var lastChar = this.inputPos === this.input.length - 1;
362                this.readChar(this.input.charAt(this.inputPos++), lastChar);
363            }
364            return this.readBuffer;
365        }
366
367        readChar(c, lastChar)
368        {
369            // note that dictRev is a simple object
370            var index = this.config.dictRev[c];
371            if (index === undefined) {
372                throw new Error("Invalid character: " + c);
373            }
374
375            this.blockVal = this.blockVal + (index * Math.pow(this.config.radix, this.blockPos--));
376            this.currentBlock += c;
377
378            if (this.blockPos < 0) {
379                var bitsInBlock = lastChar ? this.getLastBlockBitLength() : this.config.bitsPerBlock;
380                this.decodeBlock(bitsInBlock);
381
382                this.currentBlock = '';
383                this.blockVal = 0;
384                this.blockPos = this.config.charsPerBlock - 1;
385            }
386
387            if (lastChar) {
388                if (this.currentBlock.length > 0) {
389                    this.blockVal = 0;
390                    this.blockPos = this.currentBlock.length - 1;
391
392                    for (var i = 0; i < this.currentBlock.length; i++) {
393                        this.blockVal = this.blockVal + (this.config.dictRev[this.currentBlock.charAt(i)] * Math.pow(this.config.radix, this.blockPos--));
394                    }
395
396                    var lastBlockBits = this.getLastBlockBitLength();
397                    this.decodeBlock(lastBlockBits);
398                }
399
400                if (this.bitsInBuffer > 0) {
401                    throw new Error("Bitstream is not byte aligned");
402                }
403
404                this.buffer = 0;
405                this.bitsInBuffer = 0;
406                this.byteModulo = 0;
407            }
408        }
409
410        decodeBlock(numBits)
411        {
412            var extraBits = 0;
413            while (this.blockVal >>> extraBits > this.config.maxBlockValue) {
414                numBits++;
415                extraBits++;
416            }
417
418            var mask = (1 << numBits) - 1;
419            this.buffer = (this.buffer << numBits) | (this.blockVal & mask);
420            this.bitsInBuffer += numBits;
421            this.byteModulo = (this.byteModulo + numBits) % BaseXStream.BITS_PER_BYTE;
422
423            while (this.bitsInBuffer >= BaseXStream.BITS_PER_BYTE) {
424                var bitsNotToDecode = this.bitsInBuffer - BaseXStream.BITS_PER_BYTE;
425                var valueToDecode = this.buffer >>> bitsNotToDecode;
426                this.readBuffer.write(valueToDecode, BaseXStream.BITS_PER_BYTE);
427                var m = (1 << bitsNotToDecode) - 1;
428                this.buffer &= m;
429                this.bitsInBuffer = bitsNotToDecode;
430            }
431        }
432
433        getLastBlockBitLength()
434        {
435            if (this.byteModulo === 0 && this.currentBlock.length === this.config.charsPerBlock) {
436                return this.config.bitsPerBlock;
437            }
438            else {
439                // see buildFinalBlockLut() notes
440                var entry = this.byteModulo + ',' + this.currentBlock.length;
441                if (this.finalBlockLut.has(entry)) {
442                    return this.finalBlockLut.get(entry);
443                }
444                else {
445                    throw new Error("Invalid last block combination: startPos=" + this.byteModulo + ", numChars=" + this.currentBlock.length);
446                }
447            }
448        }
449
450        buildFinalBlockLut()
451        {
452            var retVal = new Map();
453
454            for (var numChars = 1; numChars <= this.config.charsPerBlock; numChars++) {
455                var minValue = Math.pow(this.config.radix, numChars - 1);
456                var minBits = Math.max(BaseXStream.log2ceil(minValue), 1);
457                var maxValue = Math.pow(this.config.radix, numChars) - 1;
458                var maxBits = Math.min(BaseXStream.log2ceil(maxValue), this.config.bitsPerBlock);
459
460                for (var modulo = 0; modulo < BaseXStream.BITS_PER_BYTE; modulo++) {
461                    for (var bitLength = minBits; bitLength <= maxBits; bitLength++) {
462                        if ((modulo + bitLength) % BaseXStream.BITS_PER_BYTE === 0) {
463                            // watch out: JS maps test equality by reference, not value, so we can't use an array pair here
464                            // instead, let's convert to a string
465                            var startState = modulo + ',' + numChars;
466                            if (!retVal.has(startState)) {
467                                retVal.set(startState, bitLength);
468                            }
469                            else {
470                                throw new Error("Configuration cannot guarantee unique final block bit length");
471                            }
472                        }
473                    }
474                }
475            }
476
477            return retVal;
478        }
479    }
480
481    BaseXStream.Decoder = BaseXStreamDecoder;
482
483    BaseXStream.DEFAULT_CONFIG = {
484        // note that this is a string
485        dict: BaseConstants.BASE62_ALPHABET,
486        charsPerBlock: 4,
487        enableBitSqueezing: true,
488        // and this is an object
489        dictRev: null,
490        radix: null,
491        bitsPerBlock: null,
492        maxBlockValue: null,
493        maxBlockCapacity: null,
494
495        init()
496        {
497            this.dictRev = {};
498            for (var i = 0; i < this.dict.length; i++) {
499                this.dictRev[this.dict.charAt(i)] = i;
500            }
501
502            this.radix = this.dict.length;
503            var bitsPerChar = Math.log(this.radix) / Math.log(2);
504            this.bitsPerBlock = Math.floor(bitsPerChar * this.charsPerBlock);
505            this.maxBlockValue = Math.pow(2, this.bitsPerBlock) - 1;
506            this.maxBlockCapacity = Math.pow(this.radix, this.charsPerBlock);
507        }
508    };
509    BaseXStream.DEFAULT_CONFIG.init();
510
511    // ----- LZW.java -----
512    class LZW
513    {
514        static get ASCII_ESCAPE_IDX()
515        {
516            return 0;
517        }
518
519        static get ASCII_ESCAPE_VAL()
520        {
521            return String.fromCharCode(LZW.ASCII_ESCAPE_IDX);
522        }
523
524        static get UNICODE_ESCAPE_IDX()
525        {
526            return 1;
527        }
528
529        static get UNICODE_ESCAPE_VAL()
530        {
531            return String.fromCharCode(LZW.UNICODE_ESCAPE_IDX);
532        }
533
534        constructor(config)
535        {
536            this.config = config || LZW.DEFAULT_CONFIG;
537            this.encodeDict = null;
538            this.decodeDict = null;
539        }
540
541        compress(input, output)
542        {
543            if (!input || input.length === 0) {
544                throw new Error("Please provide input");
545            }
546
547            if (this.encodeDict === null) {
548                this.encodeDict = new FlexDict(this.config.staticDict, this.config.enableDynamicDict, this.config.maxDictSize);
549            }
550            var ctx = new LZW.Ctx(this.encodeDict);
551
552            var last = input.charAt(0);
553            for (var i = 1; i < input.length; i++) {
554                var current = input.charAt(i);
555                var lastPlusCurrent = last + current;
556
557                if (ctx.dict.hasKey(lastPlusCurrent)) {
558                    last = lastPlusCurrent;
559                }
560                else {
561                    var isNew = this.write(output, ctx, last);
562                    this.checkReset(ctx.dict);
563
564                    if (isNew) {
565                        ctx.dict.add(last, ctx.dict.size());
566                    }
567
568                    ctx.dict.add(lastPlusCurrent, ctx.dict.size());
569                    last = current;
570                }
571            }
572
573            var isNew = this.write(output, ctx, last);
574            this.checkReset(ctx.dict);
575
576            if (isNew) {
577                ctx.dict.add(last, ctx.dict.size());
578            }
579
580            if (this.config.byteAlignMode && ctx.byteAlignVal > 0) {
581                var bitsUntilFullByte = 8 - ctx.byteAlignVal;
582                var bitsNeededForSeq = this.bitsNeeded(ctx.dict.size() - 1);
583                var bitsToWrite = Math.min(bitsNeededForSeq, bitsUntilFullByte);
584                output.write(LZW.ASCII_ESCAPE_IDX, bitsToWrite);
585                bitsUntilFullByte -= bitsToWrite;
586
587                if (bitsUntilFullByte > 0) {
588                    output.write(0, bitsUntilFullByte);
589                }
590                ctx.byteAlignVal = 0;
591            }
592        }
593
594        decompress(input)
595        {
596            var retVal = '';
597
598            if (this.decodeDict === null) {
599                this.decodeDict = new FlexDict(this.config.staticDictRev, this.config.enableDynamicDict, this.config.maxDictSize);
600            }
601            var ctx = new LZW.Ctx(this.decodeDict);
602
603            var nextIndex = ctx.dict.size() - 1;
604            var last = null;
605            var current;
606
607            while ((current = this.read(input, ctx, nextIndex, last)) !== null) {
608                retVal += current.value;
609
610                if (last !== null) {
611                    ctx.dict.add(ctx.dict.size(), last + current.value.charAt(0));
612                }
613
614                this.checkReset(ctx.dict);
615
616                if (current.isNew) {
617                    ctx.dict.add(ctx.dict.size(), current.value);
618                }
619
620                last = current.value;
621
622                if (this.config.enableDynamicDict) {
623                    nextIndex = (ctx.dict.size() - 1) + 1;
624                }
625            }
626
627            return retVal;
628        }
629
630        write(output, ctx, value)
631        {
632            var isNew = false;
633            var code = ctx.dict.get(value);
634            var bitsNeeded = this.bitsNeeded(ctx.dict.size() - 1);
635
636            if (code !== undefined) {
637                if (code === LZW.ASCII_ESCAPE_IDX || code === LZW.UNICODE_ESCAPE_IDX) {
638                    output.write(LZW.ASCII_ESCAPE_IDX, bitsNeeded);
639                    output.write(code, 8);
640                }
641                else {
642                    output.write(code, bitsNeeded);
643                }
644            }
645            else {
646                if (value.length === 1) {
647                    var c = value.charCodeAt(0);
648
649                    if (c < 256) {
650                        output.write(LZW.ASCII_ESCAPE_IDX, bitsNeeded);
651                        output.write(c, 8);
652                    }
653                    else {
654                        output.write(LZW.UNICODE_ESCAPE_IDX, bitsNeeded);
655                        output.write(c, 16);
656                    }
657
658                    isNew = true;
659                }
660                else {
661                    throw new Error("This shouldn't happen, all new values > 1 should be in the dict; " + value);
662                }
663            }
664
665            ctx.byteAlignVal = (ctx.byteAlignVal + bitsNeeded) % 8;
666
667            return isNew;
668        }
669
670        read(input, ctx, nextIndex, last)
671        {
672            var retVal = null;
673            var bitsNeeded = this.bitsNeeded(nextIndex);
674
675            if (input.hasNext(bitsNeeded)) {
676                var code = input.read(bitsNeeded);
677                ctx.byteAlignVal = (ctx.byteAlignVal + bitsNeeded) % 8;
678
679                retVal = new LZW.Token();
680                if (code === LZW.ASCII_ESCAPE_IDX || code === LZW.UNICODE_ESCAPE_IDX) {
681                    if (this.config.byteAlignMode && !input.hasNext(8)) {
682                        if (ctx.byteAlignVal > 0) {
683                            input.read(8 - ctx.byteAlignVal);
684                        }
685                        retVal = null;
686                    }
687                    else {
688                        // Using String.fromCharCode instead of String.valueOf for character conversion
689                        retVal.value = String.fromCharCode(input.read(code === LZW.ASCII_ESCAPE_IDX ? 8 : 16));
690                        retVal.isNew = retVal.value !== LZW.ASCII_ESCAPE_VAL && retVal.value !== LZW.UNICODE_ESCAPE_VAL;
691                    }
692                }
693                else if (ctx.dict.hasKey(code)) {
694                    retVal.value = ctx.dict.get(code);
695                }
696                else if (code === nextIndex) {
697                    retVal.value = last + last.charAt(0);
698                }
699                else {
700                    throw new Error("Invalid compressed data");
701                }
702            }
703            else {
704                if (this.config.byteAlignMode && ctx.byteAlignVal > 0) {
705                    input.read(8 - ctx.byteAlignVal);
706                }
707            }
708
709            return retVal;
710        }
711
712        checkReset(dict)
713        {
714            if (this.config.enableDynamicDict && this.config.enableDictReset && dict.size() >= this.config.maxDictSize) {
715                dict.reset();
716            }
717        }
718
719        bitsNeeded(code)
720        {
721            return code === 0 ? 1 : 32 - Math.clz32(code);
722        }
723    }
724
725    class LZWToken
726    {
727        constructor()
728        {
729            this.value = null;
730            this.isNew = false;
731        }
732    }
733
734    LZW.Token = LZWToken;
735
736    class LZWCtx
737    {
738        constructor(dict)
739        {
740            this.dict = dict;
741            this.byteAlignVal = 0;
742        }
743    }
744
745    LZW.Ctx = LZWCtx;
746
747    LZW.DEFAULT_CONFIG = {
748        INITIAL_DICT: [
749            LZW.ASCII_ESCAPE_VAL,
750            LZW.UNICODE_ESCAPE_VAL,
751            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
752            " ", ".", ",",
753            "e", "a", "r", "i", "o", "t", "n", "s", "l", "c",
754            "u", "d", "p", "m", "h", "g", "b", "f", "v", "k",
755            "w", "j", "q", "x", "y", "z",
756            "A", "M", "S", "C", "P", "D", "B", "R", "L", "T",
757            "E", "N", "H", "G", "F", "W", "I", "J", "K", "O",
758            "V", "U", "Q", "X", "Y", "Z",
759            "th", "en", "er", "in", "es", "on", "an", "re", "st", "le"
760        ],
761
762        enableDynamicDict: true,
763        maxDictSize: Math.pow(2, 10) - 1,
764        enableDictReset: true,
765        byteAlignMode: true,
766        staticDict: new Map(),
767        staticDictRev: new Map(),
768
769        init()
770        {
771            for (var i = 0; i < this.INITIAL_DICT.length; i++) {
772                var c = this.INITIAL_DICT[i];
773                if (!this.staticDict.has(c)) {
774                    this.staticDict.set(c, i);
775                    this.staticDictRev.set(i, c);
776                }
777                else {
778                    throw new Error("Duplicate dict character detected '" + c + "'");
779                }
780            }
781        },
782    };
783    LZW.DEFAULT_CONFIG.init();
784
785    // ----- Bbor.java -----
786    class Bbor
787    {
788        static get POW_2_16()
789        {
790            return Math.pow(2, 16);
791        }
792
793        static get POW_2_32()
794        {
795            return Math.pow(2, 32);
796        }
797
798        static get JS_MAX_SAFE_INTEGER()
799        {
800            return Number.MAX_SAFE_INTEGER;
801        }
802    }
803
804    Bbor.Token = {
805        END_OBJECT: 'END_OBJECT',
806        START_OBJECT: 'START_OBJECT',
807        END_ARRAY: 'END_ARRAY',
808        START_ARRAY: 'START_ARRAY',
809        FIELD_NAME: 'FIELD_NAME',
810        VALUE_STRING: 'VALUE_STRING',
811        VALUE_NUMBER_INT: 'VALUE_NUMBER_INT',
812        VALUE_NUMBER_FLOAT: 'VALUE_NUMBER_FLOAT',
813        VALUE_TRUE: 'VALUE_TRUE',
814        VALUE_FALSE: 'VALUE_FALSE',
815        VALUE_NULL: 'VALUE_NULL'
816    };
817
818    Bbor.TokenRev = {
819        START_OBJECT: Bbor.Token.END_OBJECT,
820        START_ARRAY: Bbor.Token.END_ARRAY
821    };
822
823    Bbor.Primitive = {
824        POSITIVE_INTEGER: 'POSITIVE_INTEGER',
825        NEGATIVE_INTEGER: 'NEGATIVE_INTEGER',
826        BYTE_STRING: 'BYTE_STRING',
827        TEXT_STRING: 'TEXT_STRING',
828        POSITIVE_BIGNUM: 'POSITIVE_BIGNUM',
829        NEGATIVE_BIGNUM: 'NEGATIVE_BIGNUM',
830        BOOLEAN: 'BOOLEAN',
831        NULL: 'NULL',
832        UNDEFINED: 'UNDEFINED',
833        BYTE: 'BYTE',
834        FLOAT16: 'FLOAT16',
835        FLOAT32: 'FLOAT32',
836        FLOAT64: 'FLOAT64'
837    };
838
839    class BborCtx
840    {
841        constructor(prev, token, size)
842        {
843            this.prev = prev;
844            this.token = token;
845            this.size = size;
846            this.pos = -1;
847            this.field = null;
848        }
849    }
850
851    Bbor.Ctx = BborCtx;
852
853    class BborEncoder
854    {
855        constructor(config)
856        {
857            this.config = config || Bbor.DEFAULT_CONFIG;
858            this.fields = new FlexDict(this.config.staticFields);
859        }
860
861        write(outputStream, compressor, value)
862        {
863            if (value === null) {
864                return this.writeNull(outputStream);
865            }
866
867            if (value === undefined) {
868                return this.writeUndefined(outputStream);
869            }
870
871            if (typeof value === 'boolean') {
872                return this.writeBoolean(outputStream, value);
873            }
874
875            if (typeof value === 'number') {
876                return this.writeNumber(outputStream, value);
877            }
878
879            if (typeof value === 'string') {
880                return this.writeString(outputStream, compressor, value);
881            }
882
883            if (value instanceof Uint8Array) {
884                return this.writeBytes(outputStream, value);
885            }
886
887            if (Array.isArray(value)) {
888                this.writeStartArray(outputStream, value.length);
889                for (var i = 0; i < value.length; i++) {
890                    this.write(outputStream, compressor, value[i]);
891                }
892                this.writeEndArray(outputStream);
893                return this;
894            }
895
896            if (typeof value === 'object') {
897                var keys = Object.keys(value);
898                this.writeStartObject(outputStream, keys.length);
899                for (var i = 0; i < keys.length; i++) {
900                    this.writeFieldName(outputStream, compressor, keys[i]);
901                    this.write(outputStream, compressor, value[keys[i]]);
902                }
903                this.writeEndObject(outputStream);
904                return this;
905            }
906
907            if (typeof value === 'function') {
908                // update 2990725: decided to add this as a NOOP
909                // so we don't need to add logic to skip the functions
910                // in some exotic objects (like fullcalendar events),
911                // but know they won't get serialized (could be a future todo or config setting)!
912                return this;
913            }
914
915            throw new Error("Unsupported type: " + typeof value);
916        }
917
918        writeNull(outputStream)
919        {
920            this.writeUint8(outputStream, 0xf6);
921            return this;
922        }
923
924        writeUndefined(outputStream)
925        {
926            this.writeUint8(outputStream, 0xf7);
927            return this;
928        }
929
930        writeBoolean(outputStream, value)
931        {
932            this.writeUint8(outputStream, value ? 0xf5 : 0xf4);
933            return this;
934        }
935
936        /**
937         * Watch out: JS has only a single numeric type: Number,
938         * which is a double-precision 64-bit floating point number (IEEE 754)
939         * All numbers are stored as 64-bit floating point numbers (doubles).
940         * Note that a side effect of this Java port is that the toPositiveBigNum() below
941         * will never trigger, since we already checked for <= Number.MAX_SAFE_INTEGER.
942         */
943        writeNumber(outputStream, value)
944        {
945            if (Math.floor(value) === value && Math.abs(value) <= Number.MAX_SAFE_INTEGER) {
946                if (value >= 0) {
947                    if (value <= Bbor.JS_MAX_SAFE_INTEGER) {
948                        this.writeTypeAndLength(outputStream, 0, value);
949                        return this;
950                    }
951                    // should never trigger
952                    else {
953                        this.writeUint8(outputStream, 0xc2);
954                        var bytes = this.toPositiveBigNum(value);
955                        this.writeTypeAndLength(outputStream, 2, bytes.length);
956                        for (var i = 0; i < bytes.length; i++) {
957                            this.writeUint8(outputStream, bytes[i]);
958                        }
959                        return this;
960                    }
961                }
962                else {
963                    if (-Bbor.JS_MAX_SAFE_INTEGER <= value) {
964                        this.writeTypeAndLength(outputStream, 1, -1 - value);
965                        return this;
966                    }
967                    // should never trigger
968                    else {
969                        this.writeUint8(outputStream, 0xc3);
970                        var bytes = this.toPositiveBigNum(-1 - value);
971                        this.writeTypeAndLength(outputStream, 2, bytes.length);
972                        for (var i = 0; i < bytes.length; i++) {
973                            this.writeUint8(outputStream, bytes[i]);
974                        }
975                        return this;
976                    }
977                }
978            }
979
980            // little trick to reduce the precision of a decimal to 32-bits
981            var float32 = new Float32Array([value])[0];
982            if (Math.abs((value - float32) / value) < 1e-7) {
983                this.writeUint8(outputStream, 0xfa);
984                this.writeFloat32(outputStream, value);
985            }
986            else {
987                this.writeUint8(outputStream, 0xfb);
988                this.writeFloat64(outputStream, value);
989            }
990
991            return this;
992        }
993
994        writeString(outputStream, compressor, value)
995        {
996            // in JS, strings are represented as 16-bit Unicode characters (UTF-16),
997            // just like in Java, so nothing to change here when compression is enabled
998            if (this.config.enableStringCompression && compressor && value.length > 0) {
999                var byteStream = new ByteStream();
1000                compressor.compress(value, byteStream);
1001                byteStream.flush();
1002                this.writeTypeAndLength(outputStream, 3, byteStream.length());
1003                while (byteStream.hasNext(8)) {
1004                    this.writeUint8(outputStream, byteStream.read(8));
1005                }
1006                return this;
1007            }
1008            else {
1009                // equivalent of String.getBytes(), returns Uint8Array
1010                // (see original cbor.js for alternative, raw implementation)
1011                var utf8Data = new TextEncoder().encode(value);
1012                this.writeTypeAndLength(outputStream, 3, utf8Data.length);
1013                for (var i = 0; i < utf8Data.length; i++) {
1014                    this.writeUint8(outputStream, utf8Data[i]);
1015                }
1016                return this;
1017            }
1018        }
1019
1020        writeBytes(outputStream, value)
1021        {
1022            this.writeTypeAndLength(outputStream, 2, value.length);
1023            for (var i = 0; i < value.length; i++) {
1024                this.writeUint8(outputStream, value[i]);
1025            }
1026            return this;
1027        }
1028
1029        writeFieldName(outputStream, compressor, value)
1030        {
1031            if (this.config.enableKeyMapping) {
1032                if (!this.fields.hasKey(value)) {
1033                    this.writeString(outputStream, compressor, value);
1034                    this.fields.add(value, this.fields.size());
1035                }
1036                else {
1037                    this.writeNumber(outputStream, this.fields.get(value));
1038                }
1039            }
1040            else {
1041                this.writeString(outputStream, compressor, value);
1042            }
1043            return this;
1044        }
1045
1046        writeStartArray(outputStream, size)
1047        {
1048            this.writeTypeAndLength(outputStream, 4, size);
1049            return this;
1050        }
1051
1052        writeEndArray(outputStream)
1053        {
1054            return this;
1055        }
1056
1057        writeStartObject(outputStream, size)
1058        {
1059            this.writeTypeAndLength(outputStream, 5, size);
1060            return this;
1061        }
1062
1063        writeEndObject(outputStream)
1064        {
1065            return this;
1066        }
1067
1068        writeTypeAndLength(outputStream, type, length)
1069        {
1070            if (length < 24) {
1071                this.writeUint8(outputStream, (type << 5) | length);
1072            }
1073            else if (length < 0x100) {
1074                this.writeUint8(outputStream, (type << 5) | 24);
1075                this.writeUint8(outputStream, length);
1076            }
1077            else if (length < 0x10000) {
1078                this.writeUint8(outputStream, (type << 5) | 25);
1079                this.writeUint16(outputStream, length);
1080            }
1081            else if (length < 0x100000000) {
1082                this.writeUint8(outputStream, (type << 5) | 26);
1083                this.writeUint32(outputStream, length);
1084            }
1085            else {
1086                this.writeUint8(outputStream, (type << 5) | 27);
1087                this.writeUint64(outputStream, length);
1088            }
1089        }
1090
1091        writeUint8(outputStream, value)
1092        {
1093            outputStream.write(value, 8);
1094        }
1095
1096        writeUint16(outputStream, value)
1097        {
1098            outputStream.write(value, 16);
1099        }
1100
1101        writeUint32(outputStream, value)
1102        {
1103            outputStream.write(value, 32);
1104        }
1105
1106        writeUint64(outputStream, value)
1107        {
1108            var low = value % Bbor.POW_2_32;
1109            var high = (value - low) / Bbor.POW_2_32;
1110            outputStream.write(high, 32);
1111            outputStream.write(low, 32);
1112        }
1113
1114        writeFloat32(outputStream, value)
1115        {
1116            this.writeUint32(outputStream, this.floatToIntBits(value));
1117        }
1118
1119        // this is a bit different from the Java implementation because we wanted to avoid BigInt
1120        // and return two 32-bit numbers instead
1121        writeFloat64(outputStream, value)
1122        {
1123            var bits = this.doubleToLongBits(value);
1124            outputStream.write(bits.high, 32);
1125            outputStream.write(bits.low, 32);
1126        }
1127
1128        toPositiveBigNum(value)
1129        {
1130            var bytes = new Array(8);
1131            for (var i = 0; i < 8; i++) {
1132                bytes[7 - i] = value & 0xFF;
1133                value = value >>> 8;
1134            }
1135
1136            var startIndex = 0;
1137            while (startIndex < 7 && bytes[startIndex] === 0) {
1138                startIndex++;
1139            }
1140
1141            return bytes.slice(startIndex);
1142        }
1143
1144        // JS port of Float.floatToIntBits()
1145        floatToIntBits(value)
1146        {
1147            // Create an ArrayBuffer with 4 bytes (32 bits)
1148            var buffer = new ArrayBuffer(4);
1149            // Create a DataView for binary manipulation
1150            var view = new DataView(buffer);
1151            // Store the float32 in the buffer
1152            view.setFloat32(0, value, false); // false = big-endian, as used in IEEE 754
1153            // Retrieve the 32-bit integer representation
1154            return view.getInt32(0, false); // false = big-endian
1155        }
1156
1157        // JS port of Double.doubleToLongBits()
1158        doubleToLongBits(value)
1159        {
1160            // Create an ArrayBuffer with 8 bytes (64 bits)
1161            var buffer = new ArrayBuffer(8);
1162            // Create a DataView for binary manipulation
1163            var view = new DataView(buffer);
1164            // Store the float64 (double) in the buffer
1165            view.setFloat64(0, value, false); // false = big-endian, as used in IEEE 754
1166            // Retrieve the 64-bit representation as two 32-bit integers
1167            // since JavaScript doesn't natively support 64-bit integers,
1168            // and we want to avoid BigInt because too recent
1169            return {
1170                high: view.getUint32(0, false), // Top 32 bits
1171                low: view.getUint32(4, false) // Bottom 32 bits
1172            };
1173        }
1174    }
1175    Bbor.Encoder = BborEncoder;
1176
1177    class BborDecoder
1178    {
1179        constructor(config)
1180        {
1181            this.config = config || Bbor.DEFAULT_CONFIG;
1182            this.fields = new FlexDict(this.config.staticFieldsRev);
1183            this.ctx = null;
1184            this.primitive = null;
1185            this.value = null;
1186            this.readingValue = false;
1187            this.end = false;
1188        }
1189
1190        read(base62Decoder, compressor)
1191        {
1192            var token = this.readNext(base62Decoder, compressor);
1193            if (token === null) {
1194                return Bbor.Decoder.END;
1195            }
1196
1197            switch (token) {
1198                case Bbor.Token.START_OBJECT:
1199                    // let's use a plain object instead of new Map() because string-based keys
1200                    // retain insertion order as of ES2015, so this should be equal to LinkedHashMap
1201                    var obj = {};
1202                    var next;
1203                    while ((next = this.read(base62Decoder, compressor)) !== Bbor.Decoder.END) {
1204                        obj[next] = this.read(base62Decoder, compressor);
1205                    }
1206                    return obj;
1207
1208                case Bbor.Token.START_ARRAY:
1209                    var arr = [];
1210                    var el;
1211                    while ((el = this.read(base62Decoder, compressor)) !== Bbor.Decoder.END) {
1212                        arr.push(el);
1213                    }
1214                    return arr;
1215
1216                case Bbor.Token.END_OBJECT:
1217                case Bbor.Token.END_ARRAY:
1218                    return Bbor.Decoder.END;
1219
1220                default:
1221                    return this.value;
1222            }
1223        }
1224
1225        readNext(inputStream, compressor)
1226        {
1227            var t, initialByte, majorType, additionalInfo, length;
1228            var retVal, bytes, positive, high, low;
1229            var i;
1230
1231            if (!this.readingValue) {
1232                if (this.ctx !== null) {
1233                    t = this.ctx.token;
1234                    if (t === Bbor.Token.START_OBJECT || t === Bbor.Token.START_ARRAY) {
1235                        this.ctx.pos++;
1236                        if (this.ctx.pos === this.ctx.size) {
1237                            this.ctx = this.ctx.prev;
1238                            this.end = this.ctx === null;
1239                            return Bbor.TokenRev[t];
1240                        }
1241                    }
1242                }
1243                else {
1244                    if (this.end) {
1245                        return null;
1246                    }
1247                }
1248            }
1249
1250            initialByte = this.readUint8(inputStream);
1251            majorType = initialByte >>> 5;
1252            additionalInfo = initialByte & 0x1f;
1253            length = this.readLength(inputStream, additionalInfo);
1254
1255            this.value = null;
1256            this.primitive = null;
1257
1258            switch (majorType) {
1259                case 0:
1260                    // in case of a 64bit number, length will hold the high/low parts and we need to rebuild it
1261                    if (additionalInfo === 27) {
1262                        this.value = (length.high * Bbor.POW_2_32) + length.low;
1263                    }
1264                    else {
1265                        this.value = length;
1266                    }
1267                    this.primitive = Bbor.Primitive.POSITIVE_INTEGER;
1268                    retVal = Bbor.Token.VALUE_NUMBER_INT;
1269                    break;
1270
1271                case 1:
1272                    this.value = -1 - length;
1273                    this.primitive = Bbor.Primitive.NEGATIVE_INTEGER;
1274                    retVal = Bbor.Token.VALUE_NUMBER_INT;
1275                    break;
1276
1277                case 2:
1278                    bytes = new Uint8Array(length);
1279                    for (i = 0; i < bytes.length; i++) {
1280                        bytes[i] = inputStream.read(8);
1281                    }
1282                    this.value = bytes;
1283                    this.primitive = Bbor.Primitive.BYTE_STRING;
1284                    retVal = Bbor.Token.START_ARRAY;
1285                    break;
1286
1287                case 3:
1288                    this.value = this.readString(inputStream, compressor, length);
1289                    this.primitive = Bbor.Primitive.TEXT_STRING;
1290                    retVal = Bbor.Token.VALUE_STRING;
1291                    break;
1292
1293                case 4:
1294                    this.ctx = new Bbor.Ctx(this.ctx, Bbor.Token.START_ARRAY, length);
1295                    retVal = Bbor.Token.START_ARRAY;
1296                    break;
1297
1298                case 5:
1299                    this.ctx = new Bbor.Ctx(this.ctx, Bbor.Token.START_OBJECT, length * 2);
1300                    retVal = Bbor.Token.START_OBJECT;
1301                    break;
1302
1303                case 6:
1304                    switch (additionalInfo) {
1305                        case 2:
1306                        case 3:
1307                            positive = additionalInfo === 2;
1308                            this.readingValue = true;
1309                            if (this.readNext(inputStream, compressor) === Bbor.Token.START_ARRAY) {
1310                                this.value = positive ? this.fromPositiveBigNum(this.value) :
1311                                    -1 - this.fromPositiveBigNum(this.value);
1312                                this.primitive = positive ? Bbor.Primitive.POSITIVE_BIGNUM : Bbor.Primitive.NEGATIVE_BIGNUM;
1313                                this.readingValue = false;
1314                                retVal = Bbor.Token.VALUE_NUMBER_INT;
1315                            }
1316                            else {
1317                                throw new Error("Encountered bignum, but the next token isn't a byte array");
1318                            }
1319                            break;
1320                        default:
1321                            throw new Error("Unimplemented tag value: " + additionalInfo);
1322                    }
1323                    break;
1324
1325                case 7:
1326                    switch (additionalInfo) {
1327                        case 20:
1328                            this.value = false;
1329                            this.primitive = Bbor.Primitive.BOOLEAN;
1330                            retVal = Bbor.Token.VALUE_FALSE;
1331                            break;
1332                        case 21:
1333                            this.value = true;
1334                            this.primitive = Bbor.Primitive.BOOLEAN;
1335                            retVal = Bbor.Token.VALUE_TRUE;
1336                            break;
1337                        case 22:
1338                            this.value = null;
1339                            this.primitive = Bbor.Primitive.NULL;
1340                            retVal = Bbor.Token.VALUE_NULL;
1341                            break;
1342                        case 23:
1343                            this.value = undefined;
1344                            this.primitive = Bbor.Primitive.UNDEFINED;
1345                            retVal = Bbor.Token.VALUE_NULL;
1346                            break;
1347                        case 24:
1348                            this.value = this.readUint8(inputStream);
1349                            this.primitive = Bbor.Primitive.BYTE;
1350                            retVal = Bbor.Token.VALUE_NUMBER_INT;
1351                            break;
1352                        case 25:
1353                            throw new Error("Half-precision float not implemented");
1354                        case 26:
1355                            this.value = this.intBitsToFloat(length);
1356                            this.primitive = Bbor.Primitive.FLOAT32;
1357                            retVal = Bbor.Token.VALUE_NUMBER_FLOAT;
1358                            break;
1359                        case 27:
1360                            // note that length will hold the high/low bits here
1361                            this.value = this.longBitsToDouble(length);
1362                            this.primitive = Bbor.Primitive.FLOAT64;
1363                            retVal = Bbor.Token.VALUE_NUMBER_FLOAT;
1364                            break;
1365                        default:
1366                            throw new Error("Unimplemented floating-point or simple value: " + additionalInfo);
1367                    }
1368                    break;
1369
1370                default:
1371                    throw new Error("Unknown major type: " + majorType);
1372            }
1373
1374            if (this.ctx !== null && this.ctx.token === Bbor.Token.START_OBJECT && this.ctx.pos % 2 === 0) {
1375                this.primitive = null;
1376                this.value = this.parseField(this.value);
1377                this.ctx.field = this.value;
1378                retVal = Bbor.Token.FIELD_NAME;
1379            }
1380
1381            return retVal;
1382        }
1383
1384        readLength(inputStream, additionalInfo)
1385        {
1386            if (additionalInfo < 24) {
1387                return additionalInfo;
1388            }
1389            switch (additionalInfo) {
1390                case 24:
1391                    return this.readUint8(inputStream);
1392                case 25:
1393                    return this.readUint16(inputStream);
1394                case 26:
1395                    return this.readUint32(inputStream);
1396                case 27:
1397                    return this.readUint64(inputStream);
1398                default:
1399                    throw new Error("Invalid additional info: " + additionalInfo);
1400            }
1401        }
1402
1403        readString(inputStream, compressor, length)
1404        {
1405            var bytes, i;
1406            if (this.config.enableStringCompression && compressor && length > 0) {
1407                return compressor.decompress(new WrappedByteReader(inputStream, length));
1408            }
1409            else {
1410                bytes = new Uint8Array(length);
1411                for (i = 0; i < length; i++) {
1412                    bytes[i] = inputStream.read(8);
1413                }
1414                return new TextDecoder().decode(bytes);
1415            }
1416        }
1417
1418        readUint8(inputStream)
1419        {
1420            return inputStream.read(8) & 0xFF;
1421        }
1422
1423        readUint16(inputStream)
1424        {
1425            return inputStream.read(16) & 0xFFFF;
1426        }
1427
1428        readUint32(inputStream)
1429        {
1430            var high = this.readUint16(inputStream);
1431            var low = this.readUint16(inputStream);
1432            return (high * Bbor.POW_2_16) + low;
1433        }
1434
1435        readUint64(inputStream)
1436        {
1437            // see encoder: since there's no support for 64-bit integers, let's return a split
1438            // Also note we don't need to reconstruct the parts using POW_2_32 because we'll write them to the raw bitstream
1439            // The >>> 0 is crucial here - it forces JavaScript to interpret the number as an unsigned 32-bit integer.
1440            // Without it, the negative value would be added instead of the intended unsigned value.
1441            return {
1442                high: inputStream.read(32) >>> 0,
1443                low: inputStream.read(32) >>> 0,
1444            };
1445        }
1446
1447        fromPositiveBigNum(bytes)
1448        {
1449            var result = 0;
1450            for (var i = 0; i < bytes.length; i++) {
1451                result = (result << 8) | (bytes[i] & 0xFF);
1452            }
1453            return result;
1454        }
1455
1456        parseField(nameOrIdx)
1457        {
1458            if (this.config.enableKeyMapping) {
1459                if (typeof nameOrIdx === 'string') {
1460                    this.fields.add(this.fields.size(), nameOrIdx);
1461                }
1462                else if (typeof nameOrIdx === 'number') {
1463                    nameOrIdx = this.fields.get(nameOrIdx);
1464                }
1465                else {
1466                    throw new Error("Invalid key type: " + typeof nameOrIdx);
1467                }
1468            }
1469            return nameOrIdx;
1470        }
1471
1472        intBitsToFloat(bits)
1473        {
1474            // Create an ArrayBuffer with 4 bytes (32 bits)
1475            var buffer = new ArrayBuffer(4);
1476            // Create a DataView for binary manipulation
1477            var view = new DataView(buffer);
1478            // Store the 32-bit integer in the buffer
1479            view.setInt32(0, bits, false); // false = big-endian, as used in IEEE 754
1480            // Retrieve the floating-point number from the buffer
1481            var value = view.getFloat32(0, false); // false = big-endian
1482
1483            // The reason for 7 digits is that IEEE 754 single-precision floats can represent approximately 6-7 decimal digits of precision.
1484            // Java automatically handles this for you because it maintains the 32-bit float type,
1485            // while in JavaScript we need to handle the display precision explicitly since it converts everything to 64-bit doubles.
1486            // the Number() is needed because toPrecision() returns a string (and it removed trailing zeros)
1487            // Note that we only apply this for decimal values or we'll lose int precision since this is also called
1488            // for (large) integers like Number.MAX_SAFE_INTEGER + 1
1489            if (Math.floor(value) !== value) {
1490                value = Number(value.toPrecision(7));
1491            }
1492
1493            return value;
1494        }
1495
1496        longBitsToDouble(bits)
1497        {
1498            // Create an ArrayBuffer with 8 bytes (64 bits)
1499            var buffer = new ArrayBuffer(8);
1500            // Create a DataView for binary manipulation
1501            var view = new DataView(buffer);
1502            // Store the high 32 bits and low 32 bits in the buffer
1503            view.setUint32(0, bits.high, false); // Top 32 bits (big-endian)
1504            view.setUint32(4, bits.low, false); // Bottom 32 bits (big-endian)
1505            // Retrieve the floating-point number from the buffer
1506            return view.getFloat64(0, false); // false = big-endian
1507        }
1508    }
1509
1510    Bbor.Decoder = BborDecoder;
1511    // Empty objects compared with === or Object.is() return false unless they reference the exact same object.
1512    Bbor.Decoder.END = {};
1513
1514    Bbor.DEFAULT_CONFIG = {
1515
1516        INITIAL_FIELDS: [
1517            "id",
1518            "type",
1519            "name",
1520            "status",
1521            "count",
1522            "data",
1523            "value",
1524            "error",
1525            "response",
1526            "version"
1527        ],
1528
1529        enableKeyMapping: true,
1530        enableStringCompression: true,
1531        staticFields: new Map(),
1532        staticFieldsRev: new Map(),
1533
1534        init()
1535        {
1536            for (var i = 0; i < this.INITIAL_FIELDS.length; i++) {
1537                var c = this.INITIAL_FIELDS[i];
1538                if (!this.staticFields.has(c)) {
1539                    this.staticFields.set(c, i);
1540                    this.staticFieldsRev.set(i, c);
1541                }
1542                else {
1543                    throw new Error("Duplicate static field detected '" + c + "'");
1544                }
1545            }
1546        },
1547    };
1548    Bbor.DEFAULT_CONFIG.init();
1549
1550    // ----- MAIN -----
1551    this.encode = function (obj)
1552    {
1553        var retVal = "";
1554        var base62Encoder = new BaseXStream.Encoder(function (str)
1555        {
1556            retVal += str;
1557        });
1558        new Bbor.Encoder().write(base62Encoder, new LZW(), obj);
1559        base62Encoder.flush();
1560        return retVal;
1561    };
1562
1563    this.decode = function (str)
1564    {
1565        return new Bbor.Decoder().read(new BaseXStream.Decoder(str), new LZW());
1566    };
1567
1568}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.