v6502/vm/lzwCompress.js

205 lines
No EOL
7.5 KiB
JavaScript

var lzwCompress = function (Array, JSON, undefined) {
var _self = {},
_lzwLoggingEnabled = false,
_lzwLog = function (message) {
try {
console.log('lzwCompress: '
+ (new Date()).toISOString() + ' : ' +
(typeof(message) === 'object'
? JSON.stringify(message)
: message));
} catch (e) {
}
};
// KeyOptimize
// http://stackoverflow.com/questions/4433402/replace-keys-json-in-javascript
(function (self, Array, JSON) {
"use strict";
// http://stackoverflow.com/questions/1988349/array-push-if-does-not-exist
Array.prototype.inArray = function (comparer) {
for (var i = 0; i < this.length; i++) {
if (comparer(this[i])) return true;
}
return false;
};
Array.prototype.pushNew = function (element, comparer) {
if (!this.inArray(comparer)) {
this.push(element);
}
};
var _keys = [],
_extractKeys = function (obj) {
if (typeof obj === 'object') {
for (var key in obj) {
if (!Array.isArray(obj)) {
_keys.pushNew(key, function (e) {
return e === key;
});
}
_extractKeys(obj[key]);
}
}
},
_encode = function (obj) {
if (typeof obj !== 'object') return obj;
for (var prop in obj) {
if (!Array.isArray(obj)) {
if (obj.hasOwnProperty(prop)) {
obj[_keys.indexOf(prop)] = _encode(obj[prop]);
delete obj[prop];
}
} else {
obj[prop] = _encode(obj[prop]);
}
}
return obj;
},
_decode = function (obj) {
if (typeof obj !== 'object') return obj;
for (var prop in obj) {
if (!Array.isArray(obj)) {
if (obj.hasOwnProperty(prop)) {
obj[_keys[prop]] = _decode(obj[prop]);
delete obj[prop];
}
} else {
obj[prop] = _decode(obj[prop]);
}
}
return obj;
},
compress = function (json) {
_keys = [];
var jsonObj = JSON.parse(json);
_extractKeys(jsonObj);
_lzwLoggingEnabled && _lzwLog('keys length : ' + _keys.length);
_lzwLoggingEnabled && _lzwLog('keys : ' + _keys);
return JSON.stringify({ __k:_keys, __v:_encode(jsonObj) });
},
decompress = function (minifiedJson) {
var obj = minifiedJson;
if (typeof(obj) !== 'object') obj = JSON.parse(minifiedJson);
if (typeof(obj) !== 'object') return minifiedJson;
if (!obj.hasOwnProperty('__k')) return JSON.stringify(obj);
_keys = obj.__k;
return _decode(obj.__v);
};
self.KeyOptimize = {
pack:compress,
unpack:decompress
};
}(_self, Array, JSON));
// LZWCompress
// http://stackoverflow.com/a/2252533/218882
// http://rosettacode.org/wiki/LZW_compression#JavaScript
(function (self, Array) {
"use strict";
var compress = function (uncompressed) {
if (typeof(uncompressed) !== 'string') return uncompressed;
var i,
dictionary = {},
c,
wc,
w = "",
result = [],
dictSize = 256;
for (i = 0; i < 256; i += 1) {
dictionary[String.fromCharCode(i)] = i;
}
for (i = 0; i < uncompressed.length; i += 1) {
c = uncompressed.charAt(i);
wc = w + c;
if (dictionary[wc]) {
w = wc;
} else {
if (dictionary[w] === undefined) return uncompressed;
result.push(dictionary[w]);
dictionary[wc] = dictSize++;
w = String(c);
}
}
if (w !== "") {
result.push(dictionary[w]);
}
return result;
},
decompress = function (compressed) {
if (!Array.isArray(compressed)) return compressed;
var i,
dictionary = [],
w,
result,
k,
entry = "",
dictSize = 256;
for (i = 0; i < 256; i += 1) {
dictionary[i] = String.fromCharCode(i);
}
w = String.fromCharCode(compressed[0]);
result = w;
for (i = 1; i < compressed.length; i += 1) {
k = compressed[i];
if (dictionary[k]) {
entry = dictionary[k];
} else {
if (k === dictSize) {
entry = w + w.charAt(0);
} else {
return null;
}
}
result += entry;
dictionary[dictSize++] = w + entry.charAt(0);
w = entry;
}
return result;
};
self.LZWCompress = {
pack:compress,
unpack:decompress
};
}(_self, Array));
var _compress = function (obj) {
_lzwLoggingEnabled && _lzwLog('original (uncompressed) : ' + obj);
if (!obj || obj === true || obj instanceof Date) return obj;
var result = obj;
if (typeof obj === 'object') {
result = _self.KeyOptimize.pack(JSON.stringify(obj));
_lzwLoggingEnabled && _lzwLog('key optimized: ' + result);
}
var packedObj = _self.LZWCompress.pack(result);
_lzwLoggingEnabled && _lzwLog('packed (compressed) : ' + packedObj);
return packedObj;
},
_decompress = function (compressedObj) {
_lzwLoggingEnabled && _lzwLog('original (compressed) : ' + compressedObj);
if (!compressedObj || compressedObj === true || compressedObj instanceof Date) return compressedObj;
var result = _self.LZWCompress.unpack(compressedObj);
try {
result = JSON.parse(result);
} catch (e) {
_lzwLoggingEnabled && _lzwLog('unpacked (uncompressed) : ' + result);
return result;
}
result = _self.KeyOptimize.unpack(result);
_lzwLoggingEnabled && _lzwLog('unpacked (uncompressed) : ' + result);
return result;
},
_enableLogging = function (enable) {
_lzwLoggingEnabled = enable;
};
return {
pack:_compress,
unpack:_decompress,
enableLogging:_enableLogging
};
}(Array, JSON);