mirror of
https://github.com/araxiaonline/ets-module-collection.git
synced 2026-06-13 02:52:20 -04:00
128 lines
3.2 KiB
Lua
128 lines
3.2 KiB
Lua
-- LibCompress.lua
|
|
--
|
|
-- Authors: jjsheets and Galmok of European Stormrage (Horde)
|
|
-- Email: sheets.jeff@gmail.com and galmok@gmail.com
|
|
-- Licence: GPL version 2 (General Public License)
|
|
--
|
|
-- Hacked severely by Taehl (SelfMadeSpirit@gmail.com)
|
|
----------------------------------------------------------------------------------
|
|
|
|
assert(not TLibCompress, "LibCompress already loaded. Possibly loading different versions of LibCompress")
|
|
|
|
TLibCompress = {}
|
|
|
|
local assert = assert
|
|
local type = type
|
|
local unpack = unpack or table.unpack
|
|
local tconcat = table.concat
|
|
local schar = string.char
|
|
local ssub = string.sub
|
|
local sbyte = string.byte
|
|
local mmodf = math.modf
|
|
local floor = floor or math.floor
|
|
|
|
local function encode(x)
|
|
local bytes = {}
|
|
local xmod
|
|
repeat
|
|
x, xmod = mmodf(x/255)
|
|
xmod = xmod * 255
|
|
bytes[#bytes + 1] = xmod
|
|
until x <= 0
|
|
if #bytes == 1 and bytes[1] > 0 and bytes[1] < 250 then
|
|
return schar(bytes[1])
|
|
else
|
|
for i = 1, #bytes do bytes[i] = bytes[i] + 1 end
|
|
return schar(256 - #bytes, unpack(bytes))
|
|
end
|
|
end
|
|
|
|
local function decode(ss,i)
|
|
i = i or 1
|
|
local a = sbyte(ss,i,i)
|
|
if a > 249 then
|
|
local r = 0
|
|
a = 256 - a
|
|
for n = i+a, i+1, -1 do
|
|
r = r * 255 + sbyte(ss,n,n) - 1
|
|
end
|
|
return r, a + 1
|
|
else
|
|
return a, 1
|
|
end
|
|
end
|
|
|
|
function TLibCompress.CompressLZW(uncompressed)
|
|
assert(type(uncompressed) == 'string')
|
|
local result = {'\222'}
|
|
local ressize = 1
|
|
local w = ''
|
|
local dict = {}
|
|
local dict_size = 256
|
|
for i = 0, 255 do
|
|
dict[schar(i)] = i
|
|
end
|
|
for i = 1, #uncompressed do
|
|
local c = ssub(uncompressed,i,i)
|
|
local wc = w..c
|
|
if dict[wc] then
|
|
w = wc
|
|
else
|
|
dict[wc] = dict_size
|
|
dict_size = dict_size +1
|
|
local r = encode(dict[w])
|
|
ressize = ressize + #r
|
|
result[#result + 1] = r
|
|
w = c
|
|
end
|
|
end
|
|
if w then
|
|
local r = encode(dict[w])
|
|
ressize = ressize + #r
|
|
result[#result + 1] = r
|
|
end
|
|
if (#uncompressed+1) > ressize then
|
|
return tconcat(result)
|
|
else
|
|
return '\1'..uncompressed
|
|
end
|
|
end
|
|
|
|
function TLibCompress.DecompressLZW(compressed)
|
|
assert(type(compressed) == 'string')
|
|
local UC
|
|
UC, compressed = ssub(compressed,1,1), ssub(compressed, 2)
|
|
if UC == '\1' then
|
|
return compressed
|
|
end
|
|
if UC ~= "\222" then
|
|
return nil, "Can only decompress LZW compressed data ("..tostring(UC)..")"
|
|
end
|
|
local dict_size = 256
|
|
local dict = {}
|
|
for i = 0, 255 do
|
|
dict[i] = schar(i)
|
|
end
|
|
local result = {}
|
|
local t = 1
|
|
local delta, k
|
|
k, delta = decode(compressed,t)
|
|
t = t + delta
|
|
result[#result+1] = dict[k]
|
|
local w = dict[k]
|
|
local entry
|
|
local csize = #compressed
|
|
while t <= csize do
|
|
k, delta = decode(compressed,t)
|
|
t = t + delta
|
|
entry = dict[k] or (w..ssub(w,1,1))
|
|
result[#result+1] = entry
|
|
dict[dict_size] = w..ssub(entry,1,1)
|
|
dict_size = dict_size + 1
|
|
w = entry
|
|
end
|
|
return tconcat(result)
|
|
end
|
|
|
|
return TLibCompress
|