31

I have a big string (a base64 encoded image) and it is 1050 characters long. How can I append a big string formed of small ones, like this in C

 function GetIcon()
    return "Bigggg string 1"\
"continuation of string"\
"continuation of string"\
"End of string"
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
bratao
  • 1,980
  • 3
  • 21
  • 38

5 Answers5

43

According to Programming in Lua 2.4 Strings:

We can delimit literal strings also by matching double square brackets [[...]]. Literals in this bracketed form may run for several lines, may nest, and do not interpret escape sequences. Moreover, this form ignores the first character of the string when this character is a newline. This form is especially convenient for writing strings that contain program pieces; for instance,

page = [[
<HTML>
<HEAD>
<TITLE>An HTML Page</TITLE>
</HEAD>
<BODY>
 <A HREF="http://www.lua.org">Lua</A>
 [[a text between double brackets]]
</BODY>
</HTML>
]]

This is the closest thing to what you are asking for, but using the above method keeps the newlines embedded in the string, so this will not work directly.

You can also do this with string concatenation (using ..):

value = "long text that" ..
      " I want to carry over" ..
      "onto multiple lines"
Xavi
  • 20,111
  • 14
  • 72
  • 63
crashmstr
  • 28,043
  • 9
  • 61
  • 79
  • 4
    I'd comment against using `..` too much: Every single concatenation spawns a new string, which potentially can seriously harm performance. If you do want to put lots of tiny chunks together, putting them in a table and using `table.concat` is a better approach. – jpjacobs Jul 25 '11 at 08:15
  • 5
    Every NEW concatention spawns a new string, but multiple concatentations in one string are done all at once ==> look at the luac output for the above; there will only be 1 CONCAT opcode. – daurnimator Nov 08 '11 at 01:24
  • Is it possible to keep `[[ ... ]]` when writing to a `.lua` file? – NeoZoom.lua Apr 07 '23 at 17:55
18

Most answers here solves this issue at run-time and not at compile-time.

Lua 5.2 introduces the escape sequence \z to solve this problem elegantly without incurring any run-time expense.

> print "This is a long \z
>>                                string with \z
>>      breaks in between, \z
>> and is spanning multiple lines \z
>> but still is a single string only!"
This is a long string with breaks in between, and is spanning multiple lines but still is a single string only!

\z skips all subsequent characters in a string literal1 until the first non-space character. This works for non-multiline literal text too.

> print "This is a simple \z                string"
This is a simple string

From Lua 5.2 Reference Manual

The escape sequence '\z' skips the following span of white-space characters, including line breaks; it is particularly useful to break and indent a long literal string into multiple lines without adding the newlines and spaces into the string contents.

1: All escape sequences, including \z, work only on short literal strings ("…", '…') and, understandably, not on long literal strings ([[...]], etc.)

legends2k
  • 31,634
  • 25
  • 118
  • 222
  • Note for anyone who tries this. It apparently does not work with the `[[`, `]]` variation. – Faheem Mitha Jun 01 '19 at 18:12
  • Of course, if _shouldn't_ work for _long string literals_, since it's used to make raw strings e.g. to construct regular expression, etc. It's one of the main points of long string literals when the programmer needs more control. Excerpt [from spec](https://www.lua.org/manual/5.3/manual.html#3.1): `A long literal [...] can run for several lines, do not interpret any escape sequences`. – legends2k Jun 02 '19 at 03:54
5

I'd put all chunks in a table and use table.concat on it. This avoids the creation of new strings at every concatenation. for example (without counting overhead for strings in Lua):

             -- bytes used
foo="1234".. --          4  = 4
    "4567".. -- 4  + 4 + 8  = 16
    "89ab"   -- 16 + 4 + 12 = 32
             -- |    |    |    \_ grand total after concatenation on last line
             -- |    |    \_ second operand of concatenation
             -- |    \_ first operand of concatenation
             -- \_ total size used until last concatenation

As you can see, this explodes pretty rapidly. It's better to:

foo=table.concat{
"1234",
"4567",
"89ab"}

Which will take about 3*4+12=24 bytes.

jpjacobs
  • 9,359
  • 36
  • 45
  • Table concatenation may be great to conserve memory, but it will be about 4x slower than using pure string concatenation. – devius Aug 27 '15 at 21:28
1

Have you tried the string.sub(s, i [, j]) function. You may like to look here:

http://lua-users.org/wiki/StringLibraryTutorial

A. K.
  • 34,395
  • 15
  • 52
  • 89
  • I wonder how this is helpful; the OPs question is to build a long string from smaller ones and not the other way around, which is what this answers - getting smaller strings from a bigger one `string.sub`. – legends2k Aug 06 '14 at 07:55
1

This:

    return "Bigggg string 1"\
"continuation of string"\
"continuation of string"\
"End of string"

C/C++ syntax causes the compiler to see it all as one large string. It is generally used for readability.

The Lua equivalent would be:

    return "Bigggg string 1" ..
"continuation of string" ..
"continuation of string" ..
"End of string"

Do note that the C/C++ syntax is compile-time, while the Lua equivalent likely does the concatenation at runtime (though the compiler could theoretically optimize it). It shouldn't be a big deal though.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982