lualiteral

lualiteral

function lualiteral( value [, alias] ) --> str

Description

It creates a string containig a string representation of the argument. The string will contain a valid Lua literal, so the same limitation of the Lua parser holds:

  • Only nil, boolean, number, string or table value are allowed, no userdata or lightuserdata

  • The table must no contain any cycle

  • The table have a limited nested level size (200)

The case of table with two (or more) contents pointing to the same camera can not be written as Lua literal. However this function will support such cases generating two (or more) different tables with the same content. Cycles are still not supported.

Optionally this function let you to substitute all the references to a particular table with a supplied string. In this way also circular table may somehow handled.

Parameters

value

The Lua value you want to serialize as Lua literal.

alias

A table containig a map from other table to strings. When serializing the value, each sub-table will be subtituded by the string in the alias table (if any).

Return Values

str

The string containig a Lua literal representing the value passed as argument.

Code

--ZFUNC-lualiteral-v0
local function lualiteral( value, alias ) --> str
   --TODO
   -- export ???
   local function atomdump( val )
      local t = type( val )
      if "nil" == t then
         return 'nil'
      elseif "number" == t then
         return tostring( val )
      elseif "boolean" == t then
         return tostring( val )
      elseif "string" ~= t then
         val = tostring( val )
      end
      return string.format( "%q", val )
   end

   local function lualiteral_rec( cur, alias, result )

      if "table" ~= type( cur ) then
         table.insert( result, atomdump( cur ) )
      else

      -- If a table alias is defined, use that name
      local substitute
      if alias then substitute = alias[ cur ] end
      if substitute then
         table.insert( result, substitute )
      else

         -- Recurse over each key and each value
         table.insert( result, "{" )
         for k, v in pairs( cur ) do
            table.insert( result, "[" )
            lualiteral_rec( k, alias, result )
            table.insert( result, "]=" )
            lualiteral_rec( v, alias, result )
            table.insert( result, "," )
         end
         table.insert( result, "}" )
         end
      end

      return result
   end

   local result = lualiteral_rec( value, alias, {} )
   return table.concat( result )
end

return lualiteral

Examples

local t = require "taptest"
local lualiteral = require "lualiteral"

-- Plain types
t( lualiteral( nil ), "nil" )
t( lualiteral( true ), "true" )
t( lualiteral( 1 ), "1" )
t( lualiteral( "ok" ), '"ok"' )

-- Table type
t( lualiteral( {} ), "{}" )
t( lualiteral( { false } ), "{[1]=false,}" )
t( lualiteral( { a = true } ), '{["a"]=true,}' )
t( lualiteral( { b = 'hi' } ), '{["b"]="hi",}' )
t( lualiteral( { c = 1 } ), '{["c"]=1,}' )
t( lualiteral( { d = {} } ), '{["d"]={},}' )

-- String quoting
local astr = '"\n\r\0'
t( lualiteral( astr ), string.format( "%q", astr ) )

-- Sub-table
t( lualiteral( { e = { f = true } } ), '{["e"]={["f"]=true,},}' )

-- Table key
t( lualiteral( { [ { k = "k" } ] = true } ), '{[{["k"]="k",}]=true,}' )

-- Same tables are exapande
local atab = { t = "t" }
t( lualiteral( { atab, atab } ), '{[1]={["t"]="t",},[2]={["t"]="t",},}' )

-- Table alias support
local alias = {}
alias[ atab ] = "X"
t( lualiteral( { atab, atab }, alias ), '{[1]=X,[2]=X,}' )

-- Mix example
atab = {
   a = "a",
   b = { "c", "d", { e = "f" } },
   [ { [ "g" ] = true } ] = { [true] = "h", },
   ["i"] = atab,
}
local recon = lualiteral( atab, alias )
local function patterncheck(a, b) return (nil ~= a:match(b)) end

t( recon, '%["a"%]="a",', patterncheck )
t( recon, '%["b"%]={%[1%]="c",%[2%]="d",%[3%]={%["e"%]="f",},},', patterncheck )
t( recon, '%[{%["g"%]=true,}%]={%[true%]="h",},', patterncheck )
t( recon, '%["i"%]=X,', patterncheck )

t()

See also