Comparison

util/ztact.lua @ 337:4a1dd1c2c219

We have SRV resolving \o/
author Matthew Wild <mwild1@gmail.com>
date Tue, 18 Nov 2008 22:41:04 +0000
child 519:cccd610a0ef9
comparison
equal deleted inserted replaced
336:d97d59cfd1e8 337:4a1dd1c2c219
1
2
3 -- public domain 20080410 lua@ztact.com
4
5
6 pcall (require, 'lfs') -- lfs may not be installed/necessary.
7 pcall (require, 'pozix') -- pozix may not be installed/necessary.
8
9
10 local getfenv, ipairs, next, pairs, pcall, require, select, tostring, type =
11 getfenv, ipairs, next, pairs, pcall, require, select, tostring, type
12 local unpack, xpcall =
13 unpack, xpcall
14
15 local io, lfs, os, string, table, pozix = io, lfs, os, string, table, pozix
16
17 local assert, print = assert, print
18
19 local error = error
20
21
22 module ((...) or 'ztact') ------------------------------------- module ztact
23
24
25 -- dir -------------------------------------------------------------------- dir
26
27
28 function dir (path) -- - - - - - - - - - - - - - - - - - - - - - - - - - dir
29 local it = lfs.dir (path)
30 return function ()
31 repeat
32 local dir = it ()
33 if dir ~= '.' and dir ~= '..' then return dir end
34 until not dir
35 end end
36
37
38 function is_file (path) -- - - - - - - - - - - - - - - - - - is_file (path)
39 local mode = lfs.attributes (path, 'mode')
40 return mode == 'file' and path
41 end
42
43
44 -- network byte ordering -------------------------------- network byte ordering
45
46
47 function htons (word) -- - - - - - - - - - - - - - - - - - - - - - - - htons
48 return (word-word%0x100)/0x100, word%0x100
49 end
50
51
52 -- pcall2 -------------------------------------------------------------- pcall2
53
54
55 getfenv ().pcall = pcall -- store the original pcall as ztact.pcall
56
57
58 local argc, argv, errorhandler, pcall2_f
59
60
61 local function _pcall2 () -- - - - - - - - - - - - - - - - - - - - - _pcall2
62 local tmpv = argv
63 argv = nil
64 return pcall2_f (unpack (tmpv, 1, argc))
65 end
66
67
68 function seterrorhandler (func) -- - - - - - - - - - - - - - seterrorhandler
69 errorhandler = func
70 end
71
72
73 function pcall2 (f, ...) -- - - - - - - - - - - - - - - - - - - - - - pcall2
74
75 pcall2_f = f
76 argc = select ('#', ...)
77 argv = { ... }
78
79 if not errorhandler then
80 local debug = require ('debug')
81 errorhandler = debug.traceback
82 end
83
84 return xpcall (_pcall2, errorhandler)
85 end
86
87
88 function append (t, ...) -- - - - - - - - - - - - - - - - - - - - - - append
89 local insert = table.insert
90 for i,v in ipairs {...} do
91 insert (t, v)
92 end end
93
94
95 function print_r (d, indent) -- - - - - - - - - - - - - - - - - - - print_r
96 local rep = string.rep (' ', indent or 0)
97 if type (d) == 'table' then
98 for k,v in pairs (d) do
99 if type (v) == 'table' then
100 io.write (rep, k, '\n')
101 print_r (v, (indent or 0) + 1)
102 else io.write (rep, k, ' = ', tostring (v), '\n') end
103 end
104 else io.write (d, '\n') end
105 end
106
107
108 function tohex (s) -- - - - - - - - - - - - - - - - - - - - - - - - - tohex
109 return string.format (string.rep ('%02x ', #s), string.byte (s, 1, #s))
110 end
111
112
113 function tostring_r (d, indent, tab0) -- - - - - - - - - - - - - tostring_r
114
115 tab1 = tab0 or {}
116 local rep = string.rep (' ', indent or 0)
117 if type (d) == 'table' then
118 for k,v in pairs (d) do
119 if type (v) == 'table' then
120 append (tab1, rep, k, '\n')
121 tostring_r (v, (indent or 0) + 1, tab1)
122 else append (tab1, rep, k, ' = ', tostring (v), '\n') end
123 end
124 else append (tab1, d, '\n') end
125
126 if not tab0 then return table.concat (tab1) end
127 end
128
129
130 -- queue manipulation -------------------------------------- queue manipulation
131
132
133 -- Possible queue states. 1 (i.e. queue.p[1]) is head of queue.
134 --
135 -- 1..2
136 -- 3..4 1..2
137 -- 3..4 1..2 5..6
138 -- 1..2 5..6
139 -- 1..2
140
141
142 local function print_queue (queue, ...) -- - - - - - - - - - - - print_queue
143 for i=1,10 do io.write ((queue[i] or '.')..' ') end
144 io.write ('\t')
145 for i=1,6 do io.write ((queue.p[i] or '.')..' ') end
146 print (...)
147 end
148
149
150 function dequeue (queue) -- - - - - - - - - - - - - - - - - - - - - dequeue
151
152 local p = queue.p
153 if not p and queue[1] then queue.p = { 1, #queue } p = queue.p end
154
155 if not p[1] then return nil end
156
157 local element = queue[p[1]]
158 queue[p[1]] = nil
159
160 if p[1] < p[2] then p[1] = p[1] + 1
161
162 elseif p[4] then p[1], p[2], p[3], p[4] = p[3], p[4], nil, nil
163
164 elseif p[5] then p[1], p[2], p[5], p[6] = p[5], p[6], nil, nil
165
166 else p[1], p[2] = nil, nil end
167
168 print_queue (queue, ' de '..element)
169 return element
170 end
171
172
173 function enqueue (queue, element) -- - - - - - - - - - - - - - - - - enqueue
174
175 local p = queue.p
176 if not p then queue.p = {} p = queue.p end
177
178 if p[5] then -- p3..p4 p1..p2 p5..p6
179 p[6] = p[6]+1
180 queue[p[6]] = element
181
182 elseif p[3] then -- p3..p4 p1..p2
183
184 if p[4]+1 < p[1] then
185 p[4] = p[4] + 1
186 queue[p[4]] = element
187
188 else
189 p[5] = p[2]+1
190 p[6], queue[p[5]] = p[5], element
191 end
192
193 elseif p[1] then -- p1..p2
194 if p[1] == 1 then
195 p[2] = p[2] + 1
196 queue[p[2]] = element
197
198 else
199 p[3], p[4], queue[1] = 1, 1, element
200 end
201
202 else -- empty queue
203 p[1], p[2], queue[1] = 1, 1, element
204 end
205
206 print_queue (queue, ' '..element)
207 end
208
209
210 local function test_queue ()
211 t = {}
212 enqueue (t, 1)
213 enqueue (t, 2)
214 enqueue (t, 3)
215 enqueue (t, 4)
216 enqueue (t, 5)
217 dequeue (t)
218 dequeue (t)
219 enqueue (t, 6)
220 enqueue (t, 7)
221 enqueue (t, 8)
222 enqueue (t, 9)
223 dequeue (t)
224 dequeue (t)
225 dequeue (t)
226 dequeue (t)
227 enqueue (t, 'a')
228 dequeue (t)
229 enqueue (t, 'b')
230 enqueue (t, 'c')
231 dequeue (t)
232 dequeue (t)
233 dequeue (t)
234 dequeue (t)
235 dequeue (t)
236 enqueue (t, 'd')
237 dequeue (t)
238 dequeue (t)
239 dequeue (t)
240 end
241
242
243 -- test_queue ()
244
245
246 function queue_len (queue)
247 end
248
249
250 function queue_peek (queue)
251 end
252
253
254 -- tree manipulation ---------------------------------------- tree manipulation
255
256
257 function set (parent, ...) --- - - - - - - - - - - - - - - - - - - - - - set
258
259 -- print ('set', ...)
260
261 local len = select ('#', ...)
262 local key, value = select (len-1, ...)
263 local cutpoint, cutkey
264
265 for i=1,len-2 do
266
267 local key = select (i, ...)
268 local child = parent[key]
269
270 if value == nil then
271 if child == nil then return
272 elseif next (child, next (child)) then cutpoint = nil cutkey = nil
273 elseif cutpoint == nil then cutpoint = parent cutkey = key end
274
275 elseif child == nil then child = {} parent[key] = child end
276
277 parent = child
278 end
279
280 if value == nil and cutpoint then cutpoint[cutkey] = nil
281 else parent[key] = value return value end
282 end
283
284
285 function get (parent, ...) --- - - - - - - - - - - - - - - - - - - - - - get
286 local len = select ('#', ...)
287 for i=1,len do
288 parent = parent[select (i, ...)]
289 if parent == nil then break end
290 end
291 return parent
292 end
293
294
295 -- misc ------------------------------------------------------------------ misc
296
297
298 function find (path, ...) --------------------------------------------- find
299
300 local dirs, operators = { path }, {...}
301 for operator in ivalues (operators) do
302 if not operator (path) then break end end
303
304 while next (dirs) do
305 local parent = table.remove (dirs)
306 for child in assert (pozix.opendir (parent)) do
307 if child and child ~= '.' and child ~= '..' then
308 local path = parent..'/'..child
309 if pozix.stat (path, 'is_dir') then table.insert (dirs, path) end
310 for operator in ivalues (operators) do
311 if not operator (path) then break end end
312 end end end end
313
314
315 function ivalues (t) ----------------------------------------------- ivalues
316 local i = 0
317 return function () if t[i+1] then i = i + 1 return t[i] end end
318 end
319
320
321 function lson_encode (mixed, f, indent, indents) --------------- lson_encode
322
323
324 local capture
325 if not f then
326 capture = {}
327 f = function (s) append (capture, s) end
328 end
329
330 indent = indent or 0
331 indents = indents or {}
332 indents[indent] = indents[indent] or string.rep (' ', 2*indent)
333
334 local type = type (mixed)
335
336 if type == 'number' then f (mixed)
337
338 else if type == 'string' then f (string.format ('%q', mixed))
339
340 else if type == 'table' then
341 f ('{')
342 for k,v in pairs (mixed) do
343 f ('\n')
344 f (indents[indent])
345 f ('[') f (lson_encode (k)) f ('] = ')
346 lson_encode (v, f, indent+1, indents)
347 f (',')
348 end
349 f (' }')
350 end end end
351
352 if capture then return table.concat (capture) end
353 end
354
355
356 function timestamp (time) ---------------------------------------- timestamp
357 return os.date ('%Y%m%d.%H%M%S', time)
358 end
359
360
361 function values (t) ------------------------------------------------- values
362 local k, v
363 return function () k, v = next (t, k) return v end
364 end