Update Utils.lua

#UTILS - Make PrintTableToLog() safer against endless cycles
This commit is contained in:
Thomas
2026-03-02 12:22:13 +01:00
committed by GitHub
parent ee002fa470
commit 877ca7176a
+50 -17
View File
@@ -522,43 +522,76 @@ function UTILS.TableLength(T)
end end
--- Print a table to log in a nice format --- Print a table to log in a nice format
-- @param #table table The table to print -- @param #table t The table to print
-- @param #number indent Number of indents -- @param #number indent Number of indents
-- @param #boolean noprint Don't log but return text -- @param #boolean noprint Don't log but return text
-- @param #number maxDepth Only cycle this deep, defaults to 5.
-- @return #string text Text created on the fly of the log output -- @return #string text Text created on the fly of the log output
function UTILS.PrintTableToLog(table, indent, noprint) function UTILS.PrintTableToLog(t, indent, noprint, maxDepth, seen)
local text = "\n" maxDepth = maxDepth or 5
if not table or type(table) ~= "table" then indent = indent or 0
seen = seen or {}
if not t or type(t) ~= "table" then
env.warning("No table passed!") env.warning("No table passed!")
return nil return nil
end end
if not indent then indent = 0 end
for k, v in pairs(table) do -- Max depth guard
if string.find(k," ") then k='"'..k..'"'end if indent > maxDepth then
if type(v) == "table" and UTILS.TableLength(v) > 0 then local msg = string.rep(" ", indent) .. "<max depth reached>\n"
if not noprint then env.info(msg) end
return msg
end
-- Cycle / repeated reference guard
if seen[t] then
local msg = string.rep(" ", indent) .. "<cycle>\n"
if not noprint then env.info(msg) end
return msg
end
seen[t] = true
local text = "\n"
for k, v in pairs(t) do
local key = k
if type(key) == "string" and key:find(" ", 1, true) then
key = '"' .. key .. '"'
else
key = tostring(key)
end
if type(v) == "table" and next(v) ~= nil then
if not noprint then if not noprint then
env.info(string.rep(" ", indent) .. tostring(k) .. " = {") env.info(string.rep(" ", indent) .. key .. " = {")
end end
text = text ..string.rep(" ", indent) .. tostring(k) .. " = {\n"
text = text .. tostring(UTILS.PrintTableToLog(v, indent + 1), noprint).."\n" text = text .. string.rep(" ", indent) .. key .. " = {\n"
text = text .. UTILS.PrintTableToLog(v, indent + 1, noprint, maxDepth, seen)
text = text .. string.rep(" ", indent) .. "},\n"
if not noprint then if not noprint then
env.info(string.rep(" ", indent) .. "},") env.info(string.rep(" ", indent) .. "},")
end end
text = text .. string.rep(" ", indent) .. "},\n"
elseif type(v) == "function" then elseif type(v) == "function" then
-- skip functions (optional: log "<function>")
else else
local value local value
if tostring(v) == "true" or tostring(v) == "false" or tonumber(v) ~= nil then if type(v) == "boolean" or type(v) == "number" then
value=v value = tostring(v)
else else
value = '"'..tostring(v)..'"' value = '"' .. tostring(v) .. '"'
end end
if not noprint then if not noprint then
env.info(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n") env.info(string.rep(" ", indent) .. key .. " = " .. value .. ",")
end end
text = text .. string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n" text = text .. string.rep(" ", indent) .. key .. " = " .. value .. ",\n"
end end
end end
return text return text
end end