Last active
August 29, 2015 14:09
-
-
Save flavioribeiro/0a27a09ad9a836a2b241 to your computer and use it in GitHub Desktop.
LZString Compressor Web Worker
This file contains 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
var compress = function (uncompressed) { | |
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_string="", | |
context_data_val=0, | |
context_data_position=0, | |
ii, | |
f=String.fromCharCode; | |
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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_position = 0; | |
context_data_string += f(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 == 15) { | |
context_data_string += f(context_data_val); | |
break; | |
} | |
else context_data_position++; | |
} | |
return context_data_string; | |
} | |
var decompress = function (compressed) { | |
if (compressed == null) return ""; | |
if (compressed == "") return null; | |
var dictionary = [], | |
next, | |
enlargeIn = 4, | |
dictSize = 4, | |
numBits = 3, | |
entry = "", | |
result = "", | |
i, | |
w, | |
bits, resb, maxpower, power, | |
c, | |
f = String.fromCharCode, | |
data = {string:compressed, val:compressed.charCodeAt(0), position:32768, 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 = 32768; | |
data.val = data.string.charCodeAt(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 = 32768; | |
data.val = data.string.charCodeAt(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 = 32768; | |
data.val = data.string.charCodeAt(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
c = f(bits); | |
break; | |
case 2: | |
return ""; | |
} | |
dictionary[3] = c; | |
w = result = c; | |
while (true) { | |
if (data.index > data.string.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 = 32768; | |
data.val = data.string.charCodeAt(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 = 32768; | |
data.val = data.string.charCodeAt(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 = 32768; | |
data.val = data.string.charCodeAt(data.index++); | |
} | |
bits |= (resb>0 ? 1 : 0) * power; | |
power <<= 1; | |
} | |
dictionary[dictSize++] = f(bits); | |
c = dictSize-1; | |
enlargeIn--; | |
break; | |
case 2: | |
return result; | |
} | |
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 += 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++; | |
} | |
} | |
} | |
this.addEventListener('message', function(event) { | |
if (event.data.type === "compress") { | |
postMessage({url: event.data.url, chunk: compress(event.data.chunk)}); | |
} else if (event.data.type === "decompress") { | |
postMessage({url: event.data.url, chunk: decompress(event.data.chunk)}); | |
} | |
}, false); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment