Files
awakening-lua/AIO_Server/LibCompress.lua
2024-05-17 23:27:34 +00:00

128 lines
3.3 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