lotrointerface.com
Search Downloads

LoTROInterface SVN SequenceBars

[/] [trunk/] [Thurallor/] [Common/] [Utils/] [LibCompress/] [LibCompress.lua.bak] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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

All times are GMT -5. The time now is 02:57 PM.


Our Network
EQInterface | EQ2Interface | Minion | WoWInterface | ESOUI | LoTROInterface | MMOUI | Swtorui