js 压缩库 LZString,压缩率大约 10%

发布时间 2023-09-01 14:24:55作者: 万物有序
  1 // Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
  2 // This work is free. You can redistribute it and/or modify it
  3 // under the terms of the WTFPL, Version 2
  4 // For more information see LICENSE.txt or http://www.wtfpl.net/
  5 //
  6 // For more information, the home page:
  7 // http://pieroxy.net/blog/pages/lz-string/testing.html
  8 //
  9 // LZ-based compression algorithm, version 1.4.4
 10 var LZString = (function() {
 11 
 12 // private property
 13 var f = String.fromCharCode;
 14 var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 15 var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
 16 var baseReverseDic = {};
 17 
 18 function getBaseValue(alphabet, character) {
 19   if (!baseReverseDic[alphabet]) {
 20     baseReverseDic[alphabet] = {};
 21     for (var i=0 ; i<alphabet.length ; i++) {
 22       baseReverseDic[alphabet][alphabet.charAt(i)] = i;
 23     }
 24   }
 25   return baseReverseDic[alphabet][character];
 26 }
 27 
 28 var LZString = {
 29   compressToBase64 : function (input) {
 30     if (input == null) return "";
 31     var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});
 32     switch (res.length % 4) { // To produce valid Base64
 33     default: // When could this happen ?
 34     case 0 : return res;
 35     case 1 : return res+"===";
 36     case 2 : return res+"==";
 37     case 3 : return res+"=";
 38     }
 39   },
 40 
 41   decompressFromBase64 : function (input) {
 42     if (input == null) return "";
 43     if (input == "") return null;
 44     return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });
 45   },
 46 
 47   compressToUTF16 : function (input) {
 48     if (input == null) return "";
 49     return LZString._compress(input, 15, function(a){return f(a+32);}) + " ";
 50   },
 51 
 52   decompressFromUTF16: function (compressed) {
 53     if (compressed == null) return "";
 54     if (compressed == "") return null;
 55     return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; });
 56   },
 57 
 58   //compress into uint8array (UCS-2 big endian format)
 59   compressToUint8Array: function (uncompressed) {
 60     var compressed = LZString.compress(uncompressed);
 61     var buf=new Uint8Array(compressed.length*2); // 2 bytes per character
 62 
 63     for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) {
 64       var current_value = compressed.charCodeAt(i);
 65       buf[i*2] = current_value >>> 8;
 66       buf[i*2+1] = current_value % 256;
 67     }
 68     return buf;
 69   },
 70 
 71   //decompress from uint8array (UCS-2 big endian format)
 72   decompressFromUint8Array:function (compressed) {
 73     if (compressed===null || compressed===undefined){
 74         return LZString.decompress(compressed);
 75     } else {
 76         var buf=new Array(compressed.length/2); // 2 bytes per character
 77         for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {
 78           buf[i]=compressed[i*2]*256+compressed[i*2+1];
 79         }
 80 
 81         var result = [];
 82         buf.forEach(function (c) {
 83           result.push(f(c));
 84         });
 85         return LZString.decompress(result.join(''));
 86 
 87     }
 88 
 89   },
 90 
 91 
 92   //compress into a string that is already URI encoded
 93   compressToEncodedURIComponent: function (input) {
 94     if (input == null) return "";
 95     return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});
 96   },
 97 
 98   //decompress from an output of compressToEncodedURIComponent
 99   decompressFromEncodedURIComponent:function (input) {
100     if (input == null) return "";
101     if (input == "") return null;
102     input = input.replace(/ /g, "+");
103     return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });
104   },
105 
106   compress: function (uncompressed) {
107     return LZString._compress(uncompressed, 16, function(a){return f(a);});
108   },
109   _compress: function (uncompressed, bitsPerChar, getCharFromInt) {
110     if (uncompressed == null) return "";
111     var i, value,
112         context_dictionary= {},
113         context_dictionaryToCreate= {},
114         context_c="",
115         context_wc="",
116         context_w="",
117         context_enlargeIn= 2, // Compensate for the first entry which should not count
118         context_dictSize= 3,
119         context_numBits= 2,
120         context_data=[],
121         context_data_val=0,
122         context_data_position=0,
123         ii;
124 
125     for (ii = 0; ii < uncompressed.length; ii += 1) {
126       context_c = uncompressed.charAt(ii);
127       if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {
128         context_dictionary[context_c] = context_dictSize++;
129         context_dictionaryToCreate[context_c] = true;
130       }
131 
132       context_wc = context_w + context_c;
133       if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {
134         context_w = context_wc;
135       } else {
136         if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
137           if (context_w.charCodeAt(0)<256) {
138             for (i=0 ; i<context_numBits ; i++) {
139               context_data_val = (context_data_val << 1);
140               if (context_data_position == bitsPerChar-1) {
141                 context_data_position = 0;
142                 context_data.push(getCharFromInt(context_data_val));
143                 context_data_val = 0;
144               } else {
145                 context_data_position++;
146               }
147             }
148             value = context_w.charCodeAt(0);
149             for (i=0 ; i<8 ; i++) {
150               context_data_val = (context_data_val << 1) | (value&1);
151               if (context_data_position == bitsPerChar-1) {
152                 context_data_position = 0;
153                 context_data.push(getCharFromInt(context_data_val));
154                 context_data_val = 0;
155               } else {
156                 context_data_position++;
157               }
158               value = value >> 1;
159             }
160           } else {
161             value = 1;
162             for (i=0 ; i<context_numBits ; i++) {
163               context_data_val = (context_data_val << 1) | value;
164               if (context_data_position ==bitsPerChar-1) {
165                 context_data_position = 0;
166                 context_data.push(getCharFromInt(context_data_val));
167                 context_data_val = 0;
168               } else {
169                 context_data_position++;
170               }
171               value = 0;
172             }
173             value = context_w.charCodeAt(0);
174             for (i=0 ; i<16 ; i++) {
175               context_data_val = (context_data_val << 1) | (value&1);
176               if (context_data_position == bitsPerChar-1) {
177                 context_data_position = 0;
178                 context_data.push(getCharFromInt(context_data_val));
179                 context_data_val = 0;
180               } else {
181                 context_data_position++;
182               }
183               value = value >> 1;
184             }
185           }
186           context_enlargeIn--;
187           if (context_enlargeIn == 0) {
188             context_enlargeIn = Math.pow(2, context_numBits);
189             context_numBits++;
190           }
191           delete context_dictionaryToCreate[context_w];
192         } else {
193           value = context_dictionary[context_w];
194           for (i=0 ; i<context_numBits ; i++) {
195             context_data_val = (context_data_val << 1) | (value&1);
196             if (context_data_position == bitsPerChar-1) {
197               context_data_position = 0;
198               context_data.push(getCharFromInt(context_data_val));
199               context_data_val = 0;
200             } else {
201               context_data_position++;
202             }
203             value = value >> 1;
204           }
205 
206 
207         }
208         context_enlargeIn--;
209         if (context_enlargeIn == 0) {
210           context_enlargeIn = Math.pow(2, context_numBits);
211           context_numBits++;
212         }
213         // Add wc to the dictionary.
214         context_dictionary[context_wc] = context_dictSize++;
215         context_w = String(context_c);
216       }
217     }
218 
219     // Output the code for w.
220     if (context_w !== "") {
221       if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
222         if (context_w.charCodeAt(0)<256) {
223           for (i=0 ; i<context_numBits ; i++) {
224             context_data_val = (context_data_val << 1);
225             if (context_data_position == bitsPerChar-1) {
226               context_data_position = 0;
227               context_data.push(getCharFromInt(context_data_val));
228               context_data_val = 0;
229             } else {
230               context_data_position++;
231             }
232           }
233           value = context_w.charCodeAt(0);
234           for (i=0 ; i<8 ; i++) {
235             context_data_val = (context_data_val << 1) | (value&1);
236             if (context_data_position == bitsPerChar-1) {
237               context_data_position = 0;
238               context_data.push(getCharFromInt(context_data_val));
239               context_data_val = 0;
240             } else {
241               context_data_position++;
242             }
243             value = value >> 1;
244           }
245         } else {
246           value = 1;
247           for (i=0 ; i<context_numBits ; i++) {
248             context_data_val = (context_data_val << 1) | value;
249             if (context_data_position == bitsPerChar-1) {
250               context_data_position = 0;
251               context_data.push(getCharFromInt(context_data_val));
252               context_data_val = 0;
253             } else {
254               context_data_position++;
255             }
256             value = 0;
257           }
258           value = context_w.charCodeAt(0);
259           for (i=0 ; i<16 ; i++) {
260             context_data_val = (context_data_val << 1) | (value&1);
261             if (context_data_position == bitsPerChar-1) {
262               context_data_position = 0;
263               context_data.push(getCharFromInt(context_data_val));
264               context_data_val = 0;
265             } else {
266               context_data_position++;
267             }
268             value = value >> 1;
269           }
270         }
271         context_enlargeIn--;
272         if (context_enlargeIn == 0) {
273           context_enlargeIn = Math.pow(2, context_numBits);
274           context_numBits++;
275         }
276         delete context_dictionaryToCreate[context_w];
277       } else {
278         value = context_dictionary[context_w];
279         for (i=0 ; i<context_numBits ; i++) {
280           context_data_val = (context_data_val << 1) | (value&1);
281           if (context_data_position == bitsPerChar-1) {
282             context_data_position = 0;
283             context_data.push(getCharFromInt(context_data_val));
284             context_data_val = 0;
285           } else {
286             context_data_position++;
287           }
288           value = value >> 1;
289         }
290 
291 
292       }
293       context_enlargeIn--;
294       if (context_enlargeIn == 0) {
295         context_enlargeIn = Math.pow(2, context_numBits);
296         context_numBits++;
297       }
298     }
299 
300     // Mark the end of the stream
301     value = 2;
302     for (i=0 ; i<context_numBits ; i++) {
303       context_data_val = (context_data_val << 1) | (value&1);
304       if (context_data_position == bitsPerChar-1) {
305         context_data_position = 0;
306         context_data.push(getCharFromInt(context_data_val));
307         context_data_val = 0;
308       } else {
309         context_data_position++;
310       }
311       value = value >> 1;
312     }
313 
314     // Flush the last char
315     while (true) {
316       context_data_val = (context_data_val << 1);
317       if (context_data_position == bitsPerChar-1) {
318         context_data.push(getCharFromInt(context_data_val));
319         break;
320       }
321       else context_data_position++;
322     }
323     return context_data.join('');
324   },
325 
326   decompress: function (compressed) {
327     if (compressed == null) return "";
328     if (compressed == "") return null;
329     return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });
330   },
331 
332   _decompress: function (length, resetValue, getNextValue) {
333     var dictionary = [],
334         next,
335         enlargeIn = 4,
336         dictSize = 4,
337         numBits = 3,
338         entry = "",
339         result = [],
340         i,
341         w,
342         bits, resb, maxpower, power,
343         c,
344         data = {val:getNextValue(0), position:resetValue, index:1};
345 
346     for (i = 0; i < 3; i += 1) {
347       dictionary[i] = i;
348     }
349 
350     bits = 0;
351     maxpower = Math.pow(2,2);
352     power=1;
353     while (power!=maxpower) {
354       resb = data.val & data.position;
355       data.position >>= 1;
356       if (data.position == 0) {
357         data.position = resetValue;
358         data.val = getNextValue(data.index++);
359       }
360       bits |= (resb>0 ? 1 : 0) * power;
361       power <<= 1;
362     }
363 
364     switch (next = bits) {
365       case 0:
366           bits = 0;
367           maxpower = Math.pow(2,8);
368           power=1;
369           while (power!=maxpower) {
370             resb = data.val & data.position;
371             data.position >>= 1;
372             if (data.position == 0) {
373               data.position = resetValue;
374               data.val = getNextValue(data.index++);
375             }
376             bits |= (resb>0 ? 1 : 0) * power;
377             power <<= 1;
378           }
379         c = f(bits);
380         break;
381       case 1:
382           bits = 0;
383           maxpower = Math.pow(2,16);
384           power=1;
385           while (power!=maxpower) {
386             resb = data.val & data.position;
387             data.position >>= 1;
388             if (data.position == 0) {
389               data.position = resetValue;
390               data.val = getNextValue(data.index++);
391             }
392             bits |= (resb>0 ? 1 : 0) * power;
393             power <<= 1;
394           }
395         c = f(bits);
396         break;
397       case 2:
398         return "";
399     }
400     dictionary[3] = c;
401     w = c;
402     result.push(c);
403     while (true) {
404       if (data.index > length) {
405         return "";
406       }
407 
408       bits = 0;
409       maxpower = Math.pow(2,numBits);
410       power=1;
411       while (power!=maxpower) {
412         resb = data.val & data.position;
413         data.position >>= 1;
414         if (data.position == 0) {
415           data.position = resetValue;
416           data.val = getNextValue(data.index++);
417         }
418         bits |= (resb>0 ? 1 : 0) * power;
419         power <<= 1;
420       }
421 
422       switch (c = bits) {
423         case 0:
424           bits = 0;
425           maxpower = Math.pow(2,8);
426           power=1;
427           while (power!=maxpower) {
428             resb = data.val & data.position;
429             data.position >>= 1;
430             if (data.position == 0) {
431               data.position = resetValue;
432               data.val = getNextValue(data.index++);
433             }
434             bits |= (resb>0 ? 1 : 0) * power;
435             power <<= 1;
436           }
437 
438           dictionary[dictSize++] = f(bits);
439           c = dictSize-1;
440           enlargeIn--;
441           break;
442         case 1:
443           bits = 0;
444           maxpower = Math.pow(2,16);
445           power=1;
446           while (power!=maxpower) {
447             resb = data.val & data.position;
448             data.position >>= 1;
449             if (data.position == 0) {
450               data.position = resetValue;
451               data.val = getNextValue(data.index++);
452             }
453             bits |= (resb>0 ? 1 : 0) * power;
454             power <<= 1;
455           }
456           dictionary[dictSize++] = f(bits);
457           c = dictSize-1;
458           enlargeIn--;
459           break;
460         case 2:
461           return result.join('');
462       }
463 
464       if (enlargeIn == 0) {
465         enlargeIn = Math.pow(2, numBits);
466         numBits++;
467       }
468 
469       if (dictionary[c]) {
470         entry = dictionary[c];
471       } else {
472         if (c === dictSize) {
473           entry = w + w.charAt(0);
474         } else {
475           return null;
476         }
477       }
478       result.push(entry);
479 
480       // Add w+entry[0] to the dictionary.
481       dictionary[dictSize++] = w + entry.charAt(0);
482       enlargeIn--;
483 
484       w = entry;
485 
486       if (enlargeIn == 0) {
487         enlargeIn = Math.pow(2, numBits);
488         numBits++;
489       }
490 
491     }
492   }
493 };
494   return LZString;
495 })();
496 
497 if (typeof define === 'function' && define.amd) {
498   define(function () { return LZString; });
499 } else if( typeof module !== 'undefined' && module != null ) {
500   module.exports = LZString
501 }
  1 // Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
  2 // This work is free. You can redistribute it and/or modify it
  3 // under the terms of the WTFPL, Version 2
  4 // For more information see LICENSE.txt or http://www.wtfpl.net/
  5 //
  6 // For more information, the home page:
  7 // http://pieroxy.net/blog/pages/lz-string/testing.html
  8 //
  9 // LZ-based compression algorithm, version 1.4.4
 10 var LZString = (function() {
 11 
 12 // private property
 13 var f = String.fromCharCode;
 14 var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 15 var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
 16 var baseReverseDic = {};
 17 
 18 function getBaseValue(alphabet, character) {
 19   if (!baseReverseDic[alphabet]) {
 20     baseReverseDic[alphabet] = {};
 21     for (var i=0 ; i<alphabet.length ; i++) {
 22       baseReverseDic[alphabet][alphabet.charAt(i)] = i;
 23     }
 24   }
 25   return baseReverseDic[alphabet][character];
 26 }
 27 
 28 var LZString = {
 29   compressToBase64 : function (input) {
 30     if (input == null) return "";
 31     var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});
 32     switch (res.length % 4) { // To produce valid Base64
 33     default: // When could this happen ?
 34     case 0 : return res;
 35     case 1 : return res+"===";
 36     case 2 : return res+"==";
 37     case 3 : return res+"=";
 38     }
 39   },
 40 
 41   decompressFromBase64 : function (input) {
 42     if (input == null) return "";
 43     if (input == "") return null;
 44     return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });
 45   },
 46 
 47   compressToUTF16 : function (input) {
 48     if (input == null) return "";
 49     return LZString._compress(input, 15, function(a){return f(a+32);}) + " ";
 50   },
 51 
 52   decompressFromUTF16: function (compressed) {
 53     if (compressed == null) return "";
 54     if (compressed == "") return null;
 55     return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; });
 56   },
 57 
 58   //compress into uint8array (UCS-2 big endian format)
 59   compressToUint8Array: function (uncompressed) {
 60     var compressed = LZString.compress(uncompressed);
 61     var buf=new Uint8Array(compressed.length*2); // 2 bytes per character
 62 
 63     for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) {
 64       var current_value = compressed.charCodeAt(i);
 65       buf[i*2] = current_value >>> 8;
 66       buf[i*2+1] = current_value % 256;
 67     }
 68     return buf;
 69   },
 70 
 71   //decompress from uint8array (UCS-2 big endian format)
 72   decompressFromUint8Array:function (compressed) {
 73     if (compressed===null || compressed===undefined){
 74         return LZString.decompress(compressed);
 75     } else {
 76         var buf=new Array(compressed.length/2); // 2 bytes per character
 77         for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {
 78           buf[i]=compressed[i*2]*256+compressed[i*2+1];
 79         }
 80 
 81         var result = [];
 82         buf.forEach(function (c) {
 83           result.push(f(c));
 84         });
 85         return LZString.decompress(result.join(''));
 86 
 87     }
 88 
 89   },
 90 
 91 
 92   //compress into a string that is already URI encoded
 93   compressToEncodedURIComponent: function (input) {
 94     if (input == null) return "";
 95     return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});
 96   },
 97 
 98   //decompress from an output of compressToEncodedURIComponent
 99   decompressFromEncodedURIComponent:function (input) {
100     if (input == null) return "";
101     if (input == "") return null;
102     input = input.replace(/ /g, "+");
103     return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });
104   },
105 
106   compress: function (uncompressed) {
107     return LZString._compress(uncompressed, 16, function(a){return f(a);});
108   },
109   _compress: function (uncompressed, bitsPerChar, getCharFromInt) {
110     if (uncompressed == null) return "";
111     var i, value,
112         context_dictionary= {},
113         context_dictionaryToCreate= {},
114         context_c="",
115         context_wc="",
116         context_w="",
117         context_enlargeIn= 2, // Compensate for the first entry which should not count
118         context_dictSize= 3,
119         context_numBits= 2,
120         context_data=[],
121         context_data_val=0,
122         context_data_position=0,
123         ii;
124 
125     for (ii = 0; ii < uncompressed.length; ii += 1) {
126       context_c = uncompressed.charAt(ii);
127       if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {
128         context_dictionary[context_c] = context_dictSize++;
129         context_dictionaryToCreate[context_c] = true;
130       }
131 
132       context_wc = context_w + context_c;
133       if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {
134         context_w = context_wc;
135       } else {
136         if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
137           if (context_w.charCodeAt(0)<256) {
138             for (i=0 ; i<context_numBits ; i++) {
139               context_data_val = (context_data_val << 1);
140               if (context_data_position == bitsPerChar-1) {
141                 context_data_position = 0;
142                 context_data.push(getCharFromInt(context_data_val));
143                 context_data_val = 0;
144               } else {
145                 context_data_position++;
146               }
147             }
148             value = context_w.charCodeAt(0);
149             for (i=0 ; i<8 ; i++) {
150               context_data_val = (context_data_val << 1) | (value&1);
151               if (context_data_position == bitsPerChar-1) {
152                 context_data_position = 0;
153                 context_data.push(getCharFromInt(context_data_val));
154                 context_data_val = 0;
155               } else {
156                 context_data_position++;
157               }
158               value = value >> 1;
159             }
160           } else {
161             value = 1;
162             for (i=0 ; i<context_numBits ; i++) {
163               context_data_val = (context_data_val << 1) | value;
164               if (context_data_position ==bitsPerChar-1) {
165                 context_data_position = 0;
166                 context_data.push(getCharFromInt(context_data_val));
167                 context_data_val = 0;
168               } else {
169                 context_data_position++;
170               }
171               value = 0;
172             }
173             value = context_w.charCodeAt(0);
174             for (i=0 ; i<16 ; i++) {
175               context_data_val = (context_data_val << 1) | (value&1);
176               if (context_data_position == bitsPerChar-1) {
177                 context_data_position = 0;
178                 context_data.push(getCharFromInt(context_data_val));
179                 context_data_val = 0;
180               } else {
181                 context_data_position++;
182               }
183               value = value >> 1;
184             }
185           }
186           context_enlargeIn--;
187           if (context_enlargeIn == 0) {
188             context_enlargeIn = Math.pow(2, context_numBits);
189             context_numBits++;
190           }
191           delete context_dictionaryToCreate[context_w];
192         } else {
193           value = context_dictionary[context_w];
194           for (i=0 ; i<context_numBits ; i++) {
195             context_data_val = (context_data_val << 1) | (value&1);
196             if (context_data_position == bitsPerChar-1) {
197               context_data_position = 0;
198               context_data.push(getCharFromInt(context_data_val));
199               context_data_val = 0;
200             } else {
201               context_data_position++;
202             }
203             value = value >> 1;
204           }
205 
206 
207         }
208         context_enlargeIn--;
209         if (context_enlargeIn == 0) {
210           context_enlargeIn = Math.pow(2, context_numBits);
211           context_numBits++;
212         }
213         // Add wc to the dictionary.
214         context_dictionary[context_wc] = context_dictSize++;
215         context_w = String(context_c);
216       }
217     }
218 
219     // Output the code for w.
220     if (context_w !== "") {
221       if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
222         if (context_w.charCodeAt(0)<256) {
223           for (i=0 ; i<context_numBits ; i++) {
224             context_data_val = (context_data_val << 1);
225             if (context_data_position == bitsPerChar-1) {
226               context_data_position = 0;
227               context_data.push(getCharFromInt(context_data_val));
228               context_data_val = 0;
229             } else {
230               context_data_position++;
231             }
232           }
233           value = context_w.charCodeAt(0);
234           for (i=0 ; i<8 ; i++) {
235             context_data_val = (context_data_val << 1) | (value&1);
236             if (context_data_position == bitsPerChar-1) {
237               context_data_position = 0;
238               context_data.push(getCharFromInt(context_data_val));
239               context_data_val = 0;
240             } else {
241               context_data_position++;
242             }
243             value = value >> 1;
244           }
245         } else {
246           value = 1;
247           for (i=0 ; i<context_numBits ; i++) {
248             context_data_val = (context_data_val << 1) | value;
249             if (context_data_position == bitsPerChar-1) {
250               context_data_position = 0;
251               context_data.push(getCharFromInt(context_data_val));
252               context_data_val = 0;
253             } else {
254               context_data_position++;
255             }
256             value = 0;
257           }
258           value = context_w.charCodeAt(0);
259           for (i=0 ; i<16 ; i++) {
260             context_data_val = (context_data_val << 1) | (value&1);
261             if (context_data_position == bitsPerChar-1) {
262               context_data_position = 0;
263               context_data.push(getCharFromInt(context_data_val));
264               context_data_val = 0;
265             } else {
266               context_data_position++;
267             }
268             value = value >> 1;
269           }
270         }
271         context_enlargeIn--;
272         if (context_enlargeIn == 0) {
273           context_enlargeIn = Math.pow(2, context_numBits);
274           context_numBits++;
275         }
276         delete context_dictionaryToCreate[context_w];
277       } else {
278         value = context_dictionary[context_w];
279         for (i=0 ; i<context_numBits ; i++) {
280           context_data_val = (context_data_val << 1) | (value&1);
281           if (context_data_position == bitsPerChar-1) {
282             context_data_position = 0;
283             context_data.push(getCharFromInt(context_data_val));
284             context_data_val = 0;
285           } else {
286             context_data_position++;
287           }
288           value = value >> 1;
289         }
290 
291 
292       }
293       context_enlargeIn--;
294       if (context_enlargeIn == 0) {
295         context_enlargeIn = Math.pow(2, context_numBits);
296         context_numBits++;
297       }
298     }
299 
300     // Mark the end of the stream
301     value = 2;
302     for (i=0 ; i<context_numBits ; i++) {
303       context_data_val = (context_data_val << 1) | (value&1);
304       if (context_data_position == bitsPerChar-1) {
305         context_data_position = 0;
306         context_data.push(getCharFromInt(context_data_val));
307         context_data_val = 0;
308       } else {
309         context_data_position++;
310       }
311       value = value >> 1;
312     }
313 
314     // Flush the last char
315     while (true) {
316       context_data_val = (context_data_val << 1);
317       if (context_data_position == bitsPerChar-1) {
318         context_data.push(getCharFromInt(context_data_val));
319         break;
320       }
321       else context_data_position++;
322     }
323     return context_data.join('');
324   },
325 
326   decompress: function (compressed) {
327     if (compressed == null) return "";
328     if (compressed == "") return null;
329     return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });
330   },
331 
332   _decompress: function (length, resetValue, getNextValue) {
333     var dictionary = [],
334         next,
335         enlargeIn = 4,
336         dictSize = 4,
337         numBits = 3,
338         entry = "",
339         result = [],
340         i,
341         w,
342         bits, resb, maxpower, power,
343         c,
344         data = {val:getNextValue(0), position:resetValue, index:1};
345 
346     for (i = 0; i < 3; i += 1) {
347       dictionary[i] = i;
348     }
349 
350     bits = 0;
351     maxpower = Math.pow(2,2);
352     power=1;
353     while (power!=maxpower) {
354       resb = data.val & data.position;
355       data.position >>= 1;
356       if (data.position == 0) {
357         data.position = resetValue;
358         data.val = getNextValue(data.index++);
359       }
360       bits |= (resb>0 ? 1 : 0) * power;
361       power <<= 1;
362     }
363 
364     switch (next = bits) {
365       case 0:
366           bits = 0;
367           maxpower = Math.pow(2,8);
368           power=1;
369           while (power!=maxpower) {
370             resb = data.val & data.position;
371             data.position >>= 1;
372             if (data.position == 0) {
373               data.position = resetValue;
374               data.val = getNextValue(data.index++);
375             }
376             bits |= (resb>0 ? 1 : 0) * power;
377             power <<= 1;
378           }
379         c = f(bits);
380         break;
381       case 1:
382           bits = 0;
383           maxpower = Math.pow(2,16);
384           power=1;
385           while (power!=maxpower) {
386             resb = data.val & data.position;
387             data.position >>= 1;
388             if (data.position == 0) {
389               data.position = resetValue;
390               data.val = getNextValue(data.index++);
391             }
392             bits |= (resb>0 ? 1 : 0) * power;
393             power <<= 1;
394           }
395         c = f(bits);
396         break;
397       case 2:
398         return "";
399     }
400     dictionary[3] = c;
401     w = c;
402     result.push(c);
403     while (true) {
404       if (data.index > length) {
405         return "";
406       }
407 
408       bits = 0;
409       maxpower = Math.pow(2,numBits);
410       power=1;
411       while (power!=maxpower) {
412         resb = data.val & data.position;
413         data.position >>= 1;
414         if (data.position == 0) {
415           data.position = resetValue;
416           data.val = getNextValue(data.index++);
417         }
418         bits |= (resb>0 ? 1 : 0) * power;
419         power <<= 1;
420       }
421 
422       switch (c = bits) {
423         case 0:
424           bits = 0;
425           maxpower = Math.pow(2,8);
426           power=1;
427           while (power!=maxpower) {
428             resb = data.val & data.position;
429             data.position >>= 1;
430             if (data.position == 0) {
431               data.position = resetValue;
432               data.val = getNextValue(data.index++);
433             }
434             bits |= (resb>0 ? 1 : 0) * power;
435             power <<= 1;
436           }
437 
438           dictionary[dictSize++] = f(bits);
439           c = dictSize-1;
440           enlargeIn--;
441           break;
442         case 1:
443           bits = 0;
444           maxpower = Math.pow(2,16);
445           power=1;
446           while (power!=maxpower) {
447             resb = data.val & data.position;
448             data.position >>= 1;
449             if (data.position == 0) {
450               data.position = resetValue;
451               data.val = getNextValue(data.index++);
452             }
453             bits |= (resb>0 ? 1 : 0) * power;
454             power <<= 1;
455           }
456           dictionary[dictSize++] = f(bits);
457           c = dictSize-1;
458           enlargeIn--;
459           break;
460         case 2:
461           return result.join('');
462       }
463 
464       if (enlargeIn == 0) {
465         enlargeIn = Math.pow(2, numBits);
466         numBits++;
467       }
468 
469       if (dictionary[c]) {
470         entry = dictionary[c];
471       } else {
472         if (c === dictSize) {
473           entry = w + w.charAt(0);
474         } else {
475           return null;
476         }
477       }
478       result.push(entry);
479 
480       // Add w+entry[0] to the dictionary.
481       dictionary[dictSize++] = w + entry.charAt(0);
482       enlargeIn--;
483 
484       w = entry;
485 
486       if (enlargeIn == 0) {
487         enlargeIn = Math.pow(2, numBits);
488         numBits++;
489       }
490 
491     }
492   }
493 };
494   return LZString;
495 })();
496 
497 if (typeof define === 'function' && define.amd) {
498   define(function () { return LZString; });
499 } else if( typeof module !== 'undefined' && module != null ) {
500   module.exports = LZString
501 }