mirror of
https://github.com/pkulchenko/serpent.git
synced 2024-11-21 23:24:24 +00:00
Fixed an issue with mixed tables that may be missing keys.
Earlier optimization depended on incorrect assumption that `next` can be started by using #t, which is not the case.
This commit is contained in:
parent
29d2e11920
commit
a4e258cb77
@ -11,7 +11,7 @@ for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'})
|
||||
for k,v in pairs(G[g]) do globals[v] = g..'.'..k end end
|
||||
|
||||
local function s(t, opts)
|
||||
local name, indent, fatal = opts.name, opts.indent, opts.fatal
|
||||
local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
|
||||
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
|
||||
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
|
||||
local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge)
|
||||
@ -54,11 +54,14 @@ local function s(t, opts)
|
||||
if level >= maxl then return tag..'{}'..comment('max', level) end
|
||||
seen[t] = insref or spath
|
||||
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
|
||||
local maxn, o, out, maxt = math.min(#t, opts.maxnum or #t), {}, {}, #t > 0 and #t or nil
|
||||
local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
|
||||
for key = 1, maxn do o[key] = key end
|
||||
for key in next, t, maxt do if not o[key] or key > maxn then o[#o+1] = key end end
|
||||
if opts.sortkeys and next(t, maxt) ~= nil then alphanumsort(o, t, opts.sortkeys) end
|
||||
if opts.maxnum and #o > opts.maxnum then o[opts.maxnum+1] = nil end
|
||||
if not maxnum or #o < maxnum then
|
||||
local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
|
||||
for key in pairs(t) do if o[key] ~= key then n = n + 1; o[n] = key end end end
|
||||
if maxnum and #o > maxnum then o[maxnum+1] = nil end
|
||||
if opts.sortkeys and #o > maxn then alphanumsort(o, t, opts.sortkeys) end
|
||||
local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
|
||||
for n, key in ipairs(o) do
|
||||
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
|
||||
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
|
||||
|
44
t/test.lua
44
t/test.lua
@ -235,4 +235,48 @@ do
|
||||
assert(#_a.b == 2, "table with maxnum=3 has no more than 3 elements 3/3: failed")
|
||||
end
|
||||
|
||||
-- test serialization of mixed tables
|
||||
do
|
||||
local a = {a='a', b='b', c='c', [3]=3, [2]=2,[1]=1}
|
||||
local diffable = {sortkeys = true, comment = false, nocode = true, indent = ' '}
|
||||
local _a = assert(loadstring(serpent.dump(a, diffable)))()
|
||||
|
||||
for k,v in pairs(a) do
|
||||
assert(v == _a[k],
|
||||
("mixed table with sorted keys (key = '%s'): failed"):format(k))
|
||||
end
|
||||
end
|
||||
|
||||
-- test sorting is not called on numeric-only tables
|
||||
do
|
||||
local a = {1,2,3,4,5}
|
||||
local called = false
|
||||
local sortfunc = function() called = true end
|
||||
|
||||
serpent.dump(a, {sortkeys = sortfunc, sparse = false})
|
||||
assert(called == false, "sorting is not called on numeric-only tables: failed")
|
||||
|
||||
called = false
|
||||
serpent.dump(a, {sortkeys = sortfunc, sparse = false, maxnum = 3})
|
||||
assert(called == false, "sorting is not called on numeric-only tables with maxnum: failed")
|
||||
end
|
||||
|
||||
-- test serializing large numeric-only tables
|
||||
do
|
||||
local a, str = {}
|
||||
for i = 1, 100000 do a[i] = i end
|
||||
|
||||
local start = os.clock()
|
||||
str = serpent.dump(a)
|
||||
print("dump: "..(os.clock() - start), #str)
|
||||
|
||||
start = os.clock()
|
||||
str = serpent.dump(a, {maxnum = 400})
|
||||
print("dump/maxnum: "..(os.clock() - start), #str)
|
||||
|
||||
start = os.clock()
|
||||
str = serpent.dump(a, {sparse = false})
|
||||
print("dump/sparse=false: "..(os.clock() - start), #str)
|
||||
end
|
||||
|
||||
print("All tests passed.")
|
||||
|
Loading…
Reference in New Issue
Block a user