mirror of
https://github.com/pkulchenko/serpent.git
synced 2024-11-21 23:24:24 +00:00
Fixed (properly this time) order of elements in the array part (fixes #13).
This commit is contained in:
parent
7d56d50a9c
commit
ca4140a2d1
@ -1,4 +1,4 @@
|
||||
local n, v = "serpent", 0.261 -- (C) 2012-13 Paul Kulchenko; MIT License
|
||||
local n, v = "serpent", 0.262 -- (C) 2012-13 Paul Kulchenko; MIT License
|
||||
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
|
||||
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
|
||||
local badtype = {thread = true, userdata = true, cdata = true}
|
||||
@ -34,9 +34,9 @@ local function s(t, opts)
|
||||
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
|
||||
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
|
||||
table.sort(k, function(a,b)
|
||||
-- sort numeric keys first: `o[key] == key and type(key) == 'number'` is true for numeric keys
|
||||
return (o[a] == a and type(a) == 'number' and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
|
||||
< (o[b] == b and type(b) == 'number' and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
|
||||
-- sort numeric keys first: k[key] is not nil for numerical keys
|
||||
return (k[a] ~= nil and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
|
||||
< (k[b] ~= nil and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
|
||||
local function val2str(t, name, indent, insref, path, plainindex, level)
|
||||
local ttype, level, mt = type(t), (level or 0), getmetatable(t)
|
||||
local spath, sname = safename(path, name)
|
||||
|
88
t/test.lua
88
t/test.lua
@ -290,14 +290,94 @@ do
|
||||
local f = assert(loadstring('return '..serpent.line(a)),
|
||||
"serializing table with numerical and boolean keys: failed")
|
||||
local _a = f()
|
||||
assert(#_a == #a, "table with array and hash part has the right number of elements: failed")
|
||||
assert(_a[3] == a[3], "table with array and hash parts has the right order of elements 1/2: failed")
|
||||
assert(_a[4] == a[4], "table with array and hash parts has the right order of elements 2/2: failed")
|
||||
assert(#_a == #a, "table with array and hash parts has the right number of elements: failed")
|
||||
assert(_a[3] == a[3], "table with array and hash parts has the right order of elements 1/4: failed")
|
||||
assert(_a[4] == a[4], "table with array and hash parts has the right order of elements 2/4: failed")
|
||||
|
||||
a = {1, [0] = 0}
|
||||
f = assert(loadstring('return '..serpent.line(a)),
|
||||
"serializing table with two numerical keys: failed")
|
||||
local _a = f()
|
||||
assert(_a[1] == 1, "table with array and hash parts has the right order of elements 3/4: failed")
|
||||
assert(_a[0] == 0, "table with array and hash parts has the right order of elements 4/4: failed")
|
||||
end
|
||||
|
||||
-- based on https://gist.github.com/mpeterv/8360307
|
||||
local function random_var(is_key, deep)
|
||||
local key = math.random(1000)
|
||||
|
||||
if key <= 100 then
|
||||
return is_key and 0 or nil
|
||||
elseif key <= 200 then
|
||||
return false
|
||||
elseif key <= 500 then
|
||||
return math.random(-1e6, 1e6)
|
||||
elseif key <= 900 then
|
||||
local len = math.random(0, 100)
|
||||
local res = {}
|
||||
|
||||
for i=1, len do
|
||||
table.insert(res, string.char(math.random(65, 90)))
|
||||
end
|
||||
|
||||
return table.concat(res)
|
||||
else
|
||||
if deep > 3 or is_key then
|
||||
return 0
|
||||
else
|
||||
local len = math.random(0, 10)
|
||||
local res = {}
|
||||
|
||||
for i=1, len do
|
||||
if math.random(0, 1) == 0 then
|
||||
table.insert(res, random_var(false, deep+1))
|
||||
else
|
||||
res[random_var(true, deep+1)] = random_var(false, deep+1)
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function deepsame(a1, a2)
|
||||
if type(a1) == type(a2) and type(a1) == 'table' then
|
||||
local e1, e2
|
||||
while true do
|
||||
e1, e2 = next(a1, e1), next(a2, e2)
|
||||
-- looped through all the elements and they are the same
|
||||
if e1 == nil and e2 == nil then return true end
|
||||
local res
|
||||
if e1 == e2 then
|
||||
res = deepsame(a1[e1], a2[e2])
|
||||
else
|
||||
res = deepsame(a1[e1], a2[e1]) and deepsame(a1[e2], a2[e2])
|
||||
end
|
||||
-- found two different elements
|
||||
if not res then return false end
|
||||
end
|
||||
end
|
||||
return type(a1) == type(a2) and a1 == a2
|
||||
end
|
||||
|
||||
do
|
||||
local seed = os.time()
|
||||
math.randomseed(seed)
|
||||
|
||||
local max = 100
|
||||
for i = 1, max do
|
||||
local x = random_var(false, 0)
|
||||
local s = serpent.block(x)
|
||||
local ok, x2 = serpent.load(s)
|
||||
assert(ok, ("deserialization of randomly generated values %d/%d (seed=%d): failed"):format(i, max, seed))
|
||||
assert(deepsame(x, x2),
|
||||
("randomly generated values are the same after deserialization %d/%d (seed=%d): failed"):format(i, max, seed))
|
||||
end
|
||||
end
|
||||
|
||||
print("All tests passed.")
|
||||
|
||||
do
|
||||
if arg[1] == 'perf' then
|
||||
print("\nSerializing large numeric-only tables:")
|
||||
|
||||
local a, str = {}
|
||||
|
Loading…
Reference in New Issue
Block a user