summaryrefslogtreecommitdiff
path: root/tex/context/base/l-table.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/l-table.lua')
-rw-r--r--tex/context/base/l-table.lua249
1 files changed, 132 insertions, 117 deletions
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index 70c04e69c..abaaa62ba 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -61,24 +61,26 @@ end
-- extra functions, some might go (when not used)
function table.strip(tab)
- local lst = { }
+ local lst, l = { }, 0
for i=1,#tab do
local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
- lst[#lst+1] = s
+ l = l + 1
+ lst[l] = s
end
end
return lst
end
function table.keys(t)
- local k = { }
+ local keys, k = { }, 0
for key, _ in next, t do
- k[#k+1] = key
+ k = k + 1
+ keys[k] = key
end
- return k
+ return keys
end
local function compare(a,b)
@@ -91,9 +93,10 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt, kind, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
- srt[#srt+1] = key
+ s = s + 1
+ srt[s] = key
if kind == 3 then
-- no further check
else
@@ -116,10 +119,11 @@ local function sortedkeys(tab)
end
local function sortedhashkeys(tab) -- fast one
- local srt = { }
+ local srt, s = { }, 0
for key,_ in next, tab do
if key then
- srt[#srt+1] = key
+ s= s + 1
+ srt[s] = key
end
end
sort(srt)
@@ -133,8 +137,7 @@ local function nothing() end
local function sortedhash(t)
if t then
- local s = sortedhashkeys(t) -- maybe just sortedkeys
- local n = 0
+ local n, s = 0, sortedkeys(t) -- the robust one
local function kv(s)
n = n + 1
local k = s[n]
@@ -150,20 +153,30 @@ table.sortedhash = sortedhash
table.sortedpairs = sortedhash
function table.append(t, list)
- for _,v in next, list do
- insert(t,v)
+ local n = #t
+ for i=1,#list do
+ n = n + 1
+ t[n] = list[i]
end
+ return t
end
function table.prepend(t, list)
- for k,v in next, list do
- insert(t,k,v)
+ local nl = #list
+ local nt = nl + #t
+ for i=#t,1,-1 do
+ t[nt] = t[i]
+ nt = nt - 1
+ end
+ for i=1,#list do
+ t[i] = list[i]
end
+ return t
end
function table.merge(t, ...) -- first one is target
t = t or { }
- local lst = {...}
+ local lst = { ... }
for i=1,#lst do
for k, v in next, lst[i] do
t[k] = v
@@ -173,7 +186,7 @@ function table.merge(t, ...) -- first one is target
end
function table.merged(...)
- local tmp, lst = { }, {...}
+ local tmp, lst = { }, { ... }
for i=1,#lst do
for k, v in next, lst[i] do
tmp[k] = v
@@ -183,22 +196,24 @@ function table.merged(...)
end
function table.imerge(t, ...)
- local lst = {...}
+ local lst, nt = { ... }, #t
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- t[#t+1] = nst[j]
+ nt = nt + 1
+ t[nt] = nst[j]
end
end
return t
end
function table.imerged(...)
- local tmp, lst = { }, {...}
+ local tmp, ntmp, lst = { }, 0, {...}
for i=1,#lst do
local nst = lst[i]
for j=1,#nst do
- tmp[#tmp+1] = nst[j]
+ ntmp = ntmp + 1
+ tmp[ntmp] = nst[j]
end
end
return tmp
@@ -274,11 +289,14 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local h = { }
+ local hsh, h = { }, 0
for k, v in next, t do -- no ipairs here
- if v then h[#h+1] = k end
+ if v then
+ h = h + 1
+ hsh[h] = k
+ end
end
- return h
+ return hsh
end
table.serialize_functions = true
@@ -299,20 +317,23 @@ local function simple_table(t)
n = n + 1
end
if n == #t then
- local tt = { }
+ 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[#tt+1] = format("0x%04X",v)
+ tt[nt] = format("0x%04X",v)
else
- tt[#tt+1] = tostring(v) -- tostring not needed
+ tt[nt] = tostring(v) -- tostring not needed
end
elseif tv == "boolean" then
- tt[#tt+1] = tostring(v)
+ nt = nt + 1
+ tt[nt] = tostring(v)
elseif tv == "string" then
- tt[#tt+1] = format("%q",v)
+ nt = nt + 1
+ tt[nt] = format("%q",v)
else
tt = nil
break
@@ -618,10 +639,11 @@ end
--~ 'return' : return { }
--~ number : [number] = { }
-function table.serialize(root,name,reduce,noquotes,hexify)
- local t = { }
+function table.serialize(root,name,reduce,noquotes,hexify) -- can be faster if flush == false and t as argument
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
+ n = n + 1
+ t[n] = s
end
serialize(root,name,flush,reduce,noquotes,hexify)
return concat(t,"\n")
@@ -647,12 +669,13 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
if f then
local maxtab = table.tofile_maxtab
if maxtab > 1 then
- local t = { }
+ local t, n = { }, 0
local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
+ n = n + 1
+ t[n] = s
+ if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
+ t, n = { }, 0 -- we could recycle t if needed
end
end
serialize(root,name,flush,reduce,noquotes,hexify)
@@ -668,52 +691,72 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
end
end
-local function flatten(t,f,complete) -- is this used? meybe a variant with next, ...
- 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)
+local function flattened(t,f,depth)
+ if f == nil then
+ f = { }
+ depth = 0xFFFF
+ elseif tonumber(f) then
+ -- assume then only two arguments are given
+ depth = f
+ f = { }
+ elseif not depth then
+ depth = 0xFFFF
+ end
+ for k, v in next, t do
+ if type(k) ~= "number" then
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
else
- f[#f+1] = v
+ f[k] = v
end
+ end
+ end
+ local n = #f
+ for k=1,#t do
+ local v = t[k]
+ if depth > 0 and type(v) == "table" then
+ flattened(v,f,depth-1)
+ n = #f
else
- f[#f+1] = v
+ n = n + 1
+ f[n] = v
end
end
-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
-table.flattenonelevel = table.unnest
-
--- a better one:
+table.flattened = flattened
-local function flattened(t,f)
- if not f then
+local function unnest(t,f) -- only used in mk, for old times sake
+ if not f then -- and only relevant for token lists
f = { }
end
- for k, v in next, t do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
- flattened(v,f)
+ if type(v[1]) == "table" then
+ unnest(v,f)
+ else
+ f[#f+1] = v
+ end
else
- f[k] = v
+ f[#f+1] = v
end
end
return f
end
-table.flattened = flattened
+function table.unnest(t) -- bad name
+ return unnest(t)
+end
+
+--~ function table.unnest(t) -- for old times sake, undocumented (only in mk)
+--~ return flattened(t,1)
+--~ end
+
+--~ function table.are_equal(a,b)
+--~ return table.serialize(a) == table.serialize(b)
+--~ end
local function are_equal(a,b,n,m) -- indexed
if a and b and #a == #b then
@@ -739,7 +782,7 @@ end
local function identical(a,b) -- assumes same structure
for ka, va in next, a do
- local vb = b[k]
+ local vb = b[ka]
if va == vb then
-- same
elseif type(va) == "table" and type(vb) == "table" then
@@ -753,8 +796,8 @@ local function identical(a,b) -- assumes same structure
return true
end
-table.are_equal = are_equal
table.identical = identical
+table.are_equal = are_equal
-- maybe also make a combined one
@@ -780,14 +823,14 @@ function table.contains(t, v)
end
function table.count(t)
- local n, e = 0, next(t)
- while e do
- n, e = n + 1, next(t,e)
+ local n = 0
+ for k, v in next, t do
+ n = n + 1
end
return n
end
-function table.swapped(t,s)
+function table.swapped(t,s) -- hash
local n = { }
if s then
--~ for i=1,#s do
@@ -809,55 +852,34 @@ function table.swapped(t,s)
return n
end
---~ function table.are_equal(a,b)
---~ return table.serialize(a) == table.serialize(b)
---~ end
-
-function table.clone(t,p) -- t is optional or nil or table
- if not p then
- t, p = { }, t or { }
- elseif not t then
- t = { }
- end
- setmetatable(t, { __index = function(_,key) return p[key] end }) -- why not __index = p ?
- return t
-end
-
-function table.hexed(t,seperator)
- local tt = { }
- for i=1,#t do tt[i] = format("0x%04X",t[i]) end
- return concat(tt,seperator or " ")
-end
-
-function table.swaphash(h) -- needs another name
- local r = { }
- for k,v in next, h do
- r[v] = lower(gsub(k," ",""))
- end
- return r
-end
-
-function table.reverse(t)
- local tt = { }
- if #t > 0 then
- for i=#t,1,-1 do
- tt[#tt+1] = t[i]
+function table.reversed(t)
+ if t then
+ local tt, tn = { }, #t
+ if tn > 0 then
+ local ttn = 0
+ for i=tn,1,-1 do
+ ttn = ttn + 1
+ tt[ttn] = t[i]
+ end
end
+ return tt
end
- return tt
end
function table.sequenced(t,sep,simple) -- hash only
- local s = { }
+ local s, n = { }, 0
for k, v in sortedhash(t) do
if simple then
if v == true then
- s[#s+1] = k
+ n = n + 1
+ s[n] = k
elseif v and v~= "" then
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
else
- s[#s+1] = k .. "=" .. tostring(v)
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
end
end
return concat(s, sep or " | ")
@@ -867,7 +889,7 @@ function table.print(...)
table.tohandle(print,...)
end
--- -- -- obsolete but we keep them for a while and will comment them later -- -- --
+-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -882,12 +904,5 @@ function table.is_empty(t)
end
function table.has_one_entry(t)
- local n = next(t)
- return n and not next(t,n)
-end
-
-function table.replace(a,b)
- for k,v in next, b do
- a[k] = v
- end
+ return t and not next(t,next(t))
end