Skip to content

Instantly share code, notes, and snippets.

@loilo
Last active April 26, 2024 23:37
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loilo/92220c23567d6ed085a28f2c3e84e311 to your computer and use it in GitHub Desktop.
Save loilo/92220c23567d6ed085a28f2c3e84e311 to your computer and use it in GitHub Desktop.
URL-Safe LZMA Compression

URL-Safe LZMA Compression

This Gist provides JavaScript functions to compress a string for usage in URLs using a very space-efficient but comparatively slow algorithm. It's great for sharing larger amounts of data as part of a URL.

The raw algorithm is taken from lzma-js, converted to an ES module and with some features stripped off (e.g. async mode, worker support), the URL-safe functionality was added by me.

If you need to compress data very frequently (e.g. on each keystroke of a user), you probably should look out for a faster alternative (e.g. lz-string).

Usage

Note: The JavaScript files of this Gist are using some ES2015 features in general and ES modules in particular. You can safely use them in modern browsers, however using them in Node.js or legacy browsers would need an additional transpile and/or bundling step.

Compress

Let's compress this example JSON data set (you can see the code in action on CodeSandbox):

import { compressUrlSafe } from './lzma-url.mjs'

const data = {
  id: '0001',
  type: 'donut',
  name: 'Cake',
  ppu: 0.55,
  batters: {
    batter: [
      { id: '1001', type: 'Regular' },
      { id: '1002', type: 'Chocolate' },
      { id: '1003', type: 'Blueberry' },
      { id: '1004', type: "Devil's Food" }
    ]
  },
  topping: [
    { id: '5001', type: 'None' },
    { id: '5002', type: 'Glazed' },
    { id: '5005', type: 'Sugar' },
    { id: '5007', type: 'Powdered Sugar' },
    { id: '5006', type: 'Chocolate with Sprinkles' },
    { id: '5003', type: 'Chocolate' },
    { id: '5004', type: 'Maple' }
  ]
}

const serializedData = JSON.stringify(data)
const compressedSerializedData = compressUrlSafe(serializedData)

console.log(`${serializedData.length} -> ${compressedSerializedData.length} bytes`)

This outputs 456 -> 294 bytes and generates the following compressed string:

  XQAAgADIAQAAAAAAAAA9iIkmgZNThWHvkoxYOhkMap8xuPc5WJAnOm0EWWnOco5kpp0Q6jEiL_ERvnqVST8OmSqcdDKPT_LOC3CazYNsg7FftTjd4Zel5ueEC81Jpd5wHZQR2Or1OaZBQ3T3cv4zYtBAgADqtQSoIb_JFbnNtPzJZzYWb3R6wEDt_nh-9LPC-aOKFlNdD2fxD3YrgY_VF8FHT_gZfYm3QyLnmLTiLMkEzDyXZfIlts_0cuEGCwzFxXr3RqKT4Sn_h8BYuRXcvvLu4BHB_-aH5pg%3D

This example shows a reduction of just ≈35%, however especially when encoding JSON structures (where usually there is a lot of duplicate content), space-efficiency increases greatly for larger data sets (my test dataset of 30 KB went down to just 4.9 KB).

Decompress

Inversely, we can take our generated string from above and convert it back to plain text:

import { decompressUrlSafe } from './lzma-url.mjs'

const compressedSerializedData = `XQAAgADIAQAAAAAAAAA9iIkmgZNThWHvkoxYOhkMap8xuPc5WJAnOm0EWWnOco5kpp0Q6jEiL_ERvnqVST8OmSqcdDKPT_LOC3CazYNsg7FftTjd4Zel5ueEC81Jpd5wHZQR2Or1OaZBQ3T3cv4zYtBAgADqtQSoIb_JFbnNtPzJZzYWb3R6wEDt_nh-9LPC-aOKFlNdD2fxD3YrgY_VF8FHT_gZfYm3QyLnmLTiLMkEzDyXZfIlts_0cuEGCwzFxXr3RqKT4Sn_h8BYuRXcvvLu4BHB_-aH5pg%3D`

const serializedData = decompressUrlSafe(compressedSerializedData)

The serializedData variable now contains the serialized JSON data:

{"id":"0001","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"},{"id":"1003","type":"Blueberry"},{"id":"1004","type":"Devil's Food"}]},"topping":[{"id":"5001","type":"None"},{"id":"5002","type":"Glazed"},{"id":"5005","type":"Sugar"},{"id":"5007","type":"Powdered Sugar"},{"id":"5006","type":"Chocolate with Sprinkles"},{"id":"5003","type":"Chocolate"},{"id":"5004","type":"Maple"}]}

To get back our original data, we'd just have to pass that through JSON.parse().

/**
* Convert between Uint8Array and Base64 strings
* Allows for any encoded JS string to be converted (as opposed to atob()/btoa() which only supports latin1)
*
* Original implementation by madmurphy on MDN
* @see https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_1_–_JavaScript%27s_UTF-16_%3E_base64
*/
function b64ToUint6(nChr) {
return nChr > 64 && nChr < 91
? nChr - 65
: nChr > 96 && nChr < 123
? nChr - 71
: nChr > 47 && nChr < 58
? nChr + 4
: nChr === 43
? 62
: nChr === 47
? 63
: 0
}
export function decodeToArray(base64string, blockSize) {
var sB64Enc = base64string.replace(/[^A-Za-z0-9\+\/]/g, ''),
nInLen = sB64Enc.length,
nOutLen = blockSize
? Math.ceil(((nInLen * 3 + 1) >>> 2) / blockSize) * blockSize
: (nInLen * 3 + 1) >>> 2,
aBytes = new Uint8Array(nOutLen)
for (
var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0;
nInIdx < nInLen;
nInIdx++
) {
nMod4 = nInIdx & 3
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (18 - 6 * nMod4)
if (nMod4 === 3 || nInLen - nInIdx === 1) {
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
aBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255
}
nUint24 = 0
}
}
return aBytes
}
function uint6ToB64(nUint6) {
return nUint6 < 26
? nUint6 + 65
: nUint6 < 52
? nUint6 + 71
: nUint6 < 62
? nUint6 - 4
: nUint6 === 62
? 43
: nUint6 === 63
? 47
: 65
}
export function encodeFromArray(bytes) {
var eqLen = (3 - (bytes.length % 3)) % 3,
sB64Enc = ''
for (
var nMod3, nLen = bytes.length, nUint24 = 0, nIdx = 0;
nIdx < nLen;
nIdx++
) {
nMod3 = nIdx % 3
/* Uncomment the following line in order to split the output in lines 76-character long: */
/*
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; }
*/
nUint24 |= bytes[nIdx] << ((16 >>> nMod3) & 24)
if (nMod3 === 2 || bytes.length - nIdx === 1) {
sB64Enc += String.fromCharCode(
uint6ToB64((nUint24 >>> 18) & 63),
uint6ToB64((nUint24 >>> 12) & 63),
uint6ToB64((nUint24 >>> 6) & 63),
uint6ToB64(nUint24 & 63)
)
nUint24 = 0
}
}
return eqLen === 0
? sB64Enc
: sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? '=' : '==')
}
/**
* URL-safe variants of Base64 conversion functions (aka base64url)
* @see https://tools.ietf.org/html/rfc4648#section-5
*/
export function encodeFromArrayUrlSafe(bytes) {
return encodeURIComponent(
encodeFromArray(bytes)
.replace(/\+/g, '-')
.replace(/\//g, '_')
)
}
export function decodeToArrayUrlSafe(base64string) {
return decodeToArray(
decodeURIComponent(base64string)
.replace(/-/g, '+')
.replace(/_/g, '/')
)
}
/*
The LZMA impementation is taken from https://npm.is/lzma-js, converted to an ES module and with some features stripped off (e.g. async mode, worker support)
Here's the according MIT license:
© 2016 Nathan Rugg <nmrugg@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import * as base64 from './base64.mjs'
const __4294967296 = 4294967296,
N1_longLit = [4294967295, -__4294967296],
MIN_VALUE = [0, -9223372036854775808],
P0_longLit = [0, 0],
P1_longLit = [1, 0]
function add(a, b) {
return create(a[0] + b[0], a[1] + b[1])
}
function initDim(len) {
// NOTE: This is MUCH faster than "initDim(len)" in newer versions of v8 (starting with Node.js 0.11.15, which uses v8 3.28.73).
var a = []
a[len - 1] = undefined
return a
}
function and(a, b) {
return makeFromBits(
~~Math.max(Math.min(a[1] / __4294967296, 2147483647), -2147483648) &
~~Math.max(Math.min(b[1] / __4294967296, 2147483647), -2147483648),
lowBits_0(a) & lowBits_0(b)
)
}
function compare(a, b) {
var nega, negb
if (a[0] == b[0] && a[1] == b[1]) {
return 0
}
nega = a[1] < 0
negb = b[1] < 0
if (nega && !negb) {
return -1
}
if (!nega && negb) {
return 1
}
if (sub(a, b)[1] < 0) {
return -1
}
return 1
}
function create(valueLow, valueHigh) {
var diffHigh, diffLow
valueHigh %= 1.8446744073709552e19
valueLow %= 1.8446744073709552e19
diffHigh = valueHigh % __4294967296
diffLow = Math.floor(valueLow / __4294967296) * __4294967296
valueHigh = valueHigh - diffHigh + diffLow
valueLow = valueLow - diffLow + diffHigh
while (valueLow < 0) {
valueLow += __4294967296
valueHigh -= __4294967296
}
while (valueLow > 4294967295) {
valueLow -= __4294967296
valueHigh += __4294967296
}
valueHigh = valueHigh % 1.8446744073709552e19
while (valueHigh > 9223372032559808512) {
valueHigh -= 1.8446744073709552e19
}
while (valueHigh < -9223372036854775808) {
valueHigh += 1.8446744073709552e19
}
return [valueLow, valueHigh]
}
function eq(a, b) {
return a[0] == b[0] && a[1] == b[1]
}
function fromInt(value) {
if (value >= 0) {
return [value, 0]
} else {
return [value + __4294967296, -__4294967296]
}
}
function lowBits_0(a) {
if (a[0] >= 2147483648) {
return ~~Math.max(Math.min(a[0] - __4294967296, 2147483647), -2147483648)
} else {
return ~~Math.max(Math.min(a[0], 2147483647), -2147483648)
}
}
function makeFromBits(highBits, lowBits) {
var high, low
high = highBits * __4294967296
low = lowBits
if (lowBits < 0) {
low += __4294967296
}
return [low, high]
}
function pwrAsDouble(n) {
if (n <= 30) {
return 1 << n
} else {
return pwrAsDouble(30) * pwrAsDouble(n - 30)
}
}
function shl(a, n) {
var diff, newHigh, newLow, twoToN
n &= 63
if (eq(a, MIN_VALUE)) {
if (!n) {
return a
}
return P0_longLit
}
if (a[1] < 0) {
throw new Error('Neg')
}
twoToN = pwrAsDouble(n)
newHigh = (a[1] * twoToN) % 1.8446744073709552e19
newLow = a[0] * twoToN
diff = newLow - (newLow % __4294967296)
newHigh += diff
newLow -= diff
if (newHigh >= 9223372036854775807) {
newHigh -= 1.8446744073709552e19
}
return [newLow, newHigh]
}
function shr(a, n) {
var shiftFact
n &= 63
shiftFact = pwrAsDouble(n)
return create(Math.floor(a[0] / shiftFact), a[1] / shiftFact)
}
function shru(a, n) {
var sr
n &= 63
sr = shr(a, n)
if (a[1] < 0) {
sr = add(sr, shl([2, 0], 63 - n))
}
return sr
}
function sub(a, b) {
return create(a[0] - b[0], a[1] - b[1])
}
function $ByteArrayInputStream(this$static, buf) {
this$static.buf = buf
this$static.pos = 0
this$static.count = buf.length
return this$static
}
function $read(this$static) {
if (this$static.pos >= this$static.count) return -1
return this$static.buf[this$static.pos++] & 255
}
function $read_0(this$static, buf, off, len) {
if (this$static.pos >= this$static.count) return -1
len = Math.min(len, this$static.count - this$static.pos)
arraycopy(this$static.buf, this$static.pos, buf, off, len)
this$static.pos += len
return len
}
function $ByteArrayOutputStream(this$static) {
this$static.buf = initDim(32)
this$static.count = 0
return this$static
}
function $toByteArray(this$static) {
var data = this$static.buf
data.length = this$static.count
return data
}
function $write(this$static, b) {
this$static.buf[this$static.count++] = (b << 24) >> 24
}
function $write_0(this$static, buf, off, len) {
arraycopy(buf, off, this$static.buf, this$static.count, len)
this$static.count += len
}
function $getChars(this$static, srcBegin, srcEnd, dst, dstBegin) {
var srcIdx
for (srcIdx = srcBegin; srcIdx < srcEnd; ++srcIdx) {
dst[dstBegin++] = this$static.charCodeAt(srcIdx)
}
}
function arraycopy(src, srcOfs, dest, destOfs, len) {
for (var i = 0; i < len; ++i) {
dest[destOfs + i] = src[srcOfs + i]
}
}
function $configure(this$static, encoder) {
$SetDictionarySize_0(encoder, 1 << this$static.s)
encoder._numFastBytes = this$static.f
$SetMatchFinder(encoder, this$static.m)
// lc is always 3
// lp is always 0
// pb is always 2
encoder._numLiteralPosStateBits = 0
encoder._numLiteralContextBits = 3
encoder._posStateBits = 2
encoder._posStateMask = 3
}
function $init(this$static, input, output, length_0, mode, enableEndMark) {
var encoder, i
if (compare(length_0, N1_longLit) < 0)
throw new Error('invalid length ' + length_0)
this$static.length_0 = length_0
encoder = $Encoder({})
$configure(mode, encoder)
encoder._writeEndMark = enableEndMark
$WriteCoderProperties(encoder, output)
for (i = 0; i < 64; i += 8) $write(output, lowBits_0(shr(length_0, i)) & 255)
this$static.chunker =
((encoder._needReleaseMFStream = 0),
((encoder._inStream = input),
(encoder._finished = 0),
$Create_2(encoder),
(encoder._rangeEncoder.Stream = output),
$Init_4(encoder),
$FillDistancesPrices(encoder),
$FillAlignPrices(encoder),
(encoder._lenEncoder._tableSize = encoder._numFastBytes + 1 - 2),
$UpdateTables(encoder._lenEncoder, 1 << encoder._posStateBits),
(encoder._repMatchLenEncoder._tableSize = encoder._numFastBytes + 1 - 2),
$UpdateTables(encoder._repMatchLenEncoder, 1 << encoder._posStateBits),
(encoder.nowPos64 = P0_longLit),
undefined),
$Chunker_0({}, encoder))
}
function $LZMAByteArrayCompressor(this$static, data, mode, enableEndMark) {
this$static.output = $ByteArrayOutputStream({})
$init(
this$static,
$ByteArrayInputStream({}, data),
this$static.output,
fromInt(data.length),
mode,
enableEndMark
)
return this$static
}
function $init_0(this$static, input, output) {
var decoder,
hex_length = '',
i,
properties = [],
r,
tmp_length
for (i = 0; i < 5; ++i) {
r = $read(input)
if (r == -1) throw new Error('truncated input')
properties[i] = (r << 24) >> 24
}
decoder = $Decoder({})
if (!$SetDecoderProperties(decoder, properties)) {
throw new Error('corrupted input')
}
for (i = 0; i < 64; i += 8) {
r = $read(input)
if (r == -1) throw new Error('truncated input')
r = r.toString(16)
if (r.length == 1) r = '0' + r
hex_length = r + '' + hex_length
}
// Was the length set in the header (if it was compressed from a stream, the length is all f"s).
if (/^0+$|^f+$/i.test(hex_length)) {
// The length is unknown, so set to -1.
this$static.length_0 = N1_longLit
} else {
// NOTE: If there is a problem with the decoder because of the length, you can always set the length to -1 (N1_longLit) which means unknown.
tmp_length = parseInt(hex_length, 16)
// If the length is too long to handle, just set it to unknown.
if (tmp_length > 4294967295) {
this$static.length_0 = N1_longLit
} else {
this$static.length_0 = fromInt(tmp_length)
}
}
this$static.chunker = $CodeInChunks(
decoder,
input,
output,
this$static.length_0
)
}
function $LZMAByteArrayDecompressor(this$static, data) {
this$static.output = $ByteArrayOutputStream({})
$init_0(this$static, $ByteArrayInputStream({}, data), this$static.output)
return this$static
}
function $Create_4(this$static, keepSizeBefore, keepSizeAfter, keepSizeReserv) {
var blockSize
this$static._keepSizeBefore = keepSizeBefore
this$static._keepSizeAfter = keepSizeAfter
blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv
if (this$static._bufferBase == null || this$static._blockSize != blockSize) {
this$static._bufferBase = null
this$static._blockSize = blockSize
this$static._bufferBase = initDim(this$static._blockSize)
}
this$static._pointerToLastSafePosition =
this$static._blockSize - keepSizeAfter
}
function $GetIndexByte(this$static, index) {
return this$static._bufferBase[
this$static._bufferOffset + this$static._pos + index
]
}
function $GetMatchLen(this$static, index, distance, limit) {
var i, pby
if (this$static._streamEndWasReached) {
if (this$static._pos + index + limit > this$static._streamPos) {
limit = this$static._streamPos - (this$static._pos + index)
}
}
++distance
pby = this$static._bufferOffset + this$static._pos + index
for (
i = 0;
i < limit &&
this$static._bufferBase[pby + i] ==
this$static._bufferBase[pby + i - distance];
++i
) {}
return i
}
function $GetNumAvailableBytes(this$static) {
return this$static._streamPos - this$static._pos
}
function $MoveBlock(this$static) {
var i, numBytes, offset
offset =
this$static._bufferOffset + this$static._pos - this$static._keepSizeBefore
if (offset > 0) {
--offset
}
numBytes = this$static._bufferOffset + this$static._streamPos - offset
for (i = 0; i < numBytes; ++i) {
this$static._bufferBase[i] = this$static._bufferBase[offset + i]
}
this$static._bufferOffset -= offset
}
function $MovePos_1(this$static) {
var pointerToPostion
++this$static._pos
if (this$static._pos > this$static._posLimit) {
pointerToPostion = this$static._bufferOffset + this$static._pos
if (pointerToPostion > this$static._pointerToLastSafePosition) {
$MoveBlock(this$static)
}
$ReadBlock(this$static)
}
}
function $ReadBlock(this$static) {
var numReadBytes, pointerToPostion, size
if (this$static._streamEndWasReached) return
while (1) {
size =
-this$static._bufferOffset +
this$static._blockSize -
this$static._streamPos
if (!size) return
numReadBytes = $read_0(
this$static._stream,
this$static._bufferBase,
this$static._bufferOffset + this$static._streamPos,
size
)
if (numReadBytes == -1) {
this$static._posLimit = this$static._streamPos
pointerToPostion = this$static._bufferOffset + this$static._posLimit
if (pointerToPostion > this$static._pointerToLastSafePosition) {
this$static._posLimit =
this$static._pointerToLastSafePosition - this$static._bufferOffset
}
this$static._streamEndWasReached = 1
return
}
this$static._streamPos += numReadBytes
if (
this$static._streamPos >=
this$static._pos + this$static._keepSizeAfter
) {
this$static._posLimit =
this$static._streamPos - this$static._keepSizeAfter
}
}
}
function $ReduceOffsets(this$static, subValue) {
this$static._bufferOffset += subValue
this$static._posLimit -= subValue
this$static._pos -= subValue
this$static._streamPos -= subValue
}
var CrcTable = (function() {
var i,
j,
r,
CrcTable = []
for (i = 0; i < 256; ++i) {
r = i
for (j = 0; j < 8; ++j)
if ((r & 1) != 0) {
r = (r >>> 1) ^ -306674912
} else {
r >>>= 1
}
CrcTable[i] = r
}
return CrcTable
})()
function $Create_3(
this$static,
historySize,
keepAddBufferBefore,
matchMaxLen,
keepAddBufferAfter
) {
var cyclicBufferSize, hs, windowReservSize
if (historySize < 1073741567) {
this$static._cutValue = 16 + (matchMaxLen >> 1)
windowReservSize =
~~(
(historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) /
2
) + 256
$Create_4(
this$static,
historySize + keepAddBufferBefore,
matchMaxLen + keepAddBufferAfter,
windowReservSize
)
this$static._matchMaxLen = matchMaxLen
cyclicBufferSize = historySize + 1
if (this$static._cyclicBufferSize != cyclicBufferSize) {
this$static._son = initDim(
(this$static._cyclicBufferSize = cyclicBufferSize) * 2
)
}
hs = 65536
if (this$static.HASH_ARRAY) {
hs = historySize - 1
hs |= hs >> 1
hs |= hs >> 2
hs |= hs >> 4
hs |= hs >> 8
hs >>= 1
hs |= 65535
if (hs > 16777216) hs >>= 1
this$static._hashMask = hs
++hs
hs += this$static.kFixHashSize
}
if (hs != this$static._hashSizeSum) {
this$static._hash = initDim((this$static._hashSizeSum = hs))
}
}
}
function $GetMatches(this$static, distances) {
var count,
cur,
curMatch,
curMatch2,
curMatch3,
cyclicPos,
delta,
hash2Value,
hash3Value,
hashValue,
len,
len0,
len1,
lenLimit,
matchMinPos,
maxLen,
offset,
pby1,
ptr0,
ptr1,
temp
if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) {
lenLimit = this$static._matchMaxLen
} else {
lenLimit = this$static._streamPos - this$static._pos
if (lenLimit < this$static.kMinMatchCheck) {
$MovePos_0(this$static)
return 0
}
}
offset = 0
matchMinPos =
this$static._pos > this$static._cyclicBufferSize
? this$static._pos - this$static._cyclicBufferSize
: 0
cur = this$static._bufferOffset + this$static._pos
maxLen = 1
hash2Value = 0
hash3Value = 0
if (this$static.HASH_ARRAY) {
temp =
CrcTable[this$static._bufferBase[cur] & 255] ^
(this$static._bufferBase[cur + 1] & 255)
hash2Value = temp & 1023
temp ^= (this$static._bufferBase[cur + 2] & 255) << 8
hash3Value = temp & 65535
hashValue =
(temp ^ (CrcTable[this$static._bufferBase[cur + 3] & 255] << 5)) &
this$static._hashMask
} else {
hashValue =
(this$static._bufferBase[cur] & 255) ^
((this$static._bufferBase[cur + 1] & 255) << 8)
}
curMatch = this$static._hash[this$static.kFixHashSize + hashValue] || 0
if (this$static.HASH_ARRAY) {
curMatch2 = this$static._hash[hash2Value] || 0
curMatch3 = this$static._hash[1024 + hash3Value] || 0
this$static._hash[hash2Value] = this$static._pos
this$static._hash[1024 + hash3Value] = this$static._pos
if (curMatch2 > matchMinPos) {
if (
this$static._bufferBase[this$static._bufferOffset + curMatch2] ==
this$static._bufferBase[cur]
) {
distances[offset++] = maxLen = 2
distances[offset++] = this$static._pos - curMatch2 - 1
}
}
if (curMatch3 > matchMinPos) {
if (
this$static._bufferBase[this$static._bufferOffset + curMatch3] ==
this$static._bufferBase[cur]
) {
if (curMatch3 == curMatch2) {
offset -= 2
}
distances[offset++] = maxLen = 3
distances[offset++] = this$static._pos - curMatch3 - 1
curMatch2 = curMatch3
}
}
if (offset != 0 && curMatch2 == curMatch) {
offset -= 2
maxLen = 1
}
}
this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos
ptr0 = (this$static._cyclicBufferPos << 1) + 1
ptr1 = this$static._cyclicBufferPos << 1
len0 = len1 = this$static.kNumHashDirectBytes
if (this$static.kNumHashDirectBytes != 0) {
if (curMatch > matchMinPos) {
if (
this$static._bufferBase[
this$static._bufferOffset + curMatch + this$static.kNumHashDirectBytes
] != this$static._bufferBase[cur + this$static.kNumHashDirectBytes]
) {
distances[offset++] = maxLen = this$static.kNumHashDirectBytes
distances[offset++] = this$static._pos - curMatch - 1
}
}
}
count = this$static._cutValue
while (1) {
if (curMatch <= matchMinPos || count-- == 0) {
this$static._son[ptr0] = this$static._son[ptr1] = 0
break
}
delta = this$static._pos - curMatch
cyclicPos =
(delta <= this$static._cyclicBufferPos
? this$static._cyclicBufferPos - delta
: this$static._cyclicBufferPos -
delta +
this$static._cyclicBufferSize) << 1
pby1 = this$static._bufferOffset + curMatch
len = len0 < len1 ? len0 : len1
if (
this$static._bufferBase[pby1 + len] == this$static._bufferBase[cur + len]
) {
while (++len != lenLimit) {
if (
this$static._bufferBase[pby1 + len] !=
this$static._bufferBase[cur + len]
) {
break
}
}
if (maxLen < len) {
distances[offset++] = maxLen = len
distances[offset++] = delta - 1
if (len == lenLimit) {
this$static._son[ptr1] = this$static._son[cyclicPos]
this$static._son[ptr0] = this$static._son[cyclicPos + 1]
break
}
}
}
if (
(this$static._bufferBase[pby1 + len] & 255) <
(this$static._bufferBase[cur + len] & 255)
) {
this$static._son[ptr1] = curMatch
ptr1 = cyclicPos + 1
curMatch = this$static._son[ptr1]
len1 = len
} else {
this$static._son[ptr0] = curMatch
ptr0 = cyclicPos
curMatch = this$static._son[ptr0]
len0 = len
}
}
$MovePos_0(this$static)
return offset
}
function $Init_5(this$static) {
this$static._bufferOffset = 0
this$static._pos = 0
this$static._streamPos = 0
this$static._streamEndWasReached = 0
$ReadBlock(this$static)
this$static._cyclicBufferPos = 0
$ReduceOffsets(this$static, -1)
}
function $MovePos_0(this$static) {
var subValue
if (++this$static._cyclicBufferPos >= this$static._cyclicBufferSize) {
this$static._cyclicBufferPos = 0
}
$MovePos_1(this$static)
if (this$static._pos == 1073741823) {
subValue = this$static._pos - this$static._cyclicBufferSize
$NormalizeLinks(
this$static._son,
this$static._cyclicBufferSize * 2,
subValue
)
$NormalizeLinks(this$static._hash, this$static._hashSizeSum, subValue)
$ReduceOffsets(this$static, subValue)
}
}
// NOTE: This is only called after reading one whole gigabyte.
function $NormalizeLinks(items, numItems, subValue) {
var i, value
for (i = 0; i < numItems; ++i) {
value = items[i] || 0
if (value <= subValue) {
value = 0
} else {
value -= subValue
}
items[i] = value
}
}
function $SetType(this$static, numHashBytes) {
this$static.HASH_ARRAY = numHashBytes > 2
if (this$static.HASH_ARRAY) {
this$static.kNumHashDirectBytes = 0
this$static.kMinMatchCheck = 4
this$static.kFixHashSize = 66560
} else {
this$static.kNumHashDirectBytes = 2
this$static.kMinMatchCheck = 3
this$static.kFixHashSize = 0
}
}
function $Skip(this$static, num) {
var count,
cur,
curMatch,
cyclicPos,
delta,
hash2Value,
hash3Value,
hashValue,
len,
len0,
len1,
lenLimit,
matchMinPos,
pby1,
ptr0,
ptr1,
temp
do {
if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) {
lenLimit = this$static._matchMaxLen
} else {
lenLimit = this$static._streamPos - this$static._pos
if (lenLimit < this$static.kMinMatchCheck) {
$MovePos_0(this$static)
continue
}
}
matchMinPos =
this$static._pos > this$static._cyclicBufferSize
? this$static._pos - this$static._cyclicBufferSize
: 0
cur = this$static._bufferOffset + this$static._pos
if (this$static.HASH_ARRAY) {
temp =
CrcTable[this$static._bufferBase[cur] & 255] ^
(this$static._bufferBase[cur + 1] & 255)
hash2Value = temp & 1023
this$static._hash[hash2Value] = this$static._pos
temp ^= (this$static._bufferBase[cur + 2] & 255) << 8
hash3Value = temp & 65535
this$static._hash[1024 + hash3Value] = this$static._pos
hashValue =
(temp ^ (CrcTable[this$static._bufferBase[cur + 3] & 255] << 5)) &
this$static._hashMask
} else {
hashValue =
(this$static._bufferBase[cur] & 255) ^
((this$static._bufferBase[cur + 1] & 255) << 8)
}
curMatch = this$static._hash[this$static.kFixHashSize + hashValue]
this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos
ptr0 = (this$static._cyclicBufferPos << 1) + 1
ptr1 = this$static._cyclicBufferPos << 1
len0 = len1 = this$static.kNumHashDirectBytes
count = this$static._cutValue
while (1) {
if (curMatch <= matchMinPos || count-- == 0) {
this$static._son[ptr0] = this$static._son[ptr1] = 0
break
}
delta = this$static._pos - curMatch
cyclicPos =
(delta <= this$static._cyclicBufferPos
? this$static._cyclicBufferPos - delta
: this$static._cyclicBufferPos -
delta +
this$static._cyclicBufferSize) << 1
pby1 = this$static._bufferOffset + curMatch
len = len0 < len1 ? len0 : len1
if (
this$static._bufferBase[pby1 + len] ==
this$static._bufferBase[cur + len]
) {
while (++len != lenLimit) {
if (
this$static._bufferBase[pby1 + len] !=
this$static._bufferBase[cur + len]
) {
break
}
}
if (len == lenLimit) {
this$static._son[ptr1] = this$static._son[cyclicPos]
this$static._son[ptr0] = this$static._son[cyclicPos + 1]
break
}
}
if (
(this$static._bufferBase[pby1 + len] & 255) <
(this$static._bufferBase[cur + len] & 255)
) {
this$static._son[ptr1] = curMatch
ptr1 = cyclicPos + 1
curMatch = this$static._son[ptr1]
len1 = len
} else {
this$static._son[ptr0] = curMatch
ptr0 = cyclicPos
curMatch = this$static._son[ptr0]
len0 = len
}
}
$MovePos_0(this$static)
} while (--num != 0)
}
function $CopyBlock(this$static, distance, len) {
var pos = this$static._pos - distance - 1
if (pos < 0) {
pos += this$static._windowSize
}
for (; len != 0; --len) {
if (pos >= this$static._windowSize) {
pos = 0
}
this$static._buffer[this$static._pos++] = this$static._buffer[pos++]
if (this$static._pos >= this$static._windowSize) {
$Flush_0(this$static)
}
}
}
function $Create_5(this$static, windowSize) {
if (this$static._buffer == null || this$static._windowSize != windowSize) {
this$static._buffer = initDim(windowSize)
}
this$static._windowSize = windowSize
this$static._pos = 0
this$static._streamPos = 0
}
function $Flush_0(this$static) {
var size = this$static._pos - this$static._streamPos
if (!size) {
return
}
$write_0(
this$static._stream,
this$static._buffer,
this$static._streamPos,
size
)
if (this$static._pos >= this$static._windowSize) {
this$static._pos = 0
}
this$static._streamPos = this$static._pos
}
function $GetByte(this$static, distance) {
var pos = this$static._pos - distance - 1
if (pos < 0) {
pos += this$static._windowSize
}
return this$static._buffer[pos]
}
function $PutByte(this$static, b) {
this$static._buffer[this$static._pos++] = b
if (this$static._pos >= this$static._windowSize) {
$Flush_0(this$static)
}
}
function $ReleaseStream(this$static) {
$Flush_0(this$static)
this$static._stream = null
}
function GetLenToPosState(len) {
len -= 2
if (len < 4) {
return len
}
return 3
}
function StateUpdateChar(index) {
if (index < 4) {
return 0
}
if (index < 10) {
return index - 3
}
return index - 6
}
function $Chunker_0(this$static, encoder) {
this$static.encoder = encoder
this$static.decoder = null
this$static.alive = 1
return this$static
}
function $Chunker(this$static, decoder) {
this$static.decoder = decoder
this$static.encoder = null
this$static.alive = 1
return this$static
}
function $processChunk(this$static) {
if (!this$static.alive) {
throw new Error('bad state')
}
if (this$static.encoder) {
$processEncoderChunk(this$static)
} else {
$processDecoderChunk(this$static)
}
return this$static.alive
}
function $processDecoderChunk(this$static) {
var result = $CodeOneChunk(this$static.decoder)
if (result == -1) {
throw new Error('corrupted input')
}
this$static.inBytesProcessed = N1_longLit
this$static.outBytesProcessed = this$static.decoder.nowPos64
if (
result ||
(compare(this$static.decoder.outSize, P0_longLit) >= 0 &&
compare(this$static.decoder.nowPos64, this$static.decoder.outSize) >= 0)
) {
$Flush_0(this$static.decoder.m_OutWindow)
$ReleaseStream(this$static.decoder.m_OutWindow)
this$static.decoder.m_RangeDecoder.Stream = null
this$static.alive = 0
}
}
function $processEncoderChunk(this$static) {
$CodeOneBlock(
this$static.encoder,
this$static.encoder.processedInSize,
this$static.encoder.processedOutSize,
this$static.encoder.finished
)
this$static.inBytesProcessed = this$static.encoder.processedInSize[0]
if (this$static.encoder.finished[0]) {
$ReleaseStreams(this$static.encoder)
this$static.alive = 0
}
}
function $CodeInChunks(this$static, inStream, outStream, outSize) {
this$static.m_RangeDecoder.Stream = inStream
$ReleaseStream(this$static.m_OutWindow)
this$static.m_OutWindow._stream = outStream
$Init_1(this$static)
this$static.state = 0
this$static.rep0 = 0
this$static.rep1 = 0
this$static.rep2 = 0
this$static.rep3 = 0
this$static.outSize = outSize
this$static.nowPos64 = P0_longLit
this$static.prevByte = 0
return $Chunker({}, this$static)
}
function $CodeOneChunk(this$static) {
var decoder2, distance, len, numDirectBits, posSlot, posState
posState = lowBits_0(this$static.nowPos64) & this$static.m_PosStateMask
if (
!$DecodeBit(
this$static.m_RangeDecoder,
this$static.m_IsMatchDecoders,
(this$static.state << 4) + posState
)
) {
decoder2 = $GetDecoder(
this$static.m_LiteralDecoder,
lowBits_0(this$static.nowPos64),
this$static.prevByte
)
if (this$static.state < 7) {
this$static.prevByte = $DecodeNormal(decoder2, this$static.m_RangeDecoder)
} else {
this$static.prevByte = $DecodeWithMatchByte(
decoder2,
this$static.m_RangeDecoder,
$GetByte(this$static.m_OutWindow, this$static.rep0)
)
}
$PutByte(this$static.m_OutWindow, this$static.prevByte)
this$static.state = StateUpdateChar(this$static.state)
this$static.nowPos64 = add(this$static.nowPos64, P1_longLit)
} else {
if (
$DecodeBit(
this$static.m_RangeDecoder,
this$static.m_IsRepDecoders,
this$static.state
)
) {
len = 0
if (
!$DecodeBit(
this$static.m_RangeDecoder,
this$static.m_IsRepG0Decoders,
this$static.state
)
) {
if (
!$DecodeBit(
this$static.m_RangeDecoder,
this$static.m_IsRep0LongDecoders,
(this$static.state << 4) + posState
)
) {
this$static.state = this$static.state < 7 ? 9 : 11
len = 1
}
} else {
if (
!$DecodeBit(
this$static.m_RangeDecoder,
this$static.m_IsRepG1Decoders,
this$static.state
)
) {
distance = this$static.rep1
} else {
if (
!$DecodeBit(
this$static.m_RangeDecoder,
this$static.m_IsRepG2Decoders,
this$static.state
)
) {
distance = this$static.rep2
} else {
distance = this$static.rep3
this$static.rep3 = this$static.rep2
}
this$static.rep2 = this$static.rep1
}
this$static.rep1 = this$static.rep0
this$static.rep0 = distance
}
if (!len) {
len =
$Decode(
this$static.m_RepLenDecoder,
this$static.m_RangeDecoder,
posState
) + 2
this$static.state = this$static.state < 7 ? 8 : 11
}
} else {
this$static.rep3 = this$static.rep2
this$static.rep2 = this$static.rep1
this$static.rep1 = this$static.rep0
len =
2 +
$Decode(this$static.m_LenDecoder, this$static.m_RangeDecoder, posState)
this$static.state = this$static.state < 7 ? 7 : 10
posSlot = $Decode_0(
this$static.m_PosSlotDecoder[GetLenToPosState(len)],
this$static.m_RangeDecoder
)
if (posSlot >= 4) {
numDirectBits = (posSlot >> 1) - 1
this$static.rep0 = (2 | (posSlot & 1)) << numDirectBits
if (posSlot < 14) {
this$static.rep0 += ReverseDecode(
this$static.m_PosDecoders,
this$static.rep0 - posSlot - 1,
this$static.m_RangeDecoder,
numDirectBits
)
} else {
this$static.rep0 +=
$DecodeDirectBits(this$static.m_RangeDecoder, numDirectBits - 4) <<
4
this$static.rep0 += $ReverseDecode(
this$static.m_PosAlignDecoder,
this$static.m_RangeDecoder
)
if (this$static.rep0 < 0) {
if (this$static.rep0 == -1) {
return 1
}
return -1
}
}
} else this$static.rep0 = posSlot
}
if (
compare(fromInt(this$static.rep0), this$static.nowPos64) >= 0 ||
this$static.rep0 >= this$static.m_DictionarySizeCheck
) {
return -1
}
$CopyBlock(this$static.m_OutWindow, this$static.rep0, len)
this$static.nowPos64 = add(this$static.nowPos64, fromInt(len))
this$static.prevByte = $GetByte(this$static.m_OutWindow, 0)
}
return 0
}
function $Decoder(this$static) {
this$static.m_OutWindow = {}
this$static.m_RangeDecoder = {}
this$static.m_IsMatchDecoders = initDim(192)
this$static.m_IsRepDecoders = initDim(12)
this$static.m_IsRepG0Decoders = initDim(12)
this$static.m_IsRepG1Decoders = initDim(12)
this$static.m_IsRepG2Decoders = initDim(12)
this$static.m_IsRep0LongDecoders = initDim(192)
this$static.m_PosSlotDecoder = initDim(4)
this$static.m_PosDecoders = initDim(114)
this$static.m_PosAlignDecoder = $BitTreeDecoder({}, 4)
this$static.m_LenDecoder = $Decoder$LenDecoder({})
this$static.m_RepLenDecoder = $Decoder$LenDecoder({})
this$static.m_LiteralDecoder = {}
for (var i = 0; i < 4; ++i) {
this$static.m_PosSlotDecoder[i] = $BitTreeDecoder({}, 6)
}
return this$static
}
function $Init_1(this$static) {
this$static.m_OutWindow._streamPos = 0
this$static.m_OutWindow._pos = 0
InitBitModels(this$static.m_IsMatchDecoders)
InitBitModels(this$static.m_IsRep0LongDecoders)
InitBitModels(this$static.m_IsRepDecoders)
InitBitModels(this$static.m_IsRepG0Decoders)
InitBitModels(this$static.m_IsRepG1Decoders)
InitBitModels(this$static.m_IsRepG2Decoders)
InitBitModels(this$static.m_PosDecoders)
$Init_0(this$static.m_LiteralDecoder)
for (var i = 0; i < 4; ++i) {
InitBitModels(this$static.m_PosSlotDecoder[i].Models)
}
$Init(this$static.m_LenDecoder)
$Init(this$static.m_RepLenDecoder)
InitBitModels(this$static.m_PosAlignDecoder.Models)
$Init_8(this$static.m_RangeDecoder)
}
function $SetDecoderProperties(this$static, properties) {
var dictionarySize, i, lc, lp, pb, remainder, val
if (properties.length < 5) return 0
val = properties[0] & 255
lc = val % 9
remainder = ~~(val / 9)
lp = remainder % 5
pb = ~~(remainder / 5)
dictionarySize = 0
for (i = 0; i < 4; ++i) {
dictionarySize += (properties[1 + i] & 255) << (i * 8)
}
// NOTE: If the input is bad, it might call for an insanely large dictionary size, which would crash the script.
if (dictionarySize > 99999999 || !$SetLcLpPb(this$static, lc, lp, pb)) {
return 0
}
return $SetDictionarySize(this$static, dictionarySize)
}
function $SetDictionarySize(this$static, dictionarySize) {
if (dictionarySize < 0) {
return 0
}
if (this$static.m_DictionarySize != dictionarySize) {
this$static.m_DictionarySize = dictionarySize
this$static.m_DictionarySizeCheck = Math.max(
this$static.m_DictionarySize,
1
)
$Create_5(
this$static.m_OutWindow,
Math.max(this$static.m_DictionarySizeCheck, 4096)
)
}
return 1
}
function $SetLcLpPb(this$static, lc, lp, pb) {
if (lc > 8 || lp > 4 || pb > 4) {
return 0
}
$Create_0(this$static.m_LiteralDecoder, lp, lc)
var numPosStates = 1 << pb
$Create(this$static.m_LenDecoder, numPosStates)
$Create(this$static.m_RepLenDecoder, numPosStates)
this$static.m_PosStateMask = numPosStates - 1
return 1
}
function $Create(this$static, numPosStates) {
for (
;
this$static.m_NumPosStates < numPosStates;
++this$static.m_NumPosStates
) {
this$static.m_LowCoder[this$static.m_NumPosStates] = $BitTreeDecoder({}, 3)
this$static.m_MidCoder[this$static.m_NumPosStates] = $BitTreeDecoder({}, 3)
}
}
function $Decode(this$static, rangeDecoder, posState) {
if (!$DecodeBit(rangeDecoder, this$static.m_Choice, 0)) {
return $Decode_0(this$static.m_LowCoder[posState], rangeDecoder)
}
var symbol = 8
if (!$DecodeBit(rangeDecoder, this$static.m_Choice, 1)) {
symbol += $Decode_0(this$static.m_MidCoder[posState], rangeDecoder)
} else {
symbol += 8 + $Decode_0(this$static.m_HighCoder, rangeDecoder)
}
return symbol
}
function $Decoder$LenDecoder(this$static) {
this$static.m_Choice = initDim(2)
this$static.m_LowCoder = initDim(16)
this$static.m_MidCoder = initDim(16)
this$static.m_HighCoder = $BitTreeDecoder({}, 8)
this$static.m_NumPosStates = 0
return this$static
}
function $Init(this$static) {
InitBitModels(this$static.m_Choice)
for (var posState = 0; posState < this$static.m_NumPosStates; ++posState) {
InitBitModels(this$static.m_LowCoder[posState].Models)
InitBitModels(this$static.m_MidCoder[posState].Models)
}
InitBitModels(this$static.m_HighCoder.Models)
}
function $Create_0(this$static, numPosBits, numPrevBits) {
var i, numStates
if (
this$static.m_Coders != null &&
this$static.m_NumPrevBits == numPrevBits &&
this$static.m_NumPosBits == numPosBits
)
return
this$static.m_NumPosBits = numPosBits
this$static.m_PosMask = (1 << numPosBits) - 1
this$static.m_NumPrevBits = numPrevBits
numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
this$static.m_Coders = initDim(numStates)
for (i = 0; i < numStates; ++i)
this$static.m_Coders[i] = $Decoder$LiteralDecoder$Decoder2({})
}
function $GetDecoder(this$static, pos, prevByte) {
return this$static.m_Coders[
((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) +
((prevByte & 255) >>> (8 - this$static.m_NumPrevBits))
]
}
function $Init_0(this$static) {
var i, numStates
numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
for (i = 0; i < numStates; ++i) {
InitBitModels(this$static.m_Coders[i].m_Decoders)
}
}
function $DecodeNormal(this$static, rangeDecoder) {
var symbol = 1
do {
symbol =
(symbol << 1) | $DecodeBit(rangeDecoder, this$static.m_Decoders, symbol)
} while (symbol < 256)
return (symbol << 24) >> 24
}
function $DecodeWithMatchByte(this$static, rangeDecoder, matchByte) {
var bit,
matchBit,
symbol = 1
do {
matchBit = (matchByte >> 7) & 1
matchByte <<= 1
bit = $DecodeBit(
rangeDecoder,
this$static.m_Decoders,
((1 + matchBit) << 8) + symbol
)
symbol = (symbol << 1) | bit
if (matchBit != bit) {
while (symbol < 256) {
symbol =
(symbol << 1) |
$DecodeBit(rangeDecoder, this$static.m_Decoders, symbol)
}
break
}
} while (symbol < 256)
return (symbol << 24) >> 24
}
function $Decoder$LiteralDecoder$Decoder2(this$static) {
this$static.m_Decoders = initDim(768)
return this$static
}
var g_FastPos = (function() {
var j,
k,
slotFast,
c = 2,
g_FastPos = [0, 1]
for (slotFast = 2; slotFast < 22; ++slotFast) {
k = 1 << ((slotFast >> 1) - 1)
for (j = 0; j < k; ++j, ++c) g_FastPos[c] = (slotFast << 24) >> 24
}
return g_FastPos
})()
function $Backward(this$static, cur) {
var backCur, backMem, posMem, posPrev
this$static._optimumEndIndex = cur
posMem = this$static._optimum[cur].PosPrev
backMem = this$static._optimum[cur].BackPrev
do {
if (this$static._optimum[cur].Prev1IsChar) {
$MakeAsChar(this$static._optimum[posMem])
this$static._optimum[posMem].PosPrev = posMem - 1
if (this$static._optimum[cur].Prev2) {
this$static._optimum[posMem - 1].Prev1IsChar = 0
this$static._optimum[posMem - 1].PosPrev =
this$static._optimum[cur].PosPrev2
this$static._optimum[posMem - 1].BackPrev =
this$static._optimum[cur].BackPrev2
}
}
posPrev = posMem
backCur = backMem
backMem = this$static._optimum[posPrev].BackPrev
posMem = this$static._optimum[posPrev].PosPrev
this$static._optimum[posPrev].BackPrev = backCur
this$static._optimum[posPrev].PosPrev = cur
cur = posPrev
} while (cur > 0)
this$static.backRes = this$static._optimum[0].BackPrev
this$static._optimumCurrentIndex = this$static._optimum[0].PosPrev
return this$static._optimumCurrentIndex
}
function $BaseInit(this$static) {
this$static._state = 0
this$static._previousByte = 0
for (var i = 0; i < 4; ++i) {
this$static._repDistances[i] = 0
}
}
function $CodeOneBlock(this$static, inSize, outSize, finished) {
var baseVal,
complexState,
curByte,
distance,
footerBits,
i,
len,
lenToPosState,
matchByte,
pos,
posReduced,
posSlot,
posState,
progressPosValuePrev,
subCoder
inSize[0] = P0_longLit
outSize[0] = P0_longLit
finished[0] = 1
if (this$static._inStream) {
this$static._matchFinder._stream = this$static._inStream
$Init_5(this$static._matchFinder)
this$static._needReleaseMFStream = 1
this$static._inStream = null
}
if (this$static._finished) {
return
}
this$static._finished = 1
progressPosValuePrev = this$static.nowPos64
if (eq(this$static.nowPos64, P0_longLit)) {
if (!$GetNumAvailableBytes(this$static._matchFinder)) {
$Flush(this$static, lowBits_0(this$static.nowPos64))
return
}
$ReadMatchDistances(this$static)
posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask
$Encode_3(
this$static._rangeEncoder,
this$static._isMatch,
(this$static._state << 4) + posState,
0
)
this$static._state = StateUpdateChar(this$static._state)
curByte = $GetIndexByte(
this$static._matchFinder,
-this$static._additionalOffset
)
$Encode_1(
$GetSubCoder(
this$static._literalEncoder,
lowBits_0(this$static.nowPos64),
this$static._previousByte
),
this$static._rangeEncoder,
curByte
)
this$static._previousByte = curByte
--this$static._additionalOffset
this$static.nowPos64 = add(this$static.nowPos64, P1_longLit)
}
if (!$GetNumAvailableBytes(this$static._matchFinder)) {
$Flush(this$static, lowBits_0(this$static.nowPos64))
return
}
while (1) {
len = $GetOptimum(this$static, lowBits_0(this$static.nowPos64))
pos = this$static.backRes
posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask
complexState = (this$static._state << 4) + posState
if (len == 1 && pos == -1) {
$Encode_3(
this$static._rangeEncoder,
this$static._isMatch,
complexState,
0
)
curByte = $GetIndexByte(
this$static._matchFinder,
-this$static._additionalOffset
)
subCoder = $GetSubCoder(
this$static._literalEncoder,
lowBits_0(this$static.nowPos64),
this$static._previousByte
)
if (this$static._state < 7) {
$Encode_1(subCoder, this$static._rangeEncoder, curByte)
} else {
matchByte = $GetIndexByte(
this$static._matchFinder,
-this$static._repDistances[0] - 1 - this$static._additionalOffset
)
$EncodeMatched(subCoder, this$static._rangeEncoder, matchByte, curByte)
}
this$static._previousByte = curByte
this$static._state = StateUpdateChar(this$static._state)
} else {
$Encode_3(
this$static._rangeEncoder,
this$static._isMatch,
complexState,
1
)
if (pos < 4) {
$Encode_3(
this$static._rangeEncoder,
this$static._isRep,
this$static._state,
1
)
if (!pos) {
$Encode_3(
this$static._rangeEncoder,
this$static._isRepG0,
this$static._state,
0
)
if (len == 1) {
$Encode_3(
this$static._rangeEncoder,
this$static._isRep0Long,
complexState,
0
)
} else {
$Encode_3(
this$static._rangeEncoder,
this$static._isRep0Long,
complexState,
1
)
}
} else {
$Encode_3(
this$static._rangeEncoder,
this$static._isRepG0,
this$static._state,
1
)
if (pos == 1) {
$Encode_3(
this$static._rangeEncoder,
this$static._isRepG1,
this$static._state,
0
)
} else {
$Encode_3(
this$static._rangeEncoder,
this$static._isRepG1,
this$static._state,
1
)
$Encode_3(
this$static._rangeEncoder,
this$static._isRepG2,
this$static._state,
pos - 2
)
}
}
if (len == 1) {
this$static._state = this$static._state < 7 ? 9 : 11
} else {
$Encode_0(
this$static._repMatchLenEncoder,
this$static._rangeEncoder,
len - 2,
posState
)
this$static._state = this$static._state < 7 ? 8 : 11
}
distance = this$static._repDistances[pos]
if (pos != 0) {
for (i = pos; i >= 1; --i) {
this$static._repDistances[i] = this$static._repDistances[i - 1]
}
this$static._repDistances[0] = distance
}
} else {
$Encode_3(
this$static._rangeEncoder,
this$static._isRep,
this$static._state,
0
)
this$static._state = this$static._state < 7 ? 7 : 10
$Encode_0(
this$static._lenEncoder,
this$static._rangeEncoder,
len - 2,
posState
)
pos -= 4
posSlot = GetPosSlot(pos)
lenToPosState = GetLenToPosState(len)
$Encode_2(
this$static._posSlotEncoder[lenToPosState],
this$static._rangeEncoder,
posSlot
)
if (posSlot >= 4) {
footerBits = (posSlot >> 1) - 1
baseVal = (2 | (posSlot & 1)) << footerBits
posReduced = pos - baseVal
if (posSlot < 14) {
ReverseEncode(
this$static._posEncoders,
baseVal - posSlot - 1,
this$static._rangeEncoder,
footerBits,
posReduced
)
} else {
$EncodeDirectBits(
this$static._rangeEncoder,
posReduced >> 4,
footerBits - 4
)
$ReverseEncode(
this$static._posAlignEncoder,
this$static._rangeEncoder,
posReduced & 15
)
++this$static._alignPriceCount
}
}
distance = pos
for (i = 3; i >= 1; --i) {
this$static._repDistances[i] = this$static._repDistances[i - 1]
}
this$static._repDistances[0] = distance
++this$static._matchPriceCount
}
this$static._previousByte = $GetIndexByte(
this$static._matchFinder,
len - 1 - this$static._additionalOffset
)
}
this$static._additionalOffset -= len
this$static.nowPos64 = add(this$static.nowPos64, fromInt(len))
if (!this$static._additionalOffset) {
if (this$static._matchPriceCount >= 128) {
$FillDistancesPrices(this$static)
}
if (this$static._alignPriceCount >= 16) {
$FillAlignPrices(this$static)
}
inSize[0] = this$static.nowPos64
outSize[0] = $GetProcessedSizeAdd(this$static._rangeEncoder)
if (!$GetNumAvailableBytes(this$static._matchFinder)) {
$Flush(this$static, lowBits_0(this$static.nowPos64))
return
}
if (
compare(sub(this$static.nowPos64, progressPosValuePrev), [4096, 0]) >= 0
) {
this$static._finished = 0
finished[0] = 0
return
}
}
}
}
function $Create_2(this$static) {
var bt, numHashBytes
if (!this$static._matchFinder) {
bt = {}
numHashBytes = 4
if (!this$static._matchFinderType) {
numHashBytes = 2
}
$SetType(bt, numHashBytes)
this$static._matchFinder = bt
}
$Create_1(
this$static._literalEncoder,
this$static._numLiteralPosStateBits,
this$static._numLiteralContextBits
)
if (
this$static._dictionarySize == this$static._dictionarySizePrev &&
this$static._numFastBytesPrev == this$static._numFastBytes
) {
return
}
$Create_3(
this$static._matchFinder,
this$static._dictionarySize,
4096,
this$static._numFastBytes,
274
)
this$static._dictionarySizePrev = this$static._dictionarySize
this$static._numFastBytesPrev = this$static._numFastBytes
}
function $Encoder(this$static) {
var i
this$static._repDistances = initDim(4)
this$static._optimum = []
this$static._rangeEncoder = {}
this$static._isMatch = initDim(192)
this$static._isRep = initDim(12)
this$static._isRepG0 = initDim(12)
this$static._isRepG1 = initDim(12)
this$static._isRepG2 = initDim(12)
this$static._isRep0Long = initDim(192)
this$static._posSlotEncoder = []
this$static._posEncoders = initDim(114)
this$static._posAlignEncoder = $BitTreeEncoder({}, 4)
this$static._lenEncoder = $Encoder$LenPriceTableEncoder({})
this$static._repMatchLenEncoder = $Encoder$LenPriceTableEncoder({})
this$static._literalEncoder = {}
this$static._matchDistances = []
this$static._posSlotPrices = []
this$static._distancesPrices = []
this$static._alignPrices = initDim(16)
this$static.reps = initDim(4)
this$static.repLens = initDim(4)
this$static.processedInSize = [P0_longLit]
this$static.processedOutSize = [P0_longLit]
this$static.finished = [0]
this$static.properties = initDim(5)
this$static.tempPrices = initDim(128)
this$static._longestMatchLength = 0
this$static._matchFinderType = 1
this$static._numDistancePairs = 0
this$static._numFastBytesPrev = -1
this$static.backRes = 0
for (i = 0; i < 4096; ++i) {
this$static._optimum[i] = {}
}
for (i = 0; i < 4; ++i) {
this$static._posSlotEncoder[i] = $BitTreeEncoder({}, 6)
}
return this$static
}
function $FillAlignPrices(this$static) {
for (var i = 0; i < 16; ++i) {
this$static._alignPrices[i] = $ReverseGetPrice(
this$static._posAlignEncoder,
i
)
}
this$static._alignPriceCount = 0
}
function $FillDistancesPrices(this$static) {
var baseVal, encoder, footerBits, i, lenToPosState, posSlot, st, st2
for (i = 4; i < 128; ++i) {
posSlot = GetPosSlot(i)
footerBits = (posSlot >> 1) - 1
baseVal = (2 | (posSlot & 1)) << footerBits
this$static.tempPrices[i] = ReverseGetPrice(
this$static._posEncoders,
baseVal - posSlot - 1,
footerBits,
i - baseVal
)
}
for (lenToPosState = 0; lenToPosState < 4; ++lenToPosState) {
encoder = this$static._posSlotEncoder[lenToPosState]
st = lenToPosState << 6
for (posSlot = 0; posSlot < this$static._distTableSize; ++posSlot) {
this$static._posSlotPrices[st + posSlot] = $GetPrice_1(encoder, posSlot)
}
for (posSlot = 14; posSlot < this$static._distTableSize; ++posSlot) {
this$static._posSlotPrices[st + posSlot] += ((posSlot >> 1) - 1 - 4) << 6
}
st2 = lenToPosState * 128
for (i = 0; i < 4; ++i) {
this$static._distancesPrices[st2 + i] = this$static._posSlotPrices[st + i]
}
for (; i < 128; ++i) {
this$static._distancesPrices[st2 + i] =
this$static._posSlotPrices[st + GetPosSlot(i)] +
this$static.tempPrices[i]
}
}
this$static._matchPriceCount = 0
}
function $Flush(this$static, nowPos) {
$ReleaseMFStream(this$static)
$WriteEndMarker(this$static, nowPos & this$static._posStateMask)
for (var i = 0; i < 5; ++i) {
$ShiftLow(this$static._rangeEncoder)
}
}
function $GetOptimum(this$static, position) {
var cur,
curAnd1Price,
curAndLenCharPrice,
curAndLenPrice,
curBack,
curPrice,
currentByte,
distance,
i,
len,
lenEnd,
lenMain,
lenRes,
lenTest,
lenTest2,
lenTestTemp,
matchByte,
matchPrice,
newLen,
nextIsChar,
nextMatchPrice,
nextOptimum,
nextRepMatchPrice,
normalMatchPrice,
numAvailableBytes,
numAvailableBytesFull,
numDistancePairs,
offs,
offset,
opt,
optimum,
pos,
posPrev,
posState,
posStateNext,
price_4,
repIndex,
repLen,
repMatchPrice,
repMaxIndex,
shortRepPrice,
startLen,
state,
state2,
t,
price,
price_0,
price_1,
price_2,
price_3
if (this$static._optimumEndIndex != this$static._optimumCurrentIndex) {
lenRes =
this$static._optimum[this$static._optimumCurrentIndex].PosPrev -
this$static._optimumCurrentIndex
this$static.backRes =
this$static._optimum[this$static._optimumCurrentIndex].BackPrev
this$static._optimumCurrentIndex =
this$static._optimum[this$static._optimumCurrentIndex].PosPrev
return lenRes
}
this$static._optimumCurrentIndex = this$static._optimumEndIndex = 0
if (this$static._longestMatchWasFound) {
lenMain = this$static._longestMatchLength
this$static._longestMatchWasFound = 0
} else {
lenMain = $ReadMatchDistances(this$static)
}
numDistancePairs = this$static._numDistancePairs
numAvailableBytes = $GetNumAvailableBytes(this$static._matchFinder) + 1
if (numAvailableBytes < 2) {
this$static.backRes = -1
return 1
}
if (numAvailableBytes > 273) {
numAvailableBytes = 273
}
repMaxIndex = 0
for (i = 0; i < 4; ++i) {
this$static.reps[i] = this$static._repDistances[i]
this$static.repLens[i] = $GetMatchLen(
this$static._matchFinder,
-1,
this$static.reps[i],
273
)
if (this$static.repLens[i] > this$static.repLens[repMaxIndex]) {
repMaxIndex = i
}
}
if (this$static.repLens[repMaxIndex] >= this$static._numFastBytes) {
this$static.backRes = repMaxIndex
lenRes = this$static.repLens[repMaxIndex]
$MovePos(this$static, lenRes - 1)
return lenRes
}
if (lenMain >= this$static._numFastBytes) {
this$static.backRes = this$static._matchDistances[numDistancePairs - 1] + 4
$MovePos(this$static, lenMain - 1)
return lenMain
}
currentByte = $GetIndexByte(this$static._matchFinder, -1)
matchByte = $GetIndexByte(
this$static._matchFinder,
-this$static._repDistances[0] - 1 - 1
)
if (
lenMain < 2 &&
currentByte != matchByte &&
this$static.repLens[repMaxIndex] < 2
) {
this$static.backRes = -1
return 1
}
this$static._optimum[0].State = this$static._state
posState = position & this$static._posStateMask
this$static._optimum[1].Price =
ProbPrices[
this$static._isMatch[(this$static._state << 4) + posState] >>> 2
] +
$GetPrice_0(
$GetSubCoder(
this$static._literalEncoder,
position,
this$static._previousByte
),
this$static._state >= 7,
matchByte,
currentByte
)
$MakeAsChar(this$static._optimum[1])
matchPrice =
ProbPrices[
(2048 - this$static._isMatch[(this$static._state << 4) + posState]) >>> 2
]
repMatchPrice =
matchPrice +
ProbPrices[(2048 - this$static._isRep[this$static._state]) >>> 2]
if (matchByte == currentByte) {
shortRepPrice =
repMatchPrice +
$GetRepLen1Price(this$static, this$static._state, posState)
if (shortRepPrice < this$static._optimum[1].Price) {
this$static._optimum[1].Price = shortRepPrice
$MakeAsShortRep(this$static._optimum[1])
}
}
lenEnd =
lenMain >= this$static.repLens[repMaxIndex]
? lenMain
: this$static.repLens[repMaxIndex]
if (lenEnd < 2) {
this$static.backRes = this$static._optimum[1].BackPrev
return 1
}
this$static._optimum[1].PosPrev = 0
this$static._optimum[0].Backs0 = this$static.reps[0]
this$static._optimum[0].Backs1 = this$static.reps[1]
this$static._optimum[0].Backs2 = this$static.reps[2]
this$static._optimum[0].Backs3 = this$static.reps[3]
len = lenEnd
do {
this$static._optimum[len--].Price = 268435455
} while (len >= 2)
for (i = 0; i < 4; ++i) {
repLen = this$static.repLens[i]
if (repLen < 2) {
continue
}
price_4 =
repMatchPrice +
$GetPureRepPrice(this$static, i, this$static._state, posState)
do {
curAndLenPrice =
price_4 +
$GetPrice(this$static._repMatchLenEncoder, repLen - 2, posState)
optimum = this$static._optimum[repLen]
if (curAndLenPrice < optimum.Price) {
optimum.Price = curAndLenPrice
optimum.PosPrev = 0
optimum.BackPrev = i
optimum.Prev1IsChar = 0
}
} while (--repLen >= 2)
}
normalMatchPrice =
matchPrice + ProbPrices[this$static._isRep[this$static._state] >>> 2]
len = this$static.repLens[0] >= 2 ? this$static.repLens[0] + 1 : 2
if (len <= lenMain) {
offs = 0
while (len > this$static._matchDistances[offs]) {
offs += 2
}
for (; ; ++len) {
distance = this$static._matchDistances[offs + 1]
curAndLenPrice =
normalMatchPrice + $GetPosLenPrice(this$static, distance, len, posState)
optimum = this$static._optimum[len]
if (curAndLenPrice < optimum.Price) {
optimum.Price = curAndLenPrice
optimum.PosPrev = 0
optimum.BackPrev = distance + 4
optimum.Prev1IsChar = 0
}
if (len == this$static._matchDistances[offs]) {
offs += 2
if (offs == numDistancePairs) {
break
}
}
}
}
cur = 0
while (1) {
++cur
if (cur == lenEnd) {
return $Backward(this$static, cur)
}
newLen = $ReadMatchDistances(this$static)
numDistancePairs = this$static._numDistancePairs
if (newLen >= this$static._numFastBytes) {
this$static._longestMatchLength = newLen
this$static._longestMatchWasFound = 1
return $Backward(this$static, cur)
}
++position
posPrev = this$static._optimum[cur].PosPrev
if (this$static._optimum[cur].Prev1IsChar) {
--posPrev
if (this$static._optimum[cur].Prev2) {
state = this$static._optimum[this$static._optimum[cur].PosPrev2].State
if (this$static._optimum[cur].BackPrev2 < 4) {
state = state < 7 ? 8 : 11
} else {
state = state < 7 ? 7 : 10
}
} else {
state = this$static._optimum[posPrev].State
}
state = StateUpdateChar(state)
} else {
state = this$static._optimum[posPrev].State
}
if (posPrev == cur - 1) {
if (!this$static._optimum[cur].BackPrev) {
state = state < 7 ? 9 : 11
} else {
state = StateUpdateChar(state)
}
} else {
if (
this$static._optimum[cur].Prev1IsChar &&
this$static._optimum[cur].Prev2
) {
posPrev = this$static._optimum[cur].PosPrev2
pos = this$static._optimum[cur].BackPrev2
state = state < 7 ? 8 : 11
} else {
pos = this$static._optimum[cur].BackPrev
if (pos < 4) {
state = state < 7 ? 8 : 11
} else {
state = state < 7 ? 7 : 10
}
}
opt = this$static._optimum[posPrev]
if (pos < 4) {
if (!pos) {
this$static.reps[0] = opt.Backs0
this$static.reps[1] = opt.Backs1
this$static.reps[2] = opt.Backs2
this$static.reps[3] = opt.Backs3
} else if (pos == 1) {
this$static.reps[0] = opt.Backs1
this$static.reps[1] = opt.Backs0
this$static.reps[2] = opt.Backs2
this$static.reps[3] = opt.Backs3
} else if (pos == 2) {
this$static.reps[0] = opt.Backs2
this$static.reps[1] = opt.Backs0
this$static.reps[2] = opt.Backs1
this$static.reps[3] = opt.Backs3
} else {
this$static.reps[0] = opt.Backs3
this$static.reps[1] = opt.Backs0
this$static.reps[2] = opt.Backs1
this$static.reps[3] = opt.Backs2
}
} else {
this$static.reps[0] = pos - 4
this$static.reps[1] = opt.Backs0
this$static.reps[2] = opt.Backs1
this$static.reps[3] = opt.Backs2
}
}
this$static._optimum[cur].State = state
this$static._optimum[cur].Backs0 = this$static.reps[0]
this$static._optimum[cur].Backs1 = this$static.reps[1]
this$static._optimum[cur].Backs2 = this$static.reps[2]
this$static._optimum[cur].Backs3 = this$static.reps[3]
curPrice = this$static._optimum[cur].Price
currentByte = $GetIndexByte(this$static._matchFinder, -1)
matchByte = $GetIndexByte(
this$static._matchFinder,
-this$static.reps[0] - 1 - 1
)
posState = position & this$static._posStateMask
curAnd1Price =
curPrice +
ProbPrices[this$static._isMatch[(state << 4) + posState] >>> 2] +
$GetPrice_0(
$GetSubCoder(
this$static._literalEncoder,
position,
$GetIndexByte(this$static._matchFinder, -2)
),
state >= 7,
matchByte,
currentByte
)
nextOptimum = this$static._optimum[cur + 1]
nextIsChar = 0
if (curAnd1Price < nextOptimum.Price) {
nextOptimum.Price = curAnd1Price
nextOptimum.PosPrev = cur
nextOptimum.BackPrev = -1
nextOptimum.Prev1IsChar = 0
nextIsChar = 1
}
matchPrice =
curPrice +
ProbPrices[(2048 - this$static._isMatch[(state << 4) + posState]) >>> 2]
repMatchPrice =
matchPrice + ProbPrices[(2048 - this$static._isRep[state]) >>> 2]
if (
matchByte == currentByte &&
!(nextOptimum.PosPrev < cur && !nextOptimum.BackPrev)
) {
shortRepPrice =
repMatchPrice +
(ProbPrices[this$static._isRepG0[state] >>> 2] +
ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2])
if (shortRepPrice <= nextOptimum.Price) {
nextOptimum.Price = shortRepPrice
nextOptimum.PosPrev = cur
nextOptimum.BackPrev = 0
nextOptimum.Prev1IsChar = 0
nextIsChar = 1
}
}
numAvailableBytesFull = $GetNumAvailableBytes(this$static._matchFinder) + 1
numAvailableBytesFull =
4095 - cur < numAvailableBytesFull ? 4095 - cur : numAvailableBytesFull
numAvailableBytes = numAvailableBytesFull
if (numAvailableBytes < 2) {
continue
}
if (numAvailableBytes > this$static._numFastBytes) {
numAvailableBytes = this$static._numFastBytes
}
if (!nextIsChar && matchByte != currentByte) {
t = Math.min(numAvailableBytesFull - 1, this$static._numFastBytes)
lenTest2 = $GetMatchLen(
this$static._matchFinder,
0,
this$static.reps[0],
t
)
if (lenTest2 >= 2) {
state2 = StateUpdateChar(state)
posStateNext = (position + 1) & this$static._posStateMask
nextRepMatchPrice =
curAnd1Price +
ProbPrices[
(2048 - this$static._isMatch[(state2 << 4) + posStateNext]) >>> 2
] +
ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
offset = cur + 1 + lenTest2
while (lenEnd < offset) {
this$static._optimum[++lenEnd].Price = 268435455
}
curAndLenPrice =
nextRepMatchPrice +
((price = $GetPrice(
this$static._repMatchLenEncoder,
lenTest2 - 2,
posStateNext
)),
price + $GetPureRepPrice(this$static, 0, state2, posStateNext))
optimum = this$static._optimum[offset]
if (curAndLenPrice < optimum.Price) {
optimum.Price = curAndLenPrice
optimum.PosPrev = cur + 1
optimum.BackPrev = 0
optimum.Prev1IsChar = 1
optimum.Prev2 = 0
}
}
}
startLen = 2
for (repIndex = 0; repIndex < 4; ++repIndex) {
lenTest = $GetMatchLen(
this$static._matchFinder,
-1,
this$static.reps[repIndex],
numAvailableBytes
)
if (lenTest < 2) {
continue
}
lenTestTemp = lenTest
do {
while (lenEnd < cur + lenTest) {
this$static._optimum[++lenEnd].Price = 268435455
}
curAndLenPrice =
repMatchPrice +
((price_0 = $GetPrice(
this$static._repMatchLenEncoder,
lenTest - 2,
posState
)),
price_0 + $GetPureRepPrice(this$static, repIndex, state, posState))
optimum = this$static._optimum[cur + lenTest]
if (curAndLenPrice < optimum.Price) {
optimum.Price = curAndLenPrice
optimum.PosPrev = cur
optimum.BackPrev = repIndex
optimum.Prev1IsChar = 0
}
} while (--lenTest >= 2)
lenTest = lenTestTemp
if (!repIndex) {
startLen = lenTest + 1
}
if (lenTest < numAvailableBytesFull) {
t = Math.min(
numAvailableBytesFull - 1 - lenTest,
this$static._numFastBytes
)
lenTest2 = $GetMatchLen(
this$static._matchFinder,
lenTest,
this$static.reps[repIndex],
t
)
if (lenTest2 >= 2) {
state2 = state < 7 ? 8 : 11
posStateNext = (position + lenTest) & this$static._posStateMask
curAndLenCharPrice =
repMatchPrice +
((price_1 = $GetPrice(
this$static._repMatchLenEncoder,
lenTest - 2,
posState
)),
price_1 +
$GetPureRepPrice(this$static, repIndex, state, posState)) +
ProbPrices[
this$static._isMatch[(state2 << 4) + posStateNext] >>> 2
] +
$GetPrice_0(
$GetSubCoder(
this$static._literalEncoder,
position + lenTest,
$GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)
),
1,
$GetIndexByte(
this$static._matchFinder,
lenTest - 1 - (this$static.reps[repIndex] + 1)
),
$GetIndexByte(this$static._matchFinder, lenTest - 1)
)
state2 = StateUpdateChar(state2)
posStateNext = (position + lenTest + 1) & this$static._posStateMask
nextMatchPrice =
curAndLenCharPrice +
ProbPrices[
(2048 - this$static._isMatch[(state2 << 4) + posStateNext]) >>> 2
]
nextRepMatchPrice =
nextMatchPrice +
ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
offset = lenTest + 1 + lenTest2
while (lenEnd < cur + offset) {
this$static._optimum[++lenEnd].Price = 268435455
}
curAndLenPrice =
nextRepMatchPrice +
((price_2 = $GetPrice(
this$static._repMatchLenEncoder,
lenTest2 - 2,
posStateNext
)),
price_2 + $GetPureRepPrice(this$static, 0, state2, posStateNext))
optimum = this$static._optimum[cur + offset]
if (curAndLenPrice < optimum.Price) {
optimum.Price = curAndLenPrice
optimum.PosPrev = cur + lenTest + 1
optimum.BackPrev = 0
optimum.Prev1IsChar = 1
optimum.Prev2 = 1
optimum.PosPrev2 = cur
optimum.BackPrev2 = repIndex
}
}
}
}
if (newLen > numAvailableBytes) {
newLen = numAvailableBytes
for (
numDistancePairs = 0;
newLen > this$static._matchDistances[numDistancePairs];
numDistancePairs += 2
) {}
this$static._matchDistances[numDistancePairs] = newLen
numDistancePairs += 2
}
if (newLen >= startLen) {
normalMatchPrice =
matchPrice + ProbPrices[this$static._isRep[state] >>> 2]
while (lenEnd < cur + newLen) {
this$static._optimum[++lenEnd].Price = 268435455
}
offs = 0
while (startLen > this$static._matchDistances[offs]) {
offs += 2
}
for (lenTest = startLen; ; ++lenTest) {
curBack = this$static._matchDistances[offs + 1]
curAndLenPrice =
normalMatchPrice +
$GetPosLenPrice(this$static, curBack, lenTest, posState)
optimum = this$static._optimum[cur + lenTest]
if (curAndLenPrice < optimum.Price) {
optimum.Price = curAndLenPrice
optimum.PosPrev = cur
optimum.BackPrev = curBack + 4
optimum.Prev1IsChar = 0
}
if (lenTest == this$static._matchDistances[offs]) {
if (lenTest < numAvailableBytesFull) {
t = Math.min(
numAvailableBytesFull - 1 - lenTest,
this$static._numFastBytes
)
lenTest2 = $GetMatchLen(
this$static._matchFinder,
lenTest,
curBack,
t
)
if (lenTest2 >= 2) {
state2 = state < 7 ? 7 : 10
posStateNext = (position + lenTest) & this$static._posStateMask
curAndLenCharPrice =
curAndLenPrice +
ProbPrices[
this$static._isMatch[(state2 << 4) + posStateNext] >>> 2
] +
$GetPrice_0(
$GetSubCoder(
this$static._literalEncoder,
position + lenTest,
$GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)
),
1,
$GetIndexByte(
this$static._matchFinder,
lenTest - (curBack + 1) - 1
),
$GetIndexByte(this$static._matchFinder, lenTest - 1)
)
state2 = StateUpdateChar(state2)
posStateNext =
(position + lenTest + 1) & this$static._posStateMask
nextMatchPrice =
curAndLenCharPrice +
ProbPrices[
(2048 -
this$static._isMatch[(state2 << 4) + posStateNext]) >>>
2
]
nextRepMatchPrice =
nextMatchPrice +
ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
offset = lenTest + 1 + lenTest2
while (lenEnd < cur + offset) {
this$static._optimum[++lenEnd].Price = 268435455
}
curAndLenPrice =
nextRepMatchPrice +
((price_3 = $GetPrice(
this$static._repMatchLenEncoder,
lenTest2 - 2,
posStateNext
)),
price_3 +
$GetPureRepPrice(this$static, 0, state2, posStateNext))
optimum = this$static._optimum[cur + offset]
if (curAndLenPrice < optimum.Price) {
optimum.Price = curAndLenPrice
optimum.PosPrev = cur + lenTest + 1
optimum.BackPrev = 0
optimum.Prev1IsChar = 1
optimum.Prev2 = 1
optimum.PosPrev2 = cur
optimum.BackPrev2 = curBack + 4
}
}
}
offs += 2
if (offs == numDistancePairs) break
}
}
}
}
}
function $GetPosLenPrice(this$static, pos, len, posState) {
var price,
lenToPosState = GetLenToPosState(len)
if (pos < 128) {
price = this$static._distancesPrices[lenToPosState * 128 + pos]
} else {
price =
this$static._posSlotPrices[(lenToPosState << 6) + GetPosSlot2(pos)] +
this$static._alignPrices[pos & 15]
}
return price + $GetPrice(this$static._lenEncoder, len - 2, posState)
}
function $GetPureRepPrice(this$static, repIndex, state, posState) {
var price
if (!repIndex) {
price = ProbPrices[this$static._isRepG0[state] >>> 2]
price +=
ProbPrices[
(2048 - this$static._isRep0Long[(state << 4) + posState]) >>> 2
]
} else {
price = ProbPrices[(2048 - this$static._isRepG0[state]) >>> 2]
if (repIndex == 1) {
price += ProbPrices[this$static._isRepG1[state] >>> 2]
} else {
price += ProbPrices[(2048 - this$static._isRepG1[state]) >>> 2]
price += GetPrice(this$static._isRepG2[state], repIndex - 2)
}
}
return price
}
function $GetRepLen1Price(this$static, state, posState) {
return (
ProbPrices[this$static._isRepG0[state] >>> 2] +
ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2]
)
}
function $Init_4(this$static) {
$BaseInit(this$static)
$Init_9(this$static._rangeEncoder)
InitBitModels(this$static._isMatch)
InitBitModels(this$static._isRep0Long)
InitBitModels(this$static._isRep)
InitBitModels(this$static._isRepG0)
InitBitModels(this$static._isRepG1)
InitBitModels(this$static._isRepG2)
InitBitModels(this$static._posEncoders)
$Init_3(this$static._literalEncoder)
for (var i = 0; i < 4; ++i) {
InitBitModels(this$static._posSlotEncoder[i].Models)
}
$Init_2(this$static._lenEncoder, 1 << this$static._posStateBits)
$Init_2(this$static._repMatchLenEncoder, 1 << this$static._posStateBits)
InitBitModels(this$static._posAlignEncoder.Models)
this$static._longestMatchWasFound = 0
this$static._optimumEndIndex = 0
this$static._optimumCurrentIndex = 0
this$static._additionalOffset = 0
}
function $MovePos(this$static, num) {
if (num > 0) {
$Skip(this$static._matchFinder, num)
this$static._additionalOffset += num
}
}
function $ReadMatchDistances(this$static) {
var lenRes = 0
this$static._numDistancePairs = $GetMatches(
this$static._matchFinder,
this$static._matchDistances
)
if (this$static._numDistancePairs > 0) {
lenRes = this$static._matchDistances[this$static._numDistancePairs - 2]
if (lenRes == this$static._numFastBytes)
lenRes += $GetMatchLen(
this$static._matchFinder,
lenRes - 1,
this$static._matchDistances[this$static._numDistancePairs - 1],
273 - lenRes
)
}
++this$static._additionalOffset
return lenRes
}
function $ReleaseMFStream(this$static) {
if (this$static._matchFinder && this$static._needReleaseMFStream) {
this$static._matchFinder._stream = null
this$static._needReleaseMFStream = 0
}
}
function $ReleaseStreams(this$static) {
$ReleaseMFStream(this$static)
this$static._rangeEncoder.Stream = null
}
function $SetDictionarySize_0(this$static, dictionarySize) {
this$static._dictionarySize = dictionarySize
for (var dicLogSize = 0; dictionarySize > 1 << dicLogSize; ++dicLogSize) {}
this$static._distTableSize = dicLogSize * 2
}
function $SetMatchFinder(this$static, matchFinderIndex) {
var matchFinderIndexPrev = this$static._matchFinderType
this$static._matchFinderType = matchFinderIndex
if (
this$static._matchFinder &&
matchFinderIndexPrev != this$static._matchFinderType
) {
this$static._dictionarySizePrev = -1
this$static._matchFinder = null
}
}
function $WriteCoderProperties(this$static, outStream) {
this$static.properties[0] =
(((this$static._posStateBits * 5 + this$static._numLiteralPosStateBits) *
9 +
this$static._numLiteralContextBits) <<
24) >>
24
for (var i = 0; i < 4; ++i) {
this$static.properties[1 + i] =
((this$static._dictionarySize >> (8 * i)) << 24) >> 24
}
$write_0(outStream, this$static.properties, 0, 5)
}
function $WriteEndMarker(this$static, posState) {
if (!this$static._writeEndMark) {
return
}
$Encode_3(
this$static._rangeEncoder,
this$static._isMatch,
(this$static._state << 4) + posState,
1
)
$Encode_3(
this$static._rangeEncoder,
this$static._isRep,
this$static._state,
0
)
this$static._state = this$static._state < 7 ? 7 : 10
$Encode_0(this$static._lenEncoder, this$static._rangeEncoder, 0, posState)
var lenToPosState = GetLenToPosState(2)
$Encode_2(
this$static._posSlotEncoder[lenToPosState],
this$static._rangeEncoder,
63
)
$EncodeDirectBits(this$static._rangeEncoder, 67108863, 26)
$ReverseEncode(this$static._posAlignEncoder, this$static._rangeEncoder, 15)
}
function GetPosSlot(pos) {
if (pos < 2048) {
return g_FastPos[pos]
}
if (pos < 2097152) {
return g_FastPos[pos >> 10] + 20
}
return g_FastPos[pos >> 20] + 40
}
function GetPosSlot2(pos) {
if (pos < 131072) {
return g_FastPos[pos >> 6] + 12
}
if (pos < 134217728) {
return g_FastPos[pos >> 16] + 32
}
return g_FastPos[pos >> 26] + 52
}
function $Encode(this$static, rangeEncoder, symbol, posState) {
if (symbol < 8) {
$Encode_3(rangeEncoder, this$static._choice, 0, 0)
$Encode_2(this$static._lowCoder[posState], rangeEncoder, symbol)
} else {
symbol -= 8
$Encode_3(rangeEncoder, this$static._choice, 0, 1)
if (symbol < 8) {
$Encode_3(rangeEncoder, this$static._choice, 1, 0)
$Encode_2(this$static._midCoder[posState], rangeEncoder, symbol)
} else {
$Encode_3(rangeEncoder, this$static._choice, 1, 1)
$Encode_2(this$static._highCoder, rangeEncoder, symbol - 8)
}
}
}
function $Encoder$LenEncoder(this$static) {
this$static._choice = initDim(2)
this$static._lowCoder = initDim(16)
this$static._midCoder = initDim(16)
this$static._highCoder = $BitTreeEncoder({}, 8)
for (var posState = 0; posState < 16; ++posState) {
this$static._lowCoder[posState] = $BitTreeEncoder({}, 3)
this$static._midCoder[posState] = $BitTreeEncoder({}, 3)
}
return this$static
}
function $Init_2(this$static, numPosStates) {
InitBitModels(this$static._choice)
for (var posState = 0; posState < numPosStates; ++posState) {
InitBitModels(this$static._lowCoder[posState].Models)
InitBitModels(this$static._midCoder[posState].Models)
}
InitBitModels(this$static._highCoder.Models)
}
function $SetPrices(this$static, posState, numSymbols, prices, st) {
var a0, a1, b0, b1, i
a0 = ProbPrices[this$static._choice[0] >>> 2]
a1 = ProbPrices[(2048 - this$static._choice[0]) >>> 2]
b0 = a1 + ProbPrices[this$static._choice[1] >>> 2]
b1 = a1 + ProbPrices[(2048 - this$static._choice[1]) >>> 2]
i = 0
for (i = 0; i < 8; ++i) {
if (i >= numSymbols) return
prices[st + i] = a0 + $GetPrice_1(this$static._lowCoder[posState], i)
}
for (; i < 16; ++i) {
if (i >= numSymbols) return
prices[st + i] = b0 + $GetPrice_1(this$static._midCoder[posState], i - 8)
}
for (; i < numSymbols; ++i) {
prices[st + i] = b1 + $GetPrice_1(this$static._highCoder, i - 8 - 8)
}
}
function $Encode_0(this$static, rangeEncoder, symbol, posState) {
$Encode(this$static, rangeEncoder, symbol, posState)
if (--this$static._counters[posState] == 0) {
$SetPrices(
this$static,
posState,
this$static._tableSize,
this$static._prices,
posState * 272
)
this$static._counters[posState] = this$static._tableSize
}
}
function $Encoder$LenPriceTableEncoder(this$static) {
$Encoder$LenEncoder(this$static)
this$static._prices = []
this$static._counters = []
return this$static
}
function $GetPrice(this$static, symbol, posState) {
return this$static._prices[posState * 272 + symbol]
}
function $UpdateTables(this$static, numPosStates) {
for (var posState = 0; posState < numPosStates; ++posState) {
$SetPrices(
this$static,
posState,
this$static._tableSize,
this$static._prices,
posState * 272
)
this$static._counters[posState] = this$static._tableSize
}
}
function $Create_1(this$static, numPosBits, numPrevBits) {
var i, numStates
if (
this$static.m_Coders != null &&
this$static.m_NumPrevBits == numPrevBits &&
this$static.m_NumPosBits == numPosBits
) {
return
}
this$static.m_NumPosBits = numPosBits
this$static.m_PosMask = (1 << numPosBits) - 1
this$static.m_NumPrevBits = numPrevBits
numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
this$static.m_Coders = initDim(numStates)
for (i = 0; i < numStates; ++i) {
this$static.m_Coders[i] = $Encoder$LiteralEncoder$Encoder2({})
}
}
function $GetSubCoder(this$static, pos, prevByte) {
return this$static.m_Coders[
((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) +
((prevByte & 255) >>> (8 - this$static.m_NumPrevBits))
]
}
function $Init_3(this$static) {
var i,
numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
for (i = 0; i < numStates; ++i) {
InitBitModels(this$static.m_Coders[i].m_Encoders)
}
}
function $Encode_1(this$static, rangeEncoder, symbol) {
var bit,
i,
context = 1
for (i = 7; i >= 0; --i) {
bit = (symbol >> i) & 1
$Encode_3(rangeEncoder, this$static.m_Encoders, context, bit)
context = (context << 1) | bit
}
}
function $EncodeMatched(this$static, rangeEncoder, matchByte, symbol) {
var bit,
i,
matchBit,
state,
same = 1,
context = 1
for (i = 7; i >= 0; --i) {
bit = (symbol >> i) & 1
state = context
if (same) {
matchBit = (matchByte >> i) & 1
state += (1 + matchBit) << 8
same = matchBit == bit
}
$Encode_3(rangeEncoder, this$static.m_Encoders, state, bit)
context = (context << 1) | bit
}
}
function $Encoder$LiteralEncoder$Encoder2(this$static) {
this$static.m_Encoders = initDim(768)
return this$static
}
function $GetPrice_0(this$static, matchMode, matchByte, symbol) {
var bit,
context = 1,
i = 7,
matchBit,
price = 0
if (matchMode) {
for (; i >= 0; --i) {
matchBit = (matchByte >> i) & 1
bit = (symbol >> i) & 1
price += GetPrice(
this$static.m_Encoders[((1 + matchBit) << 8) + context],
bit
)
context = (context << 1) | bit
if (matchBit != bit) {
--i
break
}
}
}
for (; i >= 0; --i) {
bit = (symbol >> i) & 1
price += GetPrice(this$static.m_Encoders[context], bit)
context = (context << 1) | bit
}
return price
}
function $MakeAsChar(this$static) {
this$static.BackPrev = -1
this$static.Prev1IsChar = 0
}
function $MakeAsShortRep(this$static) {
this$static.BackPrev = 0
this$static.Prev1IsChar = 0
}
function $BitTreeDecoder(this$static, numBitLevels) {
this$static.NumBitLevels = numBitLevels
this$static.Models = initDim(1 << numBitLevels)
return this$static
}
function $Decode_0(this$static, rangeDecoder) {
var bitIndex,
m = 1
for (bitIndex = this$static.NumBitLevels; bitIndex != 0; --bitIndex) {
m = (m << 1) + $DecodeBit(rangeDecoder, this$static.Models, m)
}
return m - (1 << this$static.NumBitLevels)
}
function $ReverseDecode(this$static, rangeDecoder) {
var bit,
bitIndex,
m = 1,
symbol = 0
for (bitIndex = 0; bitIndex < this$static.NumBitLevels; ++bitIndex) {
bit = $DecodeBit(rangeDecoder, this$static.Models, m)
m <<= 1
m += bit
symbol |= bit << bitIndex
}
return symbol
}
function ReverseDecode(Models, startIndex, rangeDecoder, NumBitLevels) {
var bit,
bitIndex,
m = 1,
symbol = 0
for (bitIndex = 0; bitIndex < NumBitLevels; ++bitIndex) {
bit = $DecodeBit(rangeDecoder, Models, startIndex + m)
m <<= 1
m += bit
symbol |= bit << bitIndex
}
return symbol
}
function $BitTreeEncoder(this$static, numBitLevels) {
this$static.NumBitLevels = numBitLevels
this$static.Models = initDim(1 << numBitLevels)
return this$static
}
function $Encode_2(this$static, rangeEncoder, symbol) {
var bit,
bitIndex,
m = 1
for (bitIndex = this$static.NumBitLevels; bitIndex != 0; ) {
--bitIndex
bit = (symbol >>> bitIndex) & 1
$Encode_3(rangeEncoder, this$static.Models, m, bit)
m = (m << 1) | bit
}
}
function $GetPrice_1(this$static, symbol) {
var bit,
bitIndex,
m = 1,
price = 0
for (bitIndex = this$static.NumBitLevels; bitIndex != 0; ) {
--bitIndex
bit = (symbol >>> bitIndex) & 1
price += GetPrice(this$static.Models[m], bit)
m = (m << 1) + bit
}
return price
}
function $ReverseEncode(this$static, rangeEncoder, symbol) {
var bit,
i,
m = 1
for (i = 0; i < this$static.NumBitLevels; ++i) {
bit = symbol & 1
$Encode_3(rangeEncoder, this$static.Models, m, bit)
m = (m << 1) | bit
symbol >>= 1
}
}
function $ReverseGetPrice(this$static, symbol) {
var bit,
i,
m = 1,
price = 0
for (i = this$static.NumBitLevels; i != 0; --i) {
bit = symbol & 1
symbol >>>= 1
price += GetPrice(this$static.Models[m], bit)
m = (m << 1) | bit
}
return price
}
function ReverseEncode(Models, startIndex, rangeEncoder, NumBitLevels, symbol) {
var bit,
i,
m = 1
for (i = 0; i < NumBitLevels; ++i) {
bit = symbol & 1
$Encode_3(rangeEncoder, Models, startIndex + m, bit)
m = (m << 1) | bit
symbol >>= 1
}
}
function ReverseGetPrice(Models, startIndex, NumBitLevels, symbol) {
var bit,
i,
m = 1,
price = 0
for (i = NumBitLevels; i != 0; --i) {
bit = symbol & 1
symbol >>>= 1
price += ProbPrices[(((Models[startIndex + m] - bit) ^ -bit) & 2047) >>> 2]
m = (m << 1) | bit
}
return price
}
function $DecodeBit(this$static, probs, index) {
var newBound,
prob = probs[index]
newBound = (this$static.Range >>> 11) * prob
if ((this$static.Code ^ -2147483648) < (newBound ^ -2147483648)) {
this$static.Range = newBound
probs[index] = ((prob + ((2048 - prob) >>> 5)) << 16) >> 16
if (!(this$static.Range & -16777216)) {
this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
this$static.Range <<= 8
}
return 0
} else {
this$static.Range -= newBound
this$static.Code -= newBound
probs[index] = ((prob - (prob >>> 5)) << 16) >> 16
if (!(this$static.Range & -16777216)) {
this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
this$static.Range <<= 8
}
return 1
}
}
function $DecodeDirectBits(this$static, numTotalBits) {
var i,
t,
result = 0
for (i = numTotalBits; i != 0; --i) {
this$static.Range >>>= 1
t = (this$static.Code - this$static.Range) >>> 31
this$static.Code -= this$static.Range & (t - 1)
result = (result << 1) | (1 - t)
if (!(this$static.Range & -16777216)) {
this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
this$static.Range <<= 8
}
}
return result
}
function $Init_8(this$static) {
this$static.Code = 0
this$static.Range = -1
for (var i = 0; i < 5; ++i) {
this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
}
}
function InitBitModels(probs) {
for (var i = probs.length - 1; i >= 0; --i) {
probs[i] = 1024
}
}
var ProbPrices = (function() {
var end,
i,
j,
start,
ProbPrices = []
for (i = 8; i >= 0; --i) {
start = 1 << (9 - i - 1)
end = 1 << (9 - i)
for (j = start; j < end; ++j) {
ProbPrices[j] = (i << 6) + (((end - j) << 6) >>> (9 - i - 1))
}
}
return ProbPrices
})()
function $Encode_3(this$static, probs, index, symbol) {
var newBound,
prob = probs[index]
newBound = (this$static.Range >>> 11) * prob
if (!symbol) {
this$static.Range = newBound
probs[index] = ((prob + ((2048 - prob) >>> 5)) << 16) >> 16
} else {
this$static.Low = add(
this$static.Low,
and(fromInt(newBound), [4294967295, 0])
)
this$static.Range -= newBound
probs[index] = ((prob - (prob >>> 5)) << 16) >> 16
}
if (!(this$static.Range & -16777216)) {
this$static.Range <<= 8
$ShiftLow(this$static)
}
}
function $EncodeDirectBits(this$static, v, numTotalBits) {
for (var i = numTotalBits - 1; i >= 0; --i) {
this$static.Range >>>= 1
if (((v >>> i) & 1) == 1) {
this$static.Low = add(this$static.Low, fromInt(this$static.Range))
}
if (!(this$static.Range & -16777216)) {
this$static.Range <<= 8
$ShiftLow(this$static)
}
}
}
function $GetProcessedSizeAdd(this$static) {
return add(add(fromInt(this$static._cacheSize), this$static._position), [
4,
0
])
}
function $Init_9(this$static) {
this$static._position = P0_longLit
this$static.Low = P0_longLit
this$static.Range = -1
this$static._cacheSize = 1
this$static._cache = 0
}
function $ShiftLow(this$static) {
var temp,
LowHi = lowBits_0(shru(this$static.Low, 32))
if (LowHi != 0 || compare(this$static.Low, [4278190080, 0]) < 0) {
this$static._position = add(
this$static._position,
fromInt(this$static._cacheSize)
)
temp = this$static._cache
do {
$write(this$static.Stream, temp + LowHi)
temp = 255
} while (--this$static._cacheSize != 0)
this$static._cache = lowBits_0(this$static.Low) >>> 24
}
++this$static._cacheSize
this$static.Low = shl(and(this$static.Low, [16777215, 0]), 8)
}
function GetPrice(Prob, symbol) {
return ProbPrices[(((Prob - symbol) ^ -symbol) & 2047) >>> 2]
}
function decode(utf) {
var i = 0,
j = 0,
x,
y,
z,
l = utf.length,
buf = [],
charCodes = []
for (; i < l; ++i, ++j) {
x = utf[i] & 255
if (!(x & 128)) {
if (!x) {
// It appears that this is binary data, so it cannot be converted to a string, so just send it back.
return utf
}
charCodes[j] = x
} else if ((x & 224) == 192) {
if (i + 1 >= l) {
// It appears that this is binary data, so it cannot be converted to a string, so just send it back.
return utf
}
y = utf[++i] & 255
if ((y & 192) != 128) {
// It appears that this is binary data, so it cannot be converted to a string, so just send it back.
return utf
}
charCodes[j] = ((x & 31) << 6) | (y & 63)
} else if ((x & 240) == 224) {
if (i + 2 >= l) {
// It appears that this is binary data, so it cannot be converted to a string, so just send it back.
return utf
}
y = utf[++i] & 255
if ((y & 192) != 128) {
// It appears that this is binary data, so it cannot be converted to a string, so just send it back.
return utf
}
z = utf[++i] & 255
if ((z & 192) != 128) {
// It appears that this is binary data, so it cannot be converted to a string, so just send it back.
return utf
}
charCodes[j] = ((x & 15) << 12) | ((y & 63) << 6) | (z & 63)
} else {
// It appears that this is binary data, so it cannot be converted to a string, so just send it back.
return utf
}
if (j == 16383) {
buf.push(String.fromCharCode.apply(String, charCodes))
j = -1
}
}
if (j > 0) {
charCodes.length = j
buf.push(String.fromCharCode.apply(String, charCodes))
}
return buf.join('')
}
function encode(s) {
var ch,
chars = [],
data,
elen = 0,
i,
l = s.length
// Be able to handle binary arrays and buffers.
if (typeof s == 'object') {
return s
} else {
$getChars(s, 0, l, chars, 0)
}
// Add extra spaces in the array to break up the unicode symbols.
for (i = 0; i < l; ++i) {
ch = chars[i]
if (ch >= 1 && ch <= 127) {
++elen
} else if (!ch || (ch >= 128 && ch <= 2047)) {
elen += 2
} else {
elen += 3
}
}
data = []
elen = 0
for (i = 0; i < l; ++i) {
ch = chars[i]
if (ch >= 1 && ch <= 127) {
data[elen++] = (ch << 24) >> 24
} else if (!ch || (ch >= 128 && ch <= 2047)) {
data[elen++] = ((192 | ((ch >> 6) & 31)) << 24) >> 24
data[elen++] = ((128 | (ch & 63)) << 24) >> 24
} else {
data[elen++] = ((224 | ((ch >> 12) & 15)) << 24) >> 24
data[elen++] = ((128 | ((ch >> 6) & 63)) << 24) >> 24
data[elen++] = ((128 | (ch & 63)) << 24) >> 24
}
}
return data
}
// s is dictionarySize
// f is fb
// m is matchFinder
// NOTE: Because some values are always the same, they have been removed.
// lc is always 3
// lp is always 0
// pb is always 2
const modes = [
{ s: 16, f: 64, m: 0 },
{ s: 20, f: 64, m: 0 },
{ s: 19, f: 64, m: 1 },
{ s: 20, f: 64, m: 1 },
{ s: 21, f: 128, m: 1 },
{ s: 22, f: 128, m: 1 },
{ s: 23, f: 128, m: 1 },
{ s: 24, f: 255, m: 1 },
{ s: 25, f: 255, m: 1 }
]
function get_mode_obj(mode) {
return modes[mode - 1] || modes[6]
}
/**
* Compress a string with the LZMA algorithm
*
* @param {string} value The string to be compressed
* @param {object} options
* @param {1|2|3|4|5|6|7|8|9} options.mode Which mode to use (1 through 9, defaults to 7)
* @param {boolean} options.enableEndMark Whether to write an end mark
* @returns {string}
*/
export function compress(value, { mode = 7, enableEndMark = true } = {}) {
var this$static = {}
this$static.c = $LZMAByteArrayCompressor(
{},
encode(value),
get_mode_obj(mode),
enableEndMark
)
while ($processChunk(this$static.c.chunker));
return $toByteArray(this$static.c.output)
}
/**
* Compress a string with the LZMA algorithm to URL-safe characters
*
* @param {string} value The string to be compressed
* @param {object} options
* @param {1|2|3|4|5|6|7|8|9} options.mode Which mode to use (1 through 9, defaults to 7)
* @param {boolean} options.enableEndMark Whether to write an end mark
* @returns {string}
*/
export function compressUrlSafe(
string,
{ mode = 7, enableEndMark = true } = {}
) {
const compressedString = compress(string, { mode, enableEndMark })
const compressedBytes = new Uint8Array(compressedString)
return base64.encodeFromArrayUrlSafe(compressedBytes)
}
/**
* Decompress a string compressed with the LZMA algorithm
*
* @param {number[]|Int8Array} bytes The int8 array created by the compress() function
* @returns {string}
*/
export function decompress(bytes) {
var this$static = {}
this$static.d = $LZMAByteArrayDecompressor({}, bytes)
while ($processChunk(this$static.d.chunker));
return decode($toByteArray(this$static.d.output))
}
/**
* Decompress a string compressed with the URL-safe compress function
*
* @param {string} string The URL-safe string generated by the compressUrlSafe() function
* @returns {string}
*/
export function decompressUrlSafe(string) {
return decompress(new Int8Array(base64.decodeToArrayUrlSafe(string)))
}
@Codezigineer
Copy link

Without base64 at all:

const __4294967296 = 4294967296,
  N1_longLit = [4294967295, -__4294967296],
  MIN_VALUE = [0, -9223372036854775808],
  P0_longLit = [0, 0],
  P1_longLit = [1, 0]

function add(a, b) {
  return create(a[0] + b[0], a[1] + b[1])
}

function initDim(len) {
  // NOTE: This is MUCH faster than "initDim(len)" in newer versions of v8 (starting with Node.js 0.11.15, which uses v8 3.28.73).
  var a = []
  a[len - 1] = undefined
  return a
}
function and(a, b) {
  return makeFromBits(
    ~~Math.max(Math.min(a[1] / __4294967296, 2147483647), -2147483648) &
      ~~Math.max(Math.min(b[1] / __4294967296, 2147483647), -2147483648),
    lowBits_0(a) & lowBits_0(b)
  )
}
function compare(a, b) {
  var nega, negb
  if (a[0] == b[0] && a[1] == b[1]) {
    return 0
  }
  nega = a[1] < 0
  negb = b[1] < 0
  if (nega && !negb) {
    return -1
  }
  if (!nega && negb) {
    return 1
  }
  if (sub(a, b)[1] < 0) {
    return -1
  }
  return 1
}

function create(valueLow, valueHigh) {
  var diffHigh, diffLow
  valueHigh %= 1.8446744073709552e19
  valueLow %= 1.8446744073709552e19
  diffHigh = valueHigh % __4294967296
  diffLow = Math.floor(valueLow / __4294967296) * __4294967296
  valueHigh = valueHigh - diffHigh + diffLow
  valueLow = valueLow - diffLow + diffHigh
  while (valueLow < 0) {
    valueLow += __4294967296
    valueHigh -= __4294967296
  }
  while (valueLow > 4294967295) {
    valueLow -= __4294967296
    valueHigh += __4294967296
  }
  valueHigh = valueHigh % 1.8446744073709552e19
  while (valueHigh > 9223372032559808512) {
    valueHigh -= 1.8446744073709552e19
  }
  while (valueHigh < -9223372036854775808) {
    valueHigh += 1.8446744073709552e19
  }
  return [valueLow, valueHigh]
}
function eq(a, b) {
  return a[0] == b[0] && a[1] == b[1]
}
function fromInt(value) {
  if (value >= 0) {
    return [value, 0]
  } else {
    return [value + __4294967296, -__4294967296]
  }
}

function lowBits_0(a) {
  if (a[0] >= 2147483648) {
    return ~~Math.max(Math.min(a[0] - __4294967296, 2147483647), -2147483648)
  } else {
    return ~~Math.max(Math.min(a[0], 2147483647), -2147483648)
  }
}
function makeFromBits(highBits, lowBits) {
  var high, low
  high = highBits * __4294967296
  low = lowBits
  if (lowBits < 0) {
    low += __4294967296
  }
  return [low, high]
}

function pwrAsDouble(n) {
  if (n <= 30) {
    return 1 << n
  } else {
    return pwrAsDouble(30) * pwrAsDouble(n - 30)
  }
}

function shl(a, n) {
  var diff, newHigh, newLow, twoToN
  n &= 63
  if (eq(a, MIN_VALUE)) {
    if (!n) {
      return a
    }
    return P0_longLit
  }
  if (a[1] < 0) {
    throw new Error('Neg')
  }
  twoToN = pwrAsDouble(n)
  newHigh = (a[1] * twoToN) % 1.8446744073709552e19
  newLow = a[0] * twoToN
  diff = newLow - (newLow % __4294967296)
  newHigh += diff
  newLow -= diff
  if (newHigh >= 9223372036854775807) {
    newHigh -= 1.8446744073709552e19
  }
  return [newLow, newHigh]
}

function shr(a, n) {
  var shiftFact
  n &= 63
  shiftFact = pwrAsDouble(n)
  return create(Math.floor(a[0] / shiftFact), a[1] / shiftFact)
}

function shru(a, n) {
  var sr
  n &= 63
  sr = shr(a, n)
  if (a[1] < 0) {
    sr = add(sr, shl([2, 0], 63 - n))
  }
  return sr
}
function sub(a, b) {
  return create(a[0] - b[0], a[1] - b[1])
}

function $ByteArrayInputStream(this$static, buf) {
  this$static.buf = buf
  this$static.pos = 0
  this$static.count = buf.length
  return this$static
}
function $read(this$static) {
  if (this$static.pos >= this$static.count) return -1
  return this$static.buf[this$static.pos++] & 255
}
function $read_0(this$static, buf, off, len) {
  if (this$static.pos >= this$static.count) return -1
  len = Math.min(len, this$static.count - this$static.pos)
  arraycopy(this$static.buf, this$static.pos, buf, off, len)
  this$static.pos += len
  return len
}
function $ByteArrayOutputStream(this$static) {
  this$static.buf = initDim(32)
  this$static.count = 0
  return this$static
}

function $toByteArray(this$static) {
  var data = this$static.buf
  data.length = this$static.count
  return data
}
function $write(this$static, b) {
  this$static.buf[this$static.count++] = (b << 24) >> 24
}
function $write_0(this$static, buf, off, len) {
  arraycopy(buf, off, this$static.buf, this$static.count, len)
  this$static.count += len
}
function $getChars(this$static, srcBegin, srcEnd, dst, dstBegin) {
  var srcIdx
  for (srcIdx = srcBegin; srcIdx < srcEnd; ++srcIdx) {
    dst[dstBegin++] = this$static.charCodeAt(srcIdx)
  }
}
function arraycopy(src, srcOfs, dest, destOfs, len) {
  for (var i = 0; i < len; ++i) {
    dest[destOfs + i] = src[srcOfs + i]
  }
}
function $configure(this$static, encoder) {
  $SetDictionarySize_0(encoder, 1 << this$static.s)
  encoder._numFastBytes = this$static.f
  $SetMatchFinder(encoder, this$static.m)

  // lc is always 3
  // lp is always 0
  // pb is always 2
  encoder._numLiteralPosStateBits = 0
  encoder._numLiteralContextBits = 3
  encoder._posStateBits = 2
  encoder._posStateMask = 3
}

function $init(this$static, input, output, length_0, mode, enableEndMark) {
  var encoder, i
  if (compare(length_0, N1_longLit) < 0)
    throw new Error('invalid length ' + length_0)
  this$static.length_0 = length_0
  encoder = $Encoder({})
  $configure(mode, encoder)
  encoder._writeEndMark = enableEndMark
  $WriteCoderProperties(encoder, output)
  for (i = 0; i < 64; i += 8) $write(output, lowBits_0(shr(length_0, i)) & 255)
  this$static.chunker =
    ((encoder._needReleaseMFStream = 0),
    ((encoder._inStream = input),
    (encoder._finished = 0),
    $Create_2(encoder),
    (encoder._rangeEncoder.Stream = output),
    $Init_4(encoder),
    $FillDistancesPrices(encoder),
    $FillAlignPrices(encoder),
    (encoder._lenEncoder._tableSize = encoder._numFastBytes + 1 - 2),
    $UpdateTables(encoder._lenEncoder, 1 << encoder._posStateBits),
    (encoder._repMatchLenEncoder._tableSize = encoder._numFastBytes + 1 - 2),
    $UpdateTables(encoder._repMatchLenEncoder, 1 << encoder._posStateBits),
    (encoder.nowPos64 = P0_longLit),
    undefined),
    $Chunker_0({}, encoder))
}

function $LZMAByteArrayCompressor(this$static, data, mode, enableEndMark) {
  this$static.output = $ByteArrayOutputStream({})
  $init(
    this$static,
    $ByteArrayInputStream({}, data),
    this$static.output,
    fromInt(data.length),
    mode,
    enableEndMark
  )
  return this$static
}
function $init_0(this$static, input, output) {
  var decoder,
    hex_length = '',
    i,
    properties = [],
    r,
    tmp_length

  for (i = 0; i < 5; ++i) {
    r = $read(input)
    if (r == -1) throw new Error('truncated input')
    properties[i] = (r << 24) >> 24
  }

  decoder = $Decoder({})
  if (!$SetDecoderProperties(decoder, properties)) {
    throw new Error('corrupted input')
  }
  for (i = 0; i < 64; i += 8) {
    r = $read(input)
    if (r == -1) throw new Error('truncated input')
    r = r.toString(16)
    if (r.length == 1) r = '0' + r
    hex_length = r + '' + hex_length
  }

  // Was the length set in the header (if it was compressed from a stream, the length is all f"s).
  if (/^0+$|^f+$/i.test(hex_length)) {
    // The length is unknown, so set to -1.
    this$static.length_0 = N1_longLit
  } else {
    // NOTE: If there is a problem with the decoder because of the length, you can always set the length to -1 (N1_longLit) which means unknown.
    tmp_length = parseInt(hex_length, 16)
    // If the length is too long to handle, just set it to unknown.
    if (tmp_length > 4294967295) {
      this$static.length_0 = N1_longLit
    } else {
      this$static.length_0 = fromInt(tmp_length)
    }
  }

  this$static.chunker = $CodeInChunks(
    decoder,
    input,
    output,
    this$static.length_0
  )
}

function $LZMAByteArrayDecompressor(this$static, data) {
  this$static.output = $ByteArrayOutputStream({})
  $init_0(this$static, $ByteArrayInputStream({}, data), this$static.output)
  return this$static
}
function $Create_4(this$static, keepSizeBefore, keepSizeAfter, keepSizeReserv) {
  var blockSize
  this$static._keepSizeBefore = keepSizeBefore
  this$static._keepSizeAfter = keepSizeAfter
  blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv
  if (this$static._bufferBase == null || this$static._blockSize != blockSize) {
    this$static._bufferBase = null
    this$static._blockSize = blockSize
    this$static._bufferBase = initDim(this$static._blockSize)
  }
  this$static._pointerToLastSafePosition =
    this$static._blockSize - keepSizeAfter
}

function $GetIndexByte(this$static, index) {
  return this$static._bufferBase[
    this$static._bufferOffset + this$static._pos + index
  ]
}

function $GetMatchLen(this$static, index, distance, limit) {
  var i, pby
  if (this$static._streamEndWasReached) {
    if (this$static._pos + index + limit > this$static._streamPos) {
      limit = this$static._streamPos - (this$static._pos + index)
    }
  }
  ++distance
  pby = this$static._bufferOffset + this$static._pos + index
  for (
    i = 0;
    i < limit &&
    this$static._bufferBase[pby + i] ==
      this$static._bufferBase[pby + i - distance];
    ++i
  ) {}
  return i
}

function $GetNumAvailableBytes(this$static) {
  return this$static._streamPos - this$static._pos
}

function $MoveBlock(this$static) {
  var i, numBytes, offset
  offset =
    this$static._bufferOffset + this$static._pos - this$static._keepSizeBefore
  if (offset > 0) {
    --offset
  }
  numBytes = this$static._bufferOffset + this$static._streamPos - offset
  for (i = 0; i < numBytes; ++i) {
    this$static._bufferBase[i] = this$static._bufferBase[offset + i]
  }
  this$static._bufferOffset -= offset
}

function $MovePos_1(this$static) {
  var pointerToPostion
  ++this$static._pos
  if (this$static._pos > this$static._posLimit) {
    pointerToPostion = this$static._bufferOffset + this$static._pos
    if (pointerToPostion > this$static._pointerToLastSafePosition) {
      $MoveBlock(this$static)
    }
    $ReadBlock(this$static)
  }
}

function $ReadBlock(this$static) {
  var numReadBytes, pointerToPostion, size
  if (this$static._streamEndWasReached) return
  while (1) {
    size =
      -this$static._bufferOffset +
      this$static._blockSize -
      this$static._streamPos
    if (!size) return
    numReadBytes = $read_0(
      this$static._stream,
      this$static._bufferBase,
      this$static._bufferOffset + this$static._streamPos,
      size
    )
    if (numReadBytes == -1) {
      this$static._posLimit = this$static._streamPos
      pointerToPostion = this$static._bufferOffset + this$static._posLimit
      if (pointerToPostion > this$static._pointerToLastSafePosition) {
        this$static._posLimit =
          this$static._pointerToLastSafePosition - this$static._bufferOffset
      }
      this$static._streamEndWasReached = 1
      return
    }
    this$static._streamPos += numReadBytes
    if (
      this$static._streamPos >=
      this$static._pos + this$static._keepSizeAfter
    ) {
      this$static._posLimit =
        this$static._streamPos - this$static._keepSizeAfter
    }
  }
}

function $ReduceOffsets(this$static, subValue) {
  this$static._bufferOffset += subValue
  this$static._posLimit -= subValue
  this$static._pos -= subValue
  this$static._streamPos -= subValue
}

var CrcTable = (function() {
  var i,
    j,
    r,
    CrcTable = []
  for (i = 0; i < 256; ++i) {
    r = i
    for (j = 0; j < 8; ++j)
      if ((r & 1) != 0) {
        r = (r >>> 1) ^ -306674912
      } else {
        r >>>= 1
      }
    CrcTable[i] = r
  }
  return CrcTable
})()

function $Create_3(
  this$static,
  historySize,
  keepAddBufferBefore,
  matchMaxLen,
  keepAddBufferAfter
) {
  var cyclicBufferSize, hs, windowReservSize
  if (historySize < 1073741567) {
    this$static._cutValue = 16 + (matchMaxLen >> 1)
    windowReservSize =
      ~~(
        (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) /
        2
      ) + 256
    $Create_4(
      this$static,
      historySize + keepAddBufferBefore,
      matchMaxLen + keepAddBufferAfter,
      windowReservSize
    )
    this$static._matchMaxLen = matchMaxLen
    cyclicBufferSize = historySize + 1
    if (this$static._cyclicBufferSize != cyclicBufferSize) {
      this$static._son = initDim(
        (this$static._cyclicBufferSize = cyclicBufferSize) * 2
      )
    }

    hs = 65536
    if (this$static.HASH_ARRAY) {
      hs = historySize - 1
      hs |= hs >> 1
      hs |= hs >> 2
      hs |= hs >> 4
      hs |= hs >> 8
      hs >>= 1
      hs |= 65535
      if (hs > 16777216) hs >>= 1
      this$static._hashMask = hs
      ++hs
      hs += this$static.kFixHashSize
    }

    if (hs != this$static._hashSizeSum) {
      this$static._hash = initDim((this$static._hashSizeSum = hs))
    }
  }
}

function $GetMatches(this$static, distances) {
  var count,
    cur,
    curMatch,
    curMatch2,
    curMatch3,
    cyclicPos,
    delta,
    hash2Value,
    hash3Value,
    hashValue,
    len,
    len0,
    len1,
    lenLimit,
    matchMinPos,
    maxLen,
    offset,
    pby1,
    ptr0,
    ptr1,
    temp
  if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) {
    lenLimit = this$static._matchMaxLen
  } else {
    lenLimit = this$static._streamPos - this$static._pos
    if (lenLimit < this$static.kMinMatchCheck) {
      $MovePos_0(this$static)
      return 0
    }
  }
  offset = 0
  matchMinPos =
    this$static._pos > this$static._cyclicBufferSize
      ? this$static._pos - this$static._cyclicBufferSize
      : 0
  cur = this$static._bufferOffset + this$static._pos
  maxLen = 1
  hash2Value = 0
  hash3Value = 0
  if (this$static.HASH_ARRAY) {
    temp =
      CrcTable[this$static._bufferBase[cur] & 255] ^
      (this$static._bufferBase[cur + 1] & 255)
    hash2Value = temp & 1023
    temp ^= (this$static._bufferBase[cur + 2] & 255) << 8
    hash3Value = temp & 65535
    hashValue =
      (temp ^ (CrcTable[this$static._bufferBase[cur + 3] & 255] << 5)) &
      this$static._hashMask
  } else {
    hashValue =
      (this$static._bufferBase[cur] & 255) ^
      ((this$static._bufferBase[cur + 1] & 255) << 8)
  }

  curMatch = this$static._hash[this$static.kFixHashSize + hashValue] || 0
  if (this$static.HASH_ARRAY) {
    curMatch2 = this$static._hash[hash2Value] || 0
    curMatch3 = this$static._hash[1024 + hash3Value] || 0
    this$static._hash[hash2Value] = this$static._pos
    this$static._hash[1024 + hash3Value] = this$static._pos
    if (curMatch2 > matchMinPos) {
      if (
        this$static._bufferBase[this$static._bufferOffset + curMatch2] ==
        this$static._bufferBase[cur]
      ) {
        distances[offset++] = maxLen = 2
        distances[offset++] = this$static._pos - curMatch2 - 1
      }
    }
    if (curMatch3 > matchMinPos) {
      if (
        this$static._bufferBase[this$static._bufferOffset + curMatch3] ==
        this$static._bufferBase[cur]
      ) {
        if (curMatch3 == curMatch2) {
          offset -= 2
        }
        distances[offset++] = maxLen = 3
        distances[offset++] = this$static._pos - curMatch3 - 1
        curMatch2 = curMatch3
      }
    }
    if (offset != 0 && curMatch2 == curMatch) {
      offset -= 2
      maxLen = 1
    }
  }
  this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos
  ptr0 = (this$static._cyclicBufferPos << 1) + 1
  ptr1 = this$static._cyclicBufferPos << 1
  len0 = len1 = this$static.kNumHashDirectBytes
  if (this$static.kNumHashDirectBytes != 0) {
    if (curMatch > matchMinPos) {
      if (
        this$static._bufferBase[
          this$static._bufferOffset + curMatch + this$static.kNumHashDirectBytes
        ] != this$static._bufferBase[cur + this$static.kNumHashDirectBytes]
      ) {
        distances[offset++] = maxLen = this$static.kNumHashDirectBytes
        distances[offset++] = this$static._pos - curMatch - 1
      }
    }
  }
  count = this$static._cutValue
  while (1) {
    if (curMatch <= matchMinPos || count-- == 0) {
      this$static._son[ptr0] = this$static._son[ptr1] = 0
      break
    }
    delta = this$static._pos - curMatch
    cyclicPos =
      (delta <= this$static._cyclicBufferPos
        ? this$static._cyclicBufferPos - delta
        : this$static._cyclicBufferPos -
          delta +
          this$static._cyclicBufferSize) << 1
    pby1 = this$static._bufferOffset + curMatch
    len = len0 < len1 ? len0 : len1
    if (
      this$static._bufferBase[pby1 + len] == this$static._bufferBase[cur + len]
    ) {
      while (++len != lenLimit) {
        if (
          this$static._bufferBase[pby1 + len] !=
          this$static._bufferBase[cur + len]
        ) {
          break
        }
      }
      if (maxLen < len) {
        distances[offset++] = maxLen = len
        distances[offset++] = delta - 1
        if (len == lenLimit) {
          this$static._son[ptr1] = this$static._son[cyclicPos]
          this$static._son[ptr0] = this$static._son[cyclicPos + 1]
          break
        }
      }
    }
    if (
      (this$static._bufferBase[pby1 + len] & 255) <
      (this$static._bufferBase[cur + len] & 255)
    ) {
      this$static._son[ptr1] = curMatch
      ptr1 = cyclicPos + 1
      curMatch = this$static._son[ptr1]
      len1 = len
    } else {
      this$static._son[ptr0] = curMatch
      ptr0 = cyclicPos
      curMatch = this$static._son[ptr0]
      len0 = len
    }
  }
  $MovePos_0(this$static)
  return offset
}

function $Init_5(this$static) {
  this$static._bufferOffset = 0
  this$static._pos = 0
  this$static._streamPos = 0
  this$static._streamEndWasReached = 0
  $ReadBlock(this$static)
  this$static._cyclicBufferPos = 0
  $ReduceOffsets(this$static, -1)
}

function $MovePos_0(this$static) {
  var subValue
  if (++this$static._cyclicBufferPos >= this$static._cyclicBufferSize) {
    this$static._cyclicBufferPos = 0
  }
  $MovePos_1(this$static)
  if (this$static._pos == 1073741823) {
    subValue = this$static._pos - this$static._cyclicBufferSize
    $NormalizeLinks(
      this$static._son,
      this$static._cyclicBufferSize * 2,
      subValue
    )
    $NormalizeLinks(this$static._hash, this$static._hashSizeSum, subValue)
    $ReduceOffsets(this$static, subValue)
  }
}

// NOTE: This is only called after reading one whole gigabyte.
function $NormalizeLinks(items, numItems, subValue) {
  var i, value
  for (i = 0; i < numItems; ++i) {
    value = items[i] || 0
    if (value <= subValue) {
      value = 0
    } else {
      value -= subValue
    }
    items[i] = value
  }
}

function $SetType(this$static, numHashBytes) {
  this$static.HASH_ARRAY = numHashBytes > 2
  if (this$static.HASH_ARRAY) {
    this$static.kNumHashDirectBytes = 0
    this$static.kMinMatchCheck = 4
    this$static.kFixHashSize = 66560
  } else {
    this$static.kNumHashDirectBytes = 2
    this$static.kMinMatchCheck = 3
    this$static.kFixHashSize = 0
  }
}

function $Skip(this$static, num) {
  var count,
    cur,
    curMatch,
    cyclicPos,
    delta,
    hash2Value,
    hash3Value,
    hashValue,
    len,
    len0,
    len1,
    lenLimit,
    matchMinPos,
    pby1,
    ptr0,
    ptr1,
    temp
  do {
    if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) {
      lenLimit = this$static._matchMaxLen
    } else {
      lenLimit = this$static._streamPos - this$static._pos
      if (lenLimit < this$static.kMinMatchCheck) {
        $MovePos_0(this$static)
        continue
      }
    }
    matchMinPos =
      this$static._pos > this$static._cyclicBufferSize
        ? this$static._pos - this$static._cyclicBufferSize
        : 0
    cur = this$static._bufferOffset + this$static._pos
    if (this$static.HASH_ARRAY) {
      temp =
        CrcTable[this$static._bufferBase[cur] & 255] ^
        (this$static._bufferBase[cur + 1] & 255)
      hash2Value = temp & 1023
      this$static._hash[hash2Value] = this$static._pos
      temp ^= (this$static._bufferBase[cur + 2] & 255) << 8
      hash3Value = temp & 65535
      this$static._hash[1024 + hash3Value] = this$static._pos
      hashValue =
        (temp ^ (CrcTable[this$static._bufferBase[cur + 3] & 255] << 5)) &
        this$static._hashMask
    } else {
      hashValue =
        (this$static._bufferBase[cur] & 255) ^
        ((this$static._bufferBase[cur + 1] & 255) << 8)
    }
    curMatch = this$static._hash[this$static.kFixHashSize + hashValue]
    this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos
    ptr0 = (this$static._cyclicBufferPos << 1) + 1
    ptr1 = this$static._cyclicBufferPos << 1
    len0 = len1 = this$static.kNumHashDirectBytes
    count = this$static._cutValue
    while (1) {
      if (curMatch <= matchMinPos || count-- == 0) {
        this$static._son[ptr0] = this$static._son[ptr1] = 0
        break
      }
      delta = this$static._pos - curMatch
      cyclicPos =
        (delta <= this$static._cyclicBufferPos
          ? this$static._cyclicBufferPos - delta
          : this$static._cyclicBufferPos -
            delta +
            this$static._cyclicBufferSize) << 1
      pby1 = this$static._bufferOffset + curMatch
      len = len0 < len1 ? len0 : len1
      if (
        this$static._bufferBase[pby1 + len] ==
        this$static._bufferBase[cur + len]
      ) {
        while (++len != lenLimit) {
          if (
            this$static._bufferBase[pby1 + len] !=
            this$static._bufferBase[cur + len]
          ) {
            break
          }
        }
        if (len == lenLimit) {
          this$static._son[ptr1] = this$static._son[cyclicPos]
          this$static._son[ptr0] = this$static._son[cyclicPos + 1]
          break
        }
      }
      if (
        (this$static._bufferBase[pby1 + len] & 255) <
        (this$static._bufferBase[cur + len] & 255)
      ) {
        this$static._son[ptr1] = curMatch
        ptr1 = cyclicPos + 1
        curMatch = this$static._son[ptr1]
        len1 = len
      } else {
        this$static._son[ptr0] = curMatch
        ptr0 = cyclicPos
        curMatch = this$static._son[ptr0]
        len0 = len
      }
    }
    $MovePos_0(this$static)
  } while (--num != 0)
}
function $CopyBlock(this$static, distance, len) {
  var pos = this$static._pos - distance - 1
  if (pos < 0) {
    pos += this$static._windowSize
  }
  for (; len != 0; --len) {
    if (pos >= this$static._windowSize) {
      pos = 0
    }
    this$static._buffer[this$static._pos++] = this$static._buffer[pos++]
    if (this$static._pos >= this$static._windowSize) {
      $Flush_0(this$static)
    }
  }
}

function $Create_5(this$static, windowSize) {
  if (this$static._buffer == null || this$static._windowSize != windowSize) {
    this$static._buffer = initDim(windowSize)
  }
  this$static._windowSize = windowSize
  this$static._pos = 0
  this$static._streamPos = 0
}

function $Flush_0(this$static) {
  var size = this$static._pos - this$static._streamPos
  if (!size) {
    return
  }
  $write_0(
    this$static._stream,
    this$static._buffer,
    this$static._streamPos,
    size
  )
  if (this$static._pos >= this$static._windowSize) {
    this$static._pos = 0
  }
  this$static._streamPos = this$static._pos
}

function $GetByte(this$static, distance) {
  var pos = this$static._pos - distance - 1
  if (pos < 0) {
    pos += this$static._windowSize
  }
  return this$static._buffer[pos]
}

function $PutByte(this$static, b) {
  this$static._buffer[this$static._pos++] = b
  if (this$static._pos >= this$static._windowSize) {
    $Flush_0(this$static)
  }
}

function $ReleaseStream(this$static) {
  $Flush_0(this$static)
  this$static._stream = null
}
function GetLenToPosState(len) {
  len -= 2
  if (len < 4) {
    return len
  }
  return 3
}

function StateUpdateChar(index) {
  if (index < 4) {
    return 0
  }
  if (index < 10) {
    return index - 3
  }
  return index - 6
}
function $Chunker_0(this$static, encoder) {
  this$static.encoder = encoder
  this$static.decoder = null
  this$static.alive = 1
  return this$static
}
function $Chunker(this$static, decoder) {
  this$static.decoder = decoder
  this$static.encoder = null
  this$static.alive = 1
  return this$static
}
function $processChunk(this$static) {
  if (!this$static.alive) {
    throw new Error('bad state')
  }

  if (this$static.encoder) {
    $processEncoderChunk(this$static)
  } else {
    $processDecoderChunk(this$static)
  }

  return this$static.alive
}
function $processDecoderChunk(this$static) {
  var result = $CodeOneChunk(this$static.decoder)
  if (result == -1) {
    throw new Error('corrupted input')
  }
  this$static.inBytesProcessed = N1_longLit
  this$static.outBytesProcessed = this$static.decoder.nowPos64
  if (
    result ||
    (compare(this$static.decoder.outSize, P0_longLit) >= 0 &&
      compare(this$static.decoder.nowPos64, this$static.decoder.outSize) >= 0)
  ) {
    $Flush_0(this$static.decoder.m_OutWindow)
    $ReleaseStream(this$static.decoder.m_OutWindow)
    this$static.decoder.m_RangeDecoder.Stream = null
    this$static.alive = 0
  }
}
function $processEncoderChunk(this$static) {
  $CodeOneBlock(
    this$static.encoder,
    this$static.encoder.processedInSize,
    this$static.encoder.processedOutSize,
    this$static.encoder.finished
  )
  this$static.inBytesProcessed = this$static.encoder.processedInSize[0]
  if (this$static.encoder.finished[0]) {
    $ReleaseStreams(this$static.encoder)
    this$static.alive = 0
  }
}
function $CodeInChunks(this$static, inStream, outStream, outSize) {
  this$static.m_RangeDecoder.Stream = inStream
  $ReleaseStream(this$static.m_OutWindow)
  this$static.m_OutWindow._stream = outStream
  $Init_1(this$static)
  this$static.state = 0
  this$static.rep0 = 0
  this$static.rep1 = 0
  this$static.rep2 = 0
  this$static.rep3 = 0
  this$static.outSize = outSize
  this$static.nowPos64 = P0_longLit
  this$static.prevByte = 0
  return $Chunker({}, this$static)
}

function $CodeOneChunk(this$static) {
  var decoder2, distance, len, numDirectBits, posSlot, posState
  posState = lowBits_0(this$static.nowPos64) & this$static.m_PosStateMask
  if (
    !$DecodeBit(
      this$static.m_RangeDecoder,
      this$static.m_IsMatchDecoders,
      (this$static.state << 4) + posState
    )
  ) {
    decoder2 = $GetDecoder(
      this$static.m_LiteralDecoder,
      lowBits_0(this$static.nowPos64),
      this$static.prevByte
    )
    if (this$static.state < 7) {
      this$static.prevByte = $DecodeNormal(decoder2, this$static.m_RangeDecoder)
    } else {
      this$static.prevByte = $DecodeWithMatchByte(
        decoder2,
        this$static.m_RangeDecoder,
        $GetByte(this$static.m_OutWindow, this$static.rep0)
      )
    }
    $PutByte(this$static.m_OutWindow, this$static.prevByte)
    this$static.state = StateUpdateChar(this$static.state)
    this$static.nowPos64 = add(this$static.nowPos64, P1_longLit)
  } else {
    if (
      $DecodeBit(
        this$static.m_RangeDecoder,
        this$static.m_IsRepDecoders,
        this$static.state
      )
    ) {
      len = 0
      if (
        !$DecodeBit(
          this$static.m_RangeDecoder,
          this$static.m_IsRepG0Decoders,
          this$static.state
        )
      ) {
        if (
          !$DecodeBit(
            this$static.m_RangeDecoder,
            this$static.m_IsRep0LongDecoders,
            (this$static.state << 4) + posState
          )
        ) {
          this$static.state = this$static.state < 7 ? 9 : 11
          len = 1
        }
      } else {
        if (
          !$DecodeBit(
            this$static.m_RangeDecoder,
            this$static.m_IsRepG1Decoders,
            this$static.state
          )
        ) {
          distance = this$static.rep1
        } else {
          if (
            !$DecodeBit(
              this$static.m_RangeDecoder,
              this$static.m_IsRepG2Decoders,
              this$static.state
            )
          ) {
            distance = this$static.rep2
          } else {
            distance = this$static.rep3
            this$static.rep3 = this$static.rep2
          }
          this$static.rep2 = this$static.rep1
        }
        this$static.rep1 = this$static.rep0
        this$static.rep0 = distance
      }
      if (!len) {
        len =
          $Decode(
            this$static.m_RepLenDecoder,
            this$static.m_RangeDecoder,
            posState
          ) + 2
        this$static.state = this$static.state < 7 ? 8 : 11
      }
    } else {
      this$static.rep3 = this$static.rep2
      this$static.rep2 = this$static.rep1
      this$static.rep1 = this$static.rep0
      len =
        2 +
        $Decode(this$static.m_LenDecoder, this$static.m_RangeDecoder, posState)
      this$static.state = this$static.state < 7 ? 7 : 10
      posSlot = $Decode_0(
        this$static.m_PosSlotDecoder[GetLenToPosState(len)],
        this$static.m_RangeDecoder
      )
      if (posSlot >= 4) {
        numDirectBits = (posSlot >> 1) - 1
        this$static.rep0 = (2 | (posSlot & 1)) << numDirectBits
        if (posSlot < 14) {
          this$static.rep0 += ReverseDecode(
            this$static.m_PosDecoders,
            this$static.rep0 - posSlot - 1,
            this$static.m_RangeDecoder,
            numDirectBits
          )
        } else {
          this$static.rep0 +=
            $DecodeDirectBits(this$static.m_RangeDecoder, numDirectBits - 4) <<
            4
          this$static.rep0 += $ReverseDecode(
            this$static.m_PosAlignDecoder,
            this$static.m_RangeDecoder
          )
          if (this$static.rep0 < 0) {
            if (this$static.rep0 == -1) {
              return 1
            }
            return -1
          }
        }
      } else this$static.rep0 = posSlot
    }
    if (
      compare(fromInt(this$static.rep0), this$static.nowPos64) >= 0 ||
      this$static.rep0 >= this$static.m_DictionarySizeCheck
    ) {
      return -1
    }
    $CopyBlock(this$static.m_OutWindow, this$static.rep0, len)
    this$static.nowPos64 = add(this$static.nowPos64, fromInt(len))
    this$static.prevByte = $GetByte(this$static.m_OutWindow, 0)
  }
  return 0
}

function $Decoder(this$static) {
  this$static.m_OutWindow = {}
  this$static.m_RangeDecoder = {}
  this$static.m_IsMatchDecoders = initDim(192)
  this$static.m_IsRepDecoders = initDim(12)
  this$static.m_IsRepG0Decoders = initDim(12)
  this$static.m_IsRepG1Decoders = initDim(12)
  this$static.m_IsRepG2Decoders = initDim(12)
  this$static.m_IsRep0LongDecoders = initDim(192)
  this$static.m_PosSlotDecoder = initDim(4)
  this$static.m_PosDecoders = initDim(114)
  this$static.m_PosAlignDecoder = $BitTreeDecoder({}, 4)
  this$static.m_LenDecoder = $Decoder$LenDecoder({})
  this$static.m_RepLenDecoder = $Decoder$LenDecoder({})
  this$static.m_LiteralDecoder = {}
  for (var i = 0; i < 4; ++i) {
    this$static.m_PosSlotDecoder[i] = $BitTreeDecoder({}, 6)
  }
  return this$static
}

function $Init_1(this$static) {
  this$static.m_OutWindow._streamPos = 0
  this$static.m_OutWindow._pos = 0
  InitBitModels(this$static.m_IsMatchDecoders)
  InitBitModels(this$static.m_IsRep0LongDecoders)
  InitBitModels(this$static.m_IsRepDecoders)
  InitBitModels(this$static.m_IsRepG0Decoders)
  InitBitModels(this$static.m_IsRepG1Decoders)
  InitBitModels(this$static.m_IsRepG2Decoders)
  InitBitModels(this$static.m_PosDecoders)
  $Init_0(this$static.m_LiteralDecoder)
  for (var i = 0; i < 4; ++i) {
    InitBitModels(this$static.m_PosSlotDecoder[i].Models)
  }
  $Init(this$static.m_LenDecoder)
  $Init(this$static.m_RepLenDecoder)
  InitBitModels(this$static.m_PosAlignDecoder.Models)
  $Init_8(this$static.m_RangeDecoder)
}

function $SetDecoderProperties(this$static, properties) {
  var dictionarySize, i, lc, lp, pb, remainder, val
  if (properties.length < 5) return 0
  val = properties[0] & 255
  lc = val % 9
  remainder = ~~(val / 9)
  lp = remainder % 5
  pb = ~~(remainder / 5)
  dictionarySize = 0
  for (i = 0; i < 4; ++i) {
    dictionarySize += (properties[1 + i] & 255) << (i * 8)
  }
  // NOTE: If the input is bad, it might call for an insanely large dictionary size, which would crash the script.
  if (dictionarySize > 99999999 || !$SetLcLpPb(this$static, lc, lp, pb)) {
    return 0
  }
  return $SetDictionarySize(this$static, dictionarySize)
}

function $SetDictionarySize(this$static, dictionarySize) {
  if (dictionarySize < 0) {
    return 0
  }
  if (this$static.m_DictionarySize != dictionarySize) {
    this$static.m_DictionarySize = dictionarySize
    this$static.m_DictionarySizeCheck = Math.max(
      this$static.m_DictionarySize,
      1
    )
    $Create_5(
      this$static.m_OutWindow,
      Math.max(this$static.m_DictionarySizeCheck, 4096)
    )
  }
  return 1
}

function $SetLcLpPb(this$static, lc, lp, pb) {
  if (lc > 8 || lp > 4 || pb > 4) {
    return 0
  }
  $Create_0(this$static.m_LiteralDecoder, lp, lc)
  var numPosStates = 1 << pb
  $Create(this$static.m_LenDecoder, numPosStates)
  $Create(this$static.m_RepLenDecoder, numPosStates)
  this$static.m_PosStateMask = numPosStates - 1
  return 1
}

function $Create(this$static, numPosStates) {
  for (
    ;
    this$static.m_NumPosStates < numPosStates;
    ++this$static.m_NumPosStates
  ) {
    this$static.m_LowCoder[this$static.m_NumPosStates] = $BitTreeDecoder({}, 3)
    this$static.m_MidCoder[this$static.m_NumPosStates] = $BitTreeDecoder({}, 3)
  }
}

function $Decode(this$static, rangeDecoder, posState) {
  if (!$DecodeBit(rangeDecoder, this$static.m_Choice, 0)) {
    return $Decode_0(this$static.m_LowCoder[posState], rangeDecoder)
  }
  var symbol = 8
  if (!$DecodeBit(rangeDecoder, this$static.m_Choice, 1)) {
    symbol += $Decode_0(this$static.m_MidCoder[posState], rangeDecoder)
  } else {
    symbol += 8 + $Decode_0(this$static.m_HighCoder, rangeDecoder)
  }
  return symbol
}

function $Decoder$LenDecoder(this$static) {
  this$static.m_Choice = initDim(2)
  this$static.m_LowCoder = initDim(16)
  this$static.m_MidCoder = initDim(16)
  this$static.m_HighCoder = $BitTreeDecoder({}, 8)
  this$static.m_NumPosStates = 0
  return this$static
}

function $Init(this$static) {
  InitBitModels(this$static.m_Choice)
  for (var posState = 0; posState < this$static.m_NumPosStates; ++posState) {
    InitBitModels(this$static.m_LowCoder[posState].Models)
    InitBitModels(this$static.m_MidCoder[posState].Models)
  }
  InitBitModels(this$static.m_HighCoder.Models)
}

function $Create_0(this$static, numPosBits, numPrevBits) {
  var i, numStates
  if (
    this$static.m_Coders != null &&
    this$static.m_NumPrevBits == numPrevBits &&
    this$static.m_NumPosBits == numPosBits
  )
    return
  this$static.m_NumPosBits = numPosBits
  this$static.m_PosMask = (1 << numPosBits) - 1
  this$static.m_NumPrevBits = numPrevBits
  numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  this$static.m_Coders = initDim(numStates)
  for (i = 0; i < numStates; ++i)
    this$static.m_Coders[i] = $Decoder$LiteralDecoder$Decoder2({})
}

function $GetDecoder(this$static, pos, prevByte) {
  return this$static.m_Coders[
    ((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) +
      ((prevByte & 255) >>> (8 - this$static.m_NumPrevBits))
  ]
}

function $Init_0(this$static) {
  var i, numStates
  numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  for (i = 0; i < numStates; ++i) {
    InitBitModels(this$static.m_Coders[i].m_Decoders)
  }
}

function $DecodeNormal(this$static, rangeDecoder) {
  var symbol = 1
  do {
    symbol =
      (symbol << 1) | $DecodeBit(rangeDecoder, this$static.m_Decoders, symbol)
  } while (symbol < 256)
  return (symbol << 24) >> 24
}

function $DecodeWithMatchByte(this$static, rangeDecoder, matchByte) {
  var bit,
    matchBit,
    symbol = 1
  do {
    matchBit = (matchByte >> 7) & 1
    matchByte <<= 1
    bit = $DecodeBit(
      rangeDecoder,
      this$static.m_Decoders,
      ((1 + matchBit) << 8) + symbol
    )
    symbol = (symbol << 1) | bit
    if (matchBit != bit) {
      while (symbol < 256) {
        symbol =
          (symbol << 1) |
          $DecodeBit(rangeDecoder, this$static.m_Decoders, symbol)
      }
      break
    }
  } while (symbol < 256)
  return (symbol << 24) >> 24
}

function $Decoder$LiteralDecoder$Decoder2(this$static) {
  this$static.m_Decoders = initDim(768)
  return this$static
}
var g_FastPos = (function() {
  var j,
    k,
    slotFast,
    c = 2,
    g_FastPos = [0, 1]
  for (slotFast = 2; slotFast < 22; ++slotFast) {
    k = 1 << ((slotFast >> 1) - 1)
    for (j = 0; j < k; ++j, ++c) g_FastPos[c] = (slotFast << 24) >> 24
  }
  return g_FastPos
})()

function $Backward(this$static, cur) {
  var backCur, backMem, posMem, posPrev
  this$static._optimumEndIndex = cur
  posMem = this$static._optimum[cur].PosPrev
  backMem = this$static._optimum[cur].BackPrev
  do {
    if (this$static._optimum[cur].Prev1IsChar) {
      $MakeAsChar(this$static._optimum[posMem])
      this$static._optimum[posMem].PosPrev = posMem - 1
      if (this$static._optimum[cur].Prev2) {
        this$static._optimum[posMem - 1].Prev1IsChar = 0
        this$static._optimum[posMem - 1].PosPrev =
          this$static._optimum[cur].PosPrev2
        this$static._optimum[posMem - 1].BackPrev =
          this$static._optimum[cur].BackPrev2
      }
    }
    posPrev = posMem
    backCur = backMem
    backMem = this$static._optimum[posPrev].BackPrev
    posMem = this$static._optimum[posPrev].PosPrev
    this$static._optimum[posPrev].BackPrev = backCur
    this$static._optimum[posPrev].PosPrev = cur
    cur = posPrev
  } while (cur > 0)
  this$static.backRes = this$static._optimum[0].BackPrev
  this$static._optimumCurrentIndex = this$static._optimum[0].PosPrev
  return this$static._optimumCurrentIndex
}

function $BaseInit(this$static) {
  this$static._state = 0
  this$static._previousByte = 0
  for (var i = 0; i < 4; ++i) {
    this$static._repDistances[i] = 0
  }
}

function $CodeOneBlock(this$static, inSize, outSize, finished) {
  var baseVal,
    complexState,
    curByte,
    distance,
    footerBits,
    i,
    len,
    lenToPosState,
    matchByte,
    pos,
    posReduced,
    posSlot,
    posState,
    progressPosValuePrev,
    subCoder
  inSize[0] = P0_longLit
  outSize[0] = P0_longLit
  finished[0] = 1
  if (this$static._inStream) {
    this$static._matchFinder._stream = this$static._inStream
    $Init_5(this$static._matchFinder)
    this$static._needReleaseMFStream = 1
    this$static._inStream = null
  }
  if (this$static._finished) {
    return
  }
  this$static._finished = 1
  progressPosValuePrev = this$static.nowPos64
  if (eq(this$static.nowPos64, P0_longLit)) {
    if (!$GetNumAvailableBytes(this$static._matchFinder)) {
      $Flush(this$static, lowBits_0(this$static.nowPos64))
      return
    }
    $ReadMatchDistances(this$static)
    posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask
    $Encode_3(
      this$static._rangeEncoder,
      this$static._isMatch,
      (this$static._state << 4) + posState,
      0
    )
    this$static._state = StateUpdateChar(this$static._state)
    curByte = $GetIndexByte(
      this$static._matchFinder,
      -this$static._additionalOffset
    )
    $Encode_1(
      $GetSubCoder(
        this$static._literalEncoder,
        lowBits_0(this$static.nowPos64),
        this$static._previousByte
      ),
      this$static._rangeEncoder,
      curByte
    )
    this$static._previousByte = curByte
    --this$static._additionalOffset
    this$static.nowPos64 = add(this$static.nowPos64, P1_longLit)
  }
  if (!$GetNumAvailableBytes(this$static._matchFinder)) {
    $Flush(this$static, lowBits_0(this$static.nowPos64))
    return
  }
  while (1) {
    len = $GetOptimum(this$static, lowBits_0(this$static.nowPos64))
    pos = this$static.backRes
    posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask
    complexState = (this$static._state << 4) + posState
    if (len == 1 && pos == -1) {
      $Encode_3(
        this$static._rangeEncoder,
        this$static._isMatch,
        complexState,
        0
      )
      curByte = $GetIndexByte(
        this$static._matchFinder,
        -this$static._additionalOffset
      )
      subCoder = $GetSubCoder(
        this$static._literalEncoder,
        lowBits_0(this$static.nowPos64),
        this$static._previousByte
      )
      if (this$static._state < 7) {
        $Encode_1(subCoder, this$static._rangeEncoder, curByte)
      } else {
        matchByte = $GetIndexByte(
          this$static._matchFinder,
          -this$static._repDistances[0] - 1 - this$static._additionalOffset
        )
        $EncodeMatched(subCoder, this$static._rangeEncoder, matchByte, curByte)
      }
      this$static._previousByte = curByte
      this$static._state = StateUpdateChar(this$static._state)
    } else {
      $Encode_3(
        this$static._rangeEncoder,
        this$static._isMatch,
        complexState,
        1
      )
      if (pos < 4) {
        $Encode_3(
          this$static._rangeEncoder,
          this$static._isRep,
          this$static._state,
          1
        )
        if (!pos) {
          $Encode_3(
            this$static._rangeEncoder,
            this$static._isRepG0,
            this$static._state,
            0
          )
          if (len == 1) {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRep0Long,
              complexState,
              0
            )
          } else {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRep0Long,
              complexState,
              1
            )
          }
        } else {
          $Encode_3(
            this$static._rangeEncoder,
            this$static._isRepG0,
            this$static._state,
            1
          )
          if (pos == 1) {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRepG1,
              this$static._state,
              0
            )
          } else {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRepG1,
              this$static._state,
              1
            )
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRepG2,
              this$static._state,
              pos - 2
            )
          }
        }
        if (len == 1) {
          this$static._state = this$static._state < 7 ? 9 : 11
        } else {
          $Encode_0(
            this$static._repMatchLenEncoder,
            this$static._rangeEncoder,
            len - 2,
            posState
          )
          this$static._state = this$static._state < 7 ? 8 : 11
        }
        distance = this$static._repDistances[pos]
        if (pos != 0) {
          for (i = pos; i >= 1; --i) {
            this$static._repDistances[i] = this$static._repDistances[i - 1]
          }
          this$static._repDistances[0] = distance
        }
      } else {
        $Encode_3(
          this$static._rangeEncoder,
          this$static._isRep,
          this$static._state,
          0
        )
        this$static._state = this$static._state < 7 ? 7 : 10
        $Encode_0(
          this$static._lenEncoder,
          this$static._rangeEncoder,
          len - 2,
          posState
        )
        pos -= 4
        posSlot = GetPosSlot(pos)
        lenToPosState = GetLenToPosState(len)
        $Encode_2(
          this$static._posSlotEncoder[lenToPosState],
          this$static._rangeEncoder,
          posSlot
        )
        if (posSlot >= 4) {
          footerBits = (posSlot >> 1) - 1
          baseVal = (2 | (posSlot & 1)) << footerBits
          posReduced = pos - baseVal
          if (posSlot < 14) {
            ReverseEncode(
              this$static._posEncoders,
              baseVal - posSlot - 1,
              this$static._rangeEncoder,
              footerBits,
              posReduced
            )
          } else {
            $EncodeDirectBits(
              this$static._rangeEncoder,
              posReduced >> 4,
              footerBits - 4
            )
            $ReverseEncode(
              this$static._posAlignEncoder,
              this$static._rangeEncoder,
              posReduced & 15
            )
            ++this$static._alignPriceCount
          }
        }
        distance = pos
        for (i = 3; i >= 1; --i) {
          this$static._repDistances[i] = this$static._repDistances[i - 1]
        }
        this$static._repDistances[0] = distance
        ++this$static._matchPriceCount
      }
      this$static._previousByte = $GetIndexByte(
        this$static._matchFinder,
        len - 1 - this$static._additionalOffset
      )
    }
    this$static._additionalOffset -= len
    this$static.nowPos64 = add(this$static.nowPos64, fromInt(len))
    if (!this$static._additionalOffset) {
      if (this$static._matchPriceCount >= 128) {
        $FillDistancesPrices(this$static)
      }
      if (this$static._alignPriceCount >= 16) {
        $FillAlignPrices(this$static)
      }
      inSize[0] = this$static.nowPos64
      outSize[0] = $GetProcessedSizeAdd(this$static._rangeEncoder)
      if (!$GetNumAvailableBytes(this$static._matchFinder)) {
        $Flush(this$static, lowBits_0(this$static.nowPos64))
        return
      }
      if (
        compare(sub(this$static.nowPos64, progressPosValuePrev), [4096, 0]) >= 0
      ) {
        this$static._finished = 0
        finished[0] = 0
        return
      }
    }
  }
}

function $Create_2(this$static) {
  var bt, numHashBytes
  if (!this$static._matchFinder) {
    bt = {}
    numHashBytes = 4
    if (!this$static._matchFinderType) {
      numHashBytes = 2
    }
    $SetType(bt, numHashBytes)
    this$static._matchFinder = bt
  }
  $Create_1(
    this$static._literalEncoder,
    this$static._numLiteralPosStateBits,
    this$static._numLiteralContextBits
  )
  if (
    this$static._dictionarySize == this$static._dictionarySizePrev &&
    this$static._numFastBytesPrev == this$static._numFastBytes
  ) {
    return
  }
  $Create_3(
    this$static._matchFinder,
    this$static._dictionarySize,
    4096,
    this$static._numFastBytes,
    274
  )
  this$static._dictionarySizePrev = this$static._dictionarySize
  this$static._numFastBytesPrev = this$static._numFastBytes
}

function $Encoder(this$static) {
  var i
  this$static._repDistances = initDim(4)
  this$static._optimum = []
  this$static._rangeEncoder = {}
  this$static._isMatch = initDim(192)
  this$static._isRep = initDim(12)
  this$static._isRepG0 = initDim(12)
  this$static._isRepG1 = initDim(12)
  this$static._isRepG2 = initDim(12)
  this$static._isRep0Long = initDim(192)
  this$static._posSlotEncoder = []
  this$static._posEncoders = initDim(114)
  this$static._posAlignEncoder = $BitTreeEncoder({}, 4)
  this$static._lenEncoder = $Encoder$LenPriceTableEncoder({})
  this$static._repMatchLenEncoder = $Encoder$LenPriceTableEncoder({})
  this$static._literalEncoder = {}
  this$static._matchDistances = []
  this$static._posSlotPrices = []
  this$static._distancesPrices = []
  this$static._alignPrices = initDim(16)
  this$static.reps = initDim(4)
  this$static.repLens = initDim(4)
  this$static.processedInSize = [P0_longLit]
  this$static.processedOutSize = [P0_longLit]
  this$static.finished = [0]
  this$static.properties = initDim(5)
  this$static.tempPrices = initDim(128)
  this$static._longestMatchLength = 0
  this$static._matchFinderType = 1
  this$static._numDistancePairs = 0
  this$static._numFastBytesPrev = -1
  this$static.backRes = 0
  for (i = 0; i < 4096; ++i) {
    this$static._optimum[i] = {}
  }
  for (i = 0; i < 4; ++i) {
    this$static._posSlotEncoder[i] = $BitTreeEncoder({}, 6)
  }
  return this$static
}

function $FillAlignPrices(this$static) {
  for (var i = 0; i < 16; ++i) {
    this$static._alignPrices[i] = $ReverseGetPrice(
      this$static._posAlignEncoder,
      i
    )
  }
  this$static._alignPriceCount = 0
}

function $FillDistancesPrices(this$static) {
  var baseVal, encoder, footerBits, i, lenToPosState, posSlot, st, st2
  for (i = 4; i < 128; ++i) {
    posSlot = GetPosSlot(i)
    footerBits = (posSlot >> 1) - 1
    baseVal = (2 | (posSlot & 1)) << footerBits
    this$static.tempPrices[i] = ReverseGetPrice(
      this$static._posEncoders,
      baseVal - posSlot - 1,
      footerBits,
      i - baseVal
    )
  }
  for (lenToPosState = 0; lenToPosState < 4; ++lenToPosState) {
    encoder = this$static._posSlotEncoder[lenToPosState]
    st = lenToPosState << 6
    for (posSlot = 0; posSlot < this$static._distTableSize; ++posSlot) {
      this$static._posSlotPrices[st + posSlot] = $GetPrice_1(encoder, posSlot)
    }
    for (posSlot = 14; posSlot < this$static._distTableSize; ++posSlot) {
      this$static._posSlotPrices[st + posSlot] += ((posSlot >> 1) - 1 - 4) << 6
    }
    st2 = lenToPosState * 128
    for (i = 0; i < 4; ++i) {
      this$static._distancesPrices[st2 + i] = this$static._posSlotPrices[st + i]
    }
    for (; i < 128; ++i) {
      this$static._distancesPrices[st2 + i] =
        this$static._posSlotPrices[st + GetPosSlot(i)] +
        this$static.tempPrices[i]
    }
  }
  this$static._matchPriceCount = 0
}

function $Flush(this$static, nowPos) {
  $ReleaseMFStream(this$static)
  $WriteEndMarker(this$static, nowPos & this$static._posStateMask)
  for (var i = 0; i < 5; ++i) {
    $ShiftLow(this$static._rangeEncoder)
  }
}

function $GetOptimum(this$static, position) {
  var cur,
    curAnd1Price,
    curAndLenCharPrice,
    curAndLenPrice,
    curBack,
    curPrice,
    currentByte,
    distance,
    i,
    len,
    lenEnd,
    lenMain,
    lenRes,
    lenTest,
    lenTest2,
    lenTestTemp,
    matchByte,
    matchPrice,
    newLen,
    nextIsChar,
    nextMatchPrice,
    nextOptimum,
    nextRepMatchPrice,
    normalMatchPrice,
    numAvailableBytes,
    numAvailableBytesFull,
    numDistancePairs,
    offs,
    offset,
    opt,
    optimum,
    pos,
    posPrev,
    posState,
    posStateNext,
    price_4,
    repIndex,
    repLen,
    repMatchPrice,
    repMaxIndex,
    shortRepPrice,
    startLen,
    state,
    state2,
    t,
    price,
    price_0,
    price_1,
    price_2,
    price_3
  if (this$static._optimumEndIndex != this$static._optimumCurrentIndex) {
    lenRes =
      this$static._optimum[this$static._optimumCurrentIndex].PosPrev -
      this$static._optimumCurrentIndex
    this$static.backRes =
      this$static._optimum[this$static._optimumCurrentIndex].BackPrev
    this$static._optimumCurrentIndex =
      this$static._optimum[this$static._optimumCurrentIndex].PosPrev
    return lenRes
  }
  this$static._optimumCurrentIndex = this$static._optimumEndIndex = 0
  if (this$static._longestMatchWasFound) {
    lenMain = this$static._longestMatchLength
    this$static._longestMatchWasFound = 0
  } else {
    lenMain = $ReadMatchDistances(this$static)
  }
  numDistancePairs = this$static._numDistancePairs
  numAvailableBytes = $GetNumAvailableBytes(this$static._matchFinder) + 1
  if (numAvailableBytes < 2) {
    this$static.backRes = -1
    return 1
  }
  if (numAvailableBytes > 273) {
    numAvailableBytes = 273
  }
  repMaxIndex = 0
  for (i = 0; i < 4; ++i) {
    this$static.reps[i] = this$static._repDistances[i]
    this$static.repLens[i] = $GetMatchLen(
      this$static._matchFinder,
      -1,
      this$static.reps[i],
      273
    )
    if (this$static.repLens[i] > this$static.repLens[repMaxIndex]) {
      repMaxIndex = i
    }
  }
  if (this$static.repLens[repMaxIndex] >= this$static._numFastBytes) {
    this$static.backRes = repMaxIndex
    lenRes = this$static.repLens[repMaxIndex]
    $MovePos(this$static, lenRes - 1)
    return lenRes
  }
  if (lenMain >= this$static._numFastBytes) {
    this$static.backRes = this$static._matchDistances[numDistancePairs - 1] + 4
    $MovePos(this$static, lenMain - 1)
    return lenMain
  }
  currentByte = $GetIndexByte(this$static._matchFinder, -1)
  matchByte = $GetIndexByte(
    this$static._matchFinder,
    -this$static._repDistances[0] - 1 - 1
  )
  if (
    lenMain < 2 &&
    currentByte != matchByte &&
    this$static.repLens[repMaxIndex] < 2
  ) {
    this$static.backRes = -1
    return 1
  }
  this$static._optimum[0].State = this$static._state
  posState = position & this$static._posStateMask
  this$static._optimum[1].Price =
    ProbPrices[
      this$static._isMatch[(this$static._state << 4) + posState] >>> 2
    ] +
    $GetPrice_0(
      $GetSubCoder(
        this$static._literalEncoder,
        position,
        this$static._previousByte
      ),
      this$static._state >= 7,
      matchByte,
      currentByte
    )
  $MakeAsChar(this$static._optimum[1])
  matchPrice =
    ProbPrices[
      (2048 - this$static._isMatch[(this$static._state << 4) + posState]) >>> 2
    ]
  repMatchPrice =
    matchPrice +
    ProbPrices[(2048 - this$static._isRep[this$static._state]) >>> 2]
  if (matchByte == currentByte) {
    shortRepPrice =
      repMatchPrice +
      $GetRepLen1Price(this$static, this$static._state, posState)
    if (shortRepPrice < this$static._optimum[1].Price) {
      this$static._optimum[1].Price = shortRepPrice
      $MakeAsShortRep(this$static._optimum[1])
    }
  }
  lenEnd =
    lenMain >= this$static.repLens[repMaxIndex]
      ? lenMain
      : this$static.repLens[repMaxIndex]
  if (lenEnd < 2) {
    this$static.backRes = this$static._optimum[1].BackPrev
    return 1
  }
  this$static._optimum[1].PosPrev = 0
  this$static._optimum[0].Backs0 = this$static.reps[0]
  this$static._optimum[0].Backs1 = this$static.reps[1]
  this$static._optimum[0].Backs2 = this$static.reps[2]
  this$static._optimum[0].Backs3 = this$static.reps[3]
  len = lenEnd
  do {
    this$static._optimum[len--].Price = 268435455
  } while (len >= 2)
  for (i = 0; i < 4; ++i) {
    repLen = this$static.repLens[i]
    if (repLen < 2) {
      continue
    }
    price_4 =
      repMatchPrice +
      $GetPureRepPrice(this$static, i, this$static._state, posState)
    do {
      curAndLenPrice =
        price_4 +
        $GetPrice(this$static._repMatchLenEncoder, repLen - 2, posState)
      optimum = this$static._optimum[repLen]
      if (curAndLenPrice < optimum.Price) {
        optimum.Price = curAndLenPrice
        optimum.PosPrev = 0
        optimum.BackPrev = i
        optimum.Prev1IsChar = 0
      }
    } while (--repLen >= 2)
  }
  normalMatchPrice =
    matchPrice + ProbPrices[this$static._isRep[this$static._state] >>> 2]
  len = this$static.repLens[0] >= 2 ? this$static.repLens[0] + 1 : 2
  if (len <= lenMain) {
    offs = 0
    while (len > this$static._matchDistances[offs]) {
      offs += 2
    }
    for (; ; ++len) {
      distance = this$static._matchDistances[offs + 1]
      curAndLenPrice =
        normalMatchPrice + $GetPosLenPrice(this$static, distance, len, posState)
      optimum = this$static._optimum[len]
      if (curAndLenPrice < optimum.Price) {
        optimum.Price = curAndLenPrice
        optimum.PosPrev = 0
        optimum.BackPrev = distance + 4
        optimum.Prev1IsChar = 0
      }
      if (len == this$static._matchDistances[offs]) {
        offs += 2
        if (offs == numDistancePairs) {
          break
        }
      }
    }
  }
  cur = 0
  while (1) {
    ++cur
    if (cur == lenEnd) {
      return $Backward(this$static, cur)
    }
    newLen = $ReadMatchDistances(this$static)
    numDistancePairs = this$static._numDistancePairs
    if (newLen >= this$static._numFastBytes) {
      this$static._longestMatchLength = newLen
      this$static._longestMatchWasFound = 1
      return $Backward(this$static, cur)
    }
    ++position
    posPrev = this$static._optimum[cur].PosPrev
    if (this$static._optimum[cur].Prev1IsChar) {
      --posPrev
      if (this$static._optimum[cur].Prev2) {
        state = this$static._optimum[this$static._optimum[cur].PosPrev2].State
        if (this$static._optimum[cur].BackPrev2 < 4) {
          state = state < 7 ? 8 : 11
        } else {
          state = state < 7 ? 7 : 10
        }
      } else {
        state = this$static._optimum[posPrev].State
      }
      state = StateUpdateChar(state)
    } else {
      state = this$static._optimum[posPrev].State
    }
    if (posPrev == cur - 1) {
      if (!this$static._optimum[cur].BackPrev) {
        state = state < 7 ? 9 : 11
      } else {
        state = StateUpdateChar(state)
      }
    } else {
      if (
        this$static._optimum[cur].Prev1IsChar &&
        this$static._optimum[cur].Prev2
      ) {
        posPrev = this$static._optimum[cur].PosPrev2
        pos = this$static._optimum[cur].BackPrev2
        state = state < 7 ? 8 : 11
      } else {
        pos = this$static._optimum[cur].BackPrev
        if (pos < 4) {
          state = state < 7 ? 8 : 11
        } else {
          state = state < 7 ? 7 : 10
        }
      }
      opt = this$static._optimum[posPrev]
      if (pos < 4) {
        if (!pos) {
          this$static.reps[0] = opt.Backs0
          this$static.reps[1] = opt.Backs1
          this$static.reps[2] = opt.Backs2
          this$static.reps[3] = opt.Backs3
        } else if (pos == 1) {
          this$static.reps[0] = opt.Backs1
          this$static.reps[1] = opt.Backs0
          this$static.reps[2] = opt.Backs2
          this$static.reps[3] = opt.Backs3
        } else if (pos == 2) {
          this$static.reps[0] = opt.Backs2
          this$static.reps[1] = opt.Backs0
          this$static.reps[2] = opt.Backs1
          this$static.reps[3] = opt.Backs3
        } else {
          this$static.reps[0] = opt.Backs3
          this$static.reps[1] = opt.Backs0
          this$static.reps[2] = opt.Backs1
          this$static.reps[3] = opt.Backs2
        }
      } else {
        this$static.reps[0] = pos - 4
        this$static.reps[1] = opt.Backs0
        this$static.reps[2] = opt.Backs1
        this$static.reps[3] = opt.Backs2
      }
    }
    this$static._optimum[cur].State = state
    this$static._optimum[cur].Backs0 = this$static.reps[0]
    this$static._optimum[cur].Backs1 = this$static.reps[1]
    this$static._optimum[cur].Backs2 = this$static.reps[2]
    this$static._optimum[cur].Backs3 = this$static.reps[3]
    curPrice = this$static._optimum[cur].Price
    currentByte = $GetIndexByte(this$static._matchFinder, -1)
    matchByte = $GetIndexByte(
      this$static._matchFinder,
      -this$static.reps[0] - 1 - 1
    )
    posState = position & this$static._posStateMask
    curAnd1Price =
      curPrice +
      ProbPrices[this$static._isMatch[(state << 4) + posState] >>> 2] +
      $GetPrice_0(
        $GetSubCoder(
          this$static._literalEncoder,
          position,
          $GetIndexByte(this$static._matchFinder, -2)
        ),
        state >= 7,
        matchByte,
        currentByte
      )
    nextOptimum = this$static._optimum[cur + 1]
    nextIsChar = 0
    if (curAnd1Price < nextOptimum.Price) {
      nextOptimum.Price = curAnd1Price
      nextOptimum.PosPrev = cur
      nextOptimum.BackPrev = -1
      nextOptimum.Prev1IsChar = 0
      nextIsChar = 1
    }
    matchPrice =
      curPrice +
      ProbPrices[(2048 - this$static._isMatch[(state << 4) + posState]) >>> 2]
    repMatchPrice =
      matchPrice + ProbPrices[(2048 - this$static._isRep[state]) >>> 2]
    if (
      matchByte == currentByte &&
      !(nextOptimum.PosPrev < cur && !nextOptimum.BackPrev)
    ) {
      shortRepPrice =
        repMatchPrice +
        (ProbPrices[this$static._isRepG0[state] >>> 2] +
          ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2])
      if (shortRepPrice <= nextOptimum.Price) {
        nextOptimum.Price = shortRepPrice
        nextOptimum.PosPrev = cur
        nextOptimum.BackPrev = 0
        nextOptimum.Prev1IsChar = 0
        nextIsChar = 1
      }
    }
    numAvailableBytesFull = $GetNumAvailableBytes(this$static._matchFinder) + 1
    numAvailableBytesFull =
      4095 - cur < numAvailableBytesFull ? 4095 - cur : numAvailableBytesFull
    numAvailableBytes = numAvailableBytesFull
    if (numAvailableBytes < 2) {
      continue
    }
    if (numAvailableBytes > this$static._numFastBytes) {
      numAvailableBytes = this$static._numFastBytes
    }
    if (!nextIsChar && matchByte != currentByte) {
      t = Math.min(numAvailableBytesFull - 1, this$static._numFastBytes)
      lenTest2 = $GetMatchLen(
        this$static._matchFinder,
        0,
        this$static.reps[0],
        t
      )
      if (lenTest2 >= 2) {
        state2 = StateUpdateChar(state)
        posStateNext = (position + 1) & this$static._posStateMask
        nextRepMatchPrice =
          curAnd1Price +
          ProbPrices[
            (2048 - this$static._isMatch[(state2 << 4) + posStateNext]) >>> 2
          ] +
          ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
        offset = cur + 1 + lenTest2
        while (lenEnd < offset) {
          this$static._optimum[++lenEnd].Price = 268435455
        }
        curAndLenPrice =
          nextRepMatchPrice +
          ((price = $GetPrice(
            this$static._repMatchLenEncoder,
            lenTest2 - 2,
            posStateNext
          )),
          price + $GetPureRepPrice(this$static, 0, state2, posStateNext))
        optimum = this$static._optimum[offset]
        if (curAndLenPrice < optimum.Price) {
          optimum.Price = curAndLenPrice
          optimum.PosPrev = cur + 1
          optimum.BackPrev = 0
          optimum.Prev1IsChar = 1
          optimum.Prev2 = 0
        }
      }
    }
    startLen = 2
    for (repIndex = 0; repIndex < 4; ++repIndex) {
      lenTest = $GetMatchLen(
        this$static._matchFinder,
        -1,
        this$static.reps[repIndex],
        numAvailableBytes
      )
      if (lenTest < 2) {
        continue
      }
      lenTestTemp = lenTest
      do {
        while (lenEnd < cur + lenTest) {
          this$static._optimum[++lenEnd].Price = 268435455
        }
        curAndLenPrice =
          repMatchPrice +
          ((price_0 = $GetPrice(
            this$static._repMatchLenEncoder,
            lenTest - 2,
            posState
          )),
          price_0 + $GetPureRepPrice(this$static, repIndex, state, posState))
        optimum = this$static._optimum[cur + lenTest]
        if (curAndLenPrice < optimum.Price) {
          optimum.Price = curAndLenPrice
          optimum.PosPrev = cur
          optimum.BackPrev = repIndex
          optimum.Prev1IsChar = 0
        }
      } while (--lenTest >= 2)
      lenTest = lenTestTemp
      if (!repIndex) {
        startLen = lenTest + 1
      }
      if (lenTest < numAvailableBytesFull) {
        t = Math.min(
          numAvailableBytesFull - 1 - lenTest,
          this$static._numFastBytes
        )
        lenTest2 = $GetMatchLen(
          this$static._matchFinder,
          lenTest,
          this$static.reps[repIndex],
          t
        )
        if (lenTest2 >= 2) {
          state2 = state < 7 ? 8 : 11
          posStateNext = (position + lenTest) & this$static._posStateMask
          curAndLenCharPrice =
            repMatchPrice +
            ((price_1 = $GetPrice(
              this$static._repMatchLenEncoder,
              lenTest - 2,
              posState
            )),
            price_1 +
              $GetPureRepPrice(this$static, repIndex, state, posState)) +
            ProbPrices[
              this$static._isMatch[(state2 << 4) + posStateNext] >>> 2
            ] +
            $GetPrice_0(
              $GetSubCoder(
                this$static._literalEncoder,
                position + lenTest,
                $GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)
              ),
              1,
              $GetIndexByte(
                this$static._matchFinder,
                lenTest - 1 - (this$static.reps[repIndex] + 1)
              ),
              $GetIndexByte(this$static._matchFinder, lenTest - 1)
            )
          state2 = StateUpdateChar(state2)
          posStateNext = (position + lenTest + 1) & this$static._posStateMask
          nextMatchPrice =
            curAndLenCharPrice +
            ProbPrices[
              (2048 - this$static._isMatch[(state2 << 4) + posStateNext]) >>> 2
            ]
          nextRepMatchPrice =
            nextMatchPrice +
            ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
          offset = lenTest + 1 + lenTest2
          while (lenEnd < cur + offset) {
            this$static._optimum[++lenEnd].Price = 268435455
          }
          curAndLenPrice =
            nextRepMatchPrice +
            ((price_2 = $GetPrice(
              this$static._repMatchLenEncoder,
              lenTest2 - 2,
              posStateNext
            )),
            price_2 + $GetPureRepPrice(this$static, 0, state2, posStateNext))
          optimum = this$static._optimum[cur + offset]
          if (curAndLenPrice < optimum.Price) {
            optimum.Price = curAndLenPrice
            optimum.PosPrev = cur + lenTest + 1
            optimum.BackPrev = 0
            optimum.Prev1IsChar = 1
            optimum.Prev2 = 1
            optimum.PosPrev2 = cur
            optimum.BackPrev2 = repIndex
          }
        }
      }
    }
    if (newLen > numAvailableBytes) {
      newLen = numAvailableBytes
      for (
        numDistancePairs = 0;
        newLen > this$static._matchDistances[numDistancePairs];
        numDistancePairs += 2
      ) {}
      this$static._matchDistances[numDistancePairs] = newLen
      numDistancePairs += 2
    }
    if (newLen >= startLen) {
      normalMatchPrice =
        matchPrice + ProbPrices[this$static._isRep[state] >>> 2]
      while (lenEnd < cur + newLen) {
        this$static._optimum[++lenEnd].Price = 268435455
      }
      offs = 0
      while (startLen > this$static._matchDistances[offs]) {
        offs += 2
      }
      for (lenTest = startLen; ; ++lenTest) {
        curBack = this$static._matchDistances[offs + 1]
        curAndLenPrice =
          normalMatchPrice +
          $GetPosLenPrice(this$static, curBack, lenTest, posState)
        optimum = this$static._optimum[cur + lenTest]
        if (curAndLenPrice < optimum.Price) {
          optimum.Price = curAndLenPrice
          optimum.PosPrev = cur
          optimum.BackPrev = curBack + 4
          optimum.Prev1IsChar = 0
        }
        if (lenTest == this$static._matchDistances[offs]) {
          if (lenTest < numAvailableBytesFull) {
            t = Math.min(
              numAvailableBytesFull - 1 - lenTest,
              this$static._numFastBytes
            )
            lenTest2 = $GetMatchLen(
              this$static._matchFinder,
              lenTest,
              curBack,
              t
            )
            if (lenTest2 >= 2) {
              state2 = state < 7 ? 7 : 10
              posStateNext = (position + lenTest) & this$static._posStateMask
              curAndLenCharPrice =
                curAndLenPrice +
                ProbPrices[
                  this$static._isMatch[(state2 << 4) + posStateNext] >>> 2
                ] +
                $GetPrice_0(
                  $GetSubCoder(
                    this$static._literalEncoder,
                    position + lenTest,
                    $GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)
                  ),
                  1,
                  $GetIndexByte(
                    this$static._matchFinder,
                    lenTest - (curBack + 1) - 1
                  ),
                  $GetIndexByte(this$static._matchFinder, lenTest - 1)
                )
              state2 = StateUpdateChar(state2)
              posStateNext =
                (position + lenTest + 1) & this$static._posStateMask
              nextMatchPrice =
                curAndLenCharPrice +
                ProbPrices[
                  (2048 -
                    this$static._isMatch[(state2 << 4) + posStateNext]) >>>
                    2
                ]
              nextRepMatchPrice =
                nextMatchPrice +
                ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
              offset = lenTest + 1 + lenTest2
              while (lenEnd < cur + offset) {
                this$static._optimum[++lenEnd].Price = 268435455
              }
              curAndLenPrice =
                nextRepMatchPrice +
                ((price_3 = $GetPrice(
                  this$static._repMatchLenEncoder,
                  lenTest2 - 2,
                  posStateNext
                )),
                price_3 +
                  $GetPureRepPrice(this$static, 0, state2, posStateNext))
              optimum = this$static._optimum[cur + offset]
              if (curAndLenPrice < optimum.Price) {
                optimum.Price = curAndLenPrice
                optimum.PosPrev = cur + lenTest + 1
                optimum.BackPrev = 0
                optimum.Prev1IsChar = 1
                optimum.Prev2 = 1
                optimum.PosPrev2 = cur
                optimum.BackPrev2 = curBack + 4
              }
            }
          }
          offs += 2
          if (offs == numDistancePairs) break
        }
      }
    }
  }
}

function $GetPosLenPrice(this$static, pos, len, posState) {
  var price,
    lenToPosState = GetLenToPosState(len)
  if (pos < 128) {
    price = this$static._distancesPrices[lenToPosState * 128 + pos]
  } else {
    price =
      this$static._posSlotPrices[(lenToPosState << 6) + GetPosSlot2(pos)] +
      this$static._alignPrices[pos & 15]
  }
  return price + $GetPrice(this$static._lenEncoder, len - 2, posState)
}

function $GetPureRepPrice(this$static, repIndex, state, posState) {
  var price
  if (!repIndex) {
    price = ProbPrices[this$static._isRepG0[state] >>> 2]
    price +=
      ProbPrices[
        (2048 - this$static._isRep0Long[(state << 4) + posState]) >>> 2
      ]
  } else {
    price = ProbPrices[(2048 - this$static._isRepG0[state]) >>> 2]
    if (repIndex == 1) {
      price += ProbPrices[this$static._isRepG1[state] >>> 2]
    } else {
      price += ProbPrices[(2048 - this$static._isRepG1[state]) >>> 2]
      price += GetPrice(this$static._isRepG2[state], repIndex - 2)
    }
  }
  return price
}

function $GetRepLen1Price(this$static, state, posState) {
  return (
    ProbPrices[this$static._isRepG0[state] >>> 2] +
    ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2]
  )
}

function $Init_4(this$static) {
  $BaseInit(this$static)
  $Init_9(this$static._rangeEncoder)
  InitBitModels(this$static._isMatch)
  InitBitModels(this$static._isRep0Long)
  InitBitModels(this$static._isRep)
  InitBitModels(this$static._isRepG0)
  InitBitModels(this$static._isRepG1)
  InitBitModels(this$static._isRepG2)
  InitBitModels(this$static._posEncoders)
  $Init_3(this$static._literalEncoder)
  for (var i = 0; i < 4; ++i) {
    InitBitModels(this$static._posSlotEncoder[i].Models)
  }
  $Init_2(this$static._lenEncoder, 1 << this$static._posStateBits)
  $Init_2(this$static._repMatchLenEncoder, 1 << this$static._posStateBits)
  InitBitModels(this$static._posAlignEncoder.Models)
  this$static._longestMatchWasFound = 0
  this$static._optimumEndIndex = 0
  this$static._optimumCurrentIndex = 0
  this$static._additionalOffset = 0
}

function $MovePos(this$static, num) {
  if (num > 0) {
    $Skip(this$static._matchFinder, num)
    this$static._additionalOffset += num
  }
}

function $ReadMatchDistances(this$static) {
  var lenRes = 0
  this$static._numDistancePairs = $GetMatches(
    this$static._matchFinder,
    this$static._matchDistances
  )
  if (this$static._numDistancePairs > 0) {
    lenRes = this$static._matchDistances[this$static._numDistancePairs - 2]
    if (lenRes == this$static._numFastBytes)
      lenRes += $GetMatchLen(
        this$static._matchFinder,
        lenRes - 1,
        this$static._matchDistances[this$static._numDistancePairs - 1],
        273 - lenRes
      )
  }
  ++this$static._additionalOffset
  return lenRes
}

function $ReleaseMFStream(this$static) {
  if (this$static._matchFinder && this$static._needReleaseMFStream) {
    this$static._matchFinder._stream = null
    this$static._needReleaseMFStream = 0
  }
}

function $ReleaseStreams(this$static) {
  $ReleaseMFStream(this$static)
  this$static._rangeEncoder.Stream = null
}

function $SetDictionarySize_0(this$static, dictionarySize) {
  this$static._dictionarySize = dictionarySize
  for (var dicLogSize = 0; dictionarySize > 1 << dicLogSize; ++dicLogSize) {}
  this$static._distTableSize = dicLogSize * 2
}

function $SetMatchFinder(this$static, matchFinderIndex) {
  var matchFinderIndexPrev = this$static._matchFinderType
  this$static._matchFinderType = matchFinderIndex
  if (
    this$static._matchFinder &&
    matchFinderIndexPrev != this$static._matchFinderType
  ) {
    this$static._dictionarySizePrev = -1
    this$static._matchFinder = null
  }
}

function $WriteCoderProperties(this$static, outStream) {
  this$static.properties[0] =
    (((this$static._posStateBits * 5 + this$static._numLiteralPosStateBits) *
      9 +
      this$static._numLiteralContextBits) <<
      24) >>
    24
  for (var i = 0; i < 4; ++i) {
    this$static.properties[1 + i] =
      ((this$static._dictionarySize >> (8 * i)) << 24) >> 24
  }
  $write_0(outStream, this$static.properties, 0, 5)
}

function $WriteEndMarker(this$static, posState) {
  if (!this$static._writeEndMark) {
    return
  }
  $Encode_3(
    this$static._rangeEncoder,
    this$static._isMatch,
    (this$static._state << 4) + posState,
    1
  )
  $Encode_3(
    this$static._rangeEncoder,
    this$static._isRep,
    this$static._state,
    0
  )
  this$static._state = this$static._state < 7 ? 7 : 10
  $Encode_0(this$static._lenEncoder, this$static._rangeEncoder, 0, posState)
  var lenToPosState = GetLenToPosState(2)
  $Encode_2(
    this$static._posSlotEncoder[lenToPosState],
    this$static._rangeEncoder,
    63
  )
  $EncodeDirectBits(this$static._rangeEncoder, 67108863, 26)
  $ReverseEncode(this$static._posAlignEncoder, this$static._rangeEncoder, 15)
}

function GetPosSlot(pos) {
  if (pos < 2048) {
    return g_FastPos[pos]
  }
  if (pos < 2097152) {
    return g_FastPos[pos >> 10] + 20
  }
  return g_FastPos[pos >> 20] + 40
}

function GetPosSlot2(pos) {
  if (pos < 131072) {
    return g_FastPos[pos >> 6] + 12
  }
  if (pos < 134217728) {
    return g_FastPos[pos >> 16] + 32
  }
  return g_FastPos[pos >> 26] + 52
}

function $Encode(this$static, rangeEncoder, symbol, posState) {
  if (symbol < 8) {
    $Encode_3(rangeEncoder, this$static._choice, 0, 0)
    $Encode_2(this$static._lowCoder[posState], rangeEncoder, symbol)
  } else {
    symbol -= 8
    $Encode_3(rangeEncoder, this$static._choice, 0, 1)
    if (symbol < 8) {
      $Encode_3(rangeEncoder, this$static._choice, 1, 0)
      $Encode_2(this$static._midCoder[posState], rangeEncoder, symbol)
    } else {
      $Encode_3(rangeEncoder, this$static._choice, 1, 1)
      $Encode_2(this$static._highCoder, rangeEncoder, symbol - 8)
    }
  }
}

function $Encoder$LenEncoder(this$static) {
  this$static._choice = initDim(2)
  this$static._lowCoder = initDim(16)
  this$static._midCoder = initDim(16)
  this$static._highCoder = $BitTreeEncoder({}, 8)
  for (var posState = 0; posState < 16; ++posState) {
    this$static._lowCoder[posState] = $BitTreeEncoder({}, 3)
    this$static._midCoder[posState] = $BitTreeEncoder({}, 3)
  }
  return this$static
}

function $Init_2(this$static, numPosStates) {
  InitBitModels(this$static._choice)
  for (var posState = 0; posState < numPosStates; ++posState) {
    InitBitModels(this$static._lowCoder[posState].Models)
    InitBitModels(this$static._midCoder[posState].Models)
  }
  InitBitModels(this$static._highCoder.Models)
}

function $SetPrices(this$static, posState, numSymbols, prices, st) {
  var a0, a1, b0, b1, i
  a0 = ProbPrices[this$static._choice[0] >>> 2]
  a1 = ProbPrices[(2048 - this$static._choice[0]) >>> 2]
  b0 = a1 + ProbPrices[this$static._choice[1] >>> 2]
  b1 = a1 + ProbPrices[(2048 - this$static._choice[1]) >>> 2]
  i = 0
  for (i = 0; i < 8; ++i) {
    if (i >= numSymbols) return
    prices[st + i] = a0 + $GetPrice_1(this$static._lowCoder[posState], i)
  }
  for (; i < 16; ++i) {
    if (i >= numSymbols) return
    prices[st + i] = b0 + $GetPrice_1(this$static._midCoder[posState], i - 8)
  }
  for (; i < numSymbols; ++i) {
    prices[st + i] = b1 + $GetPrice_1(this$static._highCoder, i - 8 - 8)
  }
}

function $Encode_0(this$static, rangeEncoder, symbol, posState) {
  $Encode(this$static, rangeEncoder, symbol, posState)
  if (--this$static._counters[posState] == 0) {
    $SetPrices(
      this$static,
      posState,
      this$static._tableSize,
      this$static._prices,
      posState * 272
    )
    this$static._counters[posState] = this$static._tableSize
  }
}

function $Encoder$LenPriceTableEncoder(this$static) {
  $Encoder$LenEncoder(this$static)
  this$static._prices = []
  this$static._counters = []
  return this$static
}

function $GetPrice(this$static, symbol, posState) {
  return this$static._prices[posState * 272 + symbol]
}

function $UpdateTables(this$static, numPosStates) {
  for (var posState = 0; posState < numPosStates; ++posState) {
    $SetPrices(
      this$static,
      posState,
      this$static._tableSize,
      this$static._prices,
      posState * 272
    )
    this$static._counters[posState] = this$static._tableSize
  }
}

function $Create_1(this$static, numPosBits, numPrevBits) {
  var i, numStates
  if (
    this$static.m_Coders != null &&
    this$static.m_NumPrevBits == numPrevBits &&
    this$static.m_NumPosBits == numPosBits
  ) {
    return
  }
  this$static.m_NumPosBits = numPosBits
  this$static.m_PosMask = (1 << numPosBits) - 1
  this$static.m_NumPrevBits = numPrevBits
  numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  this$static.m_Coders = initDim(numStates)
  for (i = 0; i < numStates; ++i) {
    this$static.m_Coders[i] = $Encoder$LiteralEncoder$Encoder2({})
  }
}

function $GetSubCoder(this$static, pos, prevByte) {
  return this$static.m_Coders[
    ((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) +
      ((prevByte & 255) >>> (8 - this$static.m_NumPrevBits))
  ]
}

function $Init_3(this$static) {
  var i,
    numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  for (i = 0; i < numStates; ++i) {
    InitBitModels(this$static.m_Coders[i].m_Encoders)
  }
}

function $Encode_1(this$static, rangeEncoder, symbol) {
  var bit,
    i,
    context = 1
  for (i = 7; i >= 0; --i) {
    bit = (symbol >> i) & 1
    $Encode_3(rangeEncoder, this$static.m_Encoders, context, bit)
    context = (context << 1) | bit
  }
}

function $EncodeMatched(this$static, rangeEncoder, matchByte, symbol) {
  var bit,
    i,
    matchBit,
    state,
    same = 1,
    context = 1
  for (i = 7; i >= 0; --i) {
    bit = (symbol >> i) & 1
    state = context
    if (same) {
      matchBit = (matchByte >> i) & 1
      state += (1 + matchBit) << 8
      same = matchBit == bit
    }
    $Encode_3(rangeEncoder, this$static.m_Encoders, state, bit)
    context = (context << 1) | bit
  }
}

function $Encoder$LiteralEncoder$Encoder2(this$static) {
  this$static.m_Encoders = initDim(768)
  return this$static
}

function $GetPrice_0(this$static, matchMode, matchByte, symbol) {
  var bit,
    context = 1,
    i = 7,
    matchBit,
    price = 0
  if (matchMode) {
    for (; i >= 0; --i) {
      matchBit = (matchByte >> i) & 1
      bit = (symbol >> i) & 1
      price += GetPrice(
        this$static.m_Encoders[((1 + matchBit) << 8) + context],
        bit
      )
      context = (context << 1) | bit
      if (matchBit != bit) {
        --i
        break
      }
    }
  }
  for (; i >= 0; --i) {
    bit = (symbol >> i) & 1
    price += GetPrice(this$static.m_Encoders[context], bit)
    context = (context << 1) | bit
  }
  return price
}

function $MakeAsChar(this$static) {
  this$static.BackPrev = -1
  this$static.Prev1IsChar = 0
}

function $MakeAsShortRep(this$static) {
  this$static.BackPrev = 0
  this$static.Prev1IsChar = 0
}
function $BitTreeDecoder(this$static, numBitLevels) {
  this$static.NumBitLevels = numBitLevels
  this$static.Models = initDim(1 << numBitLevels)
  return this$static
}

function $Decode_0(this$static, rangeDecoder) {
  var bitIndex,
    m = 1
  for (bitIndex = this$static.NumBitLevels; bitIndex != 0; --bitIndex) {
    m = (m << 1) + $DecodeBit(rangeDecoder, this$static.Models, m)
  }
  return m - (1 << this$static.NumBitLevels)
}

function $ReverseDecode(this$static, rangeDecoder) {
  var bit,
    bitIndex,
    m = 1,
    symbol = 0
  for (bitIndex = 0; bitIndex < this$static.NumBitLevels; ++bitIndex) {
    bit = $DecodeBit(rangeDecoder, this$static.Models, m)
    m <<= 1
    m += bit
    symbol |= bit << bitIndex
  }
  return symbol
}

function ReverseDecode(Models, startIndex, rangeDecoder, NumBitLevels) {
  var bit,
    bitIndex,
    m = 1,
    symbol = 0
  for (bitIndex = 0; bitIndex < NumBitLevels; ++bitIndex) {
    bit = $DecodeBit(rangeDecoder, Models, startIndex + m)
    m <<= 1
    m += bit
    symbol |= bit << bitIndex
  }
  return symbol
}
function $BitTreeEncoder(this$static, numBitLevels) {
  this$static.NumBitLevels = numBitLevels
  this$static.Models = initDim(1 << numBitLevels)
  return this$static
}

function $Encode_2(this$static, rangeEncoder, symbol) {
  var bit,
    bitIndex,
    m = 1
  for (bitIndex = this$static.NumBitLevels; bitIndex != 0; ) {
    --bitIndex
    bit = (symbol >>> bitIndex) & 1
    $Encode_3(rangeEncoder, this$static.Models, m, bit)
    m = (m << 1) | bit
  }
}

function $GetPrice_1(this$static, symbol) {
  var bit,
    bitIndex,
    m = 1,
    price = 0
  for (bitIndex = this$static.NumBitLevels; bitIndex != 0; ) {
    --bitIndex
    bit = (symbol >>> bitIndex) & 1
    price += GetPrice(this$static.Models[m], bit)
    m = (m << 1) + bit
  }
  return price
}

function $ReverseEncode(this$static, rangeEncoder, symbol) {
  var bit,
    i,
    m = 1
  for (i = 0; i < this$static.NumBitLevels; ++i) {
    bit = symbol & 1
    $Encode_3(rangeEncoder, this$static.Models, m, bit)
    m = (m << 1) | bit
    symbol >>= 1
  }
}

function $ReverseGetPrice(this$static, symbol) {
  var bit,
    i,
    m = 1,
    price = 0
  for (i = this$static.NumBitLevels; i != 0; --i) {
    bit = symbol & 1
    symbol >>>= 1
    price += GetPrice(this$static.Models[m], bit)
    m = (m << 1) | bit
  }
  return price
}

function ReverseEncode(Models, startIndex, rangeEncoder, NumBitLevels, symbol) {
  var bit,
    i,
    m = 1
  for (i = 0; i < NumBitLevels; ++i) {
    bit = symbol & 1
    $Encode_3(rangeEncoder, Models, startIndex + m, bit)
    m = (m << 1) | bit
    symbol >>= 1
  }
}

function ReverseGetPrice(Models, startIndex, NumBitLevels, symbol) {
  var bit,
    i,
    m = 1,
    price = 0
  for (i = NumBitLevels; i != 0; --i) {
    bit = symbol & 1
    symbol >>>= 1
    price += ProbPrices[(((Models[startIndex + m] - bit) ^ -bit) & 2047) >>> 2]
    m = (m << 1) | bit
  }
  return price
}
function $DecodeBit(this$static, probs, index) {
  var newBound,
    prob = probs[index]
  newBound = (this$static.Range >>> 11) * prob
  if ((this$static.Code ^ -2147483648) < (newBound ^ -2147483648)) {
    this$static.Range = newBound
    probs[index] = ((prob + ((2048 - prob) >>> 5)) << 16) >> 16
    if (!(this$static.Range & -16777216)) {
      this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
      this$static.Range <<= 8
    }
    return 0
  } else {
    this$static.Range -= newBound
    this$static.Code -= newBound
    probs[index] = ((prob - (prob >>> 5)) << 16) >> 16
    if (!(this$static.Range & -16777216)) {
      this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
      this$static.Range <<= 8
    }
    return 1
  }
}

function $DecodeDirectBits(this$static, numTotalBits) {
  var i,
    t,
    result = 0
  for (i = numTotalBits; i != 0; --i) {
    this$static.Range >>>= 1
    t = (this$static.Code - this$static.Range) >>> 31
    this$static.Code -= this$static.Range & (t - 1)
    result = (result << 1) | (1 - t)
    if (!(this$static.Range & -16777216)) {
      this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
      this$static.Range <<= 8
    }
  }
  return result
}

function $Init_8(this$static) {
  this$static.Code = 0
  this$static.Range = -1
  for (var i = 0; i < 5; ++i) {
    this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
  }
}
function InitBitModels(probs) {
  for (var i = probs.length - 1; i >= 0; --i) {
    probs[i] = 1024
  }
}
var ProbPrices = (function() {
  var end,
    i,
    j,
    start,
    ProbPrices = []
  for (i = 8; i >= 0; --i) {
    start = 1 << (9 - i - 1)
    end = 1 << (9 - i)
    for (j = start; j < end; ++j) {
      ProbPrices[j] = (i << 6) + (((end - j) << 6) >>> (9 - i - 1))
    }
  }
  return ProbPrices
})()

function $Encode_3(this$static, probs, index, symbol) {
  var newBound,
    prob = probs[index]
  newBound = (this$static.Range >>> 11) * prob
  if (!symbol) {
    this$static.Range = newBound
    probs[index] = ((prob + ((2048 - prob) >>> 5)) << 16) >> 16
  } else {
    this$static.Low = add(
      this$static.Low,
      and(fromInt(newBound), [4294967295, 0])
    )
    this$static.Range -= newBound
    probs[index] = ((prob - (prob >>> 5)) << 16) >> 16
  }
  if (!(this$static.Range & -16777216)) {
    this$static.Range <<= 8
    $ShiftLow(this$static)
  }
}

function $EncodeDirectBits(this$static, v, numTotalBits) {
  for (var i = numTotalBits - 1; i >= 0; --i) {
    this$static.Range >>>= 1
    if (((v >>> i) & 1) == 1) {
      this$static.Low = add(this$static.Low, fromInt(this$static.Range))
    }
    if (!(this$static.Range & -16777216)) {
      this$static.Range <<= 8
      $ShiftLow(this$static)
    }
  }
}

function $GetProcessedSizeAdd(this$static) {
  return add(add(fromInt(this$static._cacheSize), this$static._position), [
    4,
    0
  ])
}

function $Init_9(this$static) {
  this$static._position = P0_longLit
  this$static.Low = P0_longLit
  this$static.Range = -1
  this$static._cacheSize = 1
  this$static._cache = 0
}

function $ShiftLow(this$static) {
  var temp,
    LowHi = lowBits_0(shru(this$static.Low, 32))
  if (LowHi != 0 || compare(this$static.Low, [4278190080, 0]) < 0) {
    this$static._position = add(
      this$static._position,
      fromInt(this$static._cacheSize)
    )
    temp = this$static._cache
    do {
      $write(this$static.Stream, temp + LowHi)
      temp = 255
    } while (--this$static._cacheSize != 0)
    this$static._cache = lowBits_0(this$static.Low) >>> 24
  }
  ++this$static._cacheSize
  this$static.Low = shl(and(this$static.Low, [16777215, 0]), 8)
}

function GetPrice(Prob, symbol) {
  return ProbPrices[(((Prob - symbol) ^ -symbol) & 2047) >>> 2]
}
function decode(utf) {
  var i = 0,
    j = 0,
    x,
    y,
    z,
    l = utf.length,
    buf = [],
    charCodes = []
  for (; i < l; ++i, ++j) {
    x = utf[i] & 255
    if (!(x & 128)) {
      if (!x) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      charCodes[j] = x
    } else if ((x & 224) == 192) {
      if (i + 1 >= l) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      y = utf[++i] & 255
      if ((y & 192) != 128) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      charCodes[j] = ((x & 31) << 6) | (y & 63)
    } else if ((x & 240) == 224) {
      if (i + 2 >= l) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      y = utf[++i] & 255
      if ((y & 192) != 128) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      z = utf[++i] & 255
      if ((z & 192) != 128) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      charCodes[j] = ((x & 15) << 12) | ((y & 63) << 6) | (z & 63)
    } else {
      // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
      return utf
    }
    if (j == 16383) {
      buf.push(String.fromCharCode.apply(String, charCodes))
      j = -1
    }
  }
  if (j > 0) {
    charCodes.length = j
    buf.push(String.fromCharCode.apply(String, charCodes))
  }
  return buf.join('')
}
function encode(s) {
  var ch,
    chars = [],
    data,
    elen = 0,
    i,
    l = s.length
  // Be able to handle binary arrays and buffers.
  if (typeof s == 'object') {
    return s
  } else {
    $getChars(s, 0, l, chars, 0)
  }
  // Add extra spaces in the array to break up the unicode symbols.
  for (i = 0; i < l; ++i) {
    ch = chars[i]
    if (ch >= 1 && ch <= 127) {
      ++elen
    } else if (!ch || (ch >= 128 && ch <= 2047)) {
      elen += 2
    } else {
      elen += 3
    }
  }
  data = []
  elen = 0
  for (i = 0; i < l; ++i) {
    ch = chars[i]
    if (ch >= 1 && ch <= 127) {
      data[elen++] = (ch << 24) >> 24
    } else if (!ch || (ch >= 128 && ch <= 2047)) {
      data[elen++] = ((192 | ((ch >> 6) & 31)) << 24) >> 24
      data[elen++] = ((128 | (ch & 63)) << 24) >> 24
    } else {
      data[elen++] = ((224 | ((ch >> 12) & 15)) << 24) >> 24
      data[elen++] = ((128 | ((ch >> 6) & 63)) << 24) >> 24
      data[elen++] = ((128 | (ch & 63)) << 24) >> 24
    }
  }
  return data
}
// s is dictionarySize
// f is fb
// m is matchFinder
// NOTE: Because some values are always the same, they have been removed.
// lc is always 3
// lp is always 0
// pb is always 2
const modes = [
  { s: 16, f: 64, m: 0 },
  { s: 20, f: 64, m: 0 },
  { s: 19, f: 64, m: 1 },
  { s: 20, f: 64, m: 1 },
  { s: 21, f: 128, m: 1 },
  { s: 22, f: 128, m: 1 },
  { s: 23, f: 128, m: 1 },
  { s: 24, f: 255, m: 1 },
  { s: 25, f: 255, m: 1 }
]

function get_mode_obj(mode) {
  return modes[mode - 1] || modes[6]
}

/**
 * Compress a string with the LZMA algorithm
 *
 * @param {string}            value                 The string to be compressed
 * @param {object}            options
 * @param {1|2|3|4|5|6|7|8|9} options.mode          Which mode to use (1 through 9, defaults to 7)
 * @param {boolean}           options.enableEndMark Whether to write an end mark
 * @returns {string}
 */
export function compress(value, { mode = 7, enableEndMark = true } = {}) {
  var this$static = {}

  this$static.c = $LZMAByteArrayCompressor(
    {},
    encode(value),
    get_mode_obj(mode),
    enableEndMark
  )
  while ($processChunk(this$static.c.chunker));
  return $toByteArray(this$static.c.output)
}

/**
 * Decompress a string compressed with the LZMA algorithm
 *
 * @param {number[]|Int8Array} bytes The int8 array created by the compress() function
 * @returns {string}
 */
export function decompress(bytes) {
  var this$static = {}

  this$static.d = $LZMAByteArrayDecompressor({}, bytes)
  while ($processChunk(this$static.d.chunker));
  return decode($toByteArray(this$static.d.output))
}

@flou-ainan
Copy link

Hey dude, I've came to same results using other method. Just for sharing, soon it will be avaliable on github.

I though that no one had this idea before so started doing it myself.
All base conversions were implemented by myself based on a mongodb shortID code that I've came across in the past and forked to fit my needs.
Intead of using LZMA I've searched for a JavaScript Gzip implementation, and after most of the hard job were already done I've searched for compressing data into URLs and found your gist.
This project is a part of this one
Then when I finished my code, I tested your data for benchmarking and curiously they reached the same result with your data

My testing results:

-----
Test Data:     |      length: 456 
{"id":"0001","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"},{"id":"1003","type":"Blueberry"},{"id":"1004","type":"Devil's Food"}]},"topping":[{"id":"5001","type":"None"},{"id":"5002","type":"Glazed"},{"id":"5005","type":"Sugar"},{"id":"5007","type":"Powdered Sugar"},{"id":"5006","type":"Chocolate with Sprinkles"},{"id":"5003","type":"Chocolate"},{"id":"5004","type":"Maple"}]}
-----
-----
Ziped Bytes Array:     |      length: 220 
31,139,8,0,150,29,44,102,0,3,125,144,203,10,194,48,16,69,127,165,204,198,77,145,250,136,66,151,42,186,82,196,46,197,69,52,67,27,140,73,72,19,165,150,254,187,17,133,24,20,119,185,156,195,100,238,180,192,25,228,144,101,217,0,82,176,141,70,159,152,146,206,250,40,233,229,25,231,244,140,62,105,237,32,207,250,132,164,112,164,214,162,169,33,111,223,79,200,247,237,107,210,32,154,180,195,210,9,106,160,75,3,30,6,60,175,212,73,9,106,49,18,70,65,152,9,135,71,52,166,137,132,113,16,22,120,229,162,87,39,75,165,24,116,135,206,3,165,53,151,101,216,136,68,27,109,148,252,248,141,68,235,172,4,189,35,139,40,9,180,112,229,103,19,15,167,1,110,213,141,161,65,150,124,91,147,31,125,147,27,183,85,82,104,195,229,89,96,29,249,163,191,247,33,81,253,53,213,2,159,189,31,235,221,89,114,200,1,0,0
-----
-----
Hexadecimal String:     |      length: 440 
1f8b0800961d2c6600037d90cb0ac23010457fa5ccc64d91fa8842972aba52c42ec54534431b8c494813a596febb1185181477b99cc364eeb4c019e49065d90052b08d469f9892cefa28e9e519e7f48c3e69ed20cffa84a470a4d6a2a9216fdf4fc8f7ed6bd2209ab4c3d2096aa04b031e063cafd449096a311246419809874734a6898471101678e5a257274ba5187487ce03a5359765d888441b6d94fcf88d44ebac04bd238b2809b470e567130fa7016ed58da141967c5b931f7d931bb7555268c3e559601df9a3bff72151fd35d5029fbd1febdd5972c8010000
-----
-----
Base 64 string:     |      length: 294 
7UI809otb6o00TSgOMH2c115vWncNASh!Ex2BOGWkIgKNkkQgNKcikwjFpr!KN6561hTKpP3peWQM1DAA6np05aMzkqvC9be!yzFVhDDZ8M!quQwP$G4F72ARGaF8m$vjYzTXmLi89GQMZ89qG1b0NU6fa$kigBGch96gpw9xQsQFEC4sh0muemylOtbFhxQxYU3Fjmnpty8h1JJBfPUzkjHH0iZ8UIE2rhMVmsj3Ws1rJmdEk6mv5Kj7TSj6XtlkCz3VlBw7vCzL$sxkvQRRgavLh$HTlBOO04000
-----
-----
Hex String from Base 64:     |      length: 441 
1f8b0800961d2c6600037d90cb0ac23010457fa5ccc64d91fa8842972aba52c42ec54534431b8c494813a596febb1185181477b99cc364eeb4c019e49065d90052b08d469f9892cefa28e9e519e7f48c3e69ed20cffa84a470a4d6a2a9216fdf4fc8f7ed6bd2209ab4c3d2096aa04b031e063cafd449096a311246419809874734a6898471101678e5a257274ba5187487ce03a5359765d888441b6d94fcf88d44ebac04bd238b2809b470e567130fa7016ed58da141967c5b931f7d931bb7555268c3e559601df9a3bff72151fd35d5029fbd1febdd5972c80100000
-----
-----
Ziped Bytes Array from hex string:     |      length: 220 
31,139,8,0,150,29,44,102,0,3,125,144,203,10,194,48,16,69,127,165,204,198,77,145,250,136,66,151,42,186,82,196,46,197,69,52,67,27,140,73,72,19,165,150,254,187,17,133,24,20,119,185,156,195,100,238,180,192,25,228,144,101,217,0,82,176,141,70,159,152,146,206,250,40,233,229,25,231,244,140,62,105,237,32,207,250,132,164,112,164,214,162,169,33,111,223,79,200,247,237,107,210,32,154,180,195,210,9,106,160,75,3,30,6,60,175,212,73,9,106,49,18,70,65,152,9,135,71,52,166,137,132,113,16,22,120,229,162,87,39,75,165,24,116,135,206,3,165,53,151,101,216,136,68,27,109,148,252,248,141,68,235,172,4,189,35,139,40,9,180,112,229,103,19,15,167,1,110,213,141,161,65,150,124,91,147,31,125,147,27,183,85,82,104,195,229,89,96,29,249,163,191,247,33,81,253,53,213,2,159,189,31,235,221,89,114,200,1,0,0
-----
-----
Original Data:     |      length: 456 
{"id":"0001","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"},{"id":"1003","type":"Blueberry"},{"id":"1004","type":"Devil's Food"}]},"topping":[{"id":"5001","type":"None"},{"id":"5002","type":"Glazed"},{"id":"5005","type":"Sugar"},{"id":"5007","type":"Powdered Sugar"},{"id":"5006","type":"Chocolate with Sprinkles"},{"id":"5003","type":"Chocolate"},{"id":"5004","type":"Maple"}]}
-----
{
  id: '0001',
  type: 'donut',
  name: 'Cake',
  ppu: 0.55,
  batters: { batter: [ [Object], [Object], [Object], [Object] ] },
  topping: [
    { id: '5001', type: 'None' },
    { id: '5002', type: 'Glazed' },
    { id: '5005', type: 'Sugar' },
    { id: '5007', type: 'Powdered Sugar' },
    { id: '5006', type: 'Chocolate with Sprinkles' },
    { id: '5003', type: 'Chocolate' },
    { id: '5004', type: 'Maple' }
  ]
}

This test can be acessed here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment