function string.hasSuffix(str, suffix) return string.sub(str, #suffix+1) == suffix end function string.hasPrefix(str, prefix) return string.sub(str, 1, #prefix) == prefix end function string.getSuffix(str, prefix) return string.sub(str, #prefix+1) end function string.getPrefix(str, suffix) return string.sub(str, 1, #suffix) end function string.join(str, ...) return table.concat(table.pack(str, ...)) end function string.delim(str, ...) return table.concat(table.pack(...), str) end function string.split(str, delim, maxResultCountOrNil) assert(#delim == 1, "only delim len 1 supported for now") maxResultCountOrNil = (maxResultCountOrNil or 0)-1 local rv = {} local buf = "" for i = 1, #str do local c = string.sub(str,i,i) if #rv ~= maxResultCountOrNil and c == delim then table.insert(rv, buf) buf = "" else buf = buf..c end end table.insert(rv, buf) return rv end function string.replace(str, search, replacement) local rv = "" local consumedLen = 1 local i = 1 while i<#str do if string.sub(str, i, i+#search-1) == search then rv = rv .. string.sub(str, consumedLen, i-1) .. replacement i=i+#search consumedLen = i end i=i+1 end return rv .. string.sub(str, consumedLen) end function table.deepcopy(orig, copies) copies = copies or {} if type(orig) ~= 'table' then return orig elseif copies[orig] then return copies[orig] end local copy = {} copies[orig] = copy for k, v in next, orig, nil do local copied_key = table.deepcopy(k, copies) local copied_val = table.deepcopy(v, copies) copy[copied_key] = copied_val end return copy end function table.hasKey(tabl, query) for i,v in pairs(tabl) do if i==query then return true end end return false end function table.hasVal(tabl, query) for i,v in pairs(tabl) do if v==query then return true end end return false end function table.proxy(tbl) local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles local function createProxy(t) if type(t) ~= "table" then return t end if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles) local proxy = {} proxies[t] = proxy local mt mt = { __index = function(_, k) local value = t[k] if type(value) == "table" then return createProxy(value) -- recursively proxy subtables else return value end end, __newindex = function() error("Attempt to modify table proxy", 2) end, __pairs = function() return function(_, k) local nextKey, nextValue = next(t, k) if type(nextValue) == "table" then nextValue = createProxy(nextValue) end return nextKey, nextValue end, nil, nil end, __ipairs = function() local i = 0 local n = #t return function() i = i + 1 if i <= n then local v = t[i] if type(v) == "table" then v = createProxy(v) end return i, v end end end, __metatable = false } setmetatable(proxy, mt) return proxy end return createProxy(tbl) end local function serialize(table) local output = "{" for i,v in pairs(table) do local coma=true if type(i) == "string" then output=output.."[\""..i.."\"]=" elseif type(i) == "number" then output=output.."["..tostring(i).."]=" end if type(v) == "table" then if v == table then output=string.sub(output,1,#output-(#i+1)) coma=false else output=output..serialize(v) end elseif type(v) == "string" then output=output.."[=["..v.."]=]" elseif type(v) == "number" then output=output..tostring(v) elseif type(v) == "boolean" then if v == true then output=output.."true" else output=output.."false" end elseif type(v) == "function" then output=output..tostring(v) else error("serialization of type \""..type(v).."\" is not supported") end if coma then output=output.."," end end if #table>0 or string.sub(output,#output,#output) == "," then output=string.sub(output,1,#output-1) end output=output.."}" return output end local oldtype=type local oldgetmetatable=getmetatable function type(object, trueType) if trueType then return oldtype(object) end if oldtype(object)~="table" then return oldtype(object) else if oldtype(oldgetmetatable(object))=="table" then local metatable = oldgetmetatable(object) if metatable.__type then return metatable.__type end else return "table" end end end function getmetatable(object) if oldtype(object)~="table" then return end if oldtype(oldgetmetatable(object))=="table" then if oldgetmetatable(object).__isuserdata then if oldtype(oldgetmetatable(object).__usermeta)=="function" then return oldgetmetatable(object).__usermeta() else return oldgetmetatable(object).__usermeta end else return oldgetmetatable(object) end else return oldgetmetatable(object) end end function isEqualToAny(a, ...) local args={...} for i=0, #args do if a==args[i] then return true end end return false end function isEqualToAll(a, ...) local args={...} for i=0, #args do if a~=args[i] then return false end end return true end function table.keys(t) local a = {} for n in pairs(t) do table.insert(a, n) end return a end function table.values(t) local a = {} for _, n in pairs(t) do table.insert(a, n) end return a end function table.indexOf(t, value) for i,v in ipairs(t) do if v==value then return i end end return -1 end syscall = setmetatable({}, { __index = function(self, name) return function(...) local res = table.pack(coroutine.yield("syscall", name, ...)) if res[1] then return table.unpack(res, 2, res.n) else error(res[2], 2) end end end }) table.serialize=serialize