2014-09-14 08:36:58 +02:00

361 lines
6.4 KiB
Lua

local _tostring = tostring
module(..., package.seeall)
function tostring(value, stack)
local str = ''
stack = stack or {}
if type(value) ~= 'table' then
if type(value) == 'string' then
str = string.format("%q", value)
else
str = _tostring(value)
end
elseif stack[value] then
return '<recursion>'
else
stack[value] = true
local auxTable = {}
for k, v in pairs(value) do
auxTable[#auxTable + 1] = k
end
table.sort(auxTable, function (a, b) return _tostring(a) < _tostring(b) end)
str = str..'{'
local separator = ""
local entry = ""
for index, fieldName in ipairs(auxTable) do
if ((tonumber(fieldName)) and (tonumber(fieldName) > 0)) then
entry = tostring(value[tonumber(fieldName)], stack)
else
entry = tostring(fieldName) .. " = " .. tostring(rawget(value, fieldName), stack)
end
str = str..separator..entry
separator = ", "
end
str = str..'}'
local mt = getmetatable(value)
if mt then
str = str .. ' @meta = ' .. tostring(mt, stack)
end
end
return str
end
function map_in_place(t, fn)
for x = 1, #t do
t[x] = fn(t[x])
end
return t
end
function map(t, fn)
local result = {}
for idx = 1, #t do
result[idx] = fn(t[idx])
end
return result
end
function mapnil(table, fn)
if not table then
return nil
else
return map(table, fn)
end
end
function get_named_arg(tab, name, context)
local v = tab[name]
if v then
return v
else
if context then
error(context .. ": argument " .. name .. " must be specified", 3)
else
error("argument " .. name .. " must be specified", 3)
end
end
end
function parse_cmdline(args, blueprint)
local index, max = 2, #args
local options, targets = {}, {}
local lookup = {}
for _, opt in ipairs(blueprint) do
if opt.Short then
lookup[opt.Short] = opt
end
if opt.Long then
lookup[opt.Long] = opt
end
end
while index <= max do
local s = args[index]
local key, val
if s:sub(1, 2) == '--' then
key, val = s:match("^%-%-([-a-zA-Z0-9]+)=(.*)$")
if not key then
key = s:sub(3)
end
elseif s:sub(1, 1) == '-' then
key = s:sub(2,2)
if s:len() > 2 then
val = s:sub(3)
end
else
table.insert(targets, s)
end
if key then
local opt = lookup[key]
if not opt then
return nil, nil, "Unknown option " .. s
end
if opt.HasValue then
if not val then
index = index + 1
val = args[index]
end
if val then
options[opt.Name] = val
else
return nil, nil, "Missing value for option "..s
end
else
local v = options[opt.Name] or 0
options[opt.Name] = v + 1
end
end
index = index + 1
end
return options, targets
end
function clone_table(t)
if t then
local r = {}
for k, v in pairs(t) do
r[k] = v
end
for k, v in ipairs(t) do
r[k] = v
end
return r
else
return nil
end
end
function deep_clone_table(t)
local function clone_value(v)
if type(v) == "table" then
return deep_clone_table(v)
else
return v
end
end
if t then
local r = {}
for k, v in pairs(t) do
r[clone_value(k)] = clone_value(v)
end
for k, v in ipairs(t) do
r[k] = clone_value(v)
end
return r
else
return nil
end
end
function clone_array(t)
local r = {}
for k, v in ipairs(t) do
r[k] = v
end
return r
end
function merge_arrays(...)
local result = {}
local count = select('#', ...)
for i = 1, count do
local tab = select(i, ...)
if tab then
for _, v in ipairs(tab) do
result[#result + 1] = v
end
end
end
return result
end
function merge_arrays_2(a, b)
if a and b then
return merge_arrays(a, b)
elseif a then
return a
elseif b then
return b
else
return {}
end
end
function matches_any(str, patterns)
for _, pattern in ipairs(patterns) do
if str:match(pattern) then
return true
end
end
return false
end
function return_nil()
end
function nil_pairs(t)
if t then
return next, t
else
return return_nil
end
end
function nil_ipairs(t)
if t then
return ipairs(t)
else
return return_nil
end
end
function clear_table(tab)
local key, val = next(tab)
while key do
tab[key] = nil
key, val = next(tab, key)
end
return tab
end
function filter(tab, predicate)
local result = {}
for _, x in ipairs(tab) do
if predicate(x) then
result[#result + 1] = x
end
end
return result
end
function filter_nil(tab, predicate)
if not predicate then return nil end
local result = {}
for _, x in ipairs(tab) do
if predicate(x) then
result[#result + 1] = x
end
end
return result
end
function filter_in_place(tab, predicate)
local i, limit = 1, #tab
while i <= limit do
if not predicate(tab[i]) then
table.remove(tab, i)
limit = limit - 1
else
i = i + 1
end
end
return tab
end
function append_table(result, items)
local offset = #result
for i = 1, #items do
result[offset + i] = items[i]
end
return result
end
function flatten(array)
local function iter(item, accum)
if type(item) == 'table' and not getmetatable(item) then
for _, sub_item in ipairs(item) do
iter(sub_item, accum)
end
else
accum[#accum + 1] = item
end
end
local accum = {}
iter(array, accum)
return accum
end
function memoize(closure)
local result = nil
return function(...)
if not result then
result = assert(closure(...))
end
return result
end
end
function uniq(array)
local seen = {}
local result = {}
for _, val in nil_ipairs(array) do
if not seen[val] then
seen[val] = true
result[#result + 1] = val
end
end
return result
end
function make_lookup_table(array)
local result = {}
for _, item in nil_ipairs(array) do
result[item] = true
end
return result
end
function table_keys(array)
local result = {}
for k, _ in nil_pairs(array) do
result[#result + 1] = k
end
return result
end
function table_values(array)
local result = {}
for _, v in nil_pairs(array) do
result[#result + 1] = v
end
return result
end
function array_contains(array, find)
for _, val in ipairs(array) do
if val == find then
return true
end
end
return false
end