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
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38local function hashed(t)
39 local s = { }
40 local n = 0
41 for k, v in next, t do
42 n = n + 1
43 if type(v) == "table" then
44 s[n] = k .. ">" .. hashed(v)
45 elseif v == true then
46 s[n] = k .. "+"
47 elseif v then
48 s[n] = k .. "=" .. v
49 else
50 s[n] = k .. "-"
51 end
52 end
53 if n == 0 then
54 return ""
55 elseif n == 1 then
56 return s[1]
57 else
58 sort(s)
59 return concat(s,",")
60 end
61end
62
63local function simplehashed(t)
64 local s = { }
65 local n = 0
66 for k, v in next, t do
67 n = n + 1
68
69 s[n] = k .. "=" .. v
70 end
71 sort(s)
72 return concat(s,",")
73end
74
75packers.hashed = hashed
76packers.simplehashed = simplehashed
77
78
79
80
81
82local function pack(t,keys,skip,hash,index)
83 if t then
84 local sk = #t > 0 and sortedkeys(t) or sortedhashkeys(t)
85 for i=1,#sk do
86 local k = sk[i]
87 if not skip or not skip[k] then
88 local v = t[k]
89 if type(v) == "table" then
90 pack(v,keys,skip,hash,index)
91 if keys[k] then
92 local h = hashed(v)
93 local i = hash[h]
94 if not i then
95 i = #index + 1
96 index[i] = v
97 hash[h] = i
98 end
99 t[k] = i
100 end
101 end
102 end
103 end
104 end
105end
106
107local function unpack(t,keys,skip,index)
108 if t then
109 for k, v in next, t do
110 if keys[k] and type(v) == "number" then
111 local iv = index[v]
112 if iv then
113 v = iv
114 t[k] = v
115 end
116 end
117 if type(v) == "table" and (not skip or not skip[k]) then
118 unpack(v,keys,skip,index)
119 end
120 end
121 end
122end
123
124function packers.new(keys,version,skip)
125 return {
126 version = version or packers.version,
127 keys = tohash(keys),
128 skip = tohash(skip),
129 hash = { },
130 index = { },
131 }
132end
133
134function packers.pack(t,p,shared)
135 if shared then
136 pack(t,p.keys,p.skip,p.hash,p.index)
137 elseif not t.packer then
138 pack(t,p.keys,p.skip,p.hash,p.index)
139 if #p.index > 0 then
140 t.packer = {
141 version = p.version or packers.version,
142 keys = p.keys,
143 skip = p.skip,
144 index = p.index,
145 }
146 end
147 p.hash = { }
148 p.index = { }
149 end
150end
151
152function packers.unpack(t,p,shared)
153 if shared then
154 if p then
155 unpack(t,p.keys,p.skip,p.index)
156 end
157 else
158 local tp = t.packer
159 if tp then
160 if tp.version == (p and p.version or packers.version) then
161 unpack(t,tp.keys,tp.skip,tp.index)
162 else
163 return false
164 end
165 t.packer = nil
166 end
167 end
168 return true
169end
170
171function packers.strip(p)
172 p.hash = nil
173end
174
175
176
177 |