Last active
July 1, 2017 23:13
-
-
Save JobLeonard/c049a255e8f551dd5c4c4cab8656bae3 to your computer and use it in GitHub Desktop.
LZString old vs new decompression (http://jsbench.github.io/#c049a255e8f551dd5c4c4cab8656bae3) #jsbench #jsperf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"/> | |
<title>LZString old vs new decompression</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script> | |
<script src="./suite.js"></script> | |
</head> | |
<body> | |
<h1>Open the console to view the results</h1> | |
<h2><code>cmd + alt + j</code> or <code>ctrl + alt + j</code></h2> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
(function (factory) { | |
if (typeof Benchmark !== "undefined") { | |
factory(Benchmark); | |
} else { | |
factory(require("benchmark")); | |
} | |
})(function (Benchmark) { | |
var suite = new Benchmark.Suite; | |
Benchmark.prototype.setup = function () { | |
var LZString = (function() { | |
// private property | |
var f = String.fromCharCode; | |
var Base64CharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(''); | |
var UriSafeCharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$".split(''); | |
var baseReverseDic = {}; | |
function getReverseDict(alphabet){ | |
if (!baseReverseDic[alphabet]) { | |
baseReverseDic[alphabet] = {}; | |
for (var i=0 ; i<alphabet.length ; i++) { | |
baseReverseDic[alphabet][alphabet[i].charCodeAt(0)] = i; | |
} | |
} | |
return baseReverseDic[alphabet]; | |
} | |
var LZString = { | |
compressToBase64 : function (input) { | |
if (input == null) return ""; | |
var res = LZString._compressToArray(input, 6, function(a){return Base64CharArray[a];}); | |
// To produce valid Base64 | |
var i = res.length % 4; | |
while(i--){ | |
res.push("="); | |
} | |
return res.join(''); | |
}, | |
decompressFromBase64 : function (input) { | |
if (input == null) return ""; | |
if (input == "") return null; | |
var reverseDict = getReverseDict(Base64CharArray); | |
return LZString._decompress(input.length, 32, function(index) { return reverseDict[input.charCodeAt(index)]; }); | |
}, | |
compressToUTF16 : function (input) { | |
if (input == null) return ""; | |
var compressed = LZString._compressToArray(input, 15, function(a){return f(a+32);}); | |
compressed.push(" "); | |
return compressed.join(''); | |
}, | |
decompressFromUTF16: function (compressed) { | |
if (compressed == null) return ""; | |
if (compressed == "") return null; | |
return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; }); | |
}, | |
//compress into uint8array (UCS-2 big endian format) | |
compressToUint8Array: function (uncompressed) { | |
var compressed = LZString.compressToArray(uncompressed); | |
var buf=new Uint8Array(compressed.length*2); // 2 bytes per character | |
for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) { | |
var current_value = compressed[i].charCodeAt(0); | |
buf[i*2] = current_value >>> 8; | |
buf[i*2+1] = current_value & 0xFF; | |
} | |
return buf; | |
}, | |
//decompress from uint8array (UCS-2 big endian format) | |
decompressFromUint8Array:function (compressed) { | |
if (compressed===null || compressed===undefined){ | |
return LZString.decompressFromArray(compressed); | |
} else if (compressed.length == 0){ | |
return null; | |
} | |
return LZString._decompress(compressed.length, 128, function (index) { return compressed[index]; }); | |
}, | |
//compress into a string that is already URI encoded | |
compressToEncodedURIComponent: function (input) { | |
if (input == null) return ""; | |
return LZString._compressToArray(input, 6, function(a){return UriSafeCharArray[a];}).join(''); | |
}, | |
//decompress from an output of compressToEncodedURIComponent | |
decompressFromEncodedURIComponent:function (input) { | |
if (input == null) return ""; | |
if (input == "") return null; | |
input = input.replace(/ /g, "+"); | |
var reverseDict = getReverseDict(UriSafeCharArray); | |
return LZString._decompress(input.length, 32, function(index) { return reverseDict[input.charCodeAt(index)]; }); | |
}, | |
compress: function (uncompressed) { | |
return LZString.compressToArray(uncompressed).join(''); | |
}, | |
compressToArray: function (uncompressed){ | |
return LZString._compressToArray(uncompressed, 16, function(a){return f(a);}); | |
}, | |
_compressToArray: function (uncompressed, bitsPerChar, getCharFromInt){ | |
if (uncompressed == null) return []; | |
var i=0, j=0, value=0, | |
dictionary={}, | |
dictionaryToCreate={}, | |
c=0, | |
c0=2, | |
node=dictionary, | |
node_c=0, | |
new_node={}, | |
enlargeIn= 2, // Compensate for the first entry which should not count | |
dictSize= 3, | |
numBits= 2, | |
data=[], | |
data_val=0, | |
data_position=0; | |
for (j = 0; j < uncompressed.length; j++) { | |
c = uncompressed.charCodeAt(j); | |
c0 = c+2; | |
// Is c a new character that needs to | |
// be stored at the root? | |
if (dictionary[c0] == undefined) { | |
new_node = {}; | |
new_node[0] = dictSize++; | |
new_node[1] = c; | |
dictionary[c0] = new_node; | |
dictionaryToCreate[c] = true; | |
} | |
new_node = node[c0]; | |
if (new_node) { | |
node = new_node; | |
} else { | |
node_c = node[1]; | |
if (dictionaryToCreate[node_c]) { | |
if (node_c<256) { | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
} | |
value = node_c; | |
for (i=0 ; i<8 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} else { | |
value = 1; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | value; | |
if (++data_position ==bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = 0; | |
} | |
value = node_c; | |
for (i=0 ; i<16 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} | |
if (--enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits++); | |
} | |
dictionaryToCreate[node_c] = false; | |
} else { | |
value = node[0]; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} | |
if (--enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits++); | |
} | |
// Add prefix to the dictionary. | |
new_node = {}; | |
new_node[0] = dictSize++; | |
new_node[1] = c; | |
node[c0] = new_node; | |
node = dictionary[c0]; | |
} | |
} | |
// Output the code for node. | |
if (node !== undefined) { | |
node_c = node[1]; | |
if (dictionaryToCreate[node_c]) { | |
if (node_c<256) { | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
} | |
value = node_c; | |
for (i=0 ; i<8 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = value >> 1; | |
} | |
} else { | |
value = 1; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | value; | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = 0; | |
} | |
value = node_c; | |
for (i=0 ; i<16 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = value >> 1; | |
} | |
} | |
enlargeIn--; | |
if (enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits); | |
numBits++; | |
} | |
dictionaryToCreate[node_c] = false; | |
} else { | |
value = node[0]; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} | |
if (--enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits++); | |
} | |
} | |
// Mark the end of the stream | |
value = 2; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
// Flush the last char | |
while (data_position++ < bitsPerChar) { | |
data_val = (data_val << 1); | |
} | |
data.push(getCharFromInt(data_val)); | |
return data; | |
}, | |
decompress: function (compressed) { | |
if (compressed == null) return ""; | |
if (compressed == "") return null; | |
return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); }); | |
}, | |
decompressFromArray: function (compressed) { | |
if (compressed == null) return ""; | |
if (compressed.length == 0) return null; | |
return LZString._decompress(compressed.length, 32768, function(index) { return compressed[index].charCodeAt(0); }); }, | |
_decompress: function (length, resetValue, getNextValue) { | |
var dictionary = [], | |
next, | |
enlargeIn = 4, | |
dictSize = 4, | |
numBits = 3, | |
entry = "", | |
result = [], | |
i, | |
w, | |
bits, resb, maxpower, power, | |
c, | |
data = {val:getNextValue(0), position:resetValue, index:1}; | |
for (i = 0; i < 3; i += 1) { | |
dictionary[i] = i; | |
} | |
bits = 0; | |
maxpower = Math.pow(2,2); | |
power=1; | |
while (power!=maxpower) { | |
resb = data.val & data.position; | |
data.position >>= 1; | |
if (data.position == 0) { | |
data.position = resetValue; | |
data.val = getNextValue(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
switch (next = bits) { | |
case 0: | |
bits = 0; | |
maxpower = Math.pow(2,8); | |
power=1; | |
while (power!=maxpower) { | |
resb = data.val & data.position; | |
data.position >>= 1; | |
if (data.position == 0) { | |
data.position = resetValue; | |
data.val = getNextValue(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
c = f(bits); | |
break; | |
case 1: | |
bits = 0; | |
maxpower = Math.pow(2,16); | |
power=1; | |
while (power!=maxpower) { | |
resb = data.val & data.position; | |
data.position >>= 1; | |
if (data.position == 0) { | |
data.position = resetValue; | |
data.val = getNextValue(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
c = f(bits); | |
break; | |
case 2: | |
return ""; | |
} | |
dictionary[3] = c; | |
w = c; | |
result.push(c); | |
while (true) { | |
if (data.index > length) { | |
return ""; | |
} | |
bits = 0; | |
maxpower = Math.pow(2,numBits); | |
power=1; | |
while (power!=maxpower) { | |
resb = data.val & data.position; | |
data.position >>= 1; | |
if (data.position == 0) { | |
data.position = resetValue; | |
data.val = getNextValue(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
switch (c = bits) { | |
case 0: | |
bits = 0; | |
maxpower = Math.pow(2,8); | |
power=1; | |
while (power!=maxpower) { | |
resb = data.val & data.position; | |
data.position >>= 1; | |
if (data.position == 0) { | |
data.position = resetValue; | |
data.val = getNextValue(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
dictionary[dictSize++] = f(bits); | |
c = dictSize-1; | |
enlargeIn--; | |
break; | |
case 1: | |
bits = 0; | |
maxpower = Math.pow(2,16); | |
power=1; | |
while (power!=maxpower) { | |
resb = data.val & data.position; | |
data.position >>= 1; | |
if (data.position == 0) { | |
data.position = resetValue; | |
data.val = getNextValue(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
dictionary[dictSize++] = f(bits); | |
c = dictSize-1; | |
enlargeIn--; | |
break; | |
case 2: | |
return result.join(''); | |
} | |
if (enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits); | |
numBits++; | |
} | |
if (dictionary[c]) { | |
entry = dictionary[c]; | |
} else { | |
if (c === dictSize) { | |
entry = w + w.charAt(0); | |
} else { | |
return null; | |
} | |
} | |
result.push(entry); | |
// Add w+entry[0] to the dictionary. | |
dictionary[dictSize++] = w + entry.charAt(0); | |
enlargeIn--; | |
w = entry; | |
if (enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits); | |
numBits++; | |
} | |
} | |
} | |
}; | |
return LZString; | |
})(); | |
var LZStringNew = (function() { | |
// private property | |
var f = String.fromCharCode; | |
var Base64CharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(''); | |
var UriSafeCharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$".split(''); | |
var baseReverseDic = {}; | |
function getReverseDict(alphabet){ | |
if (!baseReverseDic[alphabet]) { | |
baseReverseDic[alphabet] = {}; | |
for (var i=0 ; i<alphabet.length ; i++) { | |
baseReverseDic[alphabet][alphabet[i].charCodeAt(0)] = i; | |
} | |
} | |
return baseReverseDic[alphabet]; | |
} | |
var LZString = { | |
compressToBase64 : function (input) { | |
if (input == null) return ""; | |
var res = LZString._compressToArray(input, 6, function(a){return Base64CharArray[a];}); | |
// To produce valid Base64 | |
var i = res.length % 4; | |
while(i--){ | |
res.push("="); | |
} | |
return res.join(''); | |
}, | |
decompressFromBase64 : function (input) { | |
if (input == null) return ""; | |
if (input == "") return null; | |
var reverseDict = getReverseDict(Base64CharArray); | |
return LZString._decompress(input.length, 32, function(index) { return reverseDict[input.charCodeAt(index)]; }); | |
}, | |
compressToUTF16 : function (input) { | |
if (input == null) return ""; | |
var compressed = LZString._compressToArray(input, 15, function(a){return f(a+32);}); | |
compressed.push(" "); | |
return compressed.join(''); | |
}, | |
decompressFromUTF16: function (compressed) { | |
if (compressed == null) return ""; | |
if (compressed == "") return null; | |
return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; }); | |
}, | |
//compress into uint8array (UCS-2 big endian format) | |
compressToUint8Array: function (uncompressed) { | |
var compressed = LZString.compressToArray(uncompressed); | |
var buf=new Uint8Array(compressed.length*2); // 2 bytes per character | |
for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) { | |
var current_value = compressed[i].charCodeAt(0); | |
buf[i*2] = current_value >>> 8; | |
buf[i*2+1] = current_value & 0xFF; | |
} | |
return buf; | |
}, | |
//decompress from uint8array (UCS-2 big endian format) | |
decompressFromUint8Array:function (compressed) { | |
if (compressed===null || compressed===undefined){ | |
return LZString.decompressFromArray(compressed); | |
} else if (compressed.length == 0){ | |
return null; | |
} | |
return LZString._decompress(compressed.length, 128, function (index) { return compressed[index]; }); | |
}, | |
//compress into a string that is already URI encoded | |
compressToEncodedURIComponent: function (input) { | |
if (input == null) return ""; | |
return LZString._compressToArray(input, 6, function(a){return UriSafeCharArray[a];}).join(''); | |
}, | |
//decompress from an output of compressToEncodedURIComponent | |
decompressFromEncodedURIComponent:function (input) { | |
if (input == null) return ""; | |
if (input == "") return null; | |
input = input.replace(/ /g, "+"); | |
var reverseDict = getReverseDict(UriSafeCharArray); | |
return LZString._decompress(input.length, 32, function(index) { return reverseDict[input.charCodeAt(index)]; }); | |
}, | |
compress: function (uncompressed) { | |
return LZString.compressToArray(uncompressed).join(''); | |
}, | |
compressToArray: function (uncompressed){ | |
return LZString._compressToArray(uncompressed, 16, function(a){return f(a);}); | |
}, | |
_compressToArray: function (uncompressed, bitsPerChar, getCharFromInt){ | |
if (uncompressed == null) return []; | |
var i=0, j=0, value=0, | |
dictionary={}, | |
dictionaryToCreate={}, | |
c=0, | |
c0=2, | |
node=dictionary, | |
node_c=0, | |
new_node={}, | |
enlargeIn= 2, // Compensate for the first entry which should not count | |
dictSize= 3, | |
numBits= 2, | |
data=[], | |
data_val=0, | |
data_position=0; | |
for (j = 0; j < uncompressed.length; j++) { | |
c = uncompressed.charCodeAt(j); | |
c0 = c+2; | |
// Is c a new character that needs to | |
// be stored at the root? | |
if (dictionary[c0] == undefined) { | |
new_node = {}; | |
new_node[0] = dictSize++; | |
new_node[1] = c; | |
dictionary[c0] = new_node; | |
dictionaryToCreate[c] = true; | |
} | |
new_node = node[c0]; | |
if (new_node) { | |
node = new_node; | |
} else { | |
node_c = node[1]; | |
if (dictionaryToCreate[node_c]) { | |
if (node_c<256) { | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
} | |
value = node_c; | |
for (i=0 ; i<8 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} else { | |
value = 1; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | value; | |
if (++data_position ==bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = 0; | |
} | |
value = node_c; | |
for (i=0 ; i<16 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} | |
if (--enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits++); | |
} | |
dictionaryToCreate[node_c] = false; | |
} else { | |
value = node[0]; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} | |
if (--enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits++); | |
} | |
// Add prefix to the dictionary. | |
new_node = {}; | |
new_node[0] = dictSize++; | |
new_node[1] = c; | |
node[c0] = new_node; | |
node = dictionary[c0]; | |
} | |
} | |
// Output the code for node. | |
if (node !== undefined) { | |
node_c = node[1]; | |
if (dictionaryToCreate[node_c]) { | |
if (node_c<256) { | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
} | |
value = node_c; | |
for (i=0 ; i<8 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = value >> 1; | |
} | |
} else { | |
value = 1; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | value; | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = 0; | |
} | |
value = node_c; | |
for (i=0 ; i<16 ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value = value >> 1; | |
} | |
} | |
enlargeIn--; | |
if (enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits); | |
numBits++; | |
} | |
dictionaryToCreate[node_c] = false; | |
} else { | |
value = node[0]; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
} | |
if (--enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits++); | |
} | |
} | |
// Mark the end of the stream | |
value = 2; | |
for (i=0 ; i<numBits ; i++) { | |
data_val = (data_val << 1) | (value&1); | |
if (++data_position == bitsPerChar) { | |
data_position = 0; | |
data.push(getCharFromInt(data_val)); | |
data_val = 0; | |
} | |
value >>= 1; | |
} | |
// Flush the last char | |
while (data_position++ < bitsPerChar) { | |
data_val = (data_val << 1); | |
} | |
data.push(getCharFromInt(data_val)); | |
return data; | |
}, | |
decompress: function (compressed) { | |
if (compressed == null) return ""; | |
if (compressed == "") return null; | |
return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); }); | |
}, | |
decompressFromArray: function (compressed) { | |
if (compressed == null) return ""; | |
if (compressed.length == 0) return null; | |
return LZString._decompress(compressed.length, 32768, function(index) { return compressed[index].charCodeAt(0); }); }, | |
_decompress: function (length, resetValue, getNextValue) { | |
resetValue = Math.log2(resetValue) + 1; | |
var dictionary = [0, 1, 2], | |
enlargeIn = 4, | |
dictSize = 4, | |
numBits = 3, | |
entry = "", | |
result = [], | |
w = "", | |
bits = 0, | |
maxpower = 2, | |
power = 0, | |
c = "", | |
data_val = getNextValue(0), | |
data_position = resetValue, | |
data_index = 1; | |
while (power!=maxpower) { | |
bits += ((data_val >> --data_position)&1) << power++; | |
if (data_position == 0) { | |
data_position = resetValue; | |
data_val = getNextValue(data_index++); | |
} | |
} | |
if (bits == 2){ | |
return "" | |
} | |
//Math.pow(2,8 + 8*bits); | |
maxpower = bits*8+8; | |
bits = power = 0; | |
while (power!=maxpower) { | |
bits += ((data_val >> --data_position)&1) << power++; | |
if (data_position == 0) { | |
data_position = resetValue; | |
data_val = getNextValue(data_index++); | |
} | |
} | |
c = f(bits); | |
dictionary[3] = c; | |
w = c; | |
result.push(c); | |
while (true) { | |
if (data_index > length) { | |
return ""; | |
} | |
maxpower = numBits;//Math.pow(2,numBits); | |
bits = power = 0; | |
while (power!=maxpower) { | |
bits += ((data_val >> --data_position)&1) << power++; | |
if (data_position == 0) { | |
data_position = resetValue; | |
data_val = getNextValue(data_index++); | |
} | |
} | |
// 0 or 1 | |
if ((bits&1) == bits){ | |
maxpower = (8+8*bits); | |
bits = power=0; | |
while (power!=maxpower) { | |
bits += ((data_val >> --data_position)&1) << power++; | |
if (data_position == 0) { | |
data_position = resetValue; | |
data_val = getNextValue(data_index++); | |
} | |
} | |
dictionary[dictSize] = f(bits); | |
bits = dictSize++; | |
if (--enlargeIn == 0) { | |
enlargeIn = Math.pow(2, numBits++); | |
} | |
} else if (bits == 2){ | |
return result.join(''); | |
} | |
if (dictionary[bits]) { | |
entry = dictionary[bits]; | |
} else if (bits === dictSize) { | |
entry = w + w.charAt(0); | |
} else { | |
return null; | |
} | |
result.push(entry); | |
// Add w+entry[0] to the dictionary. | |
dictionary[dictSize++] = w + entry.charAt(0); | |
w = entry; | |
if (--enlargeIn == 0) { | |
enlargeIn = 1 << numBits++; | |
} | |
} | |
} | |
}; | |
return LZString; | |
})(); | |
var testStringRandomNrs = ''; | |
var i; | |
for (i=0 ; i<1000 ; i++) | |
testStringRandomNrs += Math.random() + " "; | |
var testStringTattoo = 'During tattooing, ink is injected into the skin, initiating an immune response, and cells called "macrophages" move into the area and "eat up" the ink. The macrophages carry some of the ink to the body\'s lymph nodes, but some that are filled with ink stay put, embedded in the skin. That\'s what makes the tattoo visible under the skin. Dalhousie Uiversity\'s Alec Falkenham is developing a topical cream that works by targeting the macrophages that have remained at the site of the tattoo. New macrophages move in to consume the previously pigment-filled macrophages and then migrate to the lymph nodes, eventually taking all the dye with them. "When comparing it to laser-based tattoo removal, in which you see the burns, the scarring, the blisters, in this case, we\'ve designed a drug that doesn\'t really have much off-target effect," he said. "We\'re not targeting any of the normal skin cells, so you won\'t see a lot of inflammation. In fact, based on the process that we\'re actually using, we don\'t think there will be any inflammation at all and it would actually be anti-inflammatory.'; | |
var testStringRepeat = 'aaaaabaaaaacaaaaadaaaaaeaaaaa'; | |
var testStringRepeat1024 = 'aaaaabaaaaacaaaaadaaaaaeaaaaa'; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
testStringRepeat1024 += testStringRepeat1024; | |
var testStringAllUTF16 = ''; | |
var i; | |
for (i = 32; i < 127; ++i) { | |
testStringAllUTF16 += String.fromCharCode(i); | |
} | |
for (i = 128 + 32; i < 55296; ++i) { | |
testStringAllUTF16 += String.fromCharCode(i); | |
} | |
for (i = 63744; i < 65536; ++i) { | |
testStringAllUTF16 += String.fromCharCode(i); | |
} | |
// compress old 'During tattooing, ...' | |
var testStringTattoo = LZString.compress(testStringTattoo); | |
// compress old 1000 Random Float Nrs | |
var testStringRandomNrs = LZString.compress(testStringRandomNrs); | |
// compress old 'aaaaabaaaaacaaaaadaaaaaeaaaaa' | |
var testStringRepeat = LZString.compress(testStringRepeat); | |
// compress new 'aaaaabaaaaacaaaaadaaaaaeaaaaa' * 1024 | |
var testStringRepeat1024 = LZString.compress(testStringRepeat1024); | |
// compress old all printable UTF16 | |
var testStringAllUTF16 = LZString.compress(testStringAllUTF16); | |
}; | |
suite.add("decompress old 'During tattooing, ...'", function () { | |
// decompress old 'During tattooing, ...' | |
var t = LZString.decompress(testStringTattoo); | |
}); | |
suite.add("decompress new 'During tattooing, ...'", function () { | |
// decompress new 'During tattooing, ...' | |
var t = LZString.decompress(testStringTattoo); | |
}); | |
suite.add("decompress old 1000 Random Float Nrs", function () { | |
// decompress old 1000 Random Float Nrs | |
var t = LZString.decompress(testStringRandomNrs); | |
}); | |
suite.add("decompress new 1000 Random Float Nrs", function () { | |
// decompress new 1000 Random Float Nrs | |
var t = LZString.decompress(testStringRandomNrs); | |
}); | |
suite.add("decompress old 'aaaaabaaaaacaaaaadaaaaaeaaaaa'", function () { | |
// decompress old 'aaaaabaaaaacaaaaadaaaaaeaaaaa' | |
var t = LZString.decompress(testStringRepeat); | |
}); | |
suite.add("decompress new 'aaaaabaaaaacaaaaadaaaaaeaaaaa'", function () { | |
// decompress new 'aaaaabaaaaacaaaaadaaaaaeaaaaa' | |
var t = LZString.decompress(testStringRepeat); | |
}); | |
suite.add("decompress new 'aaaaabaaaaacaaaaadaaaaaeaaaaa' * 1024", function () { | |
// decompress new 'aaaaabaaaaacaaaaadaaaaaeaaaaa' * 1024 | |
var t = LZString.decompress(testStringRepeat1024); | |
}); | |
suite.add("decompress new 'aaaaabaaaaacaaaaadaaaaaeaaaaa' * 1024", function () { | |
// decompress new 'aaaaabaaaaacaaaaadaaaaaeaaaaa' * 1024 | |
var t = LZString.decompress(testStringRepeat1024); | |
}); | |
suite.add("decompress old all printable UTF16", function () { | |
// decompress old all printable UTF16 | |
var t = LZString.decompress(testStringAllUTF16); | |
}); | |
suite.add("decompress old all printable UTF16", function () { | |
// decompress old all printable UTF16 | |
var t = LZString.decompress(testStringAllUTF16); | |
}); | |
suite.on("cycle", function (evt) { | |
console.log(" - " + evt.target); | |
}); | |
suite.on("complete", function (evt) { | |
console.log(new Array(30).join("-")); | |
var results = evt.currentTarget.sort(function (a, b) { | |
return b.hz - a.hz; | |
}); | |
results.forEach(function (item) { | |
console.log((idx + 1) + ". " + item); | |
}); | |
}); | |
console.log("LZString old vs new decompression"); | |
console.log(new Array(30).join("-")); | |
suite.run(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment