lz-string.js 16 KB

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