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