author | Waqas Hussain <waqas20@gmail.com> |
Thu, 12 Nov 2009 13:42:44 +0500 | |
changeset 2077 | e33658f6052c |
parent 1523 | 841d61be198f |
child 2958 | 49d6bf241653 |
permissions | -rw-r--r-- |
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 |