diff options
Diffstat (limited to 'tex/context/base/mkiv/util-tab.lua')
-rw-r--r-- | tex/context/base/mkiv/util-tab.lua | 170 |
1 files changed, 74 insertions, 96 deletions
diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua index a6239adf4..fb2702228 100644 --- a/tex/context/base/mkiv/util-tab.lua +++ b/tex/context/base/mkiv/util-tab.lua @@ -12,7 +12,7 @@ local tables = utilities.tables local format, gmatch, gsub, sub = string.format, string.gmatch, string.gsub, string.sub local concat, insert, remove, sort = table.concat, table.insert, table.remove, table.sort -local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring +local setmetatable, getmetatable, tonumber, tostring, rawget = setmetatable, getmetatable, tonumber, tostring, rawget local type, next, rawset, tonumber, tostring, load, select = type, next, rawset, tonumber, tostring, load, select local lpegmatch, P, Cs, Cc = lpeg.match, lpeg.P, lpeg.Cs, lpeg.Cc local sortedkeys, sortedpairs = table.sortedkeys, table.sortedpairs @@ -169,7 +169,8 @@ function table.tocsv(t,specification) r[f] = tostring(field) end end - result[#result+1] = concat(r,separator) + -- result[#result+1] = concat(r,separator) + result[i+1] = concat(r,separator) end return concat(result,"\n") else @@ -485,11 +486,12 @@ end local selfmapper = { __index = function(t,k) t[k] = k return k end } -function table.twowaymapper(t) - if not t then - t = { } - else - for i=0,#t do +function table.twowaymapper(t) -- takes a 0/1 .. n indexed table and returns + if not t then -- it with string-numbers as indices + reverse + t = { } -- mapping (all strings) .. used in cvs etc but + else -- typically a helper that one forgets about + local zero = rawget(t,0) -- so it might move someplace else + for i=zero and 0 or 1,#t do local ti = t[i] -- t[1] = "one" if ti then local i = tostring(i) @@ -497,7 +499,6 @@ function table.twowaymapper(t) t[ti] = i -- t["one"] = "1" end end - t[""] = t[0] or "" end -- setmetatableindex(t,"key") setmetatable(t,selfmapper) @@ -563,98 +564,68 @@ local original_serialize = table.serialize -- the extensive one, the one we star -- latest lua for the value of #n (with holes) .. anyway for tracing purposes we want -- indices / keys being sorted, so it will never be real fast -local function serialize(root,name,specification) - - if type(specification) == "table" then - return original_serialize(root,name,specification) -- the original one - end +local is_simple_table = table.is_simple_table - local t -- = { } - local n = 1 - local unknown = false - --- local function simple_table(t) --- local ts = #t --- if ts > 0 then --- local n = 0 --- for _, v in next, t do --- n = n + 1 --- if type(v) == "table" then +-- local function is_simple_table(t) +-- local nt = #t +-- if nt > 0 then +-- local n = 0 +-- for _, v in next, t do +-- n = n + 1 +-- if type(v) == "table" then +-- return nil +-- end +-- end +-- -- local haszero = t[0] +-- local haszero = rawget(t,0) -- don't trigger meta +-- if n == nt then +-- local tt = { } +-- for i=1,nt do +-- local v = t[i] +-- local tv = type(v) +-- if tv == "number" then +-- tt[i] = v -- not needed tostring(v) +-- elseif tv == "string" then +-- tt[i] = format("%q",v) -- f_string(v) +-- elseif tv == "boolean" then +-- tt[i] = v and "true" or "false" +-- else -- return nil -- end -- end --- if n == ts then --- local tt = { } --- local nt = 0 --- for i=1,ts do --- local v = t[i] --- local tv = type(v) --- nt = nt + 1 --- if tv == "number" then --- tt[nt] = v --- elseif tv == "string" then --- tt[nt] = format("%q",v) -- f_string(v) --- elseif tv == "boolean" then --- tt[nt] = v and "true" or "false" --- else --- return nil --- end +-- return tt +-- elseif haszero and (n == nt + 1) then +-- local tt = { } +-- for i=0,nt do +-- local v = t[i] +-- local tv = type(v) +-- if tv == "number" then +-- tt[i+1] = v -- not needed tostring(v) +-- elseif tv == "string" then +-- tt[i+1] = format("%q",v) -- f_string(v) +-- elseif tv == "boolean" then +-- tt[i+1] = v and "true" or "false" +-- else +-- return nil -- end --- return tt -- end +-- tt[1] = "[0] = " .. tt[1] +-- return tt -- end --- return nil -- end +-- return nil +-- end - local function simple_table(t) - local nt = #t - if nt > 0 then - local n = 0 - for _, v in next, t do - n = n + 1 - if type(v) == "table" then - return nil - end - end - local haszero = t[0] - if n == nt then - local tt = { } - for i=1,nt do - local v = t[i] - local tv = type(v) - if tv == "number" then - tt[i] = v -- not needed tostring(v) - elseif tv == "string" then - tt[i] = format("%q",v) -- f_string(v) - elseif tv == "boolean" then - tt[i] = v and "true" or "false" - else - return nil - end - end - return tt - elseif haszero and (n == nt + 1) then - local tt = { } - for i=0,nt do - local v = t[i] - local tv = type(v) - if tv == "number" then - tt[i+1] = v -- not needed tostring(v) - elseif tv == "string" then - tt[i+1] = format("%q",v) -- f_string(v) - elseif tv == "boolean" then - tt[i+1] = v and "true" or "false" - else - return nil - end - end - tt[1] = "[0] = " .. tt[1] - return tt - end - end - return nil +local function serialize(root,name,specification) + + if type(specification) == "table" then + return original_serialize(root,name,specification) -- the original one end + local t -- = { } + local n = 1 + local unknown = false + local function do_serialize(root,name,depth,level,indexed) if level > 0 then n = n + 1 @@ -680,7 +651,8 @@ local function serialize(root,name,specification) local last = 0 last = #root for k=1,last do - if root[k] == nil then + if rawget(root,k) == nil then + -- if root[k] == nil then last = k - 1 break end @@ -703,7 +675,7 @@ local function serialize(root,name,specification) if next(v) == nil then -- tricky as next is unpredictable in a hash n = n + 1 t[n] = f_val_not(depth) else - local st = simple_table(v) + local st = is_simple_table(v) if st then n = n + 1 t[n] = f_val_seq(depth,st) else @@ -747,7 +719,7 @@ local function serialize(root,name,specification) n = n + 1 t[n] = f_key_str_value_not(depth,tostring(k)) end else - local st = simple_table(v) + local st = is_simple_table(v) if not st then do_serialize(v,k,depth,level+1) elseif tk == "number" then @@ -810,14 +782,15 @@ local function serialize(root,name,specification) if root then -- The dummy access will initialize a table that has a delayed initialization - -- using a metatable. (maybe explicitly test for metatable) + -- using a metatable. (maybe explicitly test for metatable). This can crash on + -- metatables that check the index against a number. if getmetatable(root) then -- todo: make this an option, maybe even per subtable - local dummy = root._w_h_a_t_e_v_e_r_ + local dummy = root._w_h_a_t_e_v_e_r_ -- needed root._w_h_a_t_e_v_e_r_ = nil end -- Let's forget about empty tables. if next(root) ~= nil then - local st = simple_table(root) + local st = is_simple_table(root) if st then return t[1] .. f_fin_seq(st) -- todo: move up and in one go else @@ -833,5 +806,10 @@ end table.serialize = serialize if setinspector then - setinspector("table",function(v) if type(v) == "table" then print(serialize(v,"table",{})) return true end end) + setinspector("table",function(v) + if type(v) == "table" then + print(serialize(v,"table",{ metacheck = false })) + return true + end + end) end |