From 82a4aee176041f6f3fc8987ed07c68ac73baebf4 Mon Sep 17 00:00:00 2001 From: Paul Kulchenko Date: Wed, 13 Jun 2012 11:07:59 -0700 Subject: [PATCH] Fixed an issue with string keys with numeric values `['3']` getting mixed with real numeric keys --- README.md | 4 ++++ src/serpent.lua | 8 ++++---- t/test.lua | 8 +++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4bf25c0..79b0ff7 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,10 @@ See LICENSE file. ## History +Jun 13 2012 v0.14 + - Fixed an issue with string keys with numeric values `['3']` getting mixed + with real numeric keys (only with `sortkeys` option set to `true`). + Jun 13 2012 v0.13 - Added maxlevel option. - Fixed key sorting such that `true` and `'true'` are always sorted in diff --git a/src/serpent.lua b/src/serpent.lua index 6785ca3..4a6f50e 100644 --- a/src/serpent.lua +++ b/src/serpent.lua @@ -1,4 +1,4 @@ -local n, v = "serpent", 0.13 -- (C) 2012 Paul Kulchenko; MIT License +local n, v = "serpent", 0.14 -- (C) 2012 Paul Kulchenko; MIT License local c, d = "Paul Kulchenko", "Serializer and pretty printer of Lua data types" 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} @@ -29,11 +29,11 @@ local function s(t, opts) local safe = plain and n or '['..safestr(n)..']' return (path or '')..(plain and path and '.' or '')..safe, safe end local function alphanumsort(o, n) - local maxn = tonumber(n) or 12 + local maxn, torder = tonumber(n) or 12, {number = 'a', string = 'b'} local function padnum(d) return ("%0"..maxn.."d"):format(d) end table.sort(o, function(a,b) - return tostring(a):gsub("%d+",padnum)..type(a) - < tostring(b):gsub("%d+",padnum)..type(b) end) end + return (torder[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum)) + < (torder[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end local function val2str(t, name, indent, path, plainindex, level) local ttype, level = type(t), (level or 0) local spath, sname = safename(path, name) diff --git a/t/test.lua b/t/test.lua index 72d8f99..b127323 100644 --- a/t/test.lua +++ b/t/test.lua @@ -16,7 +16,7 @@ local a = { ['true'] = 'some value', -- keyword as a key z = c, -- function as value list={'a',nil,nil, -- embedded nils - [9]='i','f',[5]='g',[7]={}}, -- empty table + [9]='i','f',[5]='g',[7]={}, ['3'] = 33}, -- empty table [c] = print, -- function as key, global as value [io.stdin] = 3, -- global userdata as key ['label 2'] = b, -- shared reference @@ -31,8 +31,10 @@ print("line: " .. serpent.line(a) .. "\n") local str = serpent.dump(a) print("full: " .. str .. "\n") -local fun, err = loadstring(str) -if err then error(err) end +local fun, err = assert(loadstring(str)) + +assert(loadstring(serpent.line(a, {name = '_'})), "line() method produces deserializable output: failed") +assert(loadstring(serpent.block(a, {name = '_'})), "block() method produces deserializable output: failed") local _a = fun() local _b = _a['label 2'] -- shared reference