Nathan Schneider c927b4d9fc Major refactoring (big thanks to OldCoder) enabling CLI and local storage and cleaner modpol/MT split | 3 anni fa | |
---|---|---|
.. | ||
LICENSE.txt | 3 anni fa | |
README.md | 3 anni fa | |
serpent-git.tar.bz2 | 3 anni fa | |
serpent.lua | 3 anni fa |
Lua serializer and pretty printer.
{'a', 'b'}
instead of {[1] = 'a', [2] = 'b'}
).nil
values are included when expected ({1, nil, 3}
instead of {1, [3]=3}
).{foo = 'foo'}
instead of {['foo'] = 'foo'}
).loadstring()
.string.dump()
.__tostring
and __serialize
metamethods.\010
and end-of-file control \026
characters in strings.local serpent = require("serpent")
local a = {1, nil, 3, x=1, ['true'] = 2, [not true]=3}
a[a] = a -- self-reference with a table as key and value
print(serpent.dump(a)) -- full serialization
print(serpent.line(a)) -- single line, no self-ref section
print(serpent.block(a)) -- multi-line indented, no self-ref section
local fun, err = loadstring(serpent.dump(a))
if err then error(err) end
local copy = fun()
-- or using serpent.load:
local ok, copy = serpent.load(serpent.dump(a))
print(ok and copy[3] == a[3])
Serpent provides three functions that are shortcuts to the same internal function, but set different options by default:
dump(a[, {...}])
-- full serialization; sets name
, compact
and sparse
options;line(a[, {...}])
-- single line pretty printing, no self-ref section; sets sortkeys
and comment
options;block(a[, {...}])
-- multi-line indented pretty printing, no self-ref section; sets indent
, sortkeys
, and comment
options.Note that line
and block
functions return pretty-printed data structures and if you want to deserialize them, you need to add return
before running them through loadstring
.
For example: loadstring('return '..require('mobdebug').line("foo"))() == "foo"
.
While you can use loadstring
or load
functions to load serialized fragments, Serpent also provides load
function that adds safety checks and reports an error if there is any executable code in the fragment.
ok, res = serpent.load(str[, {safe = true}])
-- loads serialized fragment; you need to pass {safe = false}
as the second value if you want to turn safety checks off.Similar to pcall
and loadstring
calls, load
returns status as the first value and the result or the error message as the second value.
maxlevel
of depth).#t
).__tostring
metamethod when serializing tables (v0.29);
set to false
to disable and serialize the table as is, even when __tostring
is present.These options can be provided as a second parameter to Serpent functions.
block(a, {fatal = true})
line(a, {nocode = true, valignore = {[arrayToIgnore] = true}})
function todiff(a) return dump(a, {nocode = true, indent = ' '}) end
Serpent functions set these options to different default values:
dump
sets compact
and sparse
to true
;line
sets sortkeys
and comment
to true
;block
sets sortkeys
and comment
to true
and indent
to ' '
.If a table or a userdata value has __tostring
or __serialize
method, the method will be used to serialize the value.
If __serialize
method is present, it will be called with the value as a parameter.
if __serialize
method is not present, but __tostring
is, then tostring
will be called with the value as a parameter.
In both cases, the result will be serialized, so __serialize
method can return a table, that will be serialize and replace the original value.
A custom sort function can be provided to sort the contents of tables. The function takes 2 parameters, the first being the table (a list) with the keys, the second the original table. It should modify the first table in-place, and return nothing. For example, the following call will apply a sort function identical to the standard sort, except that it will not distinguish between lower- and uppercase.
local mysort = function(k, o) -- k=keys, o=original table
local maxn, to = 12, {number = 'a', string = 'b'}
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
local sort = function(a,b)
-- this -vvvvvvvvvv- is needed to sort array keys first
return ((k[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))):upper()
< ((k[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum))):upper()
end
table.sort(k, sort)
end
local content = { some = 1, input = 2, To = 3, serialize = 4 }
local result = require('serpent').block(content, {sortkeys = mysort})
Serpent supports a way to provide a custom formatter that allows to fully customize the output. The formatter takes four values:
{
and associated indentation and newline (if any),}
and associated indentation and newline (if any), andFor example, the following call will apply `Foo{bar} notation to its output (used by Metalua to display ASTs):
print((require "serpent").block(ast, {comment = false, custom =
function(tag,head,body,tail)
local out = head..body..tail
if tag:find('^lineinfo') then
out = out:gsub("\n%s+", "") -- collapse lineinfo to one line
elseif tag == '' then
body = body:gsub('%s*lineinfo = [^\n]+', '')
local _,_,atag = body:find('tag = "(%w+)"%s*$')
if atag then
out = "`"..atag..head.. body:gsub('%s*tag = "%w+"%s*$', '')..tail
out = out:gsub("\n%s+", ""):gsub(",}","}")
else out = head..body..tail end
end
return tag..out
end}))
io.*
table).A simple performance test against serialize.lua
from metalua, pretty.write
from Penlight, and tserialize.lua
from lua-nucleo is included in t/bench.lua
.
These are the results from one of the runs:
Serpent does additional processing to escape \010
and \026
characters in
strings (to address http://lua-users.org/lists/lua-l/2007-07/msg00362.html,
which is already fixed in Lua 5.2) and to check all numbers for math.huge
.
The seconds number excludes this processing to put it on an equal footing
with other modules that skip these checks (nucleo
still checks for math.huge
).
Paul Kulchenko (paul@kulchenko.com)
See LICENSE file.
pairs
to avoid using __pairs
in Lua 5.2+.metatostring
option to disable __tostring
processing during serialization.level
to the parameters of the custom function (closes #25).maxlength
option to limit the space taken by table elements.nocode
option is specified.__serialize
check failing (pkulchenko/ZeroBraneStudio#732).keyignore
option for the serializer.debug.metatable
when available.__tostring
(pkulchenko/ZeroBraneStudio#446).tostring
for Lua 5.3 support (pkulchenko/ZeroBraneStudio#401).tostring
for Lua 5.3 with LUA_NOCVTN2S
set (pkulchenko/ZeroBraneStudio#401).sortkeys=true
(fixes #13).load
function to deserialize; updated documentation (closes #9).load
function that (safely) loads serialized/pretty-printed values.maxnum
option to limit the number of elements in tables.getmetatable(ffi.C)
as true
.cdata
type in LuaJIT (thanks to Evan).keyallow
and valtypeignore
options (thanks to Jess Telford).ignore
to valignore
.ignore
option to allow ignoring table values.comment=num
option to set the max level up to which add comments.comment
option.['3']
getting mixed
with real numeric keys (only with sortkeys
option set to true
).maxlevel
option.true
and 'true'
are always sorted in
the same order (for a more stable output).goto
to the list of keywords for Lua 5.2.math.huge
to 1/0 for better portability.