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