chore: refractor
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
-- Module by 1waffle1 and boatbomber, optimized and fixed by iiau
|
||||
-- https://devforum.roblox.com/t/text-compression/163637/37
|
||||
|
||||
local dictionary = {} -- key to len
|
||||
|
||||
do -- populate dictionary
|
||||
local length = 0
|
||||
for i = 32, 127 do
|
||||
if i ~= 34 and i ~= 92 then
|
||||
local c = string.char(i)
|
||||
dictionary[c] = length
|
||||
dictionary[length] = c
|
||||
length = length + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local escapemap_126, escapemap_127 = {}, {}
|
||||
local unescapemap_126, unescapemap_127 = {}, {}
|
||||
|
||||
local blacklisted_126 = { 34, 92 }
|
||||
for i = 126, 180 do
|
||||
table.insert(blacklisted_126, i)
|
||||
end
|
||||
|
||||
do -- Populate escape map
|
||||
-- represents the numbers 0-31, 34, 92, 126, 127 (36 characters)
|
||||
-- and 128-180 (52 characters)
|
||||
-- https://devforum.roblox.com/t/text-compression/163637/5
|
||||
for i = 0, 31 + #blacklisted_126 do
|
||||
local b = blacklisted_126[i - 31]
|
||||
local s = i + 32
|
||||
|
||||
-- Note: 126 and 127 are magic numbers
|
||||
local c = string.char(b or i)
|
||||
local e = string.char(s + (s >= 34 and 1 or 0) + (s >= 91 and 1 or 0))
|
||||
|
||||
escapemap_126[c] = e
|
||||
unescapemap_126[e] = c
|
||||
end
|
||||
|
||||
for i = 1, 255 - 180 do
|
||||
local c = string.char(i + 180)
|
||||
local s = i + 34
|
||||
local e = string.char(s + (s >= 92 and 1 or 0))
|
||||
|
||||
escapemap_127[c] = e
|
||||
unescapemap_127[e] = c
|
||||
end
|
||||
end
|
||||
|
||||
local function escape(s)
|
||||
-- escape the control characters 0-31, double quote 34, backslash 92, Tilde 126, and DEL 127 (36 chars)
|
||||
-- escape characters 128-180 (53 chars)
|
||||
return string.gsub(string.gsub(s, '[%c"\\\126-\180]', function(c)
|
||||
return "\126" .. escapemap_126[c]
|
||||
end), '[\181-\255]', function(c)
|
||||
return "\127" .. escapemap_127[c]
|
||||
end)
|
||||
end
|
||||
local function unescape(s)
|
||||
return string.gsub(string.gsub(s, "\127(.)", function(e)
|
||||
return unescapemap_127[e]
|
||||
end), "\126(.)", function(e)
|
||||
return unescapemap_126[e]
|
||||
end)
|
||||
end
|
||||
|
||||
local b93Cache = {}
|
||||
local function tobase93(n)
|
||||
local value = b93Cache[n]
|
||||
if value then
|
||||
return value
|
||||
end
|
||||
|
||||
local c = n
|
||||
value = ""
|
||||
repeat
|
||||
local remainder = n % 93
|
||||
value = dictionary[remainder] .. value
|
||||
n = (n - remainder) / 93
|
||||
until n == 0
|
||||
|
||||
b93Cache[c] = value
|
||||
return value
|
||||
end
|
||||
|
||||
local b10Cache = {}
|
||||
local function tobase10(value)
|
||||
local n = b10Cache[value]
|
||||
if n then
|
||||
return n
|
||||
end
|
||||
|
||||
n = 0
|
||||
for i = 1, #value do
|
||||
n = n + math.pow(93, i - 1) * dictionary[string.sub(value, -i, -i)]
|
||||
end
|
||||
|
||||
b10Cache[value] = n
|
||||
return n
|
||||
end
|
||||
|
||||
local function compress(text)
|
||||
assert(type(text) == "string", "bad argument #1 to 'compress' (string expected, got " .. typeof(text) .. ")")
|
||||
local dictionaryCopy = table.clone(dictionary)
|
||||
local key, sequence, size = "", {}, #dictionary
|
||||
|
||||
local width, spans, span = 1, {}, 0
|
||||
local function listkey(k)
|
||||
local value = tobase93(dictionaryCopy[k])
|
||||
local valueLength = #value
|
||||
if valueLength > width then
|
||||
width, span, spans[width] = valueLength, 0, span
|
||||
end
|
||||
table.insert(sequence, string.rep(" ", width - valueLength) .. value)
|
||||
span += 1
|
||||
end
|
||||
text = escape(text)
|
||||
for i = 1, #text do
|
||||
local c = string.sub(text, i, i)
|
||||
local new = key .. c
|
||||
if dictionaryCopy[new] then
|
||||
key = new
|
||||
else
|
||||
listkey(key)
|
||||
key = c
|
||||
size += 1
|
||||
dictionaryCopy[new] = size
|
||||
dictionaryCopy[size] = new
|
||||
end
|
||||
end
|
||||
listkey(key)
|
||||
spans[width] = span
|
||||
return table.concat(spans, ",") .. "|" .. table.concat(sequence)
|
||||
end
|
||||
|
||||
local function decompress(text)
|
||||
assert(type(text) == "string", "bad argument #1 to 'decompress' (string expected, got " .. typeof(text) .. ")")
|
||||
local dictionaryCopy = table.clone(dictionary)
|
||||
local sequence, spans, content = {}, string.match(text, "(.-)|(.*)")
|
||||
local groups, start = {}, 1
|
||||
for span in string.gmatch(spans, "%d+") do
|
||||
local width = #groups + 1
|
||||
groups[width] = string.sub(content, start, start + span * width - 1)
|
||||
start = start + span * width
|
||||
end
|
||||
local previous
|
||||
|
||||
for width, group in ipairs(groups) do
|
||||
for value in string.gmatch(group, string.rep(".", width)) do
|
||||
local entry = dictionaryCopy[tobase10(value)]
|
||||
if previous then
|
||||
if entry then
|
||||
table.insert(dictionaryCopy, previous .. string.sub(entry, 1, 1))
|
||||
else
|
||||
entry = previous .. string.sub(previous, 1, 1)
|
||||
table.insert(dictionaryCopy, entry)
|
||||
end
|
||||
table.insert(sequence, entry)
|
||||
else
|
||||
sequence[1] = entry
|
||||
end
|
||||
previous = entry
|
||||
end
|
||||
end
|
||||
return unescape(table.concat(sequence))
|
||||
end
|
||||
|
||||
return { compress = compress, decompress = decompress }
|
||||
Reference in New Issue
Block a user