From 4295a3eb51db73a87774d59fb3a38a54690319f7 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 22 May 2015 07:55:17 +0200 Subject: sync with Context as of 2015-05-22 --- lualibs-table.lua | 280 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 181 insertions(+), 99 deletions(-) (limited to 'lualibs-table.lua') diff --git a/lualibs-table.lua b/lualibs-table.lua index 97e0441..b02f210 100644 --- a/lualibs-table.lua +++ b/lualibs-table.lua @@ -39,7 +39,7 @@ end function table.keys(t) if t then local keys, k = { }, 0 - for key, _ in next, t do + for key in next, t do k = k + 1 keys[k] = key end @@ -50,44 +50,126 @@ function table.keys(t) end -- local function compare(a,b) --- local ta, tb = type(a), type(b) -- needed, else 11 < 2 --- if ta == tb then +-- local ta = type(a) -- needed, else 11 < 2 +-- local tb = type(b) -- needed, else 11 < 2 +-- if ta == tb and ta == "number" then -- return a < b -- else -- return tostring(a) < tostring(b) -- not that efficient -- end -- end +-- local function compare(a,b) +-- local ta = type(a) -- needed, else 11 < 2 +-- local tb = type(b) -- needed, else 11 < 2 +-- if ta == tb and (ta == "number" or ta == "string") then +-- return a < b +-- else +-- return tostring(a) < tostring(b) -- not that efficient +-- end +-- end + +-- local function sortedkeys(tab) +-- if tab then +-- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed +-- for key in next, tab do +-- s = s + 1 +-- srt[s] = key +-- if category == 3 then +-- -- no further check +-- else +-- local tkey = type(key) +-- if tkey == "string" then +-- category = (category == 2 and 3) or 1 +-- elseif tkey == "number" then +-- category = (category == 1 and 3) or 2 +-- else +-- category = 3 +-- end +-- end +-- end +-- if category == 0 or category == 3 then +-- sort(srt,compare) +-- else +-- sort(srt) +-- end +-- return srt +-- else +-- return { } +-- end +-- end + +-- local function compare(a,b) +-- local ta = type(a) -- needed, else 11 < 2 +-- local tb = type(b) -- needed, else 11 < 2 +-- if ta == tb and (ta == "number" or ta == "string") then +-- return a < b +-- else +-- return tostring(a) < tostring(b) -- not that efficient +-- end +-- end + +-- local function compare(a,b) +-- local ta = type(a) -- needed, else 11 < 2 +-- if ta == "number" or ta == "string" then +-- local tb = type(b) -- needed, else 11 < 2 +-- if ta == tb then +-- return a < b +-- end +-- end +-- return tostring(a) < tostring(b) -- not that efficient +-- end + local function compare(a,b) local ta = type(a) -- needed, else 11 < 2 - local tb = type(b) -- needed, else 11 < 2 - if ta == tb and ta == "number" then - return a < b - else - return tostring(a) < tostring(b) -- not that efficient + if ta == "number" then + local tb = type(b) -- needed, else 11 < 2 + if ta == tb then + return a < b + elseif tb == "string" then + return tostring(a) < b + end + elseif ta == "string" then + local tb = type(b) -- needed, else 11 < 2 + if ta == tb then + return a < b + else + return a < tostring(b) + end end + return tostring(a) < tostring(b) -- not that efficient end local function sortedkeys(tab) if tab then local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed - for key,_ in next, tab do + for key in next, tab do s = s + 1 srt[s] = key if category == 3 then -- no further check + elseif category == 1 then + if type(key) ~= "string" then + category = 3 + end + elseif category == 2 then + if type(key) ~= "number" then + category = 3 + end else local tkey = type(key) if tkey == "string" then - category = (category == 2 and 3) or 1 + category = 1 elseif tkey == "number" then - category = (category == 1 and 3) or 2 + category = 2 else category = 3 end end end - if category == 0 or category == 3 then + if s < 2 then + -- nothing to sort + elseif category == 3 then sort(srt,compare) else sort(srt) @@ -101,13 +183,15 @@ end local function sortedhashonly(tab) if tab then local srt, s = { }, 0 - for key,_ in next, tab do + for key in next, tab do if type(key) == "string" then s = s + 1 srt[s] = key end end - sort(srt) + if s > 1 then + sort(srt) + end return srt else return { } @@ -117,13 +201,15 @@ end local function sortedindexonly(tab) if tab then local srt, s = { }, 0 - for key,_ in next, tab do + for key in next, tab do if type(key) == "number" then s = s + 1 srt[s] = key end end - sort(srt) + if s > 1 then + sort(srt) + end return srt else return { } @@ -133,13 +219,15 @@ end local function sortedhashkeys(tab,cmp) -- fast one if tab then local srt, s = { }, 0 - for key,_ in next, tab do + for key in next, tab do if key then s= s + 1 srt[s] = key end end - sort(srt,cmp) + if s > 1 then + sort(srt,cmp) + end return srt else return { } @@ -149,7 +237,7 @@ end function table.allkeys(t) local keys = { } for k, v in next, t do - for k, v in next, v do + for k in next, v do keys[k] = true end end @@ -172,19 +260,21 @@ local function sortedhash(t,cmp) else s = sortedkeys(t) -- the robust one end - local n = 0 local m = #s - local function kv() -- (s) - if n < m then - n = n + 1 - local k = s[n] - return k, t[k] + if m == 1 then + return next, t + elseif m > 0 then + local n = 0 + return function() + if n < m then + n = n + 1 + local k = s[n] + return k, t[k] + end end end - return kv -- , s - else - return nothing end + return nothing end table.sortedhash = sortedhash @@ -328,7 +418,7 @@ end local function copy(t, tables) -- taken from lua wiki, slightly adapted tables = tables or { } - local tcopy = {} + local tcopy = { } if not tables[t] then tables[t] = tcopy end @@ -388,7 +478,7 @@ function table.fromhash(t) return hsh end -local noquotes, hexify, handle, reduce, compact, inline, functions +local noquotes, hexify, handle, compact, inline, functions local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if', @@ -396,33 +486,67 @@ local reserved = table.tohash { -- intercept a language inconvenience: no reserv 'NaN', 'goto', } +-- local function simple_table(t) +-- if #t > 0 then +-- local n = 0 +-- for _,v in next, t do +-- n = n + 1 +-- end +-- if n == #t then +-- local tt, nt = { }, 0 +-- for i=1,#t do +-- local v = t[i] +-- local tv = type(v) +-- if tv == "number" then +-- nt = nt + 1 +-- if hexify then +-- tt[nt] = format("0x%X",v) +-- else +-- tt[nt] = tostring(v) -- tostring not needed +-- end +-- elseif tv == "string" then +-- nt = nt + 1 +-- tt[nt] = format("%q",v) +-- elseif tv == "boolean" then +-- nt = nt + 1 +-- tt[nt] = v and "true" or "false" +-- else +-- return nil +-- end +-- end +-- return tt +-- end +-- end +-- return nil +-- end + local function simple_table(t) - if #t > 0 then + 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 - if n == #t then - local tt, nt = { }, 0 - for i=1,#t do + if n == nt then + local tt = { } + for i=1,nt do local v = t[i] local tv = type(v) if tv == "number" then - nt = nt + 1 if hexify then - tt[nt] = format("0x%X",v) + tt[i] = format("0x%X",v) else - tt[nt] = tostring(v) -- tostring not needed + tt[i] = tostring(v) -- tostring not needed end elseif tv == "string" then - nt = nt + 1 - tt[nt] = format("%q",v) + tt[i] = format("%q",v) elseif tv == "boolean" then - nt = nt + 1 - tt[nt] = v and "true" or "false" + tt[i] = v and "true" or "false" else - tt = nil - break + return nil end end return tt @@ -480,14 +604,6 @@ local function do_serialize(root,name,depth,level,indexed) end -- we could check for k (index) being number (cardinal) if root and next(root) ~= nil then - -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone) - -- if compact then - -- -- NOT: for k=1,#root do (we need to quit at nil) - -- for k,v in ipairs(root) do -- can we use next? - -- if not first then first = k end - -- last = last + 1 - -- end - -- end local first, last = nil, 0 if compact then last = #root @@ -503,12 +619,10 @@ local function do_serialize(root,name,depth,level,indexed) end local sk = sortedkeys(root) for i=1,#sk do - local k = sk[i] - local v = root[k] - --~ if v == root then - -- circular - --~ else - local tv, tk = type(v), type(k) + local k = sk[i] + local v = root[k] + local tv = type(v) + local tk = type(k) if compact and first and tk == "number" and k >= first and k <= last then if tv == "number" then if hexify then @@ -517,11 +631,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s %s,",depth,v)) -- %.99g end elseif tv == "string" then - if reduce and tonumber(v) then - handle(format("%s %s,",depth,v)) - else - handle(format("%s %q,",depth,v)) - end + handle(format("%s %q,",depth,v)) elseif tv == "table" then if next(v) == nil then handle(format("%s {},",depth)) @@ -577,34 +687,18 @@ local function do_serialize(root,name,depth,level,indexed) end end elseif tv == "string" then - if reduce and tonumber(v) then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%s,",depth,k,v)) - else - handle(format("%s [%s]=%s,",depth,k,v)) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v)) + if tk == "number" then + if hexify then + handle(format("%s [0x%X]=%q,",depth,k,v)) else - handle(format("%s [%q]=%s,",depth,k,v)) + handle(format("%s [%s]=%q,",depth,k,v)) end + elseif tk == "boolean" then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) + elseif noquotes and not reserved[k] and lpegmatch(propername,k) then + handle(format("%s %s=%q,",depth,k,v)) else - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,v)) - else - handle(format("%s [%s]=%q,",depth,k,v)) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,v)) - else - handle(format("%s [%q]=%q,",depth,k,v)) - end + handle(format("%s [%q]=%q,",depth,k,v)) end elseif tv == "table" then if next(v) == nil then @@ -690,7 +784,6 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]=%q,",depth,k,tostring(v))) end end - --~ end end end if level > 0 then @@ -707,7 +800,6 @@ local function serialize(_handle,root,name,specification) -- handle wins noquotes = specification.noquotes hexify = specification.hexify handle = _handle or specification.handle or print - reduce = specification.reduce or false functions = specification.functions compact = specification.compact inline = specification.inline and compact @@ -724,7 +816,6 @@ local function serialize(_handle,root,name,specification) -- handle wins noquotes = false hexify = false handle = _handle or print - reduce = false compact = true inline = true functions = true @@ -798,15 +889,6 @@ end table.tohandle = serialize --- sometimes tables are real use (zapfino extra pro is some 85M) in which --- case a stepwise serialization is nice; actually, we could consider: --- --- for line in table.serializer(root,name,reduce,noquotes) do --- ...(line) --- end --- --- so this is on the todo list - local maxtab = 2*1024 function table.tofile(filename,root,name,specification) -- cgit v1.2.3