diff options
Diffstat (limited to 'tex/context/base/mkxl/util-pck.lmt')
-rw-r--r-- | tex/context/base/mkxl/util-pck.lmt | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/tex/context/base/mkxl/util-pck.lmt b/tex/context/base/mkxl/util-pck.lmt new file mode 100644 index 000000000..fff2d280a --- /dev/null +++ b/tex/context/base/mkxl/util-pck.lmt @@ -0,0 +1,176 @@ +if not modules then modules = { } end modules ['util-pck'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- moved from core-uti + +local next, tostring, type = next, tostring, type +local sort, concat = table.sort, table.concat +local format = string.format +local sortedhashkeys, sortedkeys, tohash = table.sortedhashkeys, table.sortedkeys, table.tohash + +utilities = utilities or { } +utilities.packers = utilities.packers or { } +local packers = utilities.packers +packers.version = 1.01 + +-- local fmt_kv <const> = "%s=%q" +-- local fmt_kt <const> = "%s={%q}" + +-- local function hashed(t) +-- local s, ns = { }, 0 +-- for k, v in next, t do +-- ns = ns + 1 +-- if type(v) == "table" then +-- s[ns] = format(fmt_kt,k,hashed(v)) +-- else +-- s[ns] = format(fmt_kv,k,v) +-- end +-- end +-- sort(s) +-- return concat(s,",") +-- end + +local function hashed(t) --local function tabstr_normal(t) + local s = { } + local n = 0 + for k, v in next, t do + n = n + 1 + if type(v) == "table" then + s[n] = k .. ">" .. hashed(v) + elseif v == true then + s[n] = k .. "+" -- "=true" + elseif v then + s[n] = k .. "=" .. v + else + s[n] = k .. "-" -- "=false" + end + end + if n == 0 then + return "" + elseif n == 1 then + return s[1] + else + sort(s) -- costly but needed (occasional wrong hit otherwise) + return concat(s,",") + end +end + +local function simplehashed(t) + local s = { } + local n = 0 + for k, v in next, t do + n = n + 1 + -- s[n] = format(fmt_kv,k,v) + s[n] = k .. "=" .. v + end + sort(s) + return concat(s,",") +end + +packers.hashed = hashed +packers.simplehashed = simplehashed + +-- In luatex < 0.74 (lua 5.1) a next chain was the same for each run so no sort was needed, +-- but in the latest greatest versions (lua 5.2) we really need to sort the keys in order +-- not to get endless runs due to a difference in tuc files. + +local function pack(t,keys,skip,hash,index) + if t then + local sk = #t > 0 and sortedkeys(t) or sortedhashkeys(t) + for i=1,#sk do + local k = sk[i] + if not skip or not skip[k] then + local v = t[k] + if type(v) == "table" then + pack(v,keys,skip,hash,index) + if keys[k] then + local h = hashed(v) + local i = hash[h] + if not i then + i = #index + 1 + index[i] = v + hash[h] = i + end + t[k] = i + end + end + end + end + end +end + +local function unpack(t,keys,skip,index) + if t then + for k, v in next, t do + if keys[k] and type(v) == "number" then + local iv = index[v] + if iv then + v = iv + t[k] = v + end + end + if type(v) == "table" and (not skip or not skip[k]) then + unpack(v,keys,skip,index) + end + end + end +end + +function packers.new(keys,version,skip) + return { + version = version or packers.version, + keys = tohash(keys), + skip = tohash(skip), + hash = { }, + index = { }, + } +end + +function packers.pack(t,p,shared) + if shared then + pack(t,p.keys,p.skip,p.hash,p.index) + elseif not t.packer then + pack(t,p.keys,p.skip,p.hash,p.index) + if #p.index > 0 then + t.packer = { + version = p.version or packers.version, + keys = p.keys, + skip = p.skip, + index = p.index, + } + end + p.hash = { } + p.index = { } + end +end + +function packers.unpack(t,p,shared) + if shared then + if p then + unpack(t,p.keys,p.skip,p.index) + end + else + local tp = t.packer + if tp then + if tp.version == (p and p.version or packers.version) then + unpack(t,tp.keys,tp.skip,tp.index) + else + return false + end + t.packer = nil + end + end + return true +end + +function packers.strip(p) + p.hash = nil +end + +-- We could have a packer.serialize where we first flush the shared table +-- and then use inline a reference . This saves an unpack. |