N
nick
I wanted to try making a javascript compressor (more specifically,
implement a compression engine in javascript, not necessarily for
compressing js) ... but then I found this:
http://marklomas.net/ch-egg/articles/lzwjs.htm
The code is very cleanly written, although it could use some
optimizations (stuff should be moved from constructors to prototypes
for starters).
It outputs an array of numbers (byte array) instead of text... I
wanted it to output and read base64 encoded text. After I got that
working, I tried to squeeze a few more bytes with this base 90 scheme
I came up with. Let me know what you guys think?
// BOF
this.base90 = new function () {
var slash = /\\/g, tilde = /~/g;
// encode a number as a base 90 string
this.fromNumber = function (n) {
for (var r=''; n
{
r += String.fromCharCode((n%90) + 35);
n = Math.floor(n/90);
}
return r.replace(slash,'~');
}
// decode a base 90 string to a number
this.toNumber = function (str) {
var s=str.replace(tilde,'\\');
for (var i=s.length, r=0; i--
{
r += Math.pow(90, i) * (s.charCodeAt(i) - 35);
}
return r;
}
// encode a byte array as a base 90 string
this.fromArray = function (a) {
var i, r='', q=0, e, l=a.length;
for (i=0; i<l; i++) {
q += a * Math.pow(255, i%6);
if ((i+1)%6) continue;
e = this.fromNumber(q);
r += e + (e.length < 8 ? ' ' : '');
q = 0;
}
if (q) r += this.fromNumber(q);
return r.trim();
}
// decode a base 90 string to a byte array
this.toArray = function (str) {
var i, r=[], l=str.length, c, n, p, q='';
for (i=0; i<l; i++) {
q += (c = str.charAt(i));
if (c != ' ' && q.length < 8) continue;
this.encodeChunk(q, r);
q = '';
}
if (q) this.encodeChunk(q, r);
return r;
}
this.fromString = function (str) {
var i, a=[], l=str.length, r='';
for (i=0; i<l; i++) a.push(str.charCodeAt(i));
return this.fromArray(a);
}
this.toString = function (str) {
var i, a = this.toArray(str), l=a.length, r='';
for (i=0; i<l; i++) r += String.fromCharCode(a);
return r;
}
this.encodeChunk = function (str, arr) {
for (var n=this.toNumber(str.trim()), p=6; p--
{
arr.push(n%255);
if (!n) break;
n = Math.floor(n/255);
}
}
}
// Test
var src = "The quick brown fox jumps over the lazy red dog.";
console.log(src);
var dst = base90.fromString(src);
console.log(dst);
src = base90.toString(dst);
console.log(src);
// EOF
The intermediate array storage is there so it works with the
compression script linked above. I'm going to merge everything
together and optimize some stuff, then try to get the decompressor as
small as possible...
So what do you guys think? Is this any better than base 64? It sure as
hell is ugly
implement a compression engine in javascript, not necessarily for
compressing js) ... but then I found this:
http://marklomas.net/ch-egg/articles/lzwjs.htm
The code is very cleanly written, although it could use some
optimizations (stuff should be moved from constructors to prototypes
for starters).
It outputs an array of numbers (byte array) instead of text... I
wanted it to output and read base64 encoded text. After I got that
working, I tried to squeeze a few more bytes with this base 90 scheme
I came up with. Let me know what you guys think?
// BOF
this.base90 = new function () {
var slash = /\\/g, tilde = /~/g;
// encode a number as a base 90 string
this.fromNumber = function (n) {
for (var r=''; n
r += String.fromCharCode((n%90) + 35);
n = Math.floor(n/90);
}
return r.replace(slash,'~');
}
// decode a base 90 string to a number
this.toNumber = function (str) {
var s=str.replace(tilde,'\\');
for (var i=s.length, r=0; i--
r += Math.pow(90, i) * (s.charCodeAt(i) - 35);
}
return r;
}
// encode a byte array as a base 90 string
this.fromArray = function (a) {
var i, r='', q=0, e, l=a.length;
for (i=0; i<l; i++) {
q += a * Math.pow(255, i%6);
if ((i+1)%6) continue;
e = this.fromNumber(q);
r += e + (e.length < 8 ? ' ' : '');
q = 0;
}
if (q) r += this.fromNumber(q);
return r.trim();
}
// decode a base 90 string to a byte array
this.toArray = function (str) {
var i, r=[], l=str.length, c, n, p, q='';
for (i=0; i<l; i++) {
q += (c = str.charAt(i));
if (c != ' ' && q.length < 8) continue;
this.encodeChunk(q, r);
q = '';
}
if (q) this.encodeChunk(q, r);
return r;
}
this.fromString = function (str) {
var i, a=[], l=str.length, r='';
for (i=0; i<l; i++) a.push(str.charCodeAt(i));
return this.fromArray(a);
}
this.toString = function (str) {
var i, a = this.toArray(str), l=a.length, r='';
for (i=0; i<l; i++) r += String.fromCharCode(a);
return r;
}
this.encodeChunk = function (str, arr) {
for (var n=this.toNumber(str.trim()), p=6; p--
arr.push(n%255);
if (!n) break;
n = Math.floor(n/255);
}
}
}
// Test
var src = "The quick brown fox jumps over the lazy red dog.";
console.log(src);
var dst = base90.fromString(src);
console.log(dst);
src = base90.toString(dst);
console.log(src);
// EOF
The intermediate array storage is there so it works with the
compression script linked above. I'm going to merge everything
together and optimize some stuff, then try to get the decompressor as
small as possible...
So what do you guys think? Is this any better than base 64? It sure as
hell is ugly