1if not modules then modules = { } end modules ['util-pck'] = {
2 version = 1.001,
3 comment = "companion to luat-lib.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11local next, tostring, type = next, tostring, type
12local sort, concat = table.sort, table.concat
13local format = string.format
14local sortedhashkeys, sortedkeys, tohash = table.sortedhashkeys, table.sortedkeys, table.tohash
15
16utilities = utilities or { }
17utilities.packers = utilities.packers or { }
18local packers = utilities.packers
19packers.version = 1.01
20
21local fmt_kv = JITSUPPORTED and "%s=%s" or "%s=%q"
22local fmt_kt = JITSUPPORTED and "%s={%s}" or "%s={%q}"
23
24local function hashed(t)
25 local s, ns = { }, 0
26 for k, v in next, t do
27 ns = ns + 1
28 if type(v) == "table" then
29 s[ns] = format(fmt_kt,k,hashed(v))
30 else
31 s[ns] = format(fmt_kv,k,v)
32 end
33 end
34 sort(s)
35 return concat(s,",")
36end
37
38local function simplehashed(t)
39 local s, ns = { }, 0
40 for k, v in next, t do
41 ns = ns + 1
42 s[ns] = format(fmt_kv,k,v)
43 end
44 sort(s)
45 return concat(s,",")
46end
47
48packers.hashed = hashed
49packers.simplehashed = simplehashed
50
51
52
53
54
55local function pack(t,keys,skip,hash,index)
56 if t then
57 local sk = #t > 0 and sortedkeys(t) or sortedhashkeys(t)
58 for i=1,#sk do
59 local k = sk[i]
60 if not skip or not skip[k] then
61 local v = t[k]
62 if type(v) == "table" then
63 pack(v,keys,skip,hash,index)
64 if keys[k] then
65 local h = hashed(v)
66 local i = hash[h]
67 if not i then
68 i = #index + 1
69 index[i] = v
70 hash[h] = i
71 end
72 t[k] = i
73 end
74 end
75 end
76 end
77 end
78end
79
80local function unpack(t,keys,skip,index)
81 if t then
82 for k, v in next, t do
83 if keys[k] and type(v) == "number" then
84 local iv = index[v]
85 if iv then
86 v = iv
87 t[k] = v
88 end
89 end
90 if type(v) == "table" and (not skip or not skip[k]) then
91 unpack(v,keys,skip,index)
92 end
93 end
94 end
95end
96
97function packers.new(keys,version,skip)
98 return {
99 version = version or packers.version,
100 keys = tohash(keys),
101 skip = tohash(skip),
102 hash = { },
103 index = { },
104 }
105end
106
107function packers.pack(t,p,shared)
108 if shared then
109 pack(t,p.keys,p.skip,p.hash,p.index)
110 elseif not t.packer then
111 pack(t,p.keys,p.skip,p.hash,p.index)
112 if #p.index > 0 then
113 t.packer = {
114 version = p.version or packers.version,
115 keys = p.keys,
116 skip = p.skip,
117 index = p.index,
118 }
119 end
120 p.hash = { }
121 p.index = { }
122 end
123end
124
125function packers.unpack(t,p,shared)
126 if shared then
127 if p then
128 unpack(t,p.keys,p.skip,p.index)
129 end
130 else
131 local tp = t.packer
132 if tp then
133 if tp.version == (p and p.version or packers.version) then
134 unpack(t,tp.keys,tp.skip,tp.index)
135 else
136 return false
137 end
138 t.packer = nil
139 end
140 end
141 return true
142end
143
144function packers.strip(p)
145 p.hash = nil
146end
147
148
149
150 |