Search code examples
c++luaescapingraw-data

Storing Lua script in Lua


I have an application written in C++ that can show, edit and run Lua scripts. This application stores everthing, including the full Lua scripts in a project file.

The problem here is that the project file's format is also a Lua file, written from C++ (it's not a Lua engine writing the project file).

Example Lua script in editor:

-- Message
local message =
[["First" line
Second line
Last line]]

Now, I want to save the script above in a lua file. Example project file:

-- Project file
projectName = "test"
options = {}
options.autoRun = false

-- Lua source
luaScript =
[=[
-- Message
local message =
[["First" line
Second line
Last line]]
]=]

I can of course enclose the Lua script in [=[ ... ]=] (as in the example) but if the script also contains the same sequence, it will not work. Since the script is an arbitrary script written by the user, I can't just asume that a certain sequence hasn't been used.

Is there a way to include "raw" data such as the CData in XML? I would try to avoid encoding the script because I want it to be readable in the project file.

The easiest would be if the [ and ] characters could be escaped, but apparantly the can't.

I could break up the script in individual strings, escape it and concatenate them:

-- Project file
projectName = "test"
options = {}
options.autoRun = false

-- Lua source
luaScript = "-- Message\n"..
            "local message =\n"..
            "[[\"First\" line\n"..
            "Second line\n"..
            "Last line]]\n"..

But this solution wouldn't be easy to read and edit directly in the project file.

If this isn't possible, then it's good to get it confirmed and I would brobably go with an encoding scheme instead as plan B.

SOLUTION
After exploring some options and indeas I went with the solution based on lhf's suggestion. I have written some C++ to Lua writer classes so when I write a string I check if it is a multiline string. If it is I just insert [====================================================================[ -- MULLTILINE BEGIN\r\n in the front and appends the string with \r\n]====================================================================] -- MULLTILINE END, no need to escape the string. If it's a single line string I don't add anything, only escape it.

The reason to add CR/LF pairs and comments is to make it eas for the user to edit the script straight in teh project file.

script =
[====================================================================[ -- MULLTILINE BEGIN
-- Lua script engine 5.3.4
function onData(data,ch)
  print("A 'String' within a \"string\" within a [===[string]===]")
end

-- Multiline within Multiline
a = [=[
Spicy jalapeno bacon ipsum dolor amet ground round eu chicken,
venison turkey corned beef dolore exercitation pastrami nostrud
prosciutto in drumstick deserunt meatloaf. Pastrami jowl beef
ribs minim eu pariatur est et lorem kielbasa shoulder. Dolore
officia cupidatat, biltong tempor ut ham kielbasa magna bacon
salami. Turducken tri-tip tail reprehenderit tenderloin aliquip.
]=]

print(a)
]====================================================================] -- MULLTILINE END

When reading back the string I simply look for the -- MULTILINE BEGIN\r\n at the first line. If it's there I simply remove the line including the CR/LF pair and the last CR/LF pair at the end. Since the -- MULLTILINE END it's a comment outside the multiline, it will not be a part of the string and doesn't need to be removed, only the added CR/LF pair before the end sequence.


Solution

  • You can use as many = as needed in a long string quote [====[. Just find the longest run of = in a string and add one =.

    You can also use %q in string.format, which will quote all characters that need quoting.