setmetatable(inst, {__index = class})
if inst.__init__ then
- local stat, err = pcall(inst.__init__, inst, ...)
+ local stat, err = copcall(inst.__init__, inst, ...)
if not stat then
error(err)
end
-- Checks whether a table has an object "value" in it
function contains(table, value)
- for k,v in pairs(table) do
+ for k, v in pairs(table) do
if value == v then
- return true
+ return k
end
end
return false
end
+-- Dumps and strips a Lua-Function
+function dump(f)
+ local d = string.dump(f)
+ return d and strip_bytecode(d)
+end
+
+
-- Dumps a table to stdout (useful for testing and debugging)
function dumptable(t, i)
i = i or 0
for k,v in pairs(t) do
- print(string.rep("\t", i) .. k, v)
+ print(string.rep("\t", i) .. tostring(k), tostring(v))
if type(v) == "table" then
dumptable(v, i+1)
end
end
+-- Returns an error message to stdout
+function perror(obj)
+ io.stderr:write(tostring(obj) .. "\n")
+end
+
+
-- Resets the scope of f doing a shallow copy of its scope into a new table
function resfenv(f)
setfenv(f, clone(getfenv(f)))
return t
end
+
+-- Strips lua bytecode
+-- Original version by Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
+function strip_bytecode(dump)
+ local version, format, endian, int, size, ins, num, lnum = dump:byte(5, 12)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + dump:byte(i + n - 1)
+ end
+ return val, i + l
+ end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + dump:byte(i + n - 1)
+ end
+ return val, i + l
+ end
+ end
+
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = string.rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ elseif t == 254 or t == 9 then
+ offset = offset + lnum
+ end
+ end
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. dump:sub(dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(dump:sub(offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
+ end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. string.rep("\0", int * 3)
+ return stripped, offset
+ end
+
+ return dump:sub(1,12) .. strip_function(dump:sub(13,-1))
+end
+
+
+-- Creates a new threadlocal store
+function threadlocal()
+ local tbl = {}
+
+ local function get(self, key)
+ local c = coroutine.running()
+ local thread = coxpt[c] or c or 0
+ if not rawget(self, thread) then
+ return nil
+ end
+ return rawget(self, thread)[key]
+ end
+
+ local function set(self, key, value)
+ local c = coroutine.running()
+ local thread = coxpt[c] or c or 0
+ if not rawget(self, thread) then
+ rawset(self, thread, {})
+ end
+ rawget(self, thread)[key] = value
+ end
+
+ setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"})
+
+ return tbl
+end
+
+
-- Removes whitespace from beginning and end of a string
function trim(str)
local s = str:gsub("^%s*(.-)%s*$", "%1")
return s
end
+
-- Updates given table with new values
function update(t, updates)
for k, v in pairs(updates) do
end
--- Validates a variable
-function validate(value, cast_number, cast_int)
- if cast_number or cast_int then
- value = tonumber(value)
+-- Parse units from a string and return integer value
+function parse_units(ustr)
+
+ local val = 0
+
+ -- unit map
+ local map = {
+ -- date stuff
+ y = 60 * 60 * 24 * 366,
+ m = 60 * 60 * 24 * 31,
+ w = 60 * 60 * 24 * 7,
+ d = 60 * 60 * 24,
+ h = 60 * 60,
+ min = 60,
+
+ -- storage sizes
+ kb = 1024,
+ mb = 1024 * 1024,
+ gb = 1024 * 1024 * 1024,
+
+ -- storage sizes (si)
+ kib = 1000,
+ mib = 1000 * 1000,
+ gib = 1000 * 1000 * 1000
+ }
+
+ -- parse input string
+ for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
+
+ local num = spec:gsub("[^0-9%.]+$","")
+ local spn = spec:gsub("^[0-9%.]+", "")
+
+ if map[spn] or map[spn:sub(1,1)] then
+ val = val + num * ( map[spn] or map[spn:sub(1,1)] )
+ else
+ val = val + num
+ end
+ end
+
+
+ return val
+end
+
+
+-- Provide various sorting iterators
+function _sortiter( t, f )
+ local keys = { }
+
+ for k, v in pairs(t) do
+ table.insert( keys, k )
end
-
- if cast_int and value and not(value % 1 == 0) then
- value = nil
+
+ local _pos = 0
+ local _len = table.getn( keys )
+
+ table.sort( keys, f )
+
+ return function()
+ _pos = _pos + 1
+ if _pos <= _len then
+ return keys[_pos], t[keys[_pos]]
+ end
end
-
- return value
-end
\ No newline at end of file
+end
+
+-- Return key, value pairs sorted by provided callback function
+function spairs(t,f)
+ return _sortiter( t, f )
+end
+
+-- Return key, value pairs sorted by keys
+function kspairs(t)
+ return _sortiter( t )
+end
+
+-- Return key, value pairs sorted by values
+function vspairs(t)
+ return _sortiter( t, function (a,b) return t[a] < t[b] end )
+end
+
+
+-- Coroutine safe xpcall and pcall versions modified for Luci
+-- original version:
+-- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
+local performResume, handleReturnValue
+local oldpcall, oldxpcall = pcall, xpcall
+coxpt = {}
+setmetatable(coxpt, {__mode = "kv"})
+
+function handleReturnValue(err, co, status, ...)
+ if not status then
+ return false, err(debug.traceback(co, (...)), ...)
+ end
+ if coroutine.status(co) == 'suspended' then
+ return performResume(err, co, coroutine.yield(...))
+ else
+ return true, ...
+ end
+end
+
+function performResume(err, co, ...)
+ return handleReturnValue(err, co, coroutine.resume(co, ...))
+end
+
+function coxpcall(f, err, ...)
+ local res, co = oldpcall(coroutine.create, f)
+ if not res then
+ local params = {...}
+ local newf = function() return f(unpack(params)) end
+ co = coroutine.create(newf)
+ end
+ local c = coroutine.running()
+ coxpt[co] = coxpt[c] or c or 0
+
+ return performResume(err, co, ...)
+end
+
+local function id(trace, ...)
+ return ...
+end
+
+function copcall(f, ...)
+ return coxpcall(f, id, ...)
+end