1 |
2 |
Thurallor-7095 |
LibCompress = class(); |
2 |
|
Thurallor-7095 |
|
3 |
|
Thurallor-7095 |
---------------------------------------------------------------------------------- |
4 |
|
Thurallor-7095 |
-- |
5 |
|
Thurallor-7095 |
-- LibCompress.lua |
6 |
|
Thurallor-7095 |
-- |
7 |
|
Thurallor-7095 |
-- Authors: jjsheets and Galmok of European Stormrage (Horde) |
8 |
|
Thurallor-7095 |
-- Email : sheets.jeff@gmail.com and galmok@gmail.com |
9 |
|
Thurallor-7095 |
-- Licence: GPL version 2 (General Public License) |
10 |
|
Thurallor-7095 |
---------------------------------------------------------------------------------- |
11 |
|
Thurallor-7095 |
|
12 |
|
Thurallor-7095 |
|
13 |
|
Thurallor-7095 |
-- list of codecs in this file: |
14 |
|
Thurallor-7095 |
-- \000 - Never used |
15 |
|
Thurallor-7095 |
-- \001 - Uncompressed |
16 |
|
Thurallor-7095 |
-- \002 - LZW |
17 |
|
Thurallor-7095 |
-- \003 - Huffman |
18 |
|
Thurallor-7095 |
|
19 |
|
Thurallor-7095 |
|
20 |
|
Thurallor-7095 |
-- local is faster than global |
21 |
|
Thurallor-7095 |
local type = type |
22 |
|
Thurallor-7095 |
local select = select |
23 |
|
Thurallor-7095 |
local next = next |
24 |
|
Thurallor-7095 |
local loadstring = loadstring |
25 |
|
Thurallor-7095 |
local setmetatable = setmetatable |
26 |
|
Thurallor-7095 |
local assert = assert |
27 |
|
Thurallor-7095 |
local table_insert = table.insert |
28 |
|
Thurallor-7095 |
local table_remove = table.remove |
29 |
|
Thurallor-7095 |
local table_concat = table.concat |
30 |
|
Thurallor-7095 |
local string_char = string.char |
31 |
|
Thurallor-7095 |
local string_byte = string.byte |
32 |
|
Thurallor-7095 |
local string_len = string.len |
33 |
|
Thurallor-7095 |
local string_sub = string.sub |
34 |
|
Thurallor-7095 |
local unpack = unpack |
35 |
|
Thurallor-7095 |
local pairs = pairs |
36 |
|
Thurallor-7095 |
local math_modf = math.modf |
37 |
|
Thurallor-7095 |
local bit_band = bit.band |
38 |
|
Thurallor-7095 |
local bit_bor = bit.bor |
39 |
|
Thurallor-7095 |
local bit_bxor = bit.bxor |
40 |
|
Thurallor-7095 |
local bit_bnot = bit.bnot |
41 |
|
Thurallor-7095 |
local bit_lshift = bit.lshift |
42 |
|
Thurallor-7095 |
local bit_rshift = bit.rshift |
43 |
|
Thurallor-7095 |
|
44 |
|
Thurallor-7095 |
---------------------------------------------------------------------- |
45 |
|
Thurallor-7095 |
---------------------------------------------------------------------- |
46 |
|
Thurallor-7095 |
-- |
47 |
|
Thurallor-7095 |
-- compression algorithms |
48 |
|
Thurallor-7095 |
|
49 |
|
Thurallor-7095 |
-------------------------------------------------------------------------------- |
50 |
|
Thurallor-7095 |
-- LZW codec |
51 |
|
Thurallor-7095 |
-- implemented by sheets.jeff@gmail.com |
52 |
|
Thurallor-7095 |
|
53 |
|
Thurallor-7095 |
-- encode is used to uniquely encode a number into a sequence of bytes that can be decoded using decode() |
54 |
|
Thurallor-7095 |
-- the bytes returned by this do not contain "\000" |
55 |
|
Thurallor-7095 |
local bytes = {} |
56 |
|
Thurallor-7095 |
local function encode(x) |
57 |
|
Thurallor-7095 |
for k = 1, #bytes do bytes[k] = nil end |
58 |
|
Thurallor-7095 |
local xmod |
59 |
|
Thurallor-7095 |
x, xmod = math_modf(x/255) |
60 |
|
Thurallor-7095 |
xmod = xmod * 255 |
61 |
|
Thurallor-7095 |
bytes[#bytes + 1] = xmod |
62 |
|
Thurallor-7095 |
while x > 0 do |
63 |
|
Thurallor-7095 |
x, xmod = math_modf(x/255) |
64 |
|
Thurallor-7095 |
xmod = xmod * 255 |
65 |
|
Thurallor-7095 |
bytes[#bytes + 1] = xmod |
66 |
|
Thurallor-7095 |
end |
67 |
|
Thurallor-7095 |
if #bytes == 1 and bytes[1] > 0 and bytes[1] < 250 then |
68 |
|
Thurallor-7095 |
return string_char(bytes[1]) |
69 |
|
Thurallor-7095 |
else |
70 |
|
Thurallor-7095 |
for i = 1, #bytes do bytes[i] = bytes[i] + 1 end |
71 |
|
Thurallor-7095 |
return string_char(256 - #bytes, unpack(bytes)) |
72 |
|
Thurallor-7095 |
end |
73 |
|
Thurallor-7095 |
end |
74 |
|
Thurallor-7095 |
|
75 |
|
Thurallor-7095 |
--decode converts a unique character sequence into its equivalent number, from ss, beginning at the ith char. |
76 |
|
Thurallor-7095 |
-- returns the decoded number and the count of characters used in the decode process. |
77 |
|
Thurallor-7095 |
local function decode(ss,i) |
78 |
|
Thurallor-7095 |
i = i or 1 |
79 |
|
Thurallor-7095 |
local a = string_byte(ss,i,i) |
80 |
|
Thurallor-7095 |
if a > 249 then |
81 |
|
Thurallor-7095 |
local r = 0 |
82 |
|
Thurallor-7095 |
a = 256 - a |
83 |
|
Thurallor-7095 |
for n = i+a, i+1, -1 do |
84 |
|
Thurallor-7095 |
r = r * 255 + string_byte(ss,n,n) - 1 |
85 |
|
Thurallor-7095 |
end |
86 |
|
Thurallor-7095 |
return r, a + 1 |
87 |
|
Thurallor-7095 |
else |
88 |
|
Thurallor-7095 |
return a, 1 |
89 |
|
Thurallor-7095 |
end |
90 |
|
Thurallor-7095 |
end |
91 |
|
Thurallor-7095 |
|
92 |
|
Thurallor-7095 |
-- Compresses the given uncompressed string. |
93 |
|
Thurallor-7095 |
-- Unless the uncompressed string starts with "\002", this is guaranteed to return a string equal to or smaller than |
94 |
|
Thurallor-7095 |
-- the passed string. |
95 |
|
Thurallor-7095 |
-- the returned string will only contain "\000" characters in rare circumstances, and will contain none if the |
96 |
|
Thurallor-7095 |
-- source string has none. |
97 |
|
Thurallor-7095 |
local dict = {} |
98 |
|
Thurallor-7095 |
function LibCompress:CompressLZW(uncompressed) |
99 |
|
Thurallor-7095 |
if type(uncompressed) == "string" then |
100 |
|
Thurallor-7095 |
local dict_size = 256 |
101 |
|
Thurallor-7095 |
for k in pairs(dict) do |
102 |
|
Thurallor-7095 |
dict[k] = nil |
103 |
|
Thurallor-7095 |
end |
104 |
|
Thurallor-7095 |
local result = {"\002"} |
105 |
|
Thurallor-7095 |
local w = '' |
106 |
|
Thurallor-7095 |
local ressize = 1 |
107 |
|
Thurallor-7095 |
for i = 0, 255 do |
108 |
|
Thurallor-7095 |
dict[string_char(i)] = i |
109 |
|
Thurallor-7095 |
end |
110 |
|
Thurallor-7095 |
for i = 1, #uncompressed do |
111 |
|
Thurallor-7095 |
local c = uncompressed:sub(i,i) |
112 |
|
Thurallor-7095 |
local wc = w..c |
113 |
|
Thurallor-7095 |
if dict[wc] then |
114 |
|
Thurallor-7095 |
w = wc |
115 |
|
Thurallor-7095 |
else |
116 |
|
Thurallor-7095 |
dict[wc] = dict_size |
117 |
|
Thurallor-7095 |
dict_size = dict_size +1 |
118 |
|
Thurallor-7095 |
local r = encode(dict[w]) |
119 |
|
Thurallor-7095 |
ressize = ressize + #r |
120 |
|
Thurallor-7095 |
result[#result + 1] = r |
121 |
|
Thurallor-7095 |
w = c |
122 |
|
Thurallor-7095 |
end |
123 |
|
Thurallor-7095 |
end |
124 |
|
Thurallor-7095 |
if w then |
125 |
|
Thurallor-7095 |
local r = encode(dict[w]) |
126 |
|
Thurallor-7095 |
ressize = ressize + #r |
127 |
|
Thurallor-7095 |
result[#result + 1] = r |
128 |
|
Thurallor-7095 |
end |
129 |
|
Thurallor-7095 |
if (#uncompressed+1) > ressize then |
130 |
|
Thurallor-7095 |
return table_concat(result) |
131 |
|
Thurallor-7095 |
else |
132 |
|
Thurallor-7095 |
return string_char(1)..uncompressed |
133 |
|
Thurallor-7095 |
end |
134 |
|
Thurallor-7095 |
else |
135 |
|
Thurallor-7095 |
return nil, "Can only compress strings" |
136 |
|
Thurallor-7095 |
end |
137 |
|
Thurallor-7095 |
end |
138 |
|
Thurallor-7095 |
|
139 |
|
Thurallor-7095 |
-- if the passed string is a compressed string, this will decompress it and return the decompressed string. |
140 |
|
Thurallor-7095 |
-- Otherwise it return an error message |
141 |
|
Thurallor-7095 |
-- compressed strings are marked by beginning with "\002" |
142 |
|
Thurallor-7095 |
function LibCompress:DecompressLZW(compressed) |
143 |
|
Thurallor-7095 |
if type(compressed) == "string" then |
144 |
|
Thurallor-7095 |
if compressed:sub(1,1) ~= "\002" then |
145 |
|
Thurallor-7095 |
return nil, "Can only decompress LZW compressed data ("..tostring(compressed:sub(1,1))..")" |
146 |
|
Thurallor-7095 |
end |
147 |
|
Thurallor-7095 |
compressed = compressed:sub(2) |
148 |
|
Thurallor-7095 |
local dict_size = 256 |
149 |
|
Thurallor-7095 |
for k in pairs(dict) do |
150 |
|
Thurallor-7095 |
dict[k] = nil |
151 |
|
Thurallor-7095 |
end |
152 |
|
Thurallor-7095 |
for i = 0, 255 do |
153 |
|
Thurallor-7095 |
dict[i] = string_char(i) |
154 |
|
Thurallor-7095 |
end |
155 |
|
Thurallor-7095 |
local result = {} |
156 |
|
Thurallor-7095 |
local t = 1 |
157 |
|
Thurallor-7095 |
local delta, k |
158 |
|
Thurallor-7095 |
k, delta = decode(compressed,t) |
159 |
|
Thurallor-7095 |
t = t + delta |
160 |
|
Thurallor-7095 |
result[#result+1] = dict[k] |
161 |
|
Thurallor-7095 |
local w = dict[k] |
162 |
|
Thurallor-7095 |
local entry |
163 |
|
Thurallor-7095 |
while t <= #compressed do |
164 |
|
Thurallor-7095 |
k, delta = decode(compressed,t) |
165 |
|
Thurallor-7095 |
t = t + delta |
166 |
|
Thurallor-7095 |
entry = dict[k] or (w..w:sub(1,1)) |
167 |
|
Thurallor-7095 |
result[#result+1] = entry |
168 |
|
Thurallor-7095 |
dict[dict_size] = w..entry:sub(1,1) |
169 |
|
Thurallor-7095 |
dict_size = dict_size + 1 |
170 |
|
Thurallor-7095 |
w = entry |
171 |
|
Thurallor-7095 |
end |
172 |
|
Thurallor-7095 |
return table_concat(result) |
173 |
|
Thurallor-7095 |
else |
174 |
|
Thurallor-7095 |
return nil, "Can only uncompress strings" |
175 |
|
Thurallor-7095 |
end |
176 |
|
Thurallor-7095 |
end |
177 |
|
Thurallor-7095 |
|
178 |
|
Thurallor-7095 |
|
179 |
|
Thurallor-7095 |
-------------------------------------------------------------------------------- |
180 |
|
Thurallor-7095 |
-- Huffman codec |
181 |
|
Thurallor-7095 |
-- implemented by Galmok of European Stormrage (Horde), galmok@gmail.com |
182 |
|
Thurallor-7095 |
|
183 |
|
Thurallor-7095 |
local function addCode(tree, bcode,len) |
184 |
|
Thurallor-7095 |
if tree then |
185 |
|
Thurallor-7095 |
tree.bcode = bcode; |
186 |
|
Thurallor-7095 |
tree.blength = len; |
187 |
|
Thurallor-7095 |
if tree.c1 then |
188 |
|
Thurallor-7095 |
addCode(tree.c1, bit_bor(bcode, bit_lshift(1,len)), len+1) |
189 |
|
Thurallor-7095 |
end |
190 |
|
Thurallor-7095 |
if tree.c2 then |
191 |
|
Thurallor-7095 |
addCode(tree.c2, bcode, len+1) |
192 |
|
Thurallor-7095 |
end |
193 |
|
Thurallor-7095 |
end |
194 |
|
Thurallor-7095 |
end |
195 |
|
Thurallor-7095 |
|
196 |
|
Thurallor-7095 |
local function escape_code(code, len) |
197 |
|
Thurallor-7095 |
local escaped_code = 0; |
198 |
|
Thurallor-7095 |
local b; |
199 |
|
Thurallor-7095 |
local l = 0; |
200 |
|
Thurallor-7095 |
for i = len-1, 0,- 1 do |
201 |
|
Thurallor-7095 |
b = bit_band( code, bit_lshift(1,i))==0 and 0 or 1 |
202 |
|
Thurallor-7095 |
escaped_code = bit_lshift(escaped_code,1+b) + b |
203 |
|
Thurallor-7095 |
l = l + b; |
204 |
|
Thurallor-7095 |
end |
205 |
|
Thurallor-7095 |
return escaped_code, len+l |
206 |
|
Thurallor-7095 |
end |
207 |
|
Thurallor-7095 |
|
208 |
|
Thurallor-7095 |
tables.Huffman_compressed = {} |
209 |
|
Thurallor-7095 |
tables.Huffman_large_compressed = {} |
210 |
|
Thurallor-7095 |
|
211 |
|
Thurallor-7095 |
local compressed_size = 0 |
212 |
|
Thurallor-7095 |
local remainder; |
213 |
|
Thurallor-7095 |
local remainder_length; |
214 |
|
Thurallor-7095 |
local function addBits(tbl, code, len) |
215 |
|
Thurallor-7095 |
remainder = remainder + bit_lshift(code, remainder_length) |
216 |
|
Thurallor-7095 |
remainder_length = len + remainder_length |
217 |
|
Thurallor-7095 |
if remainder_length > 32 then |
218 |
|
Thurallor-7095 |
return true -- Bits lost due to too long code-words. |
219 |
|
Thurallor-7095 |
end |
220 |
|
Thurallor-7095 |
while remainder_length>=8 do |
221 |
|
Thurallor-7095 |
compressed_size = compressed_size + 1 |
222 |
|
Thurallor-7095 |
tbl[compressed_size] = string_char(bit_band(remainder, 255)) |
223 |
|
Thurallor-7095 |
remainder = bit_rshift(remainder, 8) |
224 |
|
Thurallor-7095 |
remainder_length = remainder_length -8 |
225 |
|
Thurallor-7095 |
end |
226 |
|
Thurallor-7095 |
end |
227 |
|
Thurallor-7095 |
|
228 |
|
Thurallor-7095 |
-- word size for this huffman algorithm is 8 bits (1 byte). This means the best compression is representing 1 byte with 1 bit, i.e. compress to 0.125 of original size. |
229 |
|
Thurallor-7095 |
function LibCompress:CompressHuffman(uncompressed) |
230 |
|
Thurallor-7095 |
if not type(uncompressed)=="string" then |
231 |
|
Thurallor-7095 |
return nil, "Can only compress strings" |
232 |
|
Thurallor-7095 |
end |
233 |
|
Thurallor-7095 |
if #uncompressed == 0 then |
234 |
|
Thurallor-7095 |
return "\001" |
235 |
|
Thurallor-7095 |
end |
236 |
|
Thurallor-7095 |
|
237 |
|
Thurallor-7095 |
-- make histogram |
238 |
|
Thurallor-7095 |
local hist = {} |
239 |
|
Thurallor-7095 |
local n = 0 |
240 |
|
Thurallor-7095 |
-- dont have to use all datat to make the histogram |
241 |
|
Thurallor-7095 |
local uncompressed_size = string_len(uncompressed) |
242 |
|
Thurallor-7095 |
local c; |
243 |
|
Thurallor-7095 |
for i = 1, uncompressed_size do |
244 |
|
Thurallor-7095 |
c = string_byte(uncompressed, i) |
245 |
|
Thurallor-7095 |
hist[c] = (hist[c] or 0) + 1 |
246 |
|
Thurallor-7095 |
end |
247 |
|
Thurallor-7095 |
|
248 |
|
Thurallor-7095 |
--Start with as many leaves as there are symbols. |
249 |
|
Thurallor-7095 |
local leafs = {} |
250 |
|
Thurallor-7095 |
local leaf; |
251 |
|
Thurallor-7095 |
local symbols = {} |
252 |
|
Thurallor-7095 |
for symbol, weight in pairs(hist) do |
253 |
|
Thurallor-7095 |
leaf = { symbol=string_char(symbol), weight=weight }; |
254 |
|
Thurallor-7095 |
symbols[symbol] = leaf; |
255 |
|
Thurallor-7095 |
table_insert(leafs, leaf) |
256 |
|
Thurallor-7095 |
end |
257 |
|
Thurallor-7095 |
--Enqueue all leaf nodes into the first queue (by probability in increasing order so that the least likely item is in the head of the queue). |
258 |
|
Thurallor-7095 |
sort(leafs, function(a,b) if a.weight<b.weight then return true elseif a.weight>b.weight then return false else return nil end end) |
259 |
|
Thurallor-7095 |
|
260 |
|
Thurallor-7095 |
local nLeafs = #leafs |
261 |
|
Thurallor-7095 |
|
262 |
|
Thurallor-7095 |
-- create tree |
263 |
|
Thurallor-7095 |
local huff = {} |
264 |
|
Thurallor-7095 |
--While there is more than one node in the queues: |
265 |
|
Thurallor-7095 |
local l,h, li, hi, leaf1, leaf2 |
266 |
|
Thurallor-7095 |
local newNode; |
267 |
|
Thurallor-7095 |
while (#leafs+#huff > 1) do |
268 |
|
Thurallor-7095 |
-- Dequeue the two nodes with the lowest weight. |
269 |
|
Thurallor-7095 |
-- Dequeue first |
270 |
|
Thurallor-7095 |
if not next(huff) then |
271 |
|
Thurallor-7095 |
li, leaf1 = next(leafs) |
272 |
|
Thurallor-7095 |
table_remove(leafs, li) |
273 |
|
Thurallor-7095 |
elseif not next(leafs) then |
274 |
|
Thurallor-7095 |
hi, leaf1 = next(huff) |
275 |
|
Thurallor-7095 |
table_remove(huff, hi) |
276 |
|
Thurallor-7095 |
else |
277 |
|
Thurallor-7095 |
li, l = next(leafs); |
278 |
|
Thurallor-7095 |
hi, h = next(huff); |
279 |
|
Thurallor-7095 |
if l.weight<=h.weight then |
280 |
|
Thurallor-7095 |
leaf1 = l; |
281 |
|
Thurallor-7095 |
table_remove(leafs, li) |
282 |
|
Thurallor-7095 |
else |
283 |
|
Thurallor-7095 |
leaf1 = h; |
284 |
|
Thurallor-7095 |
table_remove(huff, hi) |
285 |
|
Thurallor-7095 |
end |
286 |
|
Thurallor-7095 |
end |
287 |
|
Thurallor-7095 |
-- Dequeue second |
288 |
|
Thurallor-7095 |
if not next(huff) then |
289 |
|
Thurallor-7095 |
li, leaf2 = next(leafs) |
290 |
|
Thurallor-7095 |
table_remove(leafs, li) |
291 |
|
Thurallor-7095 |
elseif not next(leafs) then |
292 |
|
Thurallor-7095 |
hi, leaf2 = next(huff) |
293 |
|
Thurallor-7095 |
table_remove(huff, hi) |
294 |
|
Thurallor-7095 |
else |
295 |
|
Thurallor-7095 |
li, l = next(leafs); |
296 |
|
Thurallor-7095 |
hi, h = next(huff); |
297 |
|
Thurallor-7095 |
if l.weight<=h.weight then |
298 |
|
Thurallor-7095 |
leaf2 = l; |
299 |
|
Thurallor-7095 |
table_remove(leafs, li) |
300 |
|
Thurallor-7095 |
else |
301 |
|
Thurallor-7095 |
leaf2 = h; |
302 |
|
Thurallor-7095 |
table_remove(huff, hi) |
303 |
|
Thurallor-7095 |
end |
304 |
|
Thurallor-7095 |
end |
305 |
|
Thurallor-7095 |
|
306 |
|
Thurallor-7095 |
--Create a new internal node, with the two just-removed nodes as children (either node can be either child) and the sum of their weights as the new weight. |
307 |
|
Thurallor-7095 |
newNode = { c1 = leaf1, c2 = leaf2, weight = leaf1.weight+leaf2.weight } |
308 |
|
Thurallor-7095 |
table_insert(huff,newNode) |
309 |
|
Thurallor-7095 |
end |
310 |
|
Thurallor-7095 |
if #leafs>0 then |
311 |
|
Thurallor-7095 |
li, l = next(leafs) |
312 |
|
Thurallor-7095 |
table_insert(huff, l) |
313 |
|
Thurallor-7095 |
table_remove(leafs, li) |
314 |
|
Thurallor-7095 |
end |
315 |
|
Thurallor-7095 |
huff = huff[1]; |
316 |
|
Thurallor-7095 |
|
317 |
|
Thurallor-7095 |
-- assign codes to each symbol |
318 |
|
Thurallor-7095 |
-- c1 = "0", c2 = "1" |
319 |
|
Thurallor-7095 |
-- As a common convention, bit '0' represents following the left child and bit '1' represents following the right child. |
320 |
|
Thurallor-7095 |
-- c1 = left, c2 = right |
321 |
|
Thurallor-7095 |
|
322 |
|
Thurallor-7095 |
addCode(huff,0,0); |
323 |
|
Thurallor-7095 |
if huff then |
324 |
|
Thurallor-7095 |
huff.bcode = 0 |
325 |
|
Thurallor-7095 |
huff.blength = 1 |
326 |
|
Thurallor-7095 |
end |
327 |
|
Thurallor-7095 |
|
328 |
|
Thurallor-7095 |
-- READING |
329 |
|
Thurallor-7095 |
-- bitfield = 0 |
330 |
|
Thurallor-7095 |
-- bitfield_len = 0 |
331 |
|
Thurallor-7095 |
-- read byte1 |
332 |
|
Thurallor-7095 |
-- bitfield = bitfield + bit_lshift(byte1, bitfield_len) |
333 |
|
Thurallor-7095 |
-- bitfield_len = bitfield_len + 8 |
334 |
|
Thurallor-7095 |
-- read byte2 |
335 |
|
Thurallor-7095 |
-- bitfield = bitfield + bit_lshift(byte2, bitfield_len) |
336 |
|
Thurallor-7095 |
-- bitfield_len = bitfield_len + 8 |
337 |
|
Thurallor-7095 |
-- (use 5 bits) |
338 |
|
Thurallor-7095 |
-- word = bit_band( bitfield, bit_lshift(1,5)-1) |
339 |
|
Thurallor-7095 |
-- bitfield = bit_rshift( bitfield, 5) |
340 |
|
Thurallor-7095 |
-- bitfield_len = bitfield_len - 5 |
341 |
|
Thurallor-7095 |
-- read byte3 |
342 |
|
Thurallor-7095 |
-- bitfield = bitfield + bit_lshift(byte3, bitfield_len) |
343 |
|
Thurallor-7095 |
-- bitfield_len = bitfield_len + 8 |
344 |
|
Thurallor-7095 |
|
345 |
|
Thurallor-7095 |
-- WRITING |
346 |
|
Thurallor-7095 |
remainder = 0; |
347 |
|
Thurallor-7095 |
remainder_length = 0; |
348 |
|
Thurallor-7095 |
|
349 |
|
Thurallor-7095 |
local compressed = tables.Huffman_compressed |
350 |
|
Thurallor-7095 |
--compressed_size = 0 |
351 |
|
Thurallor-7095 |
|
352 |
|
Thurallor-7095 |
-- first byte is version info. 0 = uncompressed, 1 = 8-bit word huffman compressed |
353 |
|
Thurallor-7095 |
compressed[1] = "\003" |
354 |
|
Thurallor-7095 |
|
355 |
|
Thurallor-7095 |
-- Header: byte 0=#leafs, byte 1-3=size of uncompressed data |
356 |
|
Thurallor-7095 |
-- max 2^24 bytes |
357 |
|
Thurallor-7095 |
local l = string_len(uncompressed) |
358 |
|
Thurallor-7095 |
compressed[2] = string_char(bit_band(nLeafs-1, 255)) -- number of leafs |
359 |
|
Thurallor-7095 |
compressed[3] = string_char(bit_band(l, 255)) -- bit 0-7 |
360 |
|
Thurallor-7095 |
compressed[4] = string_char(bit_band(bit_rshift(l, 8), 255)) -- bit 8-15 |
361 |
|
Thurallor-7095 |
compressed[5] = string_char(bit_band(bit_rshift(l, 16), 255)) -- bit 16-23 |
362 |
|
Thurallor-7095 |
compressed_size = 5 |
363 |
|
Thurallor-7095 |
|
364 |
|
Thurallor-7095 |
-- create symbol/code map |
365 |
|
Thurallor-7095 |
for symbol, leaf in pairs(symbols) do |
366 |
|
Thurallor-7095 |
addBits(compressed, symbol, 8); |
367 |
|
Thurallor-7095 |
if addBits(compressed, escape_code(leaf.bcode, leaf.blength)) then |
368 |
|
Thurallor-7095 |
-- code word too long. Needs new revision to be able to handle more than 32 bits |
369 |
|
Thurallor-7095 |
return string_char(0)..uncompressed |
370 |
|
Thurallor-7095 |
end |
371 |
|
Thurallor-7095 |
addBits(compressed, 3, 2); |
372 |
|
Thurallor-7095 |
end |
373 |
|
Thurallor-7095 |
|
374 |
|
Thurallor-7095 |
-- create huffman code |
375 |
|
Thurallor-7095 |
local large_compressed = tables.Huffman_large_compressed |
376 |
|
Thurallor-7095 |
local large_compressed_size = 0 |
377 |
|
Thurallor-7095 |
local ulimit |
378 |
|
Thurallor-7095 |
for i = 1, l, 200 do |
379 |
|
Thurallor-7095 |
ulimit = l<(i+199) and l or (i+199) |
380 |
|
Thurallor-7095 |
for sub_i = i, ulimit do |
381 |
|
Thurallor-7095 |
c = string_byte(uncompressed, sub_i) |
382 |
|
Thurallor-7095 |
addBits(compressed, symbols[c].bcode, symbols[c].blength) |
383 |
|
Thurallor-7095 |
end |
384 |
|
Thurallor-7095 |
large_compressed_size = large_compressed_size + 1 |
385 |
|
Thurallor-7095 |
large_compressed[large_compressed_size] = table_concat(compressed, "", 1, compressed_size) |
386 |
|
Thurallor-7095 |
compressed_size = 0 |
387 |
|
Thurallor-7095 |
end |
388 |
|
Thurallor-7095 |
|
389 |
|
Thurallor-7095 |
-- add remainding bits (if any) |
390 |
|
Thurallor-7095 |
if remainder_length>0 then |
391 |
|
Thurallor-7095 |
large_compressed_size = large_compressed_size + 1 |
392 |
|
Thurallor-7095 |
large_compressed[large_compressed_size] = string_char(remainder) |
393 |
|
Thurallor-7095 |
end |
394 |
|
Thurallor-7095 |
local compressed_string = table_concat(large_compressed, "", 1, large_compressed_size) |
395 |
|
Thurallor-7095 |
|
396 |
|
Thurallor-7095 |
-- is compression worth it? If not, return uncompressed data. |
397 |
|
Thurallor-7095 |
if (#uncompressed+1) <= #compressed_string then |
398 |
|
Thurallor-7095 |
return "\001"..uncompressed |
399 |
|
Thurallor-7095 |
end |
400 |
|
Thurallor-7095 |
|
401 |
|
Thurallor-7095 |
setCleanupTables("Huffman_compressed", "Huffman_large_compressed") |
402 |
|
Thurallor-7095 |
return compressed_string |
403 |
|
Thurallor-7095 |
end |
404 |
|
Thurallor-7095 |
|
405 |
|
Thurallor-7095 |
-- lookuptable (cached between calls) |
406 |
|
Thurallor-7095 |
local lshiftMask = {} |
407 |
|
Thurallor-7095 |
setmetatable(lshiftMask, { |
408 |
|
Thurallor-7095 |
__index = function (t, k) |
409 |
|
Thurallor-7095 |
local v = bit_lshift(1, k) |
410 |
|
Thurallor-7095 |
rawset(t, k, v) |
411 |
|
Thurallor-7095 |
return v |
412 |
|
Thurallor-7095 |
end |
413 |
|
Thurallor-7095 |
}) |
414 |
|
Thurallor-7095 |
|
415 |
|
Thurallor-7095 |
-- lookuptable (cached between calls) |
416 |
|
Thurallor-7095 |
local lshiftMinusOneMask = {} |
417 |
|
Thurallor-7095 |
setmetatable(lshiftMinusOneMask, { |
418 |
|
Thurallor-7095 |
__index = function (t, k) |
419 |
|
Thurallor-7095 |
local v = bit_lshift(1, k)-1 |
420 |
|
Thurallor-7095 |
rawset(t, k, v) |
421 |
|
Thurallor-7095 |
return v |
422 |
|
Thurallor-7095 |
end |
423 |
|
Thurallor-7095 |
}) |
424 |
|
Thurallor-7095 |
|
425 |
|
Thurallor-7095 |
local function getCode(bitfield, field_len) |
426 |
|
Thurallor-7095 |
if field_len>=2 then |
427 |
|
Thurallor-7095 |
local b; |
428 |
|
Thurallor-7095 |
local p = 0; |
429 |
|
Thurallor-7095 |
for i = 0, field_len-1 do |
430 |
|
Thurallor-7095 |
b = bit_band(bitfield, lshiftMask[i]) |
431 |
|
Thurallor-7095 |
if not (p==0) and not (b == 0) then |
432 |
|
Thurallor-7095 |
-- found 2 bits set right after each other (stop bits) |
433 |
|
Thurallor-7095 |
return bit_band( bitfield, lshiftMinusOneMask[i-1]), i-1, |
434 |
|
Thurallor-7095 |
bit_rshift(bitfield, i+1), field_len-i-1 |
435 |
|
Thurallor-7095 |
end |
436 |
|
Thurallor-7095 |
p = b |
437 |
|
Thurallor-7095 |
end |
438 |
|
Thurallor-7095 |
end |
439 |
|
Thurallor-7095 |
return nil |
440 |
|
Thurallor-7095 |
end |
441 |
|
Thurallor-7095 |
|
442 |
|
Thurallor-7095 |
local function unescape_code(code, code_len) |
443 |
|
Thurallor-7095 |
local unescaped_code=0; |
444 |
|
Thurallor-7095 |
local b; |
445 |
|
Thurallor-7095 |
local l = 0; |
446 |
|
Thurallor-7095 |
local i = 0 |
447 |
|
Thurallor-7095 |
while i < code_len do |
448 |
|
Thurallor-7095 |
b = bit_band( code, lshiftMask[i]) |
449 |
|
Thurallor-7095 |
if not (b==0) then |
450 |
|
Thurallor-7095 |
unescaped_code = bit_bor(unescaped_code, lshiftMask[l]) |
451 |
|
Thurallor-7095 |
i = i + 1 |
452 |
|
Thurallor-7095 |
end |
453 |
|
Thurallor-7095 |
i = i + 1 |
454 |
|
Thurallor-7095 |
l = l + 1 |
455 |
|
Thurallor-7095 |
end |
456 |
|
Thurallor-7095 |
return unescaped_code, l |
457 |
|
Thurallor-7095 |
end |
458 |
|
Thurallor-7095 |
|
459 |
|
Thurallor-7095 |
tables.Huffman_uncompressed = {} |
460 |
|
Thurallor-7095 |
tables.Huffman_large_uncompressed = {} -- will always be as big as the larges string ever decompressed. Bad, but clearing i every timetakes precious time. |
461 |
|
Thurallor-7095 |
|
462 |
|
Thurallor-7095 |
function LibCompress:DecompressHuffman(compressed) |
463 |
|
Thurallor-7095 |
if not type(uncompressed)=="string" then |
464 |
|
Thurallor-7095 |
return nil, "Can only uncompress strings" |
465 |
|
Thurallor-7095 |
end |
466 |
|
Thurallor-7095 |
|
467 |
|
Thurallor-7095 |
local compressed_size = #compressed |
468 |
|
Thurallor-7095 |
--decode header |
469 |
|
Thurallor-7095 |
local info_byte = string_byte(compressed) |
470 |
|
Thurallor-7095 |
-- is data compressed |
471 |
|
Thurallor-7095 |
if info_byte==1 then |
472 |
|
Thurallor-7095 |
return compressed:sub(2) --return uncompressed data |
473 |
|
Thurallor-7095 |
end |
474 |
|
Thurallor-7095 |
if not (info_byte==3) then |
475 |
|
Thurallor-7095 |
return nil, "Can only decompress Huffman compressed data ("..tostring(info_byte)..")" |
476 |
|
Thurallor-7095 |
end |
477 |
|
Thurallor-7095 |
|
478 |
|
Thurallor-7095 |
local num_symbols = string_byte(string_sub(compressed, 2, 2)) + 1 |
479 |
|
Thurallor-7095 |
local c0 = string_byte(string_sub(compressed, 3, 3)) |
480 |
|
Thurallor-7095 |
local c1 = string_byte(string_sub(compressed, 4, 4)) |
481 |
|
Thurallor-7095 |
local c2 = string_byte(string_sub(compressed, 5, 5)) |
482 |
|
Thurallor-7095 |
local orig_size = c2*65536 + c1*256 + c0 |
483 |
|
Thurallor-7095 |
if orig_size==0 then |
484 |
|
Thurallor-7095 |
return ""; |
485 |
|
Thurallor-7095 |
end |
486 |
|
Thurallor-7095 |
|
487 |
|
Thurallor-7095 |
-- decode code->symbal map |
488 |
|
Thurallor-7095 |
local bitfield = 0; |
489 |
|
Thurallor-7095 |
local bitfield_len = 0; |
490 |
|
Thurallor-7095 |
local map = {} -- only table not reused in Huffman decode. |
491 |
|
Thurallor-7095 |
setmetatable(map, { |
492 |
|
Thurallor-7095 |
__index = function (t, k) |
493 |
|
Thurallor-7095 |
local v = {} |
494 |
|
Thurallor-7095 |
rawset(t, k, v) |
495 |
|
Thurallor-7095 |
return v |
496 |
|
Thurallor-7095 |
end |
497 |
|
Thurallor-7095 |
}) |
498 |
|
Thurallor-7095 |
|
499 |
|
Thurallor-7095 |
local i = 6; -- byte 1-5 are header bytes |
500 |
|
Thurallor-7095 |
local c, cl; |
501 |
|
Thurallor-7095 |
local minCodeLen = 1000; |
502 |
|
Thurallor-7095 |
local maxCodeLen = 0; |
503 |
|
Thurallor-7095 |
local symbol, code, code_len, _bitfield, _bitfield_len; |
504 |
|
Thurallor-7095 |
local n = 0; |
505 |
|
Thurallor-7095 |
local state = 0; -- 0 = get symbol (8 bits), 1 = get code (varying bits, ends with 2 bits set) |
506 |
|
Thurallor-7095 |
while n<num_symbols do |
507 |
|
Thurallor-7095 |
if i>compressed_size then |
508 |
|
Thurallor-7095 |
return nil, "Cannot decode map" |
509 |
|
Thurallor-7095 |
end |
510 |
|
Thurallor-7095 |
|
511 |
|
Thurallor-7095 |
c = string_byte(compressed, i) |
512 |
|
Thurallor-7095 |
bitfield = bit_bor(bitfield, bit_lshift(c, bitfield_len)) |
513 |
|
Thurallor-7095 |
bitfield_len = bitfield_len + 8 |
514 |
|
Thurallor-7095 |
|
515 |
|
Thurallor-7095 |
if state == 0 then |
516 |
|
Thurallor-7095 |
symbol = bit_band(bitfield, 255) |
517 |
|
Thurallor-7095 |
bitfield = bit_rshift(bitfield, 8) |
518 |
|
Thurallor-7095 |
bitfield_len = bitfield_len -8 |
519 |
|
Thurallor-7095 |
state = 1 -- search for code now |
520 |
|
Thurallor-7095 |
else |
521 |
|
Thurallor-7095 |
code, code_len, _bitfield, _bitfield_len = getCode(bitfield, bitfield_len) |
522 |
|
Thurallor-7095 |
if code then |
523 |
|
Thurallor-7095 |
bitfield, bitfield_len = _bitfield, _bitfield_len |
524 |
|
Thurallor-7095 |
c, cl = unescape_code(code, code_len) |
525 |
|
Thurallor-7095 |
map[cl][c]=string_char(symbol) |
526 |
|
Thurallor-7095 |
minCodeLen = cl<minCodeLen and cl or minCodeLen |
527 |
|
Thurallor-7095 |
maxCodeLen = cl>maxCodeLen and cl or maxCodeLen |
528 |
|
Thurallor-7095 |
--print("symbol: "..string_char(symbol).." code: "..tobinary(c, cl)) |
529 |
|
Thurallor-7095 |
n = n + 1 |
530 |
|
Thurallor-7095 |
state = 0 -- search for next symbol (if any) |
531 |
|
Thurallor-7095 |
end |
532 |
|
Thurallor-7095 |
end |
533 |
|
Thurallor-7095 |
i=i+1 |
534 |
|
Thurallor-7095 |
end |
535 |
|
Thurallor-7095 |
|
536 |
|
Thurallor-7095 |
-- dont create new subtables for entries not in the map. Waste of space. |
537 |
|
Thurallor-7095 |
-- But do return an empty table to prevent runtime errors. (instead of returning nil) |
538 |
|
Thurallor-7095 |
local mt = {} |
539 |
|
Thurallor-7095 |
setmetatable(map, { |
540 |
|
Thurallor-7095 |
__index = function (t, k) |
541 |
|
Thurallor-7095 |
return mt |
542 |
|
Thurallor-7095 |
end |
543 |
|
Thurallor-7095 |
}) |
544 |
|
Thurallor-7095 |
|
545 |
|
Thurallor-7095 |
local uncompressed = tables.Huffman_uncompressed |
546 |
|
Thurallor-7095 |
local large_uncompressed = tables.Huffman_large_uncompressed |
547 |
|
Thurallor-7095 |
local uncompressed_size = 0 |
548 |
|
Thurallor-7095 |
local large_uncompressed_size = 0 |
549 |
|
Thurallor-7095 |
local test_code |
550 |
|
Thurallor-7095 |
local test_code_len = minCodeLen; |
551 |
|
Thurallor-7095 |
local symbol; |
552 |
|
Thurallor-7095 |
local dec_size = 0; |
553 |
|
Thurallor-7095 |
compressed_size = compressed_size + 1 |
554 |
|
Thurallor-7095 |
local temp_limit = 200; -- first limit of uncompressed data. large_uncompressed will hold strings of length 200 |
555 |
|
Thurallor-7095 |
temp_limit = temp_limit > orig_size and orig_size or temp_limit |
556 |
|
Thurallor-7095 |
while true do |
557 |
|
Thurallor-7095 |
if test_code_len<=bitfield_len then |
558 |
|
Thurallor-7095 |
test_code=bit_band( bitfield, lshiftMinusOneMask[test_code_len]) |
559 |
|
Thurallor-7095 |
symbol = map[test_code_len][test_code] |
560 |
|
Thurallor-7095 |
if symbol then |
561 |
|
Thurallor-7095 |
uncompressed_size = uncompressed_size + 1 |
562 |
|
Thurallor-7095 |
uncompressed[uncompressed_size]=symbol |
563 |
|
Thurallor-7095 |
dec_size = dec_size + 1 |
564 |
|
Thurallor-7095 |
if dec_size >= temp_limit then |
565 |
|
Thurallor-7095 |
if dec_size>=orig_size then -- checked here for speed reasons |
566 |
|
Thurallor-7095 |
break; |
567 |
|
Thurallor-7095 |
end |
568 |
|
Thurallor-7095 |
-- process compressed bytes in smaller chunks |
569 |
|
Thurallor-7095 |
large_uncompressed_size = large_uncompressed_size + 1 |
570 |
|
Thurallor-7095 |
large_uncompressed[large_uncompressed_size] = table_concat(uncompressed, "", 1, uncompressed_size) |
571 |
|
Thurallor-7095 |
uncompressed_size = 0 |
572 |
|
Thurallor-7095 |
temp_limit = temp_limit + 200 -- repeated chunk size is 200 uncompressed bytes |
573 |
|
Thurallor-7095 |
temp_limit = temp_limit > orig_size and orig_size or temp_limit |
574 |
|
Thurallor-7095 |
end |
575 |
|
Thurallor-7095 |
bitfield = bit_rshift(bitfield, test_code_len) |
576 |
|
Thurallor-7095 |
bitfield_len = bitfield_len - test_code_len |
577 |
|
Thurallor-7095 |
test_code_len = minCodeLen |
578 |
|
Thurallor-7095 |
else |
579 |
|
Thurallor-7095 |
test_code_len = test_code_len + 1 |
580 |
|
Thurallor-7095 |
if test_code_len>maxCodeLen then |
581 |
|
Thurallor-7095 |
return nil, "Decompression error at "..tostring(i).."/"..tostring(#compressed) |
582 |
|
Thurallor-7095 |
end |
583 |
|
Thurallor-7095 |
end |
584 |
|
Thurallor-7095 |
else |
585 |
|
Thurallor-7095 |
c = string_byte(compressed, i) |
586 |
|
Thurallor-7095 |
bitfield = bitfield + bit_lshift(c or 0, bitfield_len) |
587 |
|
Thurallor-7095 |
bitfield_len = bitfield_len + 8 |
588 |
|
Thurallor-7095 |
if i > compressed_size then |
589 |
|
Thurallor-7095 |
break; |
590 |
|
Thurallor-7095 |
end |
591 |
|
Thurallor-7095 |
i = i + 1 |
592 |
|
Thurallor-7095 |
end |
593 |
|
Thurallor-7095 |
end |
594 |
|
Thurallor-7095 |
|
595 |
|
Thurallor-7095 |
setCleanupTables("Huffman_uncompressed", "Huffman_large_uncompressed") |
596 |
|
Thurallor-7095 |
return table_concat(large_uncompressed, "", 1, large_uncompressed_size)..table_concat(uncompressed, "", 1, uncompressed_size) |
597 |
|
Thurallor-7095 |
end |
598 |
|
Thurallor-7095 |
|
599 |
|
Thurallor-7095 |
-------------------------------------------------------------------------------- |
600 |
|
Thurallor-7095 |
-- Generic codec interface |
601 |
|
Thurallor-7095 |
|
602 |
|
Thurallor-7095 |
function LibCompress:DecompressUncompressed(data) |
603 |
|
Thurallor-7095 |
if type(data)~="string" then |
604 |
|
Thurallor-7095 |
return nil, "Can only handle strings" |
605 |
|
Thurallor-7095 |
end |
606 |
|
Thurallor-7095 |
if string.byte(data) ~= 1 then |
607 |
|
Thurallor-7095 |
return nil, "Can only handle uncompressed data" |
608 |
|
Thurallor-7095 |
end |
609 |
|
Thurallor-7095 |
return data:sub(2) |
610 |
|
Thurallor-7095 |
end |
611 |
|
Thurallor-7095 |
|
612 |
|
Thurallor-7095 |
local compression_methods = { |
613 |
|
Thurallor-7095 |
[2] = LibCompress.CompressLZW, |
614 |
|
Thurallor-7095 |
[3] = LibCompress.CompressHuffman |
615 |
|
Thurallor-7095 |
} |
616 |
|
Thurallor-7095 |
|
617 |
|
Thurallor-7095 |
local decompression_methods = { |
618 |
|
Thurallor-7095 |
[1] = LibCompress.DecompressUncompressed, |
619 |
|
Thurallor-7095 |
[2] = LibCompress.DecompressLZW, |
620 |
|
Thurallor-7095 |
[3] = LibCompress.DecompressHuffman |
621 |
|
Thurallor-7095 |
} |
622 |
|
Thurallor-7095 |
|
623 |
|
Thurallor-7095 |
-- try all compression codecs and return best result |
624 |
|
Thurallor-7095 |
function LibCompress:Compress(data) |
625 |
|
Thurallor-7095 |
local method = next(compression_methods) |
626 |
|
Thurallor-7095 |
local result = compression_methods[method](self, data); |
627 |
|
Thurallor-7095 |
local n; |
628 |
|
Thurallor-7095 |
method = next(compression_methods, method) |
629 |
|
Thurallor-7095 |
while method do |
630 |
|
Thurallor-7095 |
n = compression_methods[method](self, data) |
631 |
|
Thurallor-7095 |
if #n < #result then |
632 |
|
Thurallor-7095 |
result = n |
633 |
|
Thurallor-7095 |
end |
634 |
|
Thurallor-7095 |
method = next(compression_methods, method) |
635 |
|
Thurallor-7095 |
end |
636 |
|
Thurallor-7095 |
return result |
637 |
|
Thurallor-7095 |
end |
638 |
|
Thurallor-7095 |
|
639 |
|
Thurallor-7095 |
function LibCompress:Decompress(data) |
640 |
|
Thurallor-7095 |
local header_info = string.byte(data) |
641 |
|
Thurallor-7095 |
if decompression_methods[header_info] then |
642 |
|
Thurallor-7095 |
return decompression_methods[header_info](self, data) |
643 |
|
Thurallor-7095 |
else |
644 |
|
Thurallor-7095 |
return nil, "Unknown compression method ("..tostring(header_info)..")" |
645 |
|
Thurallor-7095 |
end |
646 |
|
Thurallor-7095 |
end |
647 |
|
Thurallor-7095 |
|
648 |
|
Thurallor-7095 |
---------------------------------------------------------------------- |
649 |
|
Thurallor-7095 |
---------------------------------------------------------------------- |
650 |
|
Thurallor-7095 |
-- |
651 |
|
Thurallor-7095 |
-- Encoding algorithms |
652 |
|
Thurallor-7095 |
|
653 |
|
Thurallor-7095 |
-------------------------------------------------------------------------------- |
654 |
|
Thurallor-7095 |
-- Prefix encoding algorithm |
655 |
|
Thurallor-7095 |
-- implemented by Galmok of European Stormrage (Horde), galmok@gmail.com |
656 |
|
Thurallor-7095 |
|
657 |
|
Thurallor-7095 |
--[[ |
658 |
|
Thurallor-7095 |
Howto: Encode and Decode: |
659 |
|
Thurallor-7095 |
|
660 |
|
Thurallor-7095 |
3 functions are supplied, 2 of them are variants of the first. They return a table with functions to encode and decode text. |
661 |
|
Thurallor-7095 |
|
662 |
|
Thurallor-7095 |
table, msg = LibCompress:GetEncodeTable(reservedChars, escapeChars, mapChars) |
663 |
|
Thurallor-7095 |
|
664 |
|
Thurallor-7095 |
reservedChars: The characters in this string will not appear in the encoded data. |
665 |
|
Thurallor-7095 |
escapeChars: A string of characters used as escape-characters (don't supply more than needed). #escapeChars >= 1 |
666 |
|
Thurallor-7095 |
mapChars: First characters in reservedChars maps to first characters in mapChars. (#mapChars <= #reservedChars) |
667 |
|
Thurallor-7095 |
|
668 |
|
Thurallor-7095 |
return value: |
669 |
|
Thurallor-7095 |
table |
670 |
|
Thurallor-7095 |
if nil then msg holds an error message, otherwise use like this: |
671 |
|
Thurallor-7095 |
|
672 |
|
Thurallor-7095 |
encoded_message = table:Encode(message) |
673 |
|
Thurallor-7095 |
message = table:Decode(encoded_message) |
674 |
|
Thurallor-7095 |
|
675 |
|
Thurallor-7095 |
GetAddonEncodeTable: Sets up encoding for the addon channel (\000 is encoded) |
676 |
|
Thurallor-7095 |
GetChatEncodeTable: Sets up encoding for the chat channel (many bytes encoded, see the function for details) |
677 |
|
Thurallor-7095 |
|
678 |
|
Thurallor-7095 |
Except for the mapped characters, all encoding will be with 1 escape character followed by 1 suffix, i.e. 2 bytes. |
679 |
|
Thurallor-7095 |
]] |
680 |
|
Thurallor-7095 |
-- to be able to match any requested byte value, the search string must be preprocessed |
681 |
|
Thurallor-7095 |
-- characters to escape with %: |
682 |
|
Thurallor-7095 |
-- ( ) . % + - * ? [ ] ^ $ |
683 |
|
Thurallor-7095 |
-- "illegal" byte values: |
684 |
|
Thurallor-7095 |
-- 0 is replaces %z |
685 |
|
Thurallor-7095 |
local gsub_escape_table = { |
686 |
|
Thurallor-7095 |
['\000'] = "%z", |
687 |
|
Thurallor-7095 |
[('(')] = "%(", |
688 |
|
Thurallor-7095 |
[(')')] = "%)", |
689 |
|
Thurallor-7095 |
[('.')] = "%.", |
690 |
|
Thurallor-7095 |
[('%')] = "%%", |
691 |
|
Thurallor-7095 |
[('+')] = "%+", |
692 |
|
Thurallor-7095 |
[('-')] = "%-", |
693 |
|
Thurallor-7095 |
[('*')] = "%*", |
694 |
|
Thurallor-7095 |
[('?')] = "%?", |
695 |
|
Thurallor-7095 |
[('[')] = "%[", |
696 |
|
Thurallor-7095 |
[(']')] = "%]", |
697 |
|
Thurallor-7095 |
[('^')] = "%^", |
698 |
|
Thurallor-7095 |
[('$')] = "%$" |
699 |
|
Thurallor-7095 |
} |
700 |
|
Thurallor-7095 |
|
701 |
|
Thurallor-7095 |
local function escape_for_gsub(str) |
702 |
|
Thurallor-7095 |
return str:gsub("([%z%(%)%.%%%+%-%*%?%[%]%^%$])", gsub_escape_table) |
703 |
|
Thurallor-7095 |
end |
704 |
|
Thurallor-7095 |
|
705 |
|
Thurallor-7095 |
function LibCompress:GetEncodeTable(reservedChars, escapeChars, mapChars) |
706 |
|
Thurallor-7095 |
reservedChars = reservedChars or "" |
707 |
|
Thurallor-7095 |
escapeChars = escapeChars or "" |
708 |
|
Thurallor-7095 |
mapChars = mapChars or "" |
709 |
|
Thurallor-7095 |
|
710 |
|
Thurallor-7095 |
-- select a default escape character |
711 |
|
Thurallor-7095 |
if escapeChars == "" then |
712 |
|
Thurallor-7095 |
return nil, "No escape characters supplied" |
713 |
|
Thurallor-7095 |
end |
714 |
|
Thurallor-7095 |
|
715 |
|
Thurallor-7095 |
if #reservedChars < #mapChars then |
716 |
|
Thurallor-7095 |
return nil, "Number of reserved characters must be at least as many as the number of mapped chars" |
717 |
|
Thurallor-7095 |
end |
718 |
|
Thurallor-7095 |
|
719 |
|
Thurallor-7095 |
if reservedChars == "" then |
720 |
|
Thurallor-7095 |
return nil, "No characters to encode" |
721 |
|
Thurallor-7095 |
end |
722 |
|
Thurallor-7095 |
|
723 |
|
Thurallor-7095 |
-- list of characters that must be encoded |
724 |
|
Thurallor-7095 |
encodeBytes = reservedChars..escapeChars..mapChars |
725 |
|
Thurallor-7095 |
|
726 |
|
Thurallor-7095 |
-- build list of bytes not available as a suffix to a prefix byte |
727 |
|
Thurallor-7095 |
local taken = {} |
728 |
|
Thurallor-7095 |
for i=1, strlen(encodeBytes) do |
729 |
|
Thurallor-7095 |
taken[string.sub(encodeBytes, i, i)] = true |
730 |
|
Thurallor-7095 |
end |
731 |
|
Thurallor-7095 |
|
732 |
|
Thurallor-7095 |
-- allocate a table to holde encode/decode strings/functions |
733 |
|
Thurallor-7095 |
local codecTable = {} |
734 |
|
Thurallor-7095 |
|
735 |
|
Thurallor-7095 |
-- the encoding can be a single gsub, but the decoding can require multiple gsubs |
736 |
|
Thurallor-7095 |
local decode_func_string = {} |
737 |
|
Thurallor-7095 |
|
738 |
|
Thurallor-7095 |
local encode_search = {} |
739 |
|
Thurallor-7095 |
local encode_translate = {} |
740 |
|
Thurallor-7095 |
local decode_search = {} |
741 |
|
Thurallor-7095 |
local decode_translate = {} |
742 |
|
Thurallor-7095 |
local c,r,i,to,from |
743 |
|
Thurallor-7095 |
local escapeCharIndex = 0 |
744 |
|
Thurallor-7095 |
|
745 |
|
Thurallor-7095 |
-- map single byte to single byte |
746 |
|
Thurallor-7095 |
if #mapChars > 0 then |
747 |
|
Thurallor-7095 |
for i=1, #mapChars do |
748 |
|
Thurallor-7095 |
from = string.sub(reservedChars, i, i) |
749 |
|
Thurallor-7095 |
to = string.sub(mapChars, i, i) |
750 |
|
Thurallor-7095 |
encode_translate[from] = to |
751 |
|
Thurallor-7095 |
table.insert(encode_search, from) |
752 |
|
Thurallor-7095 |
decode_translate[to] = from |
753 |
|
Thurallor-7095 |
table.insert(decode_search, to) |
754 |
|
Thurallor-7095 |
end |
755 |
|
Thurallor-7095 |
codecTable["decode_search"..tostring(escapeCharIndex)] = "([".. escape_for_gsub(table.concat(decode_search)).."])" |
756 |
|
Thurallor-7095 |
codecTable["decode_translate"..tostring(escapeCharIndex)] = decode_translate |
757 |
|
Thurallor-7095 |
tinsert(decode_func_string, "str = str:gsub(self.decode_search"..tostring(escapeCharIndex)..", self.decode_translate"..tostring(escapeCharIndex)..");") |
758 |
|
Thurallor-7095 |
|
759 |
|
Thurallor-7095 |
end |
760 |
|
Thurallor-7095 |
|
761 |
|
Thurallor-7095 |
-- map single byte to double-byte |
762 |
|
Thurallor-7095 |
escapeCharIndex = escapeCharIndex +1 |
763 |
|
Thurallor-7095 |
escapeChar = string.sub(escapeChars, escapeCharIndex, escapeCharIndex) |
764 |
|
Thurallor-7095 |
r = 0 -- suffix char value to the escapeChar |
765 |
|
Thurallor-7095 |
decode_search = {} |
766 |
|
Thurallor-7095 |
decode_translate = {} |
767 |
|
Thurallor-7095 |
for i = 1, strlen(encodeBytes) do |
768 |
|
Thurallor-7095 |
c = string.sub(encodeBytes, i, i) |
769 |
|
Thurallor-7095 |
if not encode_translate[c] then |
770 |
|
Thurallor-7095 |
-- this loop will update escapeChar and r |
771 |
|
Thurallor-7095 |
while r<256 and taken[string.char(r)] do |
772 |
|
Thurallor-7095 |
r=r+1 |
773 |
|
Thurallor-7095 |
if r>255 then -- switch to next escapeChar |
774 |
|
Thurallor-7095 |
if escapeChar == "" then -- we are out of escape chars and we need more! |
775 |
|
Thurallor-7095 |
return nil, "Out of escape characters" |
776 |
|
Thurallor-7095 |
end |
777 |
|
Thurallor-7095 |
|
778 |
|
Thurallor-7095 |
codecTable["decode_search"..tostring(escapeCharIndex)] = escape_for_gsub(escapeChar).."([".. escape_for_gsub(table.concat(decode_search)).."])" |
779 |
|
Thurallor-7095 |
codecTable["decode_translate"..tostring(escapeCharIndex)] = decode_translate |
780 |
|
Thurallor-7095 |
tinsert(decode_func_string, "str = str:gsub(self.decode_search"..tostring(escapeCharIndex)..", self.decode_translate"..tostring(escapeCharIndex)..");") |
781 |
|
Thurallor-7095 |
|
782 |
|
Thurallor-7095 |
escapeCharIndex = escapeCharIndex + 1 |
783 |
|
Thurallor-7095 |
escapeChar = string.sub(escapeChars, escapeCharIndex, escapeCharIndex) |
784 |
|
Thurallor-7095 |
|
785 |
|
Thurallor-7095 |
r = 0 |
786 |
|
Thurallor-7095 |
decode_search = {} |
787 |
|
Thurallor-7095 |
decode_translate = {} |
788 |
|
Thurallor-7095 |
end |
789 |
|
Thurallor-7095 |
end |
790 |
|
Thurallor-7095 |
encode_translate[c] = escapeChar..string.char(r) |
791 |
|
Thurallor-7095 |
table.insert(encode_search, c) |
792 |
|
Thurallor-7095 |
decode_translate[string.char(r)] = c |
793 |
|
Thurallor-7095 |
table.insert(decode_search, string.char(r)) |
794 |
|
Thurallor-7095 |
r = r + 1 |
795 |
|
Thurallor-7095 |
end |
796 |
|
Thurallor-7095 |
end |
797 |
|
Thurallor-7095 |
if r>0 then |
798 |
|
Thurallor-7095 |
codecTable["decode_search"..tostring(escapeCharIndex)] = escape_for_gsub(escapeChar).."([".. escape_for_gsub(table.concat(decode_search)).."])" |
799 |
|
Thurallor-7095 |
codecTable["decode_translate"..tostring(escapeCharIndex)] = decode_translate |
800 |
|
Thurallor-7095 |
tinsert(decode_func_string, "str = str:gsub(self.decode_search"..tostring(escapeCharIndex)..", self.decode_translate"..tostring(escapeCharIndex)..");") |
801 |
|
Thurallor-7095 |
end |
802 |
|
Thurallor-7095 |
|
803 |
|
Thurallor-7095 |
-- change last line from "str = ...;" to "return ...;"; |
804 |
|
Thurallor-7095 |
decode_func_string[#decode_func_string] = decode_func_string[#decode_func_string]:gsub("str = (.*);", "return %1;"); |
805 |
|
Thurallor-7095 |
decode_func_string = "return function(self, str) "..table.concat(decode_func_string).." end" |
806 |
|
Thurallor-7095 |
|
807 |
|
Thurallor-7095 |
encode_search = "([".. escape_for_gsub(table.concat(encode_search)).."])" |
808 |
|
Thurallor-7095 |
decode_search = escape_for_gsub(escapeChars).."([".. escape_for_gsub(table.concat(decode_search)).."])" |
809 |
|
Thurallor-7095 |
|
810 |
|
Thurallor-7095 |
encode_func = assert(loadstring("return function(self, str) return str:gsub(self.encode_search, self.encode_translate); end"))() |
811 |
|
Thurallor-7095 |
decode_func = assert(loadstring(decode_func_string))() |
812 |
|
Thurallor-7095 |
|
813 |
|
Thurallor-7095 |
codecTable.encode_search = encode_search |
814 |
|
Thurallor-7095 |
codecTable.encode_translate = encode_translate |
815 |
|
Thurallor-7095 |
codecTable.Encode = encode_func |
816 |
|
Thurallor-7095 |
codecTable.decode_search = decode_search |
817 |
|
Thurallor-7095 |
codecTable.decode_translate = decode_translate |
818 |
|
Thurallor-7095 |
codecTable.Decode = decode_func |
819 |
|
Thurallor-7095 |
|
820 |
|
Thurallor-7095 |
codecTable.decode_func_string = decode_func_string -- to be deleted |
821 |
|
Thurallor-7095 |
return codecTable |
822 |
|
Thurallor-7095 |
end |
823 |
|
Thurallor-7095 |
|
824 |
|
Thurallor-7095 |
-- Addons: Call this only once and reuse the returned table for all encodings/decodings. |
825 |
|
Thurallor-7095 |
function LibCompress:GetAddonEncodeTable(reservedChars, escapeChars, mapChars ) |
826 |
|
Thurallor-7095 |
reservedChars = reservedChars or "" |
827 |
|
Thurallor-7095 |
escapeChars = escapeChars or "" |
828 |
|
Thurallor-7095 |
mapChars = mapChars or "" |
829 |
|
Thurallor-7095 |
-- Following byte values are not allowed: |
830 |
|
Thurallor-7095 |
-- \000 |
831 |
|
Thurallor-7095 |
if escapeChars == "" then |
832 |
|
Thurallor-7095 |
escapeChars = "\001" |
833 |
|
Thurallor-7095 |
end |
834 |
|
Thurallor-7095 |
return self:GetEncodeTable( (reservedChars or "").."\000", escapeChars, mapChars) |
835 |
|
Thurallor-7095 |
end |
836 |
|
Thurallor-7095 |
|
837 |
|
Thurallor-7095 |
-- Addons: Call this only once and reuse the returned table for all encodings/decodings. |
838 |
|
Thurallor-7095 |
function LibCompress:GetChatEncodeTable(reservedChars, escapeChars, mapChars) |
839 |
|
Thurallor-7095 |
reservedChars = reservedChars or "" |
840 |
|
Thurallor-7095 |
escapeChars = escapeChars or "" |
841 |
|
Thurallor-7095 |
mapChars = mapChars or "" |
842 |
|
Thurallor-7095 |
-- Following byte values are not allowed: |
843 |
|
Thurallor-7095 |
-- \000, s, S, \010, \013, \124, % |
844 |
|
Thurallor-7095 |
-- Because SendChatMessage will error if an UTF8 multibyte character is incomplete, |
845 |
|
Thurallor-7095 |
-- all character values above 127 have to be encoded to avoid this. This costs quite a bit of bandwidth (about 13-14%) |
846 |
|
Thurallor-7095 |
-- Also, because drunken status is unknown for the received, strings used with SendChatMessage should be terminated with |
847 |
|
Thurallor-7095 |
-- an identifying byte value, after which the server MAY add "...hic!" or as much as it can fit(!). |
848 |
|
Thurallor-7095 |
-- Pass the identifying byte as a reserved character to this function to ensure the encoding doesn't contain that value. |
849 |
|
Thurallor-7095 |
-- or use this: local message, match = arg1:gsub("^(.*)\029.-$", "%1") |
850 |
|
Thurallor-7095 |
-- arg1 is message from channel, \029 is the string terminator, but may be used in the encoded datastream as well. :-) |
851 |
|
Thurallor-7095 |
-- This encoding will expand data anywhere from: |
852 |
|
Thurallor-7095 |
-- 0% (average with pure ascii text) |
853 |
|
Thurallor-7095 |
-- 53.5% (average with random data valued zero to 255) |
854 |
|
Thurallor-7095 |
-- 100% (only encoding data that encodes to two bytes) |
855 |
|
Thurallor-7095 |
local i |
856 |
|
Thurallor-7095 |
local r={} |
857 |
|
Thurallor-7095 |
for i=128, 255 do |
858 |
|
Thurallor-7095 |
table.insert(r, string.char(i)) |
859 |
|
Thurallor-7095 |
end |
860 |
|
Thurallor-7095 |
reservedChars = "sS\000\010\013\124%"..table.concat(r)..(reservedChars or "") |
861 |
|
Thurallor-7095 |
if escapeChars == "" then |
862 |
|
Thurallor-7095 |
escapeChars = "\029\031" |
863 |
|
Thurallor-7095 |
end |
864 |
|
Thurallor-7095 |
if mapChars == "" then |
865 |
|
Thurallor-7095 |
mapChars = "\015\020"; |
866 |
|
Thurallor-7095 |
end |
867 |
|
Thurallor-7095 |
return self:GetEncodeTable(reservedChars, escapeChars, mapChars) |
868 |
|
Thurallor-7095 |
end |
869 |
|
Thurallor-7095 |
|
870 |
|
Thurallor-7095 |
-------------------------------------------------------------------------------- |
871 |
|
Thurallor-7095 |
-- 7 bit encoding algorithm |
872 |
|
Thurallor-7095 |
-- implemented by Galmok of European Stormrage (Horde), galmok@gmail.com |
873 |
|
Thurallor-7095 |
|
874 |
|
Thurallor-7095 |
-- The encoded data holds values from 0 to 127 inclusive. Additional encoding may be necessary. |
875 |
|
Thurallor-7095 |
-- This algorithm isn't exactly fast and be used with care and consideration |
876 |
|
Thurallor-7095 |
|
877 |
|
Thurallor-7095 |
tables.encode7bit = {} |
878 |
|
Thurallor-7095 |
|
879 |
|
Thurallor-7095 |
function LibCompress:Encode7bit(str) |
880 |
|
Thurallor-7095 |
local remainder = 0; |
881 |
|
Thurallor-7095 |
local remainder_length = 0; |
882 |
|
Thurallor-7095 |
local tbl = tables.encode7bit |
883 |
|
Thurallor-7095 |
local encoded_size = 0 |
884 |
|
Thurallor-7095 |
local l=#str |
885 |
|
Thurallor-7095 |
for i=1,l do |
886 |
|
Thurallor-7095 |
code = string.byte(str, i) |
887 |
|
Thurallor-7095 |
remainder = remainder + bit_lshift(code, remainder_length) |
888 |
|
Thurallor-7095 |
remainder_length = 8 + remainder_length |
889 |
|
Thurallor-7095 |
while remainder_length>=7 do |
890 |
|
Thurallor-7095 |
encoded_size = encoded_size + 1 |
891 |
|
Thurallor-7095 |
tbl[encoded_size] = string_char(bit_band(remainder, 127)) |
892 |
|
Thurallor-7095 |
remainder = bit_rshift(remainder, 7) |
893 |
|
Thurallor-7095 |
remainder_length = remainder_length -7 |
894 |
|
Thurallor-7095 |
end |
895 |
|
Thurallor-7095 |
end |
896 |
|
Thurallor-7095 |
if remainder_length>0 then |
897 |
|
Thurallor-7095 |
encoded_size = encoded_size + 1 |
898 |
|
Thurallor-7095 |
tbl[encoded_size] = string_char(remainder) |
899 |
|
Thurallor-7095 |
end |
900 |
|
Thurallor-7095 |
setCleanupTables("encode7bit") |
901 |
|
Thurallor-7095 |
return table.concat(tbl, "", 1, encoded_size) |
902 |
|
Thurallor-7095 |
end |
903 |
|
Thurallor-7095 |
|
904 |
|
Thurallor-7095 |
tables.decode8bit = {} |
905 |
|
Thurallor-7095 |
|
906 |
|
Thurallor-7095 |
function LibCompress:Decode7bit(str) |
907 |
|
Thurallor-7095 |
local bit8 = tables.decode8bit |
908 |
|
Thurallor-7095 |
local decoded_size = 0 |
909 |
|
Thurallor-7095 |
local ch |
910 |
|
Thurallor-7095 |
local i=1 |
911 |
|
Thurallor-7095 |
local bitfield_len=0 |
912 |
|
Thurallor-7095 |
local bitfield=0 |
913 |
|
Thurallor-7095 |
local l=#str |
914 |
|
Thurallor-7095 |
while true do |
915 |
|
Thurallor-7095 |
if bitfield_len >=8 then |
916 |
|
Thurallor-7095 |
decoded_size = decoded_size + 1 |
917 |
|
Thurallor-7095 |
bit8[decoded_size] = string_char(bit.band(bitfield, 255)) |
918 |
|
Thurallor-7095 |
bitfield = bit_rshift(bitfield, 8) |
919 |
|
Thurallor-7095 |
bitfield_len = bitfield_len - 8 |
920 |
|
Thurallor-7095 |
end |
921 |
|
Thurallor-7095 |
ch=string_byte(str,i) |
922 |
|
Thurallor-7095 |
bitfield=bitfield+bit_lshift(ch or 0, bitfield_len) |
923 |
|
Thurallor-7095 |
bitfield_len = bitfield_len + 7 |
924 |
|
Thurallor-7095 |
if i > l then |
925 |
|
Thurallor-7095 |
break |
926 |
|
Thurallor-7095 |
end |
927 |
|
Thurallor-7095 |
i=i+1 |
928 |
|
Thurallor-7095 |
end |
929 |
|
Thurallor-7095 |
setCleanupTables("decode8bit") |
930 |
|
Thurallor-7095 |
return table.concat(bit8, "", 1, decoded_size) |
931 |
|
Thurallor-7095 |
end |
932 |
|
Thurallor-7095 |
|
933 |
|
Thurallor-7095 |
---------------------------------------------------------------------- |
934 |
|
Thurallor-7095 |
---------------------------------------------------------------------- |
935 |
|
Thurallor-7095 |
-- |
936 |
|
Thurallor-7095 |
-- Checksum/hash algorithms |
937 |
|
Thurallor-7095 |
|
938 |
|
Thurallor-7095 |
-------------------------------------------------------------------------------- |
939 |
|
Thurallor-7095 |
-- FCS16/32 checksum algorithms |
940 |
|
Thurallor-7095 |
-- converted from C by Galmok of European Stormrage (Horde), galmok@gmail.com |
941 |
|
Thurallor-7095 |
-- usage: |
942 |
|
Thurallor-7095 |
-- code = LibCompress:fcs16init() |
943 |
|
Thurallor-7095 |
-- code = LibCompress:fcs16update(code, data1) |
944 |
|
Thurallor-7095 |
-- code = LibCompress:fcs16update(code, data2) |
945 |
|
Thurallor-7095 |
-- code = LibCompress:fcs16update(code, data...) |
946 |
|
Thurallor-7095 |
-- code = LibCompress:fcs16final(code) |
947 |
|
Thurallor-7095 |
-- |
948 |
|
Thurallor-7095 |
-- data = string |
949 |
|
Thurallor-7095 |
-- fcs16 provides a 16 bit checksum, fcs32 provides a 32 bit checksum. |
950 |
|
Thurallor-7095 |
|
951 |
|
Thurallor-7095 |
|
952 |
|
Thurallor-7095 |
--[[/* The following copyright notice concerns only the FCS hash algorithm |
953 |
|
Thurallor-7095 |
--------------------------------------------------------------------------- |
954 |
|
Thurallor-7095 |
Copyright (c) 2003, Dominik Reichl <dominik.reichl@t-online.de>, Germany. |
955 |
|
Thurallor-7095 |
All rights reserved. |
956 |
|
Thurallor-7095 |
|
957 |
|
Thurallor-7095 |
Distributed under the terms of the GNU General Public License v2. |
958 |
|
Thurallor-7095 |
|
959 |
|
Thurallor-7095 |
This software is provided 'as is' with no explicit or implied warranties |
960 |
|
Thurallor-7095 |
in respect of its properties, including, but not limited to, correctness |
961 |
|
Thurallor-7095 |
and/or fitness for purpose. |
962 |
|
Thurallor-7095 |
--------------------------------------------------------------------------- |
963 |
|
Thurallor-7095 |
*/]] |
964 |
|
Thurallor-7095 |
--// FCS-16 algorithm implemented as described in RFC 1331 |
965 |
|
Thurallor-7095 |
local FCSINIT16 = 65535; |
966 |
|
Thurallor-7095 |
--// Fast 16 bit FCS lookup table |
967 |
|
Thurallor-7095 |
local fcs16tab = { [0]=0, 4489, 8978, 12955, 17956, 22445, 25910, 29887, |
968 |
|
Thurallor-7095 |
35912, 40385, 44890, 48851, 51820, 56293, 59774, 63735, |
969 |
|
Thurallor-7095 |
4225, 264, 13203, 8730, 22181, 18220, 30135, 25662, |
970 |
|
Thurallor-7095 |
40137, 36160, 49115, 44626, 56045, 52068, 63999, 59510, |
971 |
|
Thurallor-7095 |
8450, 12427, 528, 5017, 26406, 30383, 17460, 21949, |
972 |
|
Thurallor-7095 |
44362, 48323, 36440, 40913, 60270, 64231, 51324, 55797, |
973 |
|
Thurallor-7095 |
12675, 8202, 4753, 792, 30631, 26158, 21685, 17724, |
974 |
|
Thurallor-7095 |
48587, 44098, 40665, 36688, 64495, 60006, 55549, 51572, |
975 |
|
Thurallor-7095 |
16900, 21389, 24854, 28831, 1056, 5545, 10034, 14011, |
976 |
|
Thurallor-7095 |
52812, 57285, 60766, 64727, 34920, 39393, 43898, 47859, |
977 |
|
Thurallor-7095 |
21125, 17164, 29079, 24606, 5281, 1320, 14259, 9786, |
978 |
|
Thurallor-7095 |
57037, 53060, 64991, 60502, 39145, 35168, 48123, 43634, |
979 |
|
Thurallor-7095 |
25350, 29327, 16404, 20893, 9506, 13483, 1584, 6073, |
980 |
|
Thurallor-7095 |
61262, 65223, 52316, 56789, 43370, 47331, 35448, 39921, |
981 |
|
Thurallor-7095 |
29575, 25102, 20629, 16668, 13731, 9258, 5809, 1848, |
982 |
|
Thurallor-7095 |
65487, 60998, 56541, 52564, 47595, 43106, 39673, 35696, |
983 |
|
Thurallor-7095 |
33800, 38273, 42778, 46739, 49708, 54181, 57662, 61623, |
984 |
|
Thurallor-7095 |
2112, 6601, 11090, 15067, 20068, 24557, 28022, 31999, |
985 |
|
Thurallor-7095 |
38025, 34048, 47003, 42514, 53933, 49956, 61887, 57398, |
986 |
|
Thurallor-7095 |
6337, 2376, 15315, 10842, 24293, 20332, 32247, 27774, |
987 |
|
Thurallor-7095 |
42250, 46211, 34328, 38801, 58158, 62119, 49212, 53685, |
988 |
|
Thurallor-7095 |
10562, 14539, 2640, 7129, 28518, 32495, 19572, 24061, |
989 |
|
Thurallor-7095 |
46475, 41986, 38553, 34576, 62383, 57894, 53437, 49460, |
990 |
|
Thurallor-7095 |
14787, 10314, 6865, 2904, 32743, 28270, 23797, 19836, |
991 |
|
Thurallor-7095 |
50700, 55173, 58654, 62615, 32808, 37281, 41786, 45747, |
992 |
|
Thurallor-7095 |
19012, 23501, 26966, 30943, 3168, 7657, 12146, 16123, |
993 |
|
Thurallor-7095 |
54925, 50948, 62879, 58390, 37033, 33056, 46011, 41522, |
994 |
|
Thurallor-7095 |
23237, 19276, 31191, 26718, 7393, 3432, 16371, 11898, |
995 |
|
Thurallor-7095 |
59150, 63111, 50204, 54677, 41258, 45219, 33336, 37809, |
996 |
|
Thurallor-7095 |
27462, 31439, 18516, 23005, 11618, 15595, 3696, 8185, |
997 |
|
Thurallor-7095 |
63375, 58886, 54429, 50452, 45483, 40994, 37561, 33584, |
998 |
|
Thurallor-7095 |
31687, 27214, 22741, 18780, 15843, 11370, 7921, 3960 } |
999 |
|
Thurallor-7095 |
|
1000 |
|
Thurallor-7095 |
function LibCompress:fcs16init() |
1001 |
|
Thurallor-7095 |
return FCSINIT16; |
1002 |
|
Thurallor-7095 |
end |
1003 |
|
Thurallor-7095 |
|
1004 |
|
Thurallor-7095 |
function LibCompress:fcs16update(uFcs16, pBuffer) |
1005 |
|
Thurallor-7095 |
local i |
1006 |
|
Thurallor-7095 |
local l=string_len(pBuffer) |
1007 |
|
Thurallor-7095 |
for i = 1,l do |
1008 |
|
Thurallor-7095 |
uFcs16 = bit_bxor(bit_rshift(uFcs16,8), fcs16tab[bit_band(bit_bxor(uFcs16, string_byte(pBuffer,i)), 255)]) |
1009 |
|
Thurallor-7095 |
end |
1010 |
|
Thurallor-7095 |
return uFcs16 |
1011 |
|
Thurallor-7095 |
end |
1012 |
|
Thurallor-7095 |
|
1013 |
|
Thurallor-7095 |
function LibCompress:fcs16final(uFcs16) |
1014 |
|
Thurallor-7095 |
return bit_bxor(uFcs16,65535) |
1015 |
|
Thurallor-7095 |
end |
1016 |
|
Thurallor-7095 |
-- END OF FCS16 |
1017 |
|
Thurallor-7095 |
|
1018 |
|
Thurallor-7095 |
--[[/* |
1019 |
|
Thurallor-7095 |
--------------------------------------------------------------------------- |
1020 |
|
Thurallor-7095 |
Copyright (c) 2003, Dominik Reichl <dominik.reichl@t-online.de>, Germany. |
1021 |
|
Thurallor-7095 |
All rights reserved. |
1022 |
|
Thurallor-7095 |
|
1023 |
|
Thurallor-7095 |
Distributed under the terms of the GNU General Public License v2. |
1024 |
|
Thurallor-7095 |
|
1025 |
|
Thurallor-7095 |
This software is provided 'as is' with no explicit or implied warranties |
1026 |
|
Thurallor-7095 |
in respect of its properties, including, but not limited to, correctness |
1027 |
|
Thurallor-7095 |
and/or fitness for purpose. |
1028 |
|
Thurallor-7095 |
--------------------------------------------------------------------------- |
1029 |
|
Thurallor-7095 |
*/]] |
1030 |
|
Thurallor-7095 |
|
1031 |
|
Thurallor-7095 |
--// FCS-32 algorithm implemented as described in RFC 1331 |
1032 |
|
Thurallor-7095 |
|
1033 |
|
Thurallor-7095 |
local FCSINIT32 = -1 |
1034 |
|
Thurallor-7095 |
|
1035 |
|
Thurallor-7095 |
--// Fast 32 bit FCS lookup table |
1036 |
|
Thurallor-7095 |
local fcs32tab = { [0]=0, 1996959894, -301047508, -1727442502, 124634137, 1886057615, -379345611, -1637575261, |
1037 |
|
Thurallor-7095 |
249268274, 2044508324, -522852066, -1747789432, 162941995, 2125561021, -407360249, -1866523247, |
1038 |
|
Thurallor-7095 |
498536548, 1789927666, -205950648, -2067906082, 450548861, 1843258603, -187386543, -2083289657, |
1039 |
|
Thurallor-7095 |
325883990, 1684777152, -43845254, -1973040660, 335633487, 1661365465, -99664541, -1928851979, |
1040 |
|
Thurallor-7095 |
997073096, 1281953886, -715111964, -1570279054, 1006888145, 1258607687, -770865667, -1526024853, |
1041 |
|
Thurallor-7095 |
901097722, 1119000684, -608450090, -1396901568, 853044451, 1172266101, -589951537, -1412350631, |
1042 |
|
Thurallor-7095 |
651767980, 1373503546, -925412992, -1076862698, 565507253, 1454621731, -809855591, -1195530993, |
1043 |
|
Thurallor-7095 |
671266974, 1594198024, -972236366, -1324619484, 795835527, 1483230225, -1050600021, -1234817731, |
1044 |
|
Thurallor-7095 |
1994146192, 31158534, -1731059524, -271249366, 1907459465, 112637215, -1614814043, -390540237, |
1045 |
|
Thurallor-7095 |
2013776290, 251722036, -1777751922, -519137256, 2137656763, 141376813, -1855689577, -429695999, |
1046 |
|
Thurallor-7095 |
1802195444, 476864866, -2056965928, -228458418, 1812370925, 453092731, -2113342271, -183516073, |
1047 |
|
Thurallor-7095 |
1706088902, 314042704, -1950435094, -54949764, 1658658271, 366619977, -1932296973, -69972891, |
1048 |
|
Thurallor-7095 |
1303535960, 984961486, -1547960204, -725929758, 1256170817, 1037604311, -1529756563, -740887301, |
1049 |
|
Thurallor-7095 |
1131014506, 879679996, -1385723834, -631195440, 1141124467, 855842277, -1442165665, -586318647, |
1050 |
|
Thurallor-7095 |
1342533948, 654459306, -1106571248, -921952122, 1466479909, 544179635, -1184443383, -832445281, |
1051 |
|
Thurallor-7095 |
1591671054, 702138776, -1328506846, -942167884, 1504918807, 783551873, -1212326853, -1061524307, |
1052 |
|
Thurallor-7095 |
-306674912, -1698712650, 62317068, 1957810842, -355121351, -1647151185, 81470997, 1943803523, |
1053 |
|
Thurallor-7095 |
-480048366, -1805370492, 225274430, 2053790376, -468791541, -1828061283, 167816743, 2097651377, |
1054 |
|
Thurallor-7095 |
-267414716, -2029476910, 503444072, 1762050814, -144550051, -2140837941, 426522225, 1852507879, |
1055 |
|
Thurallor-7095 |
-19653770, -1982649376, 282753626, 1742555852, -105259153, -1900089351, 397917763, 1622183637, |
1056 |
|
Thurallor-7095 |
-690576408, -1580100738, 953729732, 1340076626, -776247311, -1497606297, 1068828381, 1219638859, |
1057 |
|
Thurallor-7095 |
-670225446, -1358292148, 906185462, 1090812512, -547295293, -1469587627, 829329135, 1181335161, |
1058 |
|
Thurallor-7095 |
-882789492, -1134132454, 628085408, 1382605366, -871598187, -1156888829, 570562233, 1426400815, |
1059 |
|
Thurallor-7095 |
-977650754, -1296233688, 733239954, 1555261956, -1026031705, -1244606671, 752459403, 1541320221, |
1060 |
|
Thurallor-7095 |
-1687895376, -328994266, 1969922972, 40735498, -1677130071, -351390145, 1913087877, 83908371, |
1061 |
|
Thurallor-7095 |
-1782625662, -491226604, 2075208622, 213261112, -1831694693, -438977011, 2094854071, 198958881, |
1062 |
|
Thurallor-7095 |
-2032938284, -237706686, 1759359992, 534414190, -2118248755, -155638181, 1873836001, 414664567, |
1063 |
|
Thurallor-7095 |
-2012718362, -15766928, 1711684554, 285281116, -1889165569, -127750551, 1634467795, 376229701, |
1064 |
|
Thurallor-7095 |
-1609899400, -686959890, 1308918612, 956543938, -1486412191, -799009033, 1231636301, 1047427035, |
1065 |
|
Thurallor-7095 |
-1362007478, -640263460, 1088359270, 936918000, -1447252397, -558129467, 1202900863, 817233897, |
1066 |
|
Thurallor-7095 |
-1111625188, -893730166, 1404277552, 615818150, -1160759803, -841546093, 1423857449, 601450431, |
1067 |
|
Thurallor-7095 |
-1285129682, -1000256840, 1567103746, 711928724, -1274298825, -1022587231, 1510334235, 755167117 } |
1068 |
|
Thurallor-7095 |
|
1069 |
|
Thurallor-7095 |
function LibCompress:fcs32init() |
1070 |
|
Thurallor-7095 |
return FCSINIT32; |
1071 |
|
Thurallor-7095 |
end |
1072 |
|
Thurallor-7095 |
|
1073 |
|
Thurallor-7095 |
function LibCompress:fcs32update(uFcs32, pBuffer) |
1074 |
|
Thurallor-7095 |
local i |
1075 |
|
Thurallor-7095 |
local l=string_len(pBuffer) |
1076 |
|
Thurallor-7095 |
for i = 1,l do |
1077 |
|
Thurallor-7095 |
uFcs32 = bit_bxor(bit_rshift(uFcs32,8), fcs32tab[bit_band(bit_bxor(uFcs32, string_byte(pBuffer,i)), 255)]) |
1078 |
|
Thurallor-7095 |
end |
1079 |
|
Thurallor-7095 |
return uFcs32 |
1080 |
|
Thurallor-7095 |
end |
1081 |
|
Thurallor-7095 |
|
1082 |
|
Thurallor-7095 |
function LibCompress:fcs32final(uFcs32) |
1083 |
|
Thurallor-7095 |
return bit_bnot(uFcs32) |
1084 |
|
Thurallor-7095 |
end |