-
Notifications
You must be signed in to change notification settings - Fork 5
/
lzw.js
156 lines (121 loc) · 4.56 KB
/
lzw.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
(function(){
var STARTPOINT = 256;
//create "saw" global if not there
if(window.saw === undefined){
window.saw = {};
}
/**
* Returns a pre-popuated dictionary to begin encoding
* @private
* @method getDic
* @return {Object} result a hash table with ascii letters as keys
*/
function getDic(){
var result = {};
for (var i=0; i < STARTPOINT; i++) {
var ch = String.fromCharCode(i);
result[ch] = i;
};
return result;
}
/**
* Prepopulates translation table
* @private
* @method tTable
* @return {Object} translation table (hash table)
*/
function tTable(){
var result = {};
for (var i=0; i < STARTPOINT; i++) {
var ch = String.fromCharCode(i);
result[i] = ch;
};
return result;
}
//Define the object and public methods
var LZW = {
/**
* Encodes the string as an LZW compressed binary stream...except
* because we can't really use binary in javascript we are using the unicode
* character specified by the decimal code output by the algorithm in each place
*
* @method encode
* @static
* @param {String} str The string to encode
* @return {String} str The encoded string
*/
encode:function(str){
var index = STARTPOINT, //start at 256, the first 255 are the ascii set
//initialize the dictionary
dictionary = getDic(),
//arr to hold output string
outStr = [],
//this will be the buffer
s = '';
var len = str.length, //for performance
s = str[0]; //lets start
for(var i=1; i < len; i++){
var c = str[i];
if(dictionary[s+c]){ //already in the dictionary
s = s+c;
}else{ //need to add it to the dictionary
var code = ++index;
outStr.push(String.fromCharCode(dictionary[s]));
dictionary[s+c] = code;
s = c;
}
}
for(var c in s ){
outStr.push(s[c]);
}
return outStr.join('');
},
decode:function(str){
//init translation table
var table = tTable(),
//buffer will store the string we are working on
buffer = '',
//store the characters in an array as they are added
outStr = [],
//init first_code
first_code = str[0].charCodeAt(0),
//get string length for loop
len = str.length,
//counter so we know where to start after the base table
counter = STARTPOINT-1,
//this will be handy for the case where next_code does not exist in the table
character = '';
var decodearr= [];
//main decode loop
for (var i=0; i < len; i++) {
var next_code = str[i].charCodeAt(0);
if(!table[next_code]){ //handles the exception case
buffer = table[first_code];
buffer = buffer + character;
}else{
//add decoded char to buffer
buffer = table[next_code];
}
//add buffer to output
outStr.push(buffer);
character = buffer[0];
//add new substring to table
table[++counter] = table[first_code] +
character;
//time for the next char
first_code = next_code;
};
return outStr.join('');
},
/**
* Utitilty method that returns the size of a unicode string in bytes
* @method strSize
* @param {String} str The string to evaluate
* @return {Number} num the length of the string in bytes
*/
strSize:function(str){
return encodeURIComponent(str).replace(/%../g, 'x').length;
}
};
window.saw.lzw = LZW;
}());