How to make encode and decode functions as I want? - lua

--encode
function strToBytes(str)
local bytes = { str:byte(1, -1)
for i = 1, #bytes do
bytes[i] = bytes[i] + 100
end
return table.concat(bytes, ',')
end
--decode
function bytesToStr(str)
local function gsub(c)return string.char(c - 100) end
return str:gsub('(%d+),?', gsub) end
implemented :
str = "hello world"
strbyte = strToBytes(str)
bytestr = bytesToStr(strbyte)
print(strbyte)
Output :
204,201,208,208,211,132,219,211,214,208,200
print(bytestr)
Output :
"Hello world"
Hi, I need improving my code above. Actually encode and decode functions is work fine, but I need a little bit change.
I want to make encode functions similar like code above, but, the results is table like below :
{204,201,208,208,211,132,219,211,214,208,200}
Then, same as like my first decode functions, all bytes inside the table should be back to "hello world".
I hope my purpose and explanation above is easy to understand. Thanks in advance for any help and suggestions.
Update explanation :
It is a little bit complicated to explain what is my purposes. But I will try to explain as good as I can.
I am trying to make scripts encoder. Encode functions is in encoder scripts side, and decode function is in encoded scripts side. So I must write concatenate decode function before encoded string.
To clearly my explanation, encoder scripts will load undecode source code.
file = io.open(path, "r")
local data = file:read("*l")
The problem is, table cant concatenate with string.
local data = encode(str)--the result is byte array
local data = "decode("..data..")"
file:write(data)
file:close()
local data = string.dump(load(data),true,true)
My first purpose is to hide some important string, because string.dump result is not hide all string.
My second purpose is, to make an obsfucated code using byteArray.
Any solution or suggestion?
SOLVED
function strToBytes(str)
local byteArray= { str:byte(1, -1) }
for i = 1, #byteArray do
byteArray[i] = byteArray[i] + 100
encoded = '{' ..table.concat(byteArray, ',') .. '}'
end
return "load(string.dump(load(bytesToStr("..encoded.."))))()\n"
end
Thank you so much... 👍

Your code was very close to what you were looking for.
--encode
function strToBytes(str)
local byteArray= { str:byte(1, -1) }
for i = 1, #byteArray do
byteArray[i] = byteArray[i] + 100
end
return '{' .. table.concat(byteArray, ',') .. '}'
end
For the encode I removed the table.concat and now just return the byteArray
--decode
function bytesToStr(byteArray)
local output = "" --initialize output variable
for _,b in ipairs(byteArray) do --use ipairs to preserve order
output = output .. string.char(b - 100) --convert each byte to a char and add to output
end
return output
end
For the decode I use a for loop with ipairs to iterate over each byte and concatenate the values into an output variable.
-- test
str = "hello world!"
strbyte = strToBytes(str)
bytestr = 'return bytesToStr(' .. strbyte .. ')'
strBack = string.dump(load(bytestr),true,true)
print(strbyte)
print(bytestr)
print(load(strBack)())
Test output:
{204,201,208,208,211,132,219,211,214,208,200,133}
return bytesToStr({204,201,208,208,211,132,219,211,214,208,200,133})
hello world!

Related

Lua: replace a substring

I have something like
str = "What a wonderful string //011// this is"
I have to replace the //011// with something like convertToRoman(011) and then get
str = "What a wonderful string XI this is"
However, the conversion into roman numbers is no problem here.
It is also possible that the string str didn't has a //...//. In this case it should simply return the same string.
function convertSTR(str)
if not string.find(str,"//") then
return str
else
replace //...// with convertToRoman(...)
end
return str
end
I know that I can use string.find to get the complete \\...\\ sequence. Is there an easier solution with pattern matching or something similiar?
string.gsub accepts a function as a replacement. So, this should work
new = str:gsub("//(.-)//", convertToRoman)
I like LPEG, therefore here is a solution with LPEG:
local lpeg = require"lpeg"
local C, Ct, P, R = lpeg.C, lpeg.Ct, lpeg.P, lpeg.R
local convert = function(x)
return "ROMAN"
end
local slashed = P"//" * (R("09")^1 / convert) * P"//"
local other = C((1 - slashed)^0)
local grammar = Ct(other * (slashed * other)^0)
print(table.concat(grammar:match("What a wonderful string //011// this is"),""))

Lua, Modify print function

I am writing a generic Log() function in lua which utilizes lua print function:
Log (variable, 'String: %s ', str, 'Word: %d', w)
Currently I'm using below approach:
print(string.format (variable, 'String: %s ', str, 'Word: %d', w))
I tried something like:
Log = function(...) begin
return print(string.format(...))
end
But it doesn't work, Is this correct approach? Or Is there any better more generic way to get this done?
If you just want to print a sequence of values, you can do that with print:
print(variable, 'String: %s ', str, 'Word: %d', w)
What you seem to want is something more complicated. Your algorithm seems to be:
For each argument:
If the argument is not a string, then convert it to a string and print it.
If the argument is a string, figure out how many % patterns it has (let us call this number k). Pass string.format the current argument string and the following k parameters, printing the resulting string. Advance k parameters.
That's a much more complicated algorithm than can be done in a one-line system.
Using Lua 5.3, here's what such a function would look like (note: barely tested code):
function Log(...)
local values = {}
local params = table.pack(...)
local curr_ix = 1
while (curr_ix <= params.n) do
local value = params[curr_ix]
if(type(value) == "string") then
--Count the number of `%` characters, *except* for
--sequential `%%`.
local num_formats = 0
for _ in value:gmatch("%%[^%%]") do
num_formats = num_formats + 1
end
value = string.format(table.unpack(params, curr_ix, num_formats + curr_ix))
curr_ix = curr_ix + num_formats
end
values[#values + 1] = value
curr_ix = curr_ix + 1
end
print(table.unpack(values))
end
I don't think your current approach works, because the first argument of string.format expects the format specifier, not the rest of the arguments.
Anyway, this is the way to combine formatting and printing together:
Log = function(...)
return print(string.format(...))
end
And call it like this:
Log("String: %s Number: %d", 'hello' , 42)
Also, it might be better to make the format specifier argument more explicit, and use io.write instead of print to get more control over printing:
function Log(fmt, ...)
return io.write(string.format(fmt, ...))
end

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.
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)
The code you provided should not run at all.
You define function LZWCompressor.new() but call CLZWCompression.new()
Inside Encode you call self:InitDictionary(true) which has not been defined.
Maybe you did not paste all relevant code here.
The reason for the error you get though is that you call compressor:Encode(sInput) which is equivalent to compressor.Encode(self, sInput). (syntactic sugar) As function parameters are not passed by name but by their position sInput inside Encode is now compressor, not your string.
Your first argument (which happens to be self, a table) is then passed to string.len which expects a string.
So you acutally call string.len(compressor) which of course results in an error.
Please make sure you know how to call and define functions and how to use self properly!

Lua - util_server.lua:440 attempt to index local 'self' (a nil value)

Good evening
Will you help me solve this problem?
ERROR: race/util_server.lua:440: attempt to index local 'self' (a nil value)
function string:split(separator)
if separator == '.' then
separator = '%.'
end
local result = {}
for part in self:gmatch('(.-)' .. separator) do
result[#result+1] = part
end
result[#result+1] = self:match('.*' .. separator .. '(.*)$') or self
return result
end
You're probably calling it wrong.
function string:split(separator)
Is short hand for:
function string.split(self, separator)
Given a string and separator:
s = 'This is a test'
separator = ' '
You need to call it like this:
string.split(s, separator)
Or:
s:split(separator)
If you call it like this:
s.split(separator)
You're failing to provide a value for the self argument.
Side note, you can write split more simply like this:
function string:split(separators)
local result = {}
for part in self:gmatch('[^'..separators..']+') do
result[#result + 1] = part
end
return result
end
This has the disadvantage that you can't used multi-character strings as delimiters, but the advantage that you can specify more than one delimiter. For instance, you could strip all the punctuation from a sentence and grab just the words:
s = 'This is an example: homemade, freshly-baked pies are delicious!'
for _,word in pairs(s:split(' :.,!-')) do
print(word)
end
Output:
This
is
an
example
homemade
freshly
baked
pies
are
delicious

Decompressing LZW in Lua [duplicate]

Here is the Pseudocode for Lempel-Ziv-Welch Compression.
pattern = get input character
while ( not end-of-file ) {
K = get input character
if ( <<pattern, K>> is NOT in
the string table ){
output the code for pattern
add <<pattern, K>> to the string table
pattern = K
}
else { pattern = <<pattern, K>> }
}
output the code for pattern
output EOF_CODE
I am trying to code this in Lua, but it is not really working. Here is the code I modeled after an LZW function in Python, but I am getting an "attempt to call a string value" error on line 8.
function compress(uncompressed)
local dict_size = 256
local dictionary = {}
w = ""
result = {}
for c in uncompressed do
-- while c is in the function compress
local wc = w + c
if dictionary[wc] == true then
w = wc
else
dictionary[w] = ""
-- Add wc to the dictionary.
dictionary[wc] = dict_size
dict_size = dict_size + 1
w = c
end
-- Output the code for w.
if w then
dictionary[w] = ""
end
end
return dictionary
end
compressed = compress('TOBEORNOTTOBEORTOBEORNOT')
print (compressed)
I would really like some help either getting my code to run, or helping me code the LZW compression in Lua. Thank you so much!
Assuming uncompressed is a string, you'll need to use something like this to iterate over it:
for i = 1, #uncompressed do
local c = string.sub(uncompressed, i, i)
-- etc
end
There's another issue on line 10; .. is used for string concatenation in Lua, so this line should be local wc = w .. c.
You may also want to read this with regard to the performance of string concatenation. Long story short, it's often more efficient to keep each element in a table and return it with table.concat().
You should also take a look here to download the source for a high-performance LZW compression algorithm in Lua...

Resources