Skip to content

Instantly share code, notes, and snippets.

@JobLeonard
Last active July 5, 2017 15:43
Show Gist options
  • Save JobLeonard/da32b5d1100c24c7744bb58ca3fff440 to your computer and use it in GitHub Desktop.
Save JobLeonard/da32b5d1100c24c7744bb58ca3fff440 to your computer and use it in GitHub Desktop.
LZString 1.4.4 vs pull request #98 - decompression (http://jsbench.github.io/#da32b5d1100c24c7744bb58ca3fff440) #jsbench #jsperf
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>LZString 1.4.4 vs pull request #98 - 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>
"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 keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
var baseReverseDic = {};
function getBaseValue(alphabet, character) {
if (!baseReverseDic[alphabet]) {
baseReverseDic[alphabet] = {};
for (var i=0 ; i<alphabet.length ; i++) {
baseReverseDic[alphabet][alphabet.charAt(i)] = i;
}
}
return baseReverseDic[alphabet][character];
}
var LZString = {
compressToBase64 : function (input) {
if (input == null) return "";
var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});
switch (res.length % 4) { // To produce valid Base64
default: // When could this happen ?
case 0 : return res;
case 1 : return res+"===";
case 2 : return res+"==";
case 3 : return res+"=";
}
},
decompressFromBase64 : function (input) {
if (input == null) return "";
if (input == "") return null;
return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });
},
compressToUTF16 : function (input) {
if (input == null) return "";
return LZString._compress(input, 15, function(a){return f(a+32);}) + " ";
},
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.compress(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.charCodeAt(i);
buf[i*2] = current_value >>> 8;
buf[i*2+1] = current_value % 256;
}
return buf;
},
//decompress from uint8array (UCS-2 big endian format)
decompressFromUint8Array:function (compressed) {
if (compressed===null || compressed===undefined){
return LZString.decompress(compressed);
} else {
var buf=new Array(compressed.length/2); // 2 bytes per character
for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {
buf[i]=compressed[i*2]*256+compressed[i*2+1];
}
var result = [];
buf.forEach(function (c) {
result.push(f(c));
});
return LZString.decompress(result.join(''));
}
},
//compress into a string that is already URI encoded
compressToEncodedURIComponent: function (input) {
if (input == null) return "";
return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});
},
//decompress from an output of compressToEncodedURIComponent
decompressFromEncodedURIComponent:function (input) {
if (input == null) return "";
if (input == "") return null;
input = input.replace(/ /g, "+");
return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });
},
compress: function (uncompressed) {
return LZString._compress(uncompressed, 16, function(a){return f(a);});
},
_compress: function (uncompressed, bitsPerChar, getCharFromInt) {
if (uncompressed == null) return "";
var i, value,
context_dictionary= {},
context_dictionaryToCreate= {},
context_c="",
context_wc="",
context_w="",
context_enlargeIn= 2, // Compensate for the first entry which should not count
context_dictSize= 3,
context_numBits= 2,
context_data=[],
context_data_val=0,
context_data_position=0,
ii;
for (ii = 0; ii < uncompressed.length; ii += 1) {
context_c = uncompressed.charAt(ii);
if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {
context_dictionary[context_c] = context_dictSize++;
context_dictionaryToCreate[context_c] = true;
}
context_wc = context_w + context_c;
if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {
context_w = context_wc;
} else {
if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
if (context_w.charCodeAt(0)<256) {
for (i=0 ; i<context_numBits ; i++) {
context_data_val = (context_data_val << 1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
}
value = context_w.charCodeAt(0);
for (i=0 ; i<8 ; i++) {
context_data_val = (context_data_val << 1) | (value&1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = value >> 1;
}
} else {
value = 1;
for (i=0 ; i<context_numBits ; i++) {
context_data_val = (context_data_val << 1) | value;
if (context_data_position ==bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = 0;
}
value = context_w.charCodeAt(0);
for (i=0 ; i<16 ; i++) {
context_data_val = (context_data_val << 1) | (value&1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = value >> 1;
}
}
context_enlargeIn--;
if (context_enlargeIn == 0) {
context_enlargeIn = Math.pow(2, context_numBits);
context_numBits++;
}
delete context_dictionaryToCreate[context_w];
} else {
value = context_dictionary[context_w];
for (i=0 ; i<context_numBits ; i++) {
context_data_val = (context_data_val << 1) | (value&1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = value >> 1;
}
}
context_enlargeIn--;
if (context_enlargeIn == 0) {
context_enlargeIn = Math.pow(2, context_numBits);
context_numBits++;
}
// Add wc to the dictionary.
context_dictionary[context_wc] = context_dictSize++;
context_w = String(context_c);
}
}
// Output the code for w.
if (context_w !== "") {
if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
if (context_w.charCodeAt(0)<256) {
for (i=0 ; i<context_numBits ; i++) {
context_data_val = (context_data_val << 1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
}
value = context_w.charCodeAt(0);
for (i=0 ; i<8 ; i++) {
context_data_val = (context_data_val << 1) | (value&1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = value >> 1;
}
} else {
value = 1;
for (i=0 ; i<context_numBits ; i++) {
context_data_val = (context_data_val << 1) | value;
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = 0;
}
value = context_w.charCodeAt(0);
for (i=0 ; i<16 ; i++) {
context_data_val = (context_data_val << 1) | (value&1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = value >> 1;
}
}
context_enlargeIn--;
if (context_enlargeIn == 0) {
context_enlargeIn = Math.pow(2, context_numBits);
context_numBits++;
}
delete context_dictionaryToCreate[context_w];
} else {
value = context_dictionary[context_w];
for (i=0 ; i<context_numBits ; i++) {
context_data_val = (context_data_val << 1) | (value&1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = value >> 1;
}
}
context_enlargeIn--;
if (context_enlargeIn == 0) {
context_enlargeIn = Math.pow(2, context_numBits);
context_numBits++;
}
}
// Mark the end of the stream
value = 2;
for (i=0 ; i<context_numBits ; i++) {
context_data_val = (context_data_val << 1) | (value&1);
if (context_data_position == bitsPerChar-1) {
context_data_position = 0;
context_data.push(getCharFromInt(context_data_val));
context_data_val = 0;
} else {
context_data_position++;
}
value = value >> 1;
}
// Flush the last char
while (true) {
context_data_val = (context_data_val << 1);
if (context_data_position == bitsPerChar-1) {
context_data.push(getCharFromInt(context_data_val));
break;
}
else context_data_position++;
}
return context_data.join('');
},
decompress: function (compressed) {
if (compressed == null) return "";
if (compressed == "") return null;
return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });
},
_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,
Base64CharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(''),
UriSafeCharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$".split(''),
Base64ReverseDic = {},
UriSafeReverseDic = {},
i = 65;
while (i--) {
Base64ReverseDic[Base64CharArray[i].charCodeAt(0)] = i;
UriSafeReverseDic[UriSafeCharArray[i].charCodeAt(0)] = i;
}
var getChar16Bits = function (a) { return f(a); },
getCharFromBase64 = function (a) { return Base64CharArray[a]; },
getCharFromURISafe = function (a) { return UriSafeCharArray[a]; },
getCharFromUTF16 = function (a) { return f(a + 32); };
var LZString = {
compressToBase64: function (input) {
if (input == null) return "";
var res = LZString._compressToArray(input, 6, getCharFromBase64);
// 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;
return LZString._decompress(input.length, 32, function (index) { return Base64ReverseDic[input.charCodeAt(index)]; });
},
compressToUTF16: function (input) {
if (input == null) return "";
var compressed = LZString._compressToArray(input, 15, getCharFromUTF16);
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, getCharFromURISafe).join('');
},
//decompress from an output of compressToEncodedURIComponent
decompressFromEncodedURIComponent: function (input) {
if (input == null) return "";
if (input == "") return null;
input = input.replace(/ /g, "+");
return LZString._decompress(input.length, 32, function (index) { return UriSafeReverseDic[input.charCodeAt(index)]; });
},
compress: function (uncompressed) {
return LZString.compressToArray(uncompressed).join('');
},
compressToArray: function (uncompressed) {
return LZString._compressToArray(uncompressed, 16, getChar16Bits);
},
_compressToArray: function (uncompressed, bitsPerChar, getCharFromInt) {
if (uncompressed == null) return [];
var i = 0, j = 0, value = 0,
dictionary = {},
freshNode = true,
c = 0,
c0 = 1,
node = dictionary,
new_node = {},
enlargeIn = 2,
dictSize = 3,
numBits = 2,
data = [],
data_val = 0,
data_position = 0;
if (uncompressed.length) {
// If there IS a charCode, the first is guaranteed to be new,
// so we write it to output stream, add it to the dictionary,
// initialize freshNode as true, and set it as the root node.
c = uncompressed.charCodeAt(0);
c0 = c + 1;
// == Write first charCode token to output ==
// 8 or 16 bit?
value = c < 256 ? 0 : 1
// insert "new 8/16 bit charCode" token
// into bitstream (value 1)
for (i = 0; i < numBits; i++) {
// Value is 0 (8 bit) or 1 (16 bit).
// We shift it into the bitstream in reverse
// (shifting has precedence over bitmasking)
data_val = value >> i | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
// insert charCode
// Nasty but effective hack:
// loop 8 or 16 times based on token value
value = 8 + 8 * value;
for (i = 0; i < value; i++) {
// shifting has precedence over bitmasking
data_val = c >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
// Add charCode to the dictionary.
new_node = {};
new_node[0] = dictSize++;
node[c0] = new_node;
// start in this node
node = new_node;
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
for (j = 1; j < uncompressed.length; j++) {
c = uncompressed.charCodeAt(j);
c0 = c + 1;
// does the new charCode match an existing prefix?
new_node = node[c0];
if (new_node) {
// continue with next prefix
node = new_node;
} else {
// write out the current prefix token
if (freshNode) {
// character token already written to output
freshNode = false;
} else {
value = node[0];
for (i = 0; i < numBits; i++) {
// shifting has precedence over bitmasking
data_val = value >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
}
// Is the new charCode a new character
// that needs to be stored at the root?
new_node = dictionary[c0];
if (new_node == undefined) {
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
// insert "new 8/16 bit charCode" token,
// see comments above for explanation
value = c < 256 ? 0 : 1
for (i = 0; i < numBits; i++) {
data_val = value >> i | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
value = 8 + 8 * value;
for (i = 0; i < value; i++) {
data_val = c >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
new_node = {};
new_node[0] = dictSize++;
dictionary[c0] = new_node;
// Note of that we already wrote
// the charCode token to the bitstream
freshNode = true;
}
// add node representing prefix + new charCode to trie
new_node = {};
new_node[0] = dictSize++;
node[c0] = new_node;
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
// set node to first charCode of new prefix
node = dictionary[c0];
}
}
if (node) { // Write last node to output
if (freshNode) {
// character token already written to output
freshNode = false;
} else {
// write out the prefix token
value = node[0];
for (i = 0; i < numBits; i++) {
// shifting has precedence over bitmasking
data_val = value >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
}
// Is c a new character?
new_node = dictionary[c0];
if (new_node == undefined) {
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
// insert "new 8/16 bit charCode" token,
// see comments above for explanation
value = c < 256 ? 0 : 1
for (i = 0; i < numBits; i++) {
data_val = value >> i | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
value = 8 + 8 * value;
for (i = 0; i < value; i++) {
data_val = c >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
}
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
}
}
// Mark the end of the stream
for (i = 0; i < numBits; i++) {
// shifting has precedence over bitmasking
data_val = 2 >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
// Flush the last char
data_val <<= bitsPerChar - data_position;
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) {
// "Math.log2(resetValue)" is ES6, so we use
// this while loop instead for backwards compatibility
var _resetValue = 0;
while(resetValue >> ++_resetValue){}
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;
// Get first token, guaranteed to be either
// a new character token (8 or 16 bits)
// or end of stream token.
while (power != maxpower) {
// shifting has precedence over bitmasking
bits += (data_val >> --data_position & 1) << power++;
if (data_position == 0) {
data_position = _resetValue;
data_val = getNextValue(data_index++);
}
}
// if end of stream token, return empty string
if (bits == 2) {
return "";
}
// else, get character
maxpower = bits * 8 + 8;
bits = power = 0;
while (power != maxpower) {
// shifting has precedence over bitmasking
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);
// read rest of string
while (data_index <= length) {
// read out next token
maxpower = numBits;
bits = power = 0;
while (power != maxpower) {
// shifting has precedence over bitmasking
bits += (data_val >> --data_position & 1) << power++;
if (data_position == 0) {
data_position = _resetValue;
data_val = getNextValue(data_index++);
}
}
// 0 or 1 implies new character token
if (bits < 2) {
maxpower = (8 + 8 * bits);
bits = power = 0;
while (power != maxpower) {
// shifting has precedence over bitmasking
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 = 1 << numBits++;
}
} else if (bits == 2) {
// end of stream token
return result.join('');
}
if (bits > dictionary.length) {
return null;
}
entry = bits < dictionary.length ? dictionary[bits] : w + w.charAt(0);
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 "";
}
};
return LZString;
}
)();
var testString = '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. 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. 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 testStringRandomNrs = '';
var i;
for (i=0 ; i<1000 ; i++)
testStringRandomNrs += Math.random() + " ";
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);
}
var compressedString = LZString.compress(testString);
var compressedStringRandomNrs = LZString.compress(testStringRandomNrs);
var compressedStringRepeat1024 = LZString.compress(testStringRepeat1024);
var compressedStringAllUTF16 = LZString.compress(testStringAllUTF16);
};
suite.add("OLD Tattoing", function () {
// OLD Tattoing
var t = LZString.decompress(compressedString);
});
suite.add("NEW Tattoing", function () {
// NEW Tattoing
var t = LZStringNew.decompress(compressedString);
});
suite.add("OLD RandomNrs", function () {
// OLD RandomNrs
var t = LZString.decompress(compressedStringRandomNrs);
});
suite.add("NEW RandomNrs", function () {
// NEW RandomNrs
var t = LZStringNew.decompress(compressedStringRandomNrs);
});
suite.add("OLD Repeat1024", function () {
// OLD Repeat1024
var t = LZString.decompress(compressedStringRepeat1024);
});
suite.add("NEW Repeat1024", function () {
// NEW Repeat1024
var t = LZStringNew.decompress(compressedStringRepeat1024);
});
suite.add("OLD All Printable UTF16", function () {
// OLD All Printable UTF16
var t = LZString.decompress(compressedStringAllUTF16);
});
suite.add("NEW All Printable UTF16", function () {
// NEW All Printable UTF16
var t = LZStringNew.decompress(compressedStringAllUTF16);
});
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 1.4.4 vs pull request #98 - 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