Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/lz-string.js

Issue 29350042: Issue 4023 - Move storage of subscription lists to localStorage (Closed)
Patch Set: Make sure entry["compressed"] is truthful Created Sept. 8, 2016, 11:40 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/io.js ('k') | lib/prefs.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567 89+/=";
15 var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456 789+-$";
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.charA t(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 getBa seValue(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) { retu rn 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 getBa seValue(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,cont ext_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,contex t_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) { retu rn 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 } else if( typeof angular !== 'undefined' && angular != null ) {
502 angular.module('LZString', [])
503 .factory('LZString', function () {
504 return LZString;
505 });
506 }
OLDNEW
« no previous file with comments | « lib/io.js ('k') | lib/prefs.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld