La plupart des fonctions de table d'impression pure lua que j'ai vues ont un problème de récursivité profonde et ont tendance à provoquer un débordement de pile lorsqu'elles vont trop loin. Cette fonction de table d'impression que j'ai écrite n'a pas ce problème. Il devrait également être capable de gérer des tables très volumineuses en raison de la façon dont il gère la concaténation. Dans mon utilisation personnelle de cette fonction, il a généré 63k lignes dans un fichier en une seconde environ.
La sortie conserve également la syntaxe lua et le script peut facilement être modifié pour un stockage persistant simple en écrivant la sortie dans un fichier si elle est modifiée pour permettre uniquement le formatage des types de données nombre, booléen, chaîne et table.
function print_table(node)
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 .. string.rep('\t',depth) .. key .. " = "..tostring(v)
elseif (type(v) == "table") then
output_str = output_str .. string.rep('\t',depth) .. key .. " = {\n"
table.insert(stack,node)
table.insert(stack,v)
cache[node] = cur_index+1
break
else
output_str = output_str .. string.rep('\t',depth) .. key .. " = '"..tostring(v).."'"
end
if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
else
output_str = output_str .. ","
end
else
-- close the table
if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
end
end
cur_index = cur_index + 1
end
if (size == 0) then
output_str = output_str .. "\n" .. string.rep('\t',depth-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
Voici un exemple:
local t = {
["abe"] = {1,2,3,4,5},
"string1",
50,
["depth1"] = { ["depth2"] = { ["depth3"] = { ["depth4"] = { ["depth5"] = { ["depth6"] = { ["depth7"]= { ["depth8"] = { ["depth9"] = { ["depth10"] = {1000}, 900}, 800},700},600},500}, 400 }, 300}, 200}, 100},
["ted"] = {true,false,"some text"},
"string2",
[function() return end] = function() return end,
75
}
print_table(t)
Production:
{
[1] = 'string1',
[2] = 50,
[3] = 'string2',
[4] = 75,
['abe'] = {
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 4,
[5] = 5
},
['function: 06472B70'] = 'function: 06472A98',
['depth1'] = {
[1] = 100,
['depth2'] = {
[1] = 200,
['depth3'] = {
[1] = 300,
['depth4'] = {
[1] = 400,
['depth5'] = {
[1] = 500,
['depth6'] = {
[1] = 600,
['depth7'] = {
[1] = 700,
['depth8'] = {
[1] = 800,
['depth9'] = {
[1] = 900,
['depth10'] = {
[1] = 1000
}
}
}
}
}
}
}
}
}
},
['ted'] = {
[1] = true,
[2] = false,
[3] = 'some text'
}
}