-- Written by Rabia Alhaffar in 24/February/2021 -- polyfill.lua, Polyfills for Lua and LuaJIT in one file! -- Updated: 11/April/2021 --[[ MIT License Copyright (c) 2021 - 2022 Rabia Alhaffar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -- require if (not require) and package then require = function(p) if package.loaded[p] then return package.loaded[p] else return package.searchpath(p, "./?/?.lua;./?.lua;./?.lc;./"..package.loaddir.."/?/init.lua"..";./"..package.loaddir.."/?.lua") end end end local polyfill = { _VERSION = 0.1, _AUTHOR = "Rabia Alhaffar (steria773/@Rabios)", _AUTHOR_URL = "https://github.com/Rabios", _URL = "https://github.com/Rabios/polyfill.lua", _LICENSE = "MIT", _DATE = "3/March/2021", _LUAJIT = ((require("jit") or jit) and true or false), } local ffi = ((require("ffi") or require("luaffi") or ffi) or nil) --> Do we have FFI? if not _VERSION then _VERSION = "Lua 5.1" end -- module: ffi -- Partial FFI polyfill for LuaJIT (And PUC-RIO's Lua if yours have FFI installed) if ffi then -- ffi.string if not ffi.string then ffi.string = function(s) local str = ffi.new("char[?]", #s) ffi.copy(str, s) return str end end -- ffi.os if polyfill._LUAJIT then if not ffi.os then ffi.os = (require("jit").os or jit.os) end end -- ffi.arch if not ffi.arch then if (0xfffffffff == 0xffffffff) then ffi.arch = "x86" else ffi.arch = "x64" end end end -- module: Runtime (Global functions) -- Functions -- setglobal if not setglobal then setglobal = function(var, val) _G[var] = val end end -- getglobal if not getglobal then getglobal = function(var) return _G[var] end end -- rawgetglobal if not rawgetglobal then rawgetglobal = function(var) return _G[var] end end -- rawsetglobal if not rawsetglobal then rawsetglobal = function(var, val) _G[var] = val end end -- globals if not globals then globals = function(t) if not t then return _G else _G = t end end end -- newtag if not newtag then newtag = function() return { __index = self } end end -- setfallback if not setfallback then setfallback = function(fname, f) _G[fname] = f end end -- select if not select then select = function(n, ...) local args = { ... } return args[n] end end -- _ALERT if not _ALERT then _ALERT = function(msg) local n = select("#", msg) for i = 1, n do local v = tostring(select(i, msg)) io.stderr:write(v) if i ~= n then io.stderr:write("\t") end end io.stderr:write("\n") io.stderr:flush() end end -- error if not error then error = function(msg) coroutine.yield(msg) end end -- print if not print then print = function(...) local n = select("#", ...) for i = 1, n do local v = tostring(select(i, ...)) io.write(v) if i ~= n then io.write("\t") end end io.write("\n") io.flush() end end -- next if not next then next = function(t, k) local m = getmetatable(t) local n = m and m.__next or next return n(t, k) end end -- nextvar if not nextvar then nextvar = function(name) local m = _G[name] local n = m and m.__next or nextvar return n(_G, name) end end -- tostring if not tostring then tostring = function(n) return "\""..(n).."\"" end end -- tonumber (Requires FFI for atof function) if not tonumber then if ffi then ffi.cdef("float atof(const char *_Str);") tonumber = function(s) return ffi.C.atof(s) end end end -- ipairs if not ipairs then iterate = function(t, i) i = i + 1 local v = t[i] if v then return i, v end end ipairs = function(t) return iterate, t, 0 end end -- pairs if not pairs then pairs = function(t) return next, t, nil end end -- foreach if not foreach then foreach = function(t, f) for k, v in pairs(t) do f(k, v) end end end -- foreachi if not foreachi then foreachi = function(t, f) for k, v in ipairs(t) do f(k, v) end end end -- foreachvar if not foreachvar then foreachvar = function(f) local n, v = nextvar(nil) while n do local res = f(n, v) if res then return res end n, v = nextvar(n) end end end -- gcinfo if not gcinfo then gcinfo = function() return collectgarbage("count") end end -- settag if not settag then settag = function(t, tag) setmetatable(t, tag) end end -- assert if not assert then assert = function(v, m) if not v then m = m or "" error("assertion failed! " .. m) end end end -- loadfile if not loadfile then loadfile = function(src) local file = io.open(src) content = "" if not (_VERSION == "Lua 5.4" or _VERSION == "Lua 5.3") then content = file:read("*all") else content = file:read("*a") end file:close() return function() if assert(load(content), "Loading code string failed!") then return load(content) end end end end -- loadstring if not loadstring then loadstring = function(str) if assert(load(str), "Loading code string failed!") then return load(str) end end end -- dofile if not dofile then dofile = function(path) if assert(loadfile(path), "Loading file " .. path .. " failed!\n") then return loadfile(path)() end end end -- dostring if not dostring then dostring = function(str) if assert(load(str), "Loading code string failed!") then return load(str) end end end -- loadlib if not loadlib then if package.loadlib then loadlib = function(lib, fname) return package.loadlib(lib, fname) end end end -- rawlen if not rawlen then rawlen = function(o) if o then return #o end end end -- rawget if not rawget then rawget = function(t, i) if t then return t[i] end end end -- rawset if not rawset then rawset = function(t, i, v) if t then t[i] = v end end end -- rawequal if not rawequal then rawequal = function(a, b) if (a and type(a) == "table") and (b and type(b) == "table") then return (#a == #b) end end end -- copytagmethods if not copytagmethods then copytagmethods = function(from, to) local funcs = {} for k, v in pairs(getmetatable(from)) do if (type(v) == "function") then funcs[k] = v end end for k, v in pairs(getmetatable(to)) do getmetatable(to)[k] = funcs[k] end end end -- gettagmethod if not gettagmethod then gettagmethod = function(tag, method) return getmetatable(tag)[method] end end -- settagmethod if not settagmethod then settagmethod = function(tag, event, newmethod) getmetatable(tag)[event] = newmethod or function() end end end -- call if not call then call = function(f, args) if (type(f) == "function") then return f(table.unpack(args)) end end end -- pcall if not pcall then pcall = function(f, ...) local args = { ... } local co = coroutine.create(f) local err = coroutine.resume(co, table.unpack(args)) if (coroutine.status == "dead") then return true else return false, err end end end -- xpcall if not xpcall then xpcall = function(f, msgh, ...) local args = { ... } local co = coroutine.create(f) local err = coroutine.resume(co, table.unpack(args)) if (coroutine.status == "dead") then return true else return false, "Error: " .. msgh end end end -- setenv if not setenv then setenv = function(t) _ENV = t --_G = t end end -- getinfo if not getinfo then getinfo = debug.getinfo end -- getlocal if not getlocal then getlocal = debug.getlocal end -- setlocal if not setlocal then setlocal = debug.setlocal end -- getlinehook if not getlinehook then getlinehook = debug.gethook end -- setlinehook if not setlinehook then setlinehook = debug.sethook end -- rawgettable if not rawgettable then rawgettable = rawget end -- rawsettable if not rawsettable then rawsettable = rawset end -- debug.debug if type(debug) == "function" then local df = debug debug = {} debug.debug = df end -- module: table table = require("table") or {} -- Functions -- table.insert if not table.insert then table.insert = function(t, i, v) if not v then t[#t + 1] = i else t[i] = v end end end -- tinsert if not tinsert then tinsert = function(t, i, v) if not v then t[#t + 1] = i else t[i] = v end end end -- table.remove if not table.remove then table.remove = function(t, i) if not i then i = #t end local result = t[i] t[i] = nil return result end end -- tremove if not tremove then tremove = function(t, i) if not i then i = #t end local result = t[i] t[i] = nil return result end end -- table.concat if not table.concat then table.concat = function(t, s) local result = "" for str in ipairs(t, str) do if (type(t[str]) == "string") then if (str == #t) then s = "" end result = result..(t[str]..s) elseif (type(t[str]) == "number") then if (str == #t) then s = "" end result = result..(tostring(t[str])..s) end end return result end end -- table.unpack if not table.unpack then table.unpack = function(t, i) i = i or 1 if (i <= #t) then return t[i], table.unpack(t, i + 1) end end end -- unpack if not unpack then unpack = function(t, i) i = i or 1 if (t[i] ~= nil) then return t[i], unpack(t, i + 1) end end end -- table.pack if not table.pack then table.pack = function(...) local t = { ... } t.n = #t return t end end -- table.move if not table.move then table.move = function(t1, f, e, t, t2) local nums = (e - 1) for i = 0, nums, 1 do t2[t + i] = t1[f + i] end end end -- table.sort if not table.sort then table.sort = function(t, f) f = f or nil if #t < 2 then return t end local pivot = t[1] if (type(pivot) == "string") then pivot = #t[1] end local a, b, c = {}, {}, {} for _, v in ipairs(t) do if (type(f) == "function") then if (type(v) == "number") then if (f(v, pivot) == true) then a[#a + 1] = v elseif(f(v, pivot) == false) then c[#c + 1] = v elseif (type(f(v, pivot)) ~= "boolean") then b[#b + 1] = v end end else if (type(v) == "number") then if v < pivot then a[#a + 1] = v elseif v > pivot then c[#c + 1] = v else b[#b + 1] = v end elseif (type(v) == "string") then if #v < pivot then a[#a + 1] = v elseif #v > pivot then c[#c + 1] = v else b[#b + 1] = v end end end end a = table.sort(a) c = table.sort(c) for _, v in ipairs(b) do a[#a + 1] = v end for _, v in ipairs(c) do a[#a + 1] = v end return a end end -- sort if not sort then sort = function(t, f) f = f or nil if #t < 2 then return t end local pivot = t[1] if (type(pivot) == "string") then pivot = #t[1] end local a, b, c = {}, {}, {} for _, v in ipairs(t) do if (type(f) == "function") then if (type(v) == "number") then if (f(v, pivot) == true) then a[#a + 1] = v elseif(f(v, pivot) == false) then c[#c + 1] = v elseif (type(f(v, pivot)) ~= "boolean") then b[#b + 1] = v end end else if (type(v) == "number") then if v < pivot then a[#a + 1] = v elseif v > pivot then c[#c + 1] = v else b[#b + 1] = v end elseif (type(v) == "string") then if #v < pivot then a[#a + 1] = v elseif #v > pivot then c[#c + 1] = v else b[#b + 1] = v end end end end a = sort(a) c = sort(c) for _, v in ipairs(b) do a[#a + 1] = v end for _, v in ipairs(c) do a[#a + 1] = v end return a end end -- table.getn if not table.getn then table.getn = function(t) if type(t.n) == "number" then return t.n end local m = 0 for i, _ in t do if (type(i) == "number" and i > max) then m = i end end return m end end -- getn if not getn then getn = function(t) if type(t.n) == "number" then return t.n end local m = 0 for i, _ in t do if (type(i) == "number" and i > max) then m = i end end return m end end -- table.setn if not table.setn then table.setn = function(t, n) setmetatable(t, { __len = function() return n end }) end end -- table.foreach if not table.foreach then table.foreach = function(t, f) for k, v in pairs(t) do if (type(f) == "function") then f(k, v) end end end end -- table.foreachi if not table.foreachi then table.foreachi = function(t, f) for k, v in pairs(t) do if (type(f) == "function") then if (type(k) == "number") then f(k, v) end end end end end -- table.maxn if not table.maxn then table.maxn = function(t) local result = 0 for i, k in ipairs(t) do if (i > result) then result = i end end return result end end -- table_ext_solar2d.lua -- Written by Rabia Alhaffar in 11/March/2021 -- Polyfill for some table functions from Corona SDK/Solar2D -- Updated: 27/March/2021 if CoronaPrototype then -- table.indexOf if not table.indexOf then table.indexOf = function(arr, elem) for i = 1, #arr do if arr[i] == elem then return i end end end end -- table.copy if not table.copy then table.copy = function(...) local arg = { ... } local result = {} if #arg == 1 then return arg[1] else for i = 1, #arg do for j = 1, #arg[i] do table.insert(result, arg[i][j]) end end end return result end end end -- table_ext_amulet.lua -- Written by Rabia Alhaffar in 11/March/2021 -- Polyfill for some table functions from Amulet -- Updated: 27/March/2021 if (type(am) == "table") then -- table.search if not table.search then table.search = function(arr, elem) for i = 1, #arr do if arr[i] == elem then return i end end end end -- table.clear if not table.clear then table.clear = function(t) for k, v in pairs(t) do if t[k] then t[k] = nil end end end end -- table.remove_all if not table.remove_all then table.remove_all = function(arr, elem) for i = 1, #arr do if arr[i] == elem then arr[i] = nil end end end end -- table.append if not table.append then table.append = function(t1, t2) for i = 1, #t2 do table.insert(t1, t2[i]) end end end -- table.merge if not table.merge then table.merge = function(t1, t2) for k, v in pairs(t2) do t1[k] = t2[k] end end end -- table.keys if not table.keys then table.keys = function(t) local result = {} for k in pairs(t) do table.insert(result, k) end end return result end -- table.values if not table.values then table.values = function(t) local result = {} for k, v in pairs(t) do table.insert(result, v) end end return result end -- table.count if not table.count then table.count = function(t) local result = 0 for k, v in pairs(t) do if t[k] then result = result + 1 end end return result end end -- table.filter if not table.filter then table.filter = function(t, f) local result = {} for i = 1, #t do local a = t[i] local b = t[i + 1] or t[i] if (f(a, b) == true) then t[i] = a t[i + 1] = b else t[i] = b t[i + 1] = a end end return result end end -- table.tostring if not table.tostring then table.tostring = function(t) local result = "{" for k, v in pairs(t) do if assert(type(tonumber(k)) == "number") then result = result .. v .. "," else result = result .. "\"" .. k .. "\"" .. " = " .. v .. "," end end result = result .. "}" return result end end -- table.shuffle if not table.shuffle then table.shuffle = function(t, r) math.randomseed(os.time()) for i = #t, 2, -1 do local j = r or math.random(i) t[i], t[j] = t[j], t[i] end return t end end end -- module: package (Config for require function polyfill) if package then if ffi then if not package.loaddir then package.loaddir = "lualibs" end if not package.config then if (ffi.os == "Windows") then package.config = "\\\n;\n?\n!\n-" else package.config = "///n;/n?/n!/n-" end end end end -- module: os (Requires FFI) os = require("os") or {} if ffi then if ffi.arch == "x86" then ffi.cdef([[ typedef long __time32_t; typedef __time32_t time_t; ]]) elseif ffi.arch == "x64" then ffi.cdef([[ typedef __int64 __time64_t; typedef __time64_t time_t; ]]) end ffi.cdef([[ typedef long clock_t; time_t time(time_t *_Time); char * ctime(const time_t *_Time); int system(const char *_Command); void exit(int _Code); int rename(const char *_OldFilename, const char *_NewFilename); int remove(const char *_Filename); char* setlocale(int _Category, const char *_Locale); char* getenv(const char *_VarName); double difftime(time_t _Time1, time_t _Time2); char tmpnam(char *_Buffer); char *_strdate(char *_Buffer); clock_t clock(void); ]]) end -- os.time if not os.time then if ffi then os.time = function() return ffi.C.time(ffi.new("time_t *")) end end end -- os.execute if not os.execute then if ffi then os.execute = function(cmd) return (ffi.C.system(cmd) == 0) end end end -- execute if not execute then if ffi then execute = function(cmd) return (ffi.C.system(cmd) == 0) end end end -- os.exit if not os.exit then if ffi then os.exit = function(c) return ffi.C.exit(c or 0) end end end -- exit if not exit then if ffi then exit = function(c) return ffi.C.exit(c or 0) end end end -- os.rename if not os.rename then if ffi then os.rename = function(o, n) return (ffi.C.rename(o, n) == 0) end end end -- rename if not rename then if ffi then rename = function(o, n) return (ffi.C.rename(o, n) == 0) end end end -- os.remove if not os.remove then if ffi then os.remove = function(f) return (ffi.C.remove(f) == 0) end end end -- remove if not remove then if ffi then remove = function(f) return (ffi.C.remove(f) == 0) end end end -- os.setlocale if not os.setlocale then if ffi then os.setlocale = function(v) return ffi.string(ffi.C.setlocale(v)) end end end -- setlocale if not setlocale then if ffi then setlocale = function(v) return ffi.string(ffi.C.setlocale(v)) end end end -- os.getenv if not os.getenv then if ffi then os.getenv = function(v) return ffi.string(ffi.C.getenv(v)) end end end -- getenv if not getenv then if ffi then getenv = function(v) return ffi.string(ffi.C.getenv(v)) end end end -- os.difftime if not os.difftime then if ffi then os.difftime = function(t1, t2) return ffi.C.difftime(t1, t2) end end end -- os.tmpname if not os.tmpname then if ffi then os.tmpname = function(str) return ffi.string(ffi.C.tmpnam(str)) end end end -- os.date if not os.date == "nil" then if ffi then os.date = function(form) return ffi.string(ffi.C._strdate(form)) end end end -- date if not date == "nil" then if ffi then date = function(form) return ffi.string(ffi.C._strdate(form)) end end end -- os.clock if not os.clock then if ffi then os.clock = function() return ffi.C.clock() end end end -- clock if not clock then if ffi then clock = function() return ffi.C.clock() end end end -- module: math math = require("math") or {} -- Variables -- math.pi if not math.pi then math.pi = 3.14159265358979323846 end -- PI if not PI then PI = 3.14159265358979323846 end -- math.huge if not math.huge then math.huge = 1 / 0 end -- math.mininteger if not math.mininteger then math.mininteger = -2147483648 end -- math.maxinteger if not math.maxinteger then math.maxinteger = 2147483647 end -- Functions -- math.sqrt if not math.sqrt then if ffi then ffi.cdef("double sqrt(double);") math.sqrt = function(n) return ffi.C.sqrt(n) end end end -- sqrt if not sqrt then if ffi then ffi.cdef("double sqrt(double);") sqrt = function(n) return ffi.C.sqrt(n) end end end -- math.sinh if not math.sinh then if ffi then ffi.cdef("double sinh(double);") math.sinh = function(n) return ffi.C.sinh(n) end end end -- math.cosh if not math.cosh then if ffi then ffi.cdef("double cosh(double);") math.cosh = function(n) return ffi.C.cosh(n) end end end -- math.tanh if not math.tanh then if ffi then ffi.cdef("double tanh(double);") math.tanh = function(n) return ffi.C.tanh(n) end end end -- math.asin if not math.asin then if ffi then ffi.cdef("double asin(double);") math.asin = function(n) return ffi.C.asin(n) end else math.asin = function(n) return (n + (1 / 2) * (math.pow(n, 3) / 3) + ((1 * 3) / (2 * 4)) * (math.pow(n, 5) / 5) + ((1 * 3 * 5) / (2 * 4 * 6)) * (math.pow(n, 7) / 7)) end end end -- asin if not asin then if ffi then ffi.cdef("double asin(double);") asin = function(n) return ffi.C.asin(n) end else asin = function(n) return (n + (1 / 2) * (math.pow(n, 3) / 3) + ((1 * 3) / (2 * 4)) * (math.pow(n, 5) / 5) + ((1 * 3 * 5) / (2 * 4 * 6)) * (math.pow(n, 7) / 7)) end end end -- math.acos if not math.acos then if ffi then ffi.cdef("double acos(double);") math.acos = function(n) return ffi.C.acos(n) end else math.acos = function(n) return (-0.69813170079773212 * n * n - 0.87266462599716477) * n + 1.5707963267948966 end end end -- acos if not acos then if ffi then ffi.cdef("double acos(double);") acos = function(n) return ffi.C.acos(n) end else acos = function(n) return (-0.69813170079773212 * n * n - 0.87266462599716477) * n + 1.5707963267948966 end end end -- math.atan if not math.atan then if ffi then math.atan = function(...) local args = { ... } if (#args == 1) then ffi.cdef("double atan(double);") return ffi.C.atan(args[1]) elseif (#args == 2) then ffi.cdef("double atan2(double, double);") return ffi.C.atan2(args[1], args[2]) end end end end -- atan if not atan then if ffi then atan = function(...) local args = { ... } if (#args == 1) then ffi.cdef("double atan(double);") return ffi.C.atan(args[1]) elseif (#args == 2) then ffi.cdef("double atan2(double, double);") return ffi.C.atan2(args[1], args[2]) end end end end -- math.atan2 if not math.atan2 then if ffi then ffi.cdef("double atan2(double, double);") math.atan2 = function(x, y) return ffi.C.atan2(args[1], args[2]) end end end -- atan2 if not atan2 then if ffi then ffi.cdef("double atan2(double, double);") atan2 = function(x, y) return ffi.C.atan2(args[1], args[2]) end end end -- math.exp if not math.exp then if ffi then ffi.cdef("double exp(double);") math.exp = function(n) return ffi.C.exp(n) end end end -- exp if not exp then if ffi then ffi.cdef("double exp(double);") exp = function(n) return ffi.C.exp(n) end end end -- math.log if not math.log then if ffi then ffi.cdef("double log(double);") math.log = function(n) return ffi.C.log(n) end end end -- log if not log then if ffi then ffi.cdef("double log(double);") log = function(n) return ffi.C.log(n) end end end -- math.log10 if not math.log10 then if ffi then ffi.cdef("double log10(double);") math.log10 = function(n) return ffi.C.log10(n) end end end -- log10 if not log10 then if ffi then ffi.cdef("double log10(double);") log10 = function(n) return ffi.C.log10(n) end end end -- math.ldexp if not math.ldexp then if ffi then ffi.cdef("double ldexp(double, int);") math.ldexp = function(x, y) return ffi.C.ldexp(x, y) end end end -- ldexp if not ldexp then if ffi then ffi.cdef("double ldexp(double, int);") ldexp = function(x, y) return ffi.C.ldexp(x, y) end end end -- math.frexp if not math.frexp then if ffi then ffi.cdef("double frexp(double, int*);") math.frexp = function(x, y) return ffi.C.frexp(x, y) end end end -- frexp if not frexp then if ffi then ffi.cdef("double frexp(double, int*);") frexp = function(x, y) return ffi.C.frexp(x, y) end end end -- math.modf if not math.modf then if ffi then ffi.cdef("double modf(double, double*);") math.modf = function(x, y) return ffi.C.modf(x, y) end end end -- math.mod if not math.mod then if ffi then ffi.cdef("double fmod(double, double);") math.mod = function(x, y) return ffi.C.fmod(x, y) end end end -- math.fmod if not math.fmod then if ffi then ffi.cdef("double fmod(double, double);") math.fmod = function(x, y) return ffi.C.fmod(x, y) end end end -- mod if not mod then if ffi then ffi.cdef("double fmod(double, double);") mod = function(x, y) return ffi.C.fmod(x, y) end end end -- math.pow if not math.pow then if ffi then ffi.cdef("double pow(double, double);") math.pow = function(n, p) return ffi.C.pow(n, p) end else math.pow = function(n, p) local e = n if (p == 0) then return 1 end if (p < 0) then p = p * -1 end for c = p, 2, -1 do e = e * n end return e end end end -- math.abs if not math.abs then math.abs = function(n) if (n < 0) then return -n else return n end end end -- abs if not abs then abs = function(n) if (n < 0) then return -n else return n end end end -- math.deg if not math.deg then math.deg = function(n) return n * (180 / math.pi) end end -- deg if not deg then deg = function(n) return n * (180 / math.pi) end end -- math.rad if not math.rad then math.rad = function(d) return d * (math.pi / 180) end end -- rad if not rad then rad = function(d) return d * (math.pi / 180) end end -- math.min if not math.min then math.min = function(x, y) if x < y then return x else return y end end end -- min if not min then min = function(x, y) if x < y then return x else return y end end end -- math.max if not math.max then math.max = function(x, y) if x > y then return x else return y end end end -- max if not max then max = function(x, y) if x > y then return x else return y end end end -- math.tointeger if not math.tointeger then math.tointeger = function(n) return math.floor(n) end end -- math.hypot if not math.hypot then if ffi then ffi.cdef("double hypot(double, double);") math.hypot = function(x, y) return ffi.C.hypot(x, y) end else math.hypot = function(x, y) return math.sqrt(math.pow(x, 2) + math.pow(y, 2)) end end end -- math.sin if not math.sin then if ffi then ffi.cdef("double sin(double);") math.sin = function(n) return ffi.C.sin(n) end end end -- sin if not sin then if ffi then ffi.cdef("double sin(double);") sin = function(n) return ffi.C.sin(n) end end end -- math.cos if not math.cos then if ffi then ffi.cdef("double cos(double);") math.cos = function(n) return ffi.C.cos(n) end else function fact(a) if (a == 1) or (a == 0) then return 1 end local e = 1 for c = a, 1, -1 do e = e * c end return e end function correctRadians(v) while v > math.pi * 2 do v = v - math.pi * 2 end while v < -math.pi * 2 do v = v + math.pi * 2 end return v end math.cos = function(a, b) local e = 1 a = correctRadians(a) b = b or 10 for i = 1, b do e = e + (math.pow(-1, i) * math.pow(a, 2 * i) / fact(2 * i)) end return e end end end -- cos if not cos then if ffi then ffi.cdef("double cos(double);") cos = function(n) return ffi.C.cos(n) end else function fact(a) if (a == 1) or (a == 0) then return 1 end local e = 1 for c = a, 1, -1 do e = e * c end return e end function correctRadians(v) while v > math.pi * 2 do v = v - math.pi * 2 end while v < -math.pi * 2 do v = v + math.pi * 2 end return v end cos = function(a, b) local e = 1 a = correctRadians(a) b = b or 10 for i = 1, b do e = e + (math.pow(-1, i) * math.pow(a, 2 * i) / fact(2 * i)) end return e end end end -- math.tan if not math.tan then if ffi then ffi.cdef("double tan(double);") math.tan = function(n) return ffi.C.tan(n) end end end -- tan if not tan then if ffi then ffi.cdef("double tan(double);") tan = function(n) return ffi.C.tan(n) end end end -- math.ult if not math.ult then if ffi then math.ult = function(x, y) return (ffi.cast("unsigned int", x) < ffi.cast("unsigned int", y)) end end end -- math.ceil if not math.ceil then if ffi then math.ceil = function(n) ffi.cdef("double ceil(double);") return ffi.C.ceil(n) end end end -- ceil if not ceil then if ffi then ceil = function(n) ffi.cdef("double ceil(double);") return ffi.C.ceil(n) end end end -- math.round if not math.round then if ffi then math.round = function(n) ffi.cdef("double round(double);") return ffi.C.round(n) end end end -- round if not round then if ffi then round = function(n) ffi.cdef("double round(double);") return ffi.C.round(n) end end end -- math.floor if not math.floor then if ffi then math.floor = function(n) ffi.cdef("double floor(double);") return ffi.C.floor(n) end end end -- floor if not floor then if ffi then floor = function(n) ffi.cdef("double floor(double);") return ffi.C.floor(n) end end end -- math.randomseed if not math.randomseed then if ffi then ffi.cdef("void srand(unsigned int _Seed);") math.randomseed = function(n) ffi.C.srand(n) end end end -- randomseed if not randomseed then if ffi then ffi.cdef("void srand(unsigned int _Seed);") randomseed = function(n) ffi.C.srand(n) end end end -- math.random if not math.random then if ffi then ffi.cdef("int rand(void);") math.random = function(...) local pownum = 100000 local n = { ... } if (#n == 0) then return (ffi.C.rand() / pownum) elseif (#n == 1) then local num = (n[1] * (n[1] - 2)) local result = math.floor((ffi.C.rand() / pownum) * num) if (result > n[1]) then return n[1] end return result elseif (#n == 2) then local num1 = (n[1] * (n[1] - 2)) local num2 = (n[2] * (n[2] - 2)) local result = math.floor((ffi.C.rand() / pownum) * (num2 - num1) + num1) if (result > n[2]) then return n[2] end if (result < n[1]) then return n[1] end return result end end end end -- random if not random then if ffi then ffi.cdef("int rand(void);") random = function(...) local pownum = 100000 local n = { ... } if (#n == 0) then return (ffi.C.rand() / pownum) elseif (#n == 1) then local num = (n[1] * (n[1] - 2)) local result = math.floor((ffi.C.rand() / pownum) * num) if (result > n[1]) then return n[1] end return result elseif (#n == 2) then local num1 = (n[1] * (n[1] - 2)) local num2 = (n[2] * (n[2] - 2)) local result = math.floor((ffi.C.rand() / pownum) * (num2 - num1) + num1) if (result > n[2]) then return n[2] end if (result < n[1]) then return n[1] end return result end end end end -- module: bit32 bit32 = bit32 or {} bit32.bits = 32 bit32.powtab = { 1 } for b = 1, bit32.bits - 1 do bit32.powtab[#bit32.powtab + 1] = math.pow(2, b) end -- Functions -- bit32.band if not bit32.band then bit32.band = function(a, b) local result = 0 for x = 1, bit32.bits do result = result + result if (a < 0) then if (b < 0) then result = result + 1 end end a = a + a b = b + b end return result end end -- bit32.bor if not bit32.bor then bit32.bor = function(a, b) local result = 0 for x = 1, bit32.bits do result = result + result if (a < 0) then result = result + 1 elseif (b < 0) then result = result + 1 end a = a + a b = b + b end return result end end -- bit32.bnot if not bit32.bnot then bit32.bnot = function(x) return bit32.bxor(x, math.pow((bit32.bits or math.floor(math.log(x, 2))), 2) - 1) end end -- bit32.lshift if not bit32.lshift then bit32.lshift = function(a, n) if (n > bit32.bits) then a = 0 else a = a * bit32.powtab[n] end return a end end -- bit32.rshift if not bit32.rshift then bit32.rshift = function(a, n) if (n > bit32.bits) then a = 0 elseif (n > 0) then if (a < 0) then a = a - bit32.powtab[#bit32.powtab] a = a / bit32.powtab[n] a = a + bit32.powtab[bit32.bits - n] else a = a / bit32.powtab[n] end end return a end end -- bit32.arshift if not bit32.arshift then bit32.arshift = function(a, n) if (n >= bit32.bits) then if (a < 0) then a = -1 else a = 0 end elseif (n > 0) then if (a < 0) then a = a - bit32.powtab[#bit32.powtab] a = a / bit32.powtab[n] a = a - bit32.powtab[bit32.bits - n] else a = a / bit32.powtab[n] end end return a end end -- bit32.bxor if not bit32.bxor then bit32.bxor = function(a, b) local result = 0 for x = 1, bit32.bits, 1 do result = result + result if (a < 0) then if (b >= 0) then result = result + 1 end elseif (b < 0) then result = result + 1 end a = a + a b = b + b end return result end end -- bit32.btest if not bit32.btest then bit32.btest = function(a, b) return (bit32.band(a, b) ~= 0) end end -- bit32.lrotate if not bit32.lrotate then bit32.lrotate = function(a, b) local bits = bit32.band(b, bit32.bits - 1) a = bit32.band(a, 0xffffffff) a = bit32.bor(bit32.lshift(a, b), bit32.rshift(a, ((bit32.bits - 1) - b))) return bit32.band(n, 0xffffffff) end end -- bit32.rrotate if not bit32.rrotate then bit32.rrotate = function(a, b) return bit32.lrotate(a, -b) end end -- bit32.extract if not bit32.extract then bit32.extract = function(a, b, c) c = c or 1 return bit32.band(bit32.rshift(a, b, c), math.pow(b, 2) - 1) end end -- bit32.replace if not bit32.replace then bit32.replace = function(a, b, c, d) d = d or 1 local mask1 = math.pow(d, 2) -1 b = bit32.band(b, mask1) local mask = bit32.bnot(bit32.lshift(mask1, c)) return bit32.band(n, mask) + bit32.lshift(b, c) end end -- module: bit bit = bit or {} bit.bits = 32 bit.powtab = { 1 } for b = 1, bit.bits - 1 do bit.powtab[#bit.powtab + 1] = math.pow(2, b) end -- Functions -- bit.band if not bit.band then bit.band = function(a, b) local result = 0 for x = 1, bit.bits do result = result + result if (a < 0) then if (b < 0) then result = result + 1 end end a = a + a b = b + b end return result end end -- bit.bor if not bit.bor then bit.bor = function(a, b) local result = 0 for x = 1, bit.bits do result = result + result if (a < 0) then result = result + 1 elseif (b < 0) then result = result + 1 end a = a + a b = b + b end return result end end -- bit.bnot if not bit.bnot then bit.bnot = function(x) return bit.bxor(x, math.pow((bit.bits or math.floor(math.log(x, 2))), 2) - 1) end end -- bit.lshift if not bit.lshift then bit.lshift = function(a, n) if (n > bit.bits) then a = 0 else a = a * bit.powtab[n] end return a end end -- bit.rshift if not bit.rshift then bit.rshift = function(a, n) if (n > bit.bits) then a = 0 elseif (n > 0) then if (a < 0) then a = a - bit.powtab[#bit.powtab] a = a / bit.powtab[n] a = a + bit.powtab[bit.bits - n] else a = a / bit.powtab[n] end end return a end end -- bit.arshift if not bit.arshift then bit.arshift = function(a, n) if (n >= bit.bits) then if (a < 0) then a = -1 else a = 0 end elseif (n > 0) then if (a < 0) then a = a - bit.powtab[#bit.powtab] a = a / bit.powtab[n] a = a - bit.powtab[bit.bits - n] else a = a / bit.powtab[n] end end return a end end -- bit.bxor if not bit.bxor then bit.bxor = function(a, b) local result = 0 for x = 1, bit.bits, 1 do result = result + result if (a < 0) then if (b >= 0) then result = result + 1 end elseif (b < 0) then result = result + 1 end a = a + a b = b + b end return result end end -- bit.rol if not bit.rol then bit.rol = function(a, b) local bits = bit.band(b, bit.bits - 1) a = bit.band(a,0xffffffff) a = bit.bor(bit.lshift(a, b), bit.rshift(a, ((bit.bits - 1) - b))) return bit.band(n, 0xffffffff) end end -- bit.ror if not bit.ror then bit.ror = function(a, b) return bit.rol(a, -b) end end -- bit.bswap if not bit.bswap then bit.bswap = function(n) local a = bit.band(n, 0xff) n = bit.rshift(n, 8) local b = bit.band(n, 0xff) n = bit.rshift(n, 8) local c = bit.band(n, 0xff) n = bit.rshift(n, 8) local d = bit.band(n, 0xff) return bit.lshift(bit.lshift(bit.lshift(a, 8) + b, 8) + c, 8) + d end end -- bit.tobit if not bit.tobit then bit.tobit = function(n) local MOD = 2^32 n = n % MOD if (n >= 0x80000000) then n = n - MOD end return n end end -- bit.tohex if not bit.tohex then bit.tohex = function(x, n) n = n or 8 local up if n <= 0 then if n == 0 then return '' end up = true n = -n end x = bit.band(x, 16^n-1) return ('%0'..n..(up and 'X' or 'x')):format(x) end end -- module: io io = require("io") or {} if not _INPUT then _INPUT = io.stdin end if not _OUTPUT then _OUTPUT = io.stdout end if not _STDIN then _STDIN = io.stdin end if not _STDOUT then _STDOUT = io.stdout end if not _STDERR then _STDERR = io.stderr end -- Used by io.input and io.output, And works as usable file with IO functions lol io.__DEFAULT__INPUT__FILE__ = nil io.__DEFAULT__OUTPUT__FILE__ = nil if ffi then ffi.cdef([[ struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE; typedef struct SExIO_Stream { FILE *f; /* stream (NULL for incompletely created streams) */ } SExIO_Stream; ]]) end -- Native file type _FILE = {} function _FILE:new(f, m, s) o = {} setmetatable(o, self) self.__index = self self.__FILE = f self.__MODE = m self.__STATE = "file" self.__SRC = s return o end function _FILE:close() if ffi then ffi.cdef("int fclose(FILE *_File);") local result = (ffi.C.fclose(self.__FILE) == 0) if result then self.__STATE = "closed file" end end end function _FILE:flush() if ffi then ffi.cdef("int fflush(FILE *_File);") return (ffi.C.flush(self.__FILE) == 0) end end function _FILE:seek(w, o) if ffi then ffi.cdef("int fseek(FILE *stream, long int offset, int whence);") if (w == "set") then return ffi.C.fseek(self.__FILE, o, 0) elseif (w == "cur") then return ffi.C.fseek(self.__FILE, o, 1) elseif (w == "end") then return ffi.C.fseek(self.__FILE, o, 2) else return ffi.C.fseek(self.__FILE, o, w) end end end function _FILE:read(t) if (t == "*all" or t == "*a") then while not cast("bool", ffi.C.feof(f)) do local content = "" local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(f))) if (ch ~= nil) then content = content .. ch end end elseif (t == "*line" or t == "*l") then if not cast("bool", ffi.C.feof(f)) then local line = "" while not cast("bool", ffi.C.feof(f)) do local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(f))) if (ch == "\n") then break else line = line .. ch end end return line end elseif (t == "*number" or t == "*n") then local line = "" while not cast("bool", ffi.C.feof(f)) do local ch = tonumber(ffi.string(ffi.cast("char", ffi.C.fgetc(f)))) if not ch then break else line = line .. ch end end return line elseif (type(t) == "number") then if not cast("bool", ffi.C.feof(f)) then local line = ffi.new("char[?]", t) return ffi.string(ffi.C.fgets(line, t, f)) end end end function _FILE:write(...) if ffi then ffi.cdef("int fprintf(FILE *stream, const char *format, ...);") local args = { ... } if (#args == 0) then args[1] = f end local form = args[1] table.remove(args, 1) if (#args == 0) then ffi.C.fprintf(f.__FILE, form) else ffi.C.fprintf(f.__FILE, form, table.unpack(args)) end end end function _FILE:setvbuf(m, s) if ffi then ffi.cdef("int setvbuf(FILE *stream, char *buffer, int mode, size_t size);") if (m == "no") then return (ffi.C.setvbuf(self.__FILE, nil, 0x0004, s) == 0) elseif (m == "full") then return (ffi.C.setvbuf(self.__FILE, nil, 0x0000, s) == 0) elseif (m == "line") then return (ffi.C.setvbuf(self.__FILE, nil, 0x0040, s) == 0) end end end function _FILE:lines() if ffi then local lines = {} local line = "" while not cast("bool", ffi.C.feof(self.__FILE)) do local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(self.__FILE))) if (ch == "\n") then lines[#lines + 1] = line line = "" else line = line .. ch end end return ipairs(lines) end end -- Functions and Variables -- io.tmpfile if not io.tmpfile then io.tmpfile = function() if ffi then ffi.cdef("FILE *tmpfile(void);") return _FILE:new(ffi.C.tmpfile(), nil, nil) end end end -- tmpfile if not tmpfile then tmpfile = function() if ffi then ffi.cdef("FILE *tmpfile(void);") return _FILE:new(ffi.C.tmpfile(), nil, nil) end end end -- io.open if not io.open then if ffi then io.open = function(s, m) ffi.cdef("FILE *fopen(const char *_Filename,const char *_Mode);") return _FILE:new(ffi.C.fopen(s, m), m, s) end end end -- openfile if not openfile then if ffi then openfile = function(s, m) ffi.cdef("FILE *fopen(const char *_Filename,const char *_Mode);") return _FILE:new(ffi.C.fopen(s, m), m, s) end end end -- io.write if not io.write then if ffi then io.write = function(f, ...) ffi.cdef("int fprintf(FILE *stream, const char *format, ...);") local args = { ... } if ((#args == 0) and (io.__DEFAULT__OUTPUT__FILE__)) then args[1] = f return (ffi.C.fprintf(io.__DEFAULT__OUTPUT__FILE__, args[1]) == 0) elseif (f.__FILE) then local form = args[1] table.remove(args, 1) return (ffi.C.fprintf(f.__FILE, form, table.unpack(args)) == 0) end end end end -- write if not write then if ffi then write = function(f, ...) ffi.cdef("int fprintf(FILE *stream, const char *format, ...);") local args = { ... } if ((#args == 0) and (io.__DEFAULT__OUTPUT__FILE__)) then args[1] = f return (ffi.C.fprintf(io.__DEFAULT__OUTPUT__FILE__, args[1]) == 0) elseif (f.__FILE) then local form = args[1] table.remove(args, 1) return (ffi.C.fprintf(f.__FILE, form, table.unpack(args)) == 0) end end end end -- io.seek if not io.seek then if ffi then io.seek = function(f, w, o) ffi.cdef("int fseek(FILE *stream, long int offset, int whence);") if (w == "set") then return ffi.C.fseek(f, o, 0) elseif (w == "cur") then return ffi.C.fseek(f, o, 1) elseif (w == "end") then return ffi.C.fseek(f, o, 2) else return ffi.C.fseek(f, o, w) end end end end -- seek if not seek then if ffi then seek = function(f, w, o) ffi.cdef("int fseek(FILE *stream, long int offset, int whence);") if (w == "set") then return ffi.C.fseek(f, o, 0) elseif (w == "cur") then return ffi.C.fseek(f, o, 1) elseif (w == "end") then return ffi.C.fseek(f, o, 2) else return ffi.C.fseek(f, o, w) end end end end -- io.read if not io.read then if ffi then io.read = function(f, t) ffi.cdef([[ char *fgets(char *str, int n, FILE *stream); int fgetc(FILE *stream); int feof(FILE *stream); int scanf(const char *format, ...); ]]) if t and f then if (t == "*all" or t == "*a") then while not cast("bool", ffi.C.feof(f)) do local content = "" local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(f))) if (ch ~= nil) then content = content .. ch end end elseif (t == "*line" or t == "*l") then if not cast("bool", ffi.C.feof(f)) then local line = "" while not cast("bool", ffi.C.feof(f)) do local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(f))) if (ch == "\n") then break else line = line .. ch end end return line end elseif (t == "*number" or t == "*n") then local line = "" while not cast("bool", ffi.C.feof(f)) do local ch = tonumber(ffi.string(ffi.cast("char", ffi.C.fgetc(f)))) if not ch then break else line = line .. ch end end return line elseif (type(t) == "number") then if not cast("bool", ffi.C.feof(f)) then local line = ffi.new("char[?]", t) return ffi.string(ffi.C.fgets(line, t, f)) end elseif io.__DEFAULT__INPUT__FILE__ then --if not cast("bool", ffi.C.feof(io.__DEFAULT__INPUT__FILE__)) then --local line = ffi.new("char[?]", 512) local line = "" while not cast("bool", ffi.C.feof(io.__DEFAULT__INPUT__FILE__)) do local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(io.__DEFAULT__INPUT__FILE__))) if (ch == "\n") then break else line = line .. ch end end return line --return ffi.string(ffi.C.fgets(line, 512, io.__DEFAULT__INPUT__FILE__)) else local input = ffi.new("char[?]", 512) local execution_code = ffi.C.scanf("%s\0", input) return input, (execution_code == 0) end end end end end -- read if not read then if ffi then read = function(f, t) ffi.cdef([[ char *fgets(char *str, int n, FILE *stream); int fgetc(FILE *stream); int feof(FILE *stream); int scanf(const char *format, ...); ]]) if t and f then if (t == "*all" or t == "*a") then while not cast("bool", ffi.C.feof(f)) do local content = "" local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(f))) if (ch ~= nil) then content = content .. ch end end elseif (t == "*line" or t == "*l") then if not cast("bool", ffi.C.feof(f)) then local line = "" while not cast("bool", ffi.C.feof(f)) do local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(f))) if (ch == "\n") then break else line = line .. ch end end return line end elseif (t == "*number" or t == "*n") then local line = "" while not cast("bool", ffi.C.feof(f)) do local ch = tonumber(ffi.string(ffi.cast("char", ffi.C.fgetc(f)))) if not ch then break else line = line .. ch end end return line elseif (type(t) == "number") then if not cast("bool", ffi.C.feof(f)) then local line = ffi.new("char[?]", t) return ffi.string(ffi.C.fgets(line, t, f)) end elseif io.__DEFAULT__INPUT__FILE__ then --if not cast("bool", ffi.C.feof(io.__DEFAULT__INPUT__FILE__)) then --local line = ffi.new("char[?]", 512) local line = "" while not cast("bool", ffi.C.feof(io.__DEFAULT__INPUT__FILE__)) do local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(io.__DEFAULT__INPUT__FILE__))) if (ch == "\n") then break else line = line .. ch end end return line --return ffi.string(ffi.C.fgets(line, 512, io.__DEFAULT__INPUT__FILE__)) else local input = ffi.new("char[?]", 512) local execution_code = ffi.C.scanf("%s\0", input) return input, (execution_code == 0) end end end end end -- io.close if not io.close then if ffi then io.close = function(f) if f and (f.__FILE or f.__STATE) then ffi.cdef("int fclose(FILE *_File);") local result = (ffi.C.fclose(f.__FILE) == 0) if result then f.__STATE = "closed file" end end end end end -- closefile if not closefile then if ffi then closefile = function(f) if f and (f.__FILE or f.__STATE) then ffi.cdef("int fclose(FILE *_File);") local result = (ffi.C.fclose(f.__FILE) == 0) if result then f.__STATE = "closed file" end end end end end -- io.flush if not io.flush then if ffi then io.flush = function(f) ffi.cdef("int fflush(FILE *_File);") return (ffi.C.fflush(f or io.stdout) == 0) end end end -- flush if not flush then if ffi then flush = function(f) ffi.cdef("int fflush(FILE *_File);") return (ffi.C.fflush(f or io.stdout) == 0) end end end -- io.type if not io.type then io.type = function(f) if f and f.__STATE and ffi.istype("FILE", f) then return f.__STATE else return nil end end end -- io.input if not io.input then io.input = function(f) if f and (f.__FILE or f.__STATE) then if (f.__FILE or f.__MODE or f.__STATE) then io.__DEFAULT__INPUT__FILE__ = f end end end end -- readfrom if not readfrom then readfrom = function(f) if f and (f.__FILE or f.__STATE) then if (f.__FILE or f.__MODE or f.__STATE) then io.__DEFAULT__OUTPUT__FILE__ = f end end end end -- io.output if not io.output then io.output = function(f) if f and (f.__FILE or f.__STATE) then if (f.__FILE or f.__MODE or f.__STATE) then io.__DEFAULT__OUTPUT__FILE__ = f end end end end -- writeto if not writeto then writeto = function(f) if f and (f.__FILE or f.__STATE) then if (f.__FILE or f.__MODE or f.__STATE) then io.__DEFAULT__OUTPUT__FILE__ = f end end end end -- appendto if not appendto then appendto = function(f) if f and (f.__FILE or f.__STATE) then if (f.__FILE or f.__MODE or f.__STATE) then io.__DEFAULT__OUTPUT__FILE__ = f end end end end -- io.popen if not io.popen then if ffi then io.popen = function(c, m) ffi.cdef("FILE *_popen(const char *_Command, const char *_Mode);") return _FILE:new(ffi.C._popen(c, m), m, nil) end end end -- io.lines if not io.lines then if ffi then io.lines = function(filename) local lines = {} local line = "" local file = nil if (not filename) and io.__DEFAULT__INPUT__FILE__ and io.__DEFAULT__INPUT__FILE__.__FILE then filename = io.__DEFAULT__INPUT__FILE__ file = io.__DEFAULT__INPUT__FILE__.__FILE else file = io.open(filename, "r") end while not cast("bool", ffi.C.feof(file)) do local ch = ffi.string(ffi.cast("char", ffi.C.fgetc(file))) if (ch == "\n") then lines[#lines + 1] = line line = "" else line = line .. ch end end return ipairs(lines) end end end -- io.stdin if not io.stdin then if ffi then io.stdin = _FILE:new(io.open("stdin", "w"), "w", "stdin") end end -- io.stdout if not io.stdout then if ffi then io.stdout = _FILE:new(io.open("stdout", "w"), "w", "stdout") end end -- io.stderr if not io.stderr then if ffi then io.stderr = _FILE:new(io.open("stderr", "w"), "w", "stderr") end end -- module: string -- Functions string = require("string") or {} string.chars = {} string.chars["a"] = 97 string.chars["b"] = 98 string.chars["c"] = 99 string.chars["d"] = 100 string.chars["e"] = 101 string.chars["f"] = 102 string.chars["g"] = 103 string.chars["h"] = 104 string.chars["i"] = 105 string.chars["j"] = 106 string.chars["k"] = 107 string.chars["l"] = 108 string.chars["m"] = 109 string.chars["n"] = 110 string.chars["o"] = 111 string.chars["p"] = 112 string.chars["q"] = 113 string.chars["r"] = 114 string.chars["s"] = 115 string.chars["t"] = 116 string.chars["u"] = 117 string.chars["v"] = 118 string.chars["w"] = 119 string.chars["x"] = 120 string.chars["y"] = 121 string.chars["z"] = 122 string.chars["0"] = 48 string.chars["1"] = 49 string.chars["2"] = 50 string.chars["3"] = 51 string.chars["4"] = 52 string.chars["5"] = 53 string.chars["6"] = 54 string.chars["7"] = 55 string.chars["8"] = 56 string.chars["9"] = 57 string.chars["!"] = 33 string.chars["@"] = 64 string.chars["#"] = 35 string.chars["$"] = 36 string.chars["%"] = 37 string.chars["^"] = 94 string.chars["&"] = 38 string.chars["*"] = 42 string.chars["("] = 40 string.chars[")"] = 41 string.chars["-"] = 45 string.chars["+"] = 43 string.chars["_"] = 95 string.chars["="] = 61 string.chars["{"] = 123 string.chars["}"] = 125 string.chars["["] = 91 string.chars["]"] = 93 string.chars[":"] = 58 string.chars["'"] = 39 string.chars["\""] = 34 string.chars[";"] = 95 string.chars["/"] = 47 string.chars["`"] = 96 string.chars["~"] = 126 string.chars["|"] = 124 string.chars["\\"] = 92 string.chars[","] = 44 string.chars["."] = 46 string.chars["<"] = 60 string.chars[">"] = 62 string.chars["?"] = 63 -- string.split if not string.split then string.split = function(s, sep) local result = {} local line = "" for i = 1, #s do if (string.char(string.byte(s, i)) == sep) then result[#result + 1] = line line = "" else line = line .. string.char(string.byte(s, i)) end end return result end end -- string.rep if not string.rep then string.rep = function(s, n, sep) local str = "" local sp = sep or "" for i = 1, n, 1 do if (i == n) then sp = "" end str = str .. s .. sp end return str end end -- strrep if not strrep then strrep = function(s, n, sep) local str = "" local sp = sep or "" for i = 1, n, 1 do if (i == n) then sp = "" end str = str .. s .. sp end return str end end -- string.len if not string.len then string.len = function(s) if not ffi then return #n else ffi.cdef("size_t strlen(const char *_Str);") return ffi.cast("int", ffi.C.strlen(s)) end end end -- strlen if not strlen then strlen = function(s) if not ffi then return #n else ffi.cdef("size_t strlen(const char *_Str);") return ffi.cast("int", ffi.C.strlen(s)) end end end -- string.byte if not string.byte then if (type(ffi) == "string") then string.byte = function(s, i) i = i or 1 local strarr = ffi.new("char[?]", #s) ffi.copy(strarr, s) return ffi.cast("int", strarr[i]) end end end -- strbyte if not strbyte then if (type(ffi) == "string") then strbyte = function(s, i) i = i or 1 local strarr = ffi.new("char[?]", #s) ffi.copy(strarr, s) return ffi.cast("int", strarr[i]) end end end -- string.char if not string.char then string.char = function(...) local args = { ... } local str = "" for i = 1, #args do for k, v in pairs(string.chars) do if (v == args[i]) then str = str .. k end end end return str end end -- strchar if not strchar then strchar = function(...) local args = { ... } local str = "" for i = 1, #args do for k, v in pairs(string.chars) do if (v == args[i]) then str = str .. k end end end return str end end -- string.upper if not string.upper then if ffi then string.upper = function(s) ffi.cdef("int toupper(int _C);") local result = {} local t = ffi.new("char[?]", #s) ffi.copy(t, s) for i = 1, #s, 1 do result[i] = ffi.C.toupper(string.char(ffi.cast("int", t[i]))) end return table.concat(result, "") end end end -- strupper if not strupper then if ffi then strupper = function(s) ffi.cdef("int toupper(int _C);") local result = {} local t = ffi.new("char[?]", #s) ffi.copy(t, s) for i = 1, #s, 1 do result[i] = ffi.C.toupper(string.char(ffi.cast("int", t[i]))) end return table.concat(result, "") end end end -- string.lower if not string.lower then if ffi then string.lower = function(s) ffi.cdef("int tolower(int _C);") local result = {} local t = ffi.new("char[?]", #s) ffi.copy(t, s) for i = 1, #s, 1 do result[i] = ffi.C.tolower(string.char(ffi.cast("int", t[i]))) end return table.concat(result, "") end end end -- strlower if not strlower then if ffi then string.lower = function(s) ffi.cdef("int tolower(int _C);") local result = {} local t = ffi.new("char[?]", #s) ffi.copy(t, s) for i = 1, #s, 1 do result[i] = ffi.C.tolower(string.char(ffi.cast("int", t[i]))) end return table.concat(result, "") end end end -- string.pack if not string.pack then if ffi then string.pack = function(f, ...) local packtype = string.char(string.byte(f, 1)) local arrtype = "" local arrsize = 0 if packtype == "i" then arrtype = "int" arrsize = 2 elseif packtype == "f" then arrtype = "float" arrsize = 4 elseif packtype == "d" then arrtype = "double" arrsize = 8 elseif packtype == "c" then arrtype = "char" -- char could be int? arrsize = 1 end local occurences = string.match(args[1], packtype) local args = { ... } return ffi.string(ffi.new(arrtype.."[?]", #args, args), arrsize * #args) end end end -- string.unpack if not string.unpack then if ffi then string.unpack = function(f, s, o) local packtype = string.char(string.byte(f, 1)) local arrtype = "" local arrsize = 0 if packtype == "i" then arrtype = "int" arrsize = 2 elseif packtype == "f" then arrtype = "float" arrsize = 4 elseif packtype == "d" then arrtype = "double" arrsize = 8 elseif packtype == "c" then arrtype = "char" -- char could be int? arrsize = 1 end local str = ffi.cast(arrtype .. "*", ffi.new("char[?]", #str, str)) local t = {} for i = o, #str / arrsize do t[#t + 1] = str[#t] end return table.concat(t) end end end -- string.packsize if not string.packsize then if ffi then string.packsize = function(str) if str[1] then return #str end end end end -- string.sub if not string.sub then string.sub = function(s, f, t) t = t or #s local result = "" for i = f, t do result = result .. string.char(string.byte(s, i)) end return result end end -- strsub if not strsub then strsub = function(s, f, t) t = t or #s local result = "" for i = f, t do result = result .. string.char(string.byte(s, i)) end return result end end -- string.format if not string.format then if ffi then string.format = function(...) ffi.cdef("int sprintf(char *str, const char *format, ...);") local args = { ... } local str = "" ffi.C.sprintf(str, table.unpack(args)) return ffi.string(str) end end end -- format if not format then if ffi then format = function(...) ffi.cdef("int sprintf(char *str, const char *format, ...);") local args = { ... } local str = "" ffi.C.sprintf(str, table.unpack(args)) return ffi.string(str) end end end -- string.match if not string.match then if ffi then string.match = function(s1, s2, init) ffi.cdef("char* strstr(const char*, const char*);") init = init or 0 local occurences = 0 local count = 0 local ptr = s1 local lastfind = nil while (ffi.C.strstr(ptr, s2) ~= nil) do lastfind = ffi.C.strstr(ptr, s2) ptr = lastfind + 1 if (occurences >= init) then count = count + 1 end occurences = occurences + 1 end if (occurences > 1) then return (occurences * #s2) - 1, #s2 else return occurences, #s2 end end end end -- string.gmatch if not string.gmatch then if ffi then string.gmatch = function(s1, s2) ffi.cdef("char* strstr(const char*, const char*);") local occurences = {} local ptr = s1 local lastfind = nil while (ffi.C.strstr(ptr, s2) ~= nil) do lastfind = ffi.C.strstr(ptr, s2) ptr = lastfind + 1 occurences[#occurences + 1] = lastfind end return ipairs(occurences) end end end -- string.find if not string.find then if ffi then string.find = function(s1, s2, init) ffi.cdef("char* strstr(const char*, const char*);") init = init or 0 local occurences = 0 local count = 0 local ptr = s1 local lastfind = nil while (ffi.C.strstr(ptr, s2) ~= nil) do lastfind = ffi.C.strstr(ptr, s2) ptr = lastfind + 1 if (occurences >= init) then count = count + 1 end occurences = occurences + 1 end return occurences, #s2 end end end -- strfind if not strfind then if ffi then strfind = function(s1, s2, init) ffi.cdef("char* strstr(const char*, const char*);") init = init or 0 local occurences = 0 local count = 0 local ptr = s1 local lastfind = nil while (ffi.C.strstr(ptr, s2) ~= nil) do lastfind = ffi.C.strstr(ptr, s2) ptr = lastfind + 1 if (occurences >= init) then count = count + 1 end occurences = occurences + 1 end return occurences, #s2 end end end -- string.gfind if not string.gfind then if ffi then string.gfind = function(s1, s2) ffi.cdef("char* strstr(const char*, const char*);") local occurences = {} local ptr = s1 local lastfind = nil while (ffi.C.strstr(ptr, s2) ~= nil) do lastfind = strstr(ptr, s2) ptr = lastfind + 1 occurences[#occurences + 1] = lastfind end return ipairs(occurences) end end end return polyfill