| 1 |
|
| 2 |
|
| 3 | |
| 4 |
|
| 5 |
|
| 6 | pcall (require, 'lfs') |
| 7 | pcall (require, 'pozix') |
| 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') |
| 23 |
|
| 24 |
|
| 25 | |
| 26 |
|
| 27 |
|
| 28 | function dir (path) |
| 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) |
| 39 | local mode = lfs.attributes (path, 'mode')
|
| 40 | return mode == 'file' and path
|
| 41 | end
|
| 42 |
|
| 43 |
|
| 44 | |
| 45 |
|
| 46 |
|
| 47 | function htons (word) |
| 48 | return (word-word%0x100)/0x100, word%0x100
|
| 49 | end
|
| 50 |
|
| 51 |
|
| 52 | |
| 53 |
|
| 54 |
|
| 55 | getfenv ().pcall = pcall |
| 56 |
|
| 57 |
|
| 58 | local argc, argv, errorhandler, pcall2_f
|
| 59 |
|
| 60 |
|
| 61 | local function _pcall2 () |
| 62 | local tmpv = argv
|
| 63 | argv = nil
|
| 64 | return pcall2_f (unpack (tmpv, 1, argc))
|
| 65 | end
|
| 66 |
|
| 67 |
|
| 68 | function seterrorhandler (func) |
| 69 | errorhandler = func
|
| 70 | end
|
| 71 |
|
| 72 |
|
| 73 | function pcall2 (f, ...) |
| 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, ...) |
| 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) |
| 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) |
| 109 | return string.format (string.rep ('%02x ', #s), string.byte (s, 1, #s))
|
| 110 | end
|
| 111 |
|
| 112 |
|
| 113 | function tostring_r (d, indent, tab0) |
| 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 | |
| 131 |
|
| 132 |
|
| 133 | |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 | |
| 139 | |
| 140 |
|
| 141 |
|
| 142 | local function print_queue (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) |
| 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) |
| 174 |
|
| 175 | local p = queue.p
|
| 176 | if not p then queue.p = {} p = queue.p end
|
| 177 |
|
| 178 | if p[5] then |
| 179 | p[6] = p[6]+1
|
| 180 | queue[p[6]] = element
|
| 181 |
|
| 182 | elseif p[3] then |
| 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 |
| 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 |
| 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 | |
| 244 |
|
| 245 |
|
| 246 | function queue_len (queue)
|
| 247 | end
|
| 248 |
|
| 249 |
|
| 250 | function queue_peek (queue)
|
| 251 | end
|
| 252 |
|
| 253 |
|
| 254 | |
| 255 |
|
| 256 |
|
| 257 | function set (parent, ...) |
| 258 |
|
| 259 | |
| 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, ...) |
| 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 | |
| 296 |
|
| 297 |
|
| 298 | function find (path, ...) |
| 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) |
| 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) |
| 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) |
| 357 | return os.date ('%Y%m%d.%H%M%S', time)
|
| 358 | end
|
| 359 |
|
| 360 |
|
| 361 | function values (t) |
| 362 | local k, v
|
| 363 | return function () k, v = next (t, k) return v end
|
| 364 | end
|