summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/l-table.lua
diff options
context:
space:
mode:
authorTaco Hoekwater <taco@elvenkind.com>2009-08-23 11:11:32 +0000
committerTaco Hoekwater <taco@elvenkind.com>2009-08-23 11:11:32 +0000
commit8fc3039c82d48605b5ca8b2eda3f4fdd755681e1 (patch)
tree3cd9bbdd599bc4d1ac0409e167fee2136e4c0ec9 /Master/texmf-dist/tex/context/base/l-table.lua
parent850fc99b7cd3ae7a20065531fe866ff7bae642ec (diff)
this is context 2009.08.19 17:10
git-svn-id: svn://tug.org/texlive/trunk@14827 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/l-table.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/l-table.lua913
1 files changed, 541 insertions, 372 deletions
diff --git a/Master/texmf-dist/tex/context/base/l-table.lua b/Master/texmf-dist/tex/context/base/l-table.lua
index ad2f1100186..90cb068e23e 100644
--- a/Master/texmf-dist/tex/context/base/l-table.lua
+++ b/Master/texmf-dist/tex/context/base/l-table.lua
@@ -1,18 +1,22 @@
--- filename : l-table.lua
--- comment : split off from luat-lib
--- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
--- copyright: PRAGMA ADE / ConTeXt Development Team
--- license : see context related readme files
-
-if not versions then versions = { } end versions['l-table'] = 1.001
+if not modules then modules = { } end modules ['l-table'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
table.join = table.concat
+local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+local format, find, gsub, lower, dump = string.format, string.find, string.gsub, string.lower, string.dump
+local getmetatable, setmetatable = getmetatable, setmetatable
+local type, next, tostring, ipairs = type, next, tostring, ipairs
+
function table.strip(tab)
local lst = { }
- for k, v in ipairs(tab) do
- -- s = string.gsub(v, "^%s*(.-)%s*$", "%1")
- s = v:gsub("^%s*(.-)%s*$", "%1")
+ for i=1,#tab do
+ local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
@@ -22,18 +26,13 @@ function table.strip(tab)
return lst
end
---~ function table.sortedkeys(tab)
---~ local srt = { }
---~ for key,_ in pairs(tab) do
---~ srt[#srt+1] = key
---~ end
---~ table.sort(srt)
---~ return srt
---~ end
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
-function table.sortedkeys(tab)
+local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
- for key,_ in pairs(tab) do
+ for key,_ in next, tab do
srt[#srt+1] = key
if kind == 3 then
-- no further check
@@ -51,22 +50,45 @@ function table.sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- table.sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,compare)
else
- table.sort(srt)
+ sort(srt)
+ end
+ return srt
+end
+
+local function sortedhashkeys(tab) -- fast one
+ local srt = { }
+ for key,_ in next, tab do
+ srt[#srt+1] = key
end
+ sort(srt)
return srt
end
+table.sortedkeys = sortedkeys
+table.sortedhashkeys = sortedhashkeys
+
+function table.sortedpairs(t)
+ local s = sortedhashkeys(t) -- maybe just sortedkeys
+ local n = 0
+ local function kv(s)
+ n = n + 1
+ local k = s[n]
+ return k, t[k]
+ end
+ return kv, s
+end
+
function table.append(t, list)
- for _,v in pairs(list) do
- table.insert(t,v)
+ for _,v in next, list do
+ insert(t,v)
end
end
function table.prepend(t, list)
- for k,v in pairs(list) do
- table.insert(t,k,v)
+ for k,v in next, list do
+ insert(t,k,v)
end
end
@@ -74,7 +96,7 @@ function table.merge(t, ...) -- first one is target
t = t or {}
local lst = {...}
for i=1,#lst do
- for k, v in pairs(lst[i]) do
+ for k, v in next, lst[i] do
t[k] = v
end
end
@@ -84,7 +106,7 @@ end
function table.merged(...)
local tmp, lst = { }, {...}
for i=1,#lst do
- for k, v in pairs(lst[i]) do
+ for k, v in next, lst[i] do
tmp[k] = v
end
end
@@ -113,70 +135,58 @@ function table.imerged(...)
return tmp
end
-if not table.fastcopy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function fastcopy(old) -- fast one
- if old then
- local new = { }
- for k,v in pairs(old) do
- if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
- else
- new[k] = v
- end
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+local function fastcopy(old) -- fast one
+ if old then
+ local new = { }
+ for k,v in next, old do
+ if type(v) == "table" then
+ new[k] = fastcopy(v) -- was just table.copy
+ else
+ new[k] = v
end
- return new
- else
- return { }
end
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
end
+end
- table.fastcopy = fastcopy
-
-end end
-
-if not table.copy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function copy(t, tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
- local tcopy = {}
- if not tables[t] then
- tables[t] = tcopy
- end
- for i,v in pairs(t) do -- brrr, what happens with sparse indexed
- if type(i) == "table" then
- if tables[i] then
- i = tables[i]
- else
- i = copy(i, tables)
- end
- end
- if type(v) ~= "table" then
- tcopy[i] = v
- elseif tables[v] then
- tcopy[i] = tables[v]
+local function copy(t, tables) -- taken from lua wiki, slightly adapted
+ tables = tables or { }
+ local tcopy = {}
+ if not tables[t] then
+ tables[t] = tcopy
+ end
+ for i,v in next, t do -- brrr, what happens with sparse indexed
+ if type(i) == "table" then
+ if tables[i] then
+ i = tables[i]
else
- tcopy[i] = copy(v, tables)
+ i = copy(i, tables)
end
end
- local mt = getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
+ if type(v) ~= "table" then
+ tcopy[i] = v
+ elseif tables[v] then
+ tcopy[i] = tables[v]
+ else
+ tcopy[i] = copy(v, tables)
end
- return tcopy
end
+ local mt = getmetatable(t)
+ if mt then
+ setmetatable(tcopy,mt)
+ end
+ return tcopy
+end
- table.copy = copy
-
-end end
+table.fastcopy = fastcopy
+table.copy = copy
-- rougly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -185,7 +195,7 @@ function table.sub(t,i,j)
end
function table.replace(a,b)
- for k,v in pairs(b) do
+ for k,v in next, b do
a[k] = v
end
end
@@ -205,344 +215,483 @@ function table.starts_at(t)
return ipairs(t,1)(t,0)
end
-do
-
- -- one of my first exercises in lua ...
-
- -- 34.055.092 32.403.326 arabtype.tma
- -- 1.620.614 1.513.863 lmroman10-italic.tma
- -- 1.325.585 1.233.044 lmroman10-regular.tma
- -- 1.248.157 1.158.903 lmsans10-regular.tma
- -- 194.646 153.120 lmtypewriter10-regular.tma
- -- 1.771.678 1.658.461 palatinosanscom-bold.tma
- -- 1.695.251 1.584.491 palatinosanscom-regular.tma
- -- 13.736.534 13.409.446 zapfinoextraltpro.tma
-
- -- 13.679.038 11.774.106 arabtype.tmc
- -- 886.248 754.944 lmroman10-italic.tmc
- -- 729.828 466.864 lmroman10-regular.tmc
- -- 688.482 441.962 lmsans10-regular.tmc
- -- 128.685 95.853 lmtypewriter10-regular.tmc
- -- 715.929 582.985 palatinosanscom-bold.tmc
- -- 669.942 540.126 palatinosanscom-regular.tmc
- -- 1.560.588 1.317.000 zapfinoextraltpro.tmc
-
- table.serialize_functions = true
- table.serialize_compact = true
- table.serialize_inline = true
-
- local function key(k)
- if type(k) == "number" then -- or k:find("^%d+$") then
- return "["..k.."]"
- elseif noquotes and k:find("^%a[%a%d%_]*$") then
- return k
- else
- return '["'..k..'"]'
+function table.tohash(t,value)
+ local h = { }
+ if t then
+ if value == nil then value = true end
+ for _, v in next, t do -- no ipairs here
+ h[v] = value
end
end
+ return h
+end
- local function simple_table(t)
- if #t > 0 then
- local n = 0
- for _,v in pairs(t) do
- n = n + 1
- end
- if n == #t then
- local tt = { }
- for i=1,#t do
- local v = t[i]
- local tv = type(v)
- if tv == "number" or tv == "boolean" then
- tt[#tt+1] = tostring(v)
- elseif tv == "string" then
- tt[#tt+1] = ("%q"):format(v)
+function table.fromhash(t)
+ local h = { }
+ for k, v in next, t do -- no ipairs here
+ if v then h[#h+1] = k end
+ end
+ return h
+end
+
+--~ print(table.serialize(t), "\n")
+--~ print(table.serialize(t,"name"), "\n")
+--~ print(table.serialize(t,false), "\n")
+--~ print(table.serialize(t,true), "\n")
+--~ print(table.serialize(t,"name",true), "\n")
+--~ print(table.serialize(t,"name",true,true), "\n")
+
+table.serialize_functions = true
+table.serialize_compact = true
+table.serialize_inline = true
+
+local noquotes, hexify, handle, reduce, compact, inline, functions
+
+local reserved = table.tohash { -- intercept a language flaw, no reserved words as key
+ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
+ 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
+}
+
+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 = { }
+ for i=1,#t do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ if hexify then
+ tt[#tt+1] = format("0x%04X",v)
else
- tt = nil
- break
+ tt[#tt+1] = tostring(v) -- tostring not needed
end
+ elseif tv == "boolean" then
+ tt[#tt+1] = tostring(v)
+ elseif tv == "string" then
+ tt[#tt+1] = format("%q",v)
+ else
+ tt = nil
+ break
end
- return tt
end
+ return tt
end
- return nil
end
+ return nil
+end
- local function serialize(root,name,handle,depth,level,reduce,noquotes,indexed)
- handle = handle or print
- reduce = reduce or false
- if depth then
- depth = depth .. " "
- if indexed then
- handle(("%s{"):format(depth))
- else
- handle(("%s%s={"):format(depth,key(name)))
- end
- else
- depth = ""
- local tname = type(name)
- if tname == "string" then
- if name == "return" then
- handle("return {")
+-- Because this is a core function of mkiv I moved some function calls
+-- inline.
+--
+-- twice as fast in a test:
+--
+-- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) )
+
+local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
+ depth = depth .. " "
+ if indexed then
+ handle(format("%s{",depth))
+ elseif name then
+ --~ handle(format("%s%s={",depth,key(name)))
+ if type(name) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s[0x%04X]={",depth,name))
else
- handle(name .. "={")
- end
- elseif tname == "number" then
- handle("[" .. name .. "]={")
- elseif tname == "boolean" then
- if name then
- handle("return {")
- else
- handle("{")
+ handle(format("%s[%s]={",depth,name))
end
+ elseif noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
+ handle(format("%s%s={",depth,name))
else
- handle("t={")
+ handle(format("%s[%q]={",depth,name))
end
+ else
+ handle(format("%s{",depth))
end
- if root and next(root) then
- local compact = table.serialize_compact
- local inline = compact and table.serialize_inline
- local first, last = nil, 0 -- #root cannot be trusted here
- if compact then
- for k,v in ipairs(root) do -- NOT: for k=1,#root do (why)
- if not first then first = k end
- last = last + 1
- end
+ end
+ if root and next(root) then
+ local first, last = nil, 0 -- #root cannot be trusted here
+ 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
- for _,k in pairs(table.sortedkeys(root)) do
- local v = root[k]
- local t = type(v)
- if compact and first and type(k) == "number" and k >= first and k <= last then
- if t == "number" then
- handle(("%s %s,"):format(depth,v))
- elseif t == "string" then
- if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
- handle(("%s %s,"):format(depth,v))
- else
- handle(("%s %q,"):format(depth,v))
- end
- elseif t == "table" then
- if not next(v) then
- handle(("%s {},"):format(depth))
- elseif inline then
- local st = simple_table(v)
- if st then
- handle(("%s { %s },"):format(depth,table.concat(st,", ")))
- else
- serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
- end
- else
- serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
- end
- elseif t == "boolean" then
- handle(("%s %s,"):format(depth,tostring(v)))
- elseif t == "function" then
- if table.serialize_functions then
- handle(('%s loadstring(%q),'):format(depth,string.dump(v)))
- else
- handle(('%s "function",'):format(depth))
- end
+ 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 t = type(v)
+ if compact and first and type(k) == "number" and k >= first and k <= last then
+ if t == "number" then
+ if hexify then
+ handle(format("%s 0x%04X,",depth,v))
else
- handle(("%s %q,"):format(depth,tostring(v)))
+ handle(format("%s %s,",depth,v))
end
- elseif k == "__p__" then -- parent
- if false then
- handle(("%s __p__=nil,"):format(depth))
- end
- elseif t == "number" then
- handle(("%s %s=%s,"):format(depth,key(k),v))
elseif t == "string" then
- if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
- handle(("%s %s=%s,"):format(depth,key(k),v))
+ if reduce and (find(v,"^[%-%+]?[%d]-%.?[%d+]$") == 1) then
+ handle(format("%s %s,",depth,v))
else
- handle(("%s %s=%q,"):format(depth,key(k),v))
+ handle(format("%s %q,",depth,v))
end
elseif t == "table" then
if not next(v) then
- handle(("%s %s={},"):format(depth,key(k)))
- elseif inline then
+ handle(format("%s {},",depth))
+ elseif inline then -- and #t > 0
local st = simple_table(v)
if st then
- handle(("%s %s={ %s },"):format(depth,key(k),table.concat(st,", ")))
+ handle(format("%s { %s },",depth,concat(st,", ")))
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ do_serialize(v,k,depth,level+1,true)
end
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ do_serialize(v,k,depth,level+1,true)
end
elseif t == "boolean" then
- handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
+ handle(format("%s %s,",depth,tostring(v)))
elseif t == "function" then
- if table.serialize_functions then
- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(v)))
+ if functions then
+ handle(format('%s loadstring(%q),',depth,dump(v)))
else
- handle(('%s %s="function",'):format(depth,key(k)))
+ handle(format('%s "function",',depth))
end
else
- handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
- -- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
+ handle(format("%s %q,",depth,tostring(v)))
end
- end
- if level > 0 then
- handle(("%s},"):format(depth))
- else
- handle(("%s}"):format(depth))
- end
- else
- handle(("%s}"):format(depth))
- end
- end
-
- --~ name:
- --~
- --~ true : return { }
- --~ false : { }
- --~ nil : t = { }
- --~ string : string = { }
- --~ 'return' : return { }
- --~ number : [number] = { }
-
- function table.serialize(root,name,reduce,noquotes)
- local t = { }
- local function flush(s)
- t[#t+1] = s
- end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
- return table.concat(t,"\n")
- end
-
- function table.tohandle(handle,root,name,reduce,noquotes)
- serialize(root, name, handle, nil, 0, reduce, noquotes)
- end
-
- -- 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
-
- table.tofile_maxtab = 2*1024
-
- function table.tofile(filename,root,name,reduce,noquotes)
- local f = io.open(filename,'w')
- if f then
- local concat = table.concat
- local maxtab = table.tofile_maxtab
- if maxtab > 1 then
- local t = { }
- local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
- f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
+ elseif k == "__p__" then -- parent
+ if false then
+ handle(format("%s __p__=nil,",depth))
+ end
+ elseif t == "number" then
+ --~ if hexify then
+ --~ handle(format("%s %s=0x%04X,",depth,key(k),v))
+ --~ else
+ --~ handle(format("%s %s=%s,",depth,key(k),v))
+ --~ end
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ if hexify then
+ handle(format("%s %s=0x%04X,",depth,k,v))
+ else
+ handle(format("%s %s=%s,",depth,k,v))
+ end
+ else
+ if hexify then
+ handle(format("%s [%q]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ end
+ elseif t == "string" then
+ if reduce and (find(v,"^[%-%+]?[%d]-%.?[%d+]$") == 1) then
+ --~ handle(format("%s %s=%s,",depth,key(k),v))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%s,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ else
+ --~ handle(format("%s %s=%q,",depth,key(k),v))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,v))
+ else
+ handle(format("%s [%s]=%q,",depth,k,v))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%q,",depth,k,v))
+ else
+ handle(format("%s [%q]=%q,",depth,k,v))
+ end
+ end
+ elseif t == "table" then
+ if not next(v) then
+ --~ handle(format("%s %s={},",depth,key(k)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]={},",depth,k))
+ else
+ handle(format("%s [%s]={},",depth,k))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s={},",depth,k))
+ else
+ handle(format("%s [%q]={},",depth,k))
+ end
+ elseif inline then
+ local st = simple_table(v)
+ if st then
+ --~ handle(format("%s %s={ %s },",depth,key(k),concat(st,", ")))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t == "boolean" then
+ --~ handle(format("%s %s=%s,",depth,key(k),tostring(v)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%s,",depth,k,tostring(v)))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%s,",depth,k,tostring(v)))
+ end
+ elseif t == "function" then
+ if functions then
+ --~ handle(format('%s %s=loadstring(%q),',depth,key(k),dump(v)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ else
+ handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ else
+ handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
end
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
- f:write(concat(t,"\n"),"\n")
else
- local function flush(s)
- f:write(s,"\n")
+ --~ handle(format("%s %s=%q,",depth,key(k),tostring(v)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%q,",depth,k,tostring(v)))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%q,",depth,k,tostring(v)))
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
end
- f:close()
+ --~ end
end
end
-
+ if level > 0 then
+ handle(format("%s},",depth))
+ end
end
---~ t = {
---~ b = "123",
---~ a = "x",
---~ c = 1.23,
---~ d = "1.23",
---~ e = true,
---~ f = {
---~ d = "1.23",
---~ a = "x",
---~ b = "123",
---~ c = 1.23,
---~ e = true,
---~ f = {
---~ e = true,
---~ f = {
---~ e = true
---~ },
---~ },
---~ },
---~ g = function() end
---~ }
+-- replacing handle by a direct t[#t+1] = ... (plus test) is not much
+-- faster (0.03 on 1.00 for zapfino.tma)
+
+local function serialize(root,name,_handle,_reduce,_noquotes,_hexify)
+ noquotes = _noquotes
+ hexify = _hexify
+ handle = _handle or print
+ reduce = _reduce or false
+ compact = table.serialize_compact
+ inline = compact and table.serialize_inline
+ functions = table.serialize_functions
+ local tname = type(name)
+ if tname == "string" then
+ if name == "return" then
+ handle("return {")
+ else
+ handle(name .. "={")
+ end
+ elseif tname == "number" then
+ if hexify then
+ handle(format("[0x%04X]={",name))
+ else
+ handle("[" .. name .. "]={")
+ end
+ elseif tname == "boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
+ end
+ else
+ handle("t={")
+ end
+ if root and next(root) then
+ do_serialize(root,name,"",0,indexed)
+ end
+ handle("}")
+end
---~ print(table.serialize(t), "\n")
---~ print(table.serialize(t,"name"), "\n")
---~ print(table.serialize(t,false), "\n")
---~ print(table.serialize(t,true), "\n")
---~ print(table.serialize(t,"name",true), "\n")
---~ print(table.serialize(t,"name",true,true), "\n")
+--~ name:
+--~
+--~ true : return { }
+--~ false : { }
+--~ nil : t = { }
+--~ string : string = { }
+--~ 'return' : return { }
+--~ number : [number] = { }
+
+function table.serialize(root,name,reduce,noquotes,hexify)
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ return concat(t,"\n")
+end
-do
+function table.tohandle(handle,root,name,reduce,noquotes,hexify)
+ serialize(root,name,handle,reduce,noquotes,hexify)
+end
- local function flatten(t,f,complete)
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
- else
- f[#f+1] = v
+-- 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
+
+table.tofile_maxtab = 2*1024
+
+function table.tofile(filename,root,name,reduce,noquotes,hexify)
+ local f = io.open(filename,'w')
+ if f then
+ local maxtab = table.tofile_maxtab
+ if maxtab > 1 then
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
+ if #t > maxtab then
+ f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
+ t = { }
end
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ end
+ f:close()
+ end
+end
+
+local function flatten(t,f,complete)
+ for i=1,#t do
+ local v = t[i]
+ if type(v) == "table" then
+ if complete or type(v[1]) == "table" then
+ flatten(v,f,complete)
else
f[#f+1] = v
end
+ else
+ f[#f+1] = v
end
end
+end
- function table.flatten(t)
- local f = { }
- flatten(t,f,true)
- return f
- end
+function table.flatten(t)
+ local f = { }
+ flatten(t,f,true)
+ return f
+end
- function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
- end
+function table.unnest(t) -- bad name
+ local f = { }
+ flatten(t,f,false)
+ return f
+end
+
+table.flatten_one_level = table.unnest
- table.flatten_one_level = table.unnest
+-- the next three may disappear
+function table.remove_value(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
end
function table.insert_before_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,str)
+ return
+ end
+ end
end
+ insert(t,1,str)
+ elseif value then
+ insert(t,1,value)
end
- table.insert(t,1,str)
end
function table.insert_after_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i+1,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,str)
+ return
+ end
+ end
end
+ t[#t+1] = str
+ elseif value then
+ t[#t+1] = value
end
- t[#t+1] = str
end
-function table.are_equal(a,b,n,m)
- if #a == #b then
+local function are_equal(a,b,n,m) -- indexed
+ if a and b and #a == #b then
n = n or 1
m = m or #a
for i=n,m do
local ai, bi = a[i], b[i]
- if (ai==bi) or (type(ai)=="table" and type(bi)=="table" and table.are_equal(ai,bi)) then
- -- continue
+ if ai==bi then
+ -- same
+ elseif type(ai)=="table" and type(bi)=="table" then
+ if not are_equal(ai,bi) then
+ return false
+ end
else
return false
end
@@ -553,37 +702,42 @@ function table.are_equal(a,b,n,m)
end
end
-function table.compact(t)
- if t then
- for k,v in pairs(t) do
- if not next(v) then
- t[k] = nil
+local function identical(a,b) -- assumes same structure
+ for ka, va in next, a do
+ local vb = b[k]
+ if va == vb then
+ -- same
+ elseif type(va) == "table" and type(vb) == "table" then
+ if not identical(va,vb) then
+ return false
end
+ else
+ return false
end
end
+ return true
end
-function table.tohash(t)
- local h = { }
- for _, v in pairs(t) do -- no ipairs here
- h[v] = true
- end
- return h
-end
+table.are_equal = are_equal
+table.identical = identical
-function table.fromhash(t)
- local h = { }
- for k, v in pairs(t) do -- no ipairs here
- if v then h[#h+1] = k end
+-- maybe also make a combined one
+
+function table.compact(t)
+ if t then
+ for k,v in next, t do
+ if not next(v) then
+ t[k] = nil
+ end
+ end
end
- return h
end
function table.contains(t, v)
if t then
for i=1, #t do
if t[i] == v then
- return true
+ return i
end
end
end
@@ -600,7 +754,7 @@ end
function table.swapped(t)
local s = { }
- for k, v in pairs(t) do
+ for k, v in next, t do
s[v] = k
end
return s
@@ -620,17 +774,16 @@ function table.clone(t,p) -- t is optional or nil or table
return t
end
-
function table.hexed(t,seperator)
local tt = { }
- for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end
- return table.concat(tt,seperator or " ")
+ for i=1,#t do tt[i] = format("0x%04X",t[i]) end
+ return concat(tt,seperator or " ")
end
function table.reverse_hash(h)
local r = { }
- for k,v in pairs(h) do
- r[v] = (k:gsub(" ","")):lower()
+ for k,v in next, h do
+ r[v] = lower(gsub(k," ",""))
end
return r
end
@@ -644,3 +797,19 @@ function table.reverse(t)
end
return tt
end
+
+--~ function table.keys(t)
+--~ local k = { }
+--~ for k,_ in next, t do
+--~ k[#k+1] = k
+--~ end
+--~ return k
+--~ end
+
+--~ function table.keys_as_string(t)
+--~ local k = { }
+--~ for k,_ in next, t do
+--~ k[#k+1] = k
+--~ end
+--~ return concat(k,"")
+--~ end