lz-string-1.3.3.js 20 KB

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