Search code examples
luacompressionlzw

Simple LZW Compression doesnt work


I wrote simple class to compress data. Here it is:

LZWCompressor = {}
function LZWCompressor.new()
  local self = {}
  self.mDictionary = {}
  self.mDictionaryLen = 0
  -- ...
  self.Encode = function(sInput)
    self:InitDictionary(true)
    local s = ""
    local ch = ""
    local len = string.len(sInput)
    local result = {}   
    local dic = self.mDictionary
    local temp = 0
    for i = 1, len do
        ch = string.sub(sInput, i, i)
        temp = s..ch
        if dic[temp] then
            s = temp
        else
            result[#result + 1] = dic[s]
            self.mDictionaryLen = self.mDictionaryLen + 1   
            dic[temp] = self.mDictionaryLen         
            s = ch
        end
    end
    result[#result + 1] = dic[s]
    return result
  end
  -- ...
  return self
end

And i run it by:

local compressor = LZWCompression.new()
local encodedData = compressor:Encode("I like LZW, but it doesnt want to compress this text.")


print("Input length:",string.len(originalString))
print("Output length:",#encodedData)


local decodedString = compressor:Decode(encodedData)
print(decodedString)
print(originalString == decodedString)

But when i finally run it by lua, it shows that interpreter expected string, not Table. That was strange thing, because I pass argument of type string. To test Lua's logs, i wrote at beggining of function:

print(typeof(sInput))

I got output "Table" and lua's error. So how to fix it? Why lua displays that string (That i have passed) is a table? I use Lua 5.3.


Solution

  • Issue is in definition of method Encode(), and most likely Decode() has same problem.
    You create Encode() method using dot syntax: self.Encode = function(sInput),
    but then you're calling it with colon syntax: compressor:Encode(data)
    When you call Encode() with colon syntax, its first implicit argument will be compressor itself (table from your error), not the data.
    To fix it, declare Encode() method with colon syntax: function self:Encode(sInput), or add 'self' as first argument explicitly self.Encode = function(self, sInput)