Last active
April 16, 2024 15:13
-
-
Save revolucas/dd1ecccfca32d558fddf70ddb39eb8a6 to your computer and use it in GitHub Desktop.
[Lua] Print table function for deeply nested tables
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Most pure lua print table functions I've seen have a problem with deep recursion and tend to cause a stack overflow when | |
going too deep. This print table function that I've written does not have this problem. It should also be capable of handling | |
really large tables due to the way it handles concatenation. In my personal usage of this function, it outputted 63k lines to | |
file in about a second. | |
The output also keeps lua syntax and the script can easily be modified for simple persistent storage by writing the output to | |
file if modified to allow only number, boolean, string and table data types to be formatted. | |
author: Alundaio (aka Revolucas) | |
--]] | |
function print_table(node) | |
-- to make output beautiful | |
local function tab(amt) | |
local str = "" | |
for i=1,amt do | |
str = str .. "\t" | |
end | |
return str | |
end | |
local cache, stack, output = {},{},{} | |
local depth = 1 | |
local output_str = "{\n" | |
while true do | |
local size = 0 | |
for k,v in pairs(node) do | |
size = size + 1 | |
end | |
local cur_index = 1 | |
for k,v in pairs(node) do | |
if (cache[node] == nil) or (cur_index >= cache[node]) then | |
if (string.find(output_str,"}",output_str:len())) then | |
output_str = output_str .. ",\n" | |
elseif not (string.find(output_str,"\n",output_str:len())) then | |
output_str = output_str .. "\n" | |
end | |
-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings | |
table.insert(output,output_str) | |
output_str = "" | |
local key | |
if (type(k) == "number" or type(k) == "boolean") then | |
key = "["..tostring(k).."]" | |
else | |
key = "['"..tostring(k).."']" | |
end | |
if (type(v) == "number" or type(v) == "boolean") then | |
output_str = output_str .. tab(depth) .. key .. " = "..tostring(v) | |
elseif (type(v) == "table") then | |
output_str = output_str .. tab(depth) .. key .. " = {\n" | |
table.insert(stack,node) | |
table.insert(stack,v) | |
cache[node] = cur_index+1 | |
break | |
else | |
output_str = output_str .. tab(depth) .. key .. " = '"..tostring(v).."'" | |
end | |
if (cur_index == size) then | |
output_str = output_str .. "\n" .. tab(depth-1) .. "}" | |
else | |
output_str = output_str .. "," | |
end | |
else | |
-- close the table | |
if (cur_index == size) then | |
output_str = output_str .. "\n" .. tab(depth-1) .. "}" | |
end | |
end | |
cur_index = cur_index + 1 | |
end | |
if (#stack > 0) then | |
node = stack[#stack] | |
stack[#stack] = nil | |
depth = cache[node] == nil and depth + 1 or depth - 1 | |
else | |
break | |
end | |
end | |
-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings | |
table.insert(output,output_str) | |
output_str = table.concat(output) | |
print(output_str) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment