nulllib-lua/util.lua
NullBite 8a1d772bb4
util: add traceback function that i stole
https://discord.com/channels/805969743466332191/827848307480461313/1120318388540022794

it was in a fucking shitpost channel
thanks again @dragekk this is probably the fifth thing i've stolen from
you
2023-06-25 01:33:14 -04:00

212 lines
4.4 KiB
Lua

util={}
--- Create a string representation of a table
--- @param o table
function util.dumpTable(o)
if type(o) == 'table' then
local s = '{ '
local first_loop=true
for k,v in pairs(o) do
if not first_loop then
s = s .. ', '
end
first_loop=false
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. util.dumpTable(v)
end
return s .. '} '
else
return tostring(o)
end
end
do
local function format_any_value(obj, buffer)
local _type = type(obj)
if _type == "table" then
buffer[#buffer + 1] = '{"'
for key, value in next, obj, nil do
buffer[#buffer + 1] = tostring(key) .. '":'
format_any_value(value, buffer)
buffer[#buffer + 1] = ',"'
end
buffer[#buffer] = '}' -- note the overwrite
elseif _type == "string" then
buffer[#buffer + 1] = '"' .. obj .. '"'
elseif _type == "boolean" or _type == "number" then
buffer[#buffer + 1] = tostring(obj)
else
buffer[#buffer + 1] = '"???' .. _type .. '???"'
end
end
--- Dumps object as UNSAFE json, i stole this from stackoverflow so i could
-- use json.tool to format it so it's easier to read
-- TL;DR, do NOT use this as an actual JSON implementation
function util.dumpJSON(obj)
if obj == nil then return "null" else
local buffer = {}
format_any_value(obj, buffer)
return table.concat(buffer)
end
end
end
-- TODO: accept model part to determine texture width and height
---@param uv table
function util.UV(uv)
return vec(
uv[1]/TEXTURE_WIDTH,
uv[2]/TEXTURE_HEIGHT
)
end
---@param inputstr string
---@param sep string
function util.splitstring (inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
---@param input string
function util.parse(input)
if input=="nil" then
return nil
elseif input == "true" or input == "false" then
return input=="true"
elseif tonumber(input) ~= nil then
return tonumber(input)
else
return input
end
end
---@param func function
---@param table table
function util.map(func, table)
local t={}
for k, v in pairs(table) do
t[k]=func(v)
end
return t
end
---@param func function
---@param table table
function util.filter(func, table)
local t={}
for k, v in pairs(table) do
if func(v) then
t[k]=v
end
end
return t
end
---@param tbl table
---@param val any
function util.has_value(tbl, val)
for _, v in pairs(tbl) do
if v==val then return true end
end
return false
end
--- Unordered reduction, only use when working with dictionaries and
--- execution order does not matter
---@param tbl table Table to reduce
---@param func function Function used to reduce table
---@param init any Initial operand for reduce function
function util.reduce(func, tbl, init)
local result = init
local first_loop = true
for _, v in pairs(tbl) do
if first_loop and init == nil then
result=v
else
result = func(result, v)
end
first_loop=false
end
return result
end
--- Ordered reduction, does not work with dictionaries
---@param tbl table Table to reduce
---@param func function Function used to reduce table
---@param init any Initial operand for reduce function
function util.ireduce(func, tbl, init)
local result = init
local first_loop = true
for _, v in ipairs(tbl) do
if first_loop and init == nil then
result=v
else
result = func(result, v)
end
first_loop=false
end
return result
end
--- Merge two tables. First table value takes precedence when conflict occurs.
---@param tb1 table
---@param tb2 table
function util.mergeTable(tb1, tb2)
local t={}
for k, v in pairs(tb1) do
t[k]=v
end
for k, v in pairs(tb2) do
if type(k)=="number" then
table.insert(t, v)
else
if t[k]==nil then
t[k]=v
end
end
end
return t
end
function util.debugPrint(var)
print(var)
return var
end
function util.debugPrintTable(var)
printTable(var)
return var
end
--- Recursively walk a model tree and return a table containing the group and each of its sub-groups
--- @param group table The group to recurse
--- @return table Resulting table
local function recurseModelGroup(group)
local t={}
table.insert(t, group)
if group:getType()=="GROUP" then
for k, v in pairs(group:getChildren()) do
for _, v2 in pairs(recurseModelGroup(v)) do
table.insert(t, v2)
end
end
end
return t
end
util.recurseModelGroup=recurseModelGroup
function util.traceback()
return ({pcall(function() error("", 4) end)})[2]:match("stack traceback:.+$")
end
return util