[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Saving a table in file
- From: joao lobato <btnfdp.lobato@...>
- Date: Sun, 7 Mar 2010 21:12:57 +0000
This one is http://www.lua.org/pil/12.1.html generalized to accept
tables as indices as well as values; the save function gives you a
string representation of your table that you can load using loadstring
or loadfile. I don't recall how much testing I did regarding function
environments but they're disabled by default.
On 3/7/10, Andre Leiradella <aleirade@sct.microlink.com.br> wrote:
> This version handles nested tables: http://lua-users.org/wiki/PickleTable
>
> Cheers,
>
> Andre
>
> On 07/03/2010 17:25, Nevin Flanagan wrote:
>> One way to serialize tables in Lua is to write the actual table
>> constructor text into the file. This has the advantage that you can
>> then use Lua itself to load the table from the file contents.
>>
>> This is a simplified version that does not handle nested tables:
>>
>> function table.pickle(t, fileName)
>> local output = io.open(fileName, "w")
>> output:write("return {\n")
>> for k, v in pairs(t) do
>> if (type(k) == 'string' or type(k) == 'number' or type(k) == 'boolean')
>> and (type(v) == 'string' or type(v) == 'number' or type(v) ==
>> 'boolean'') then
>> if type(k) == 'string' then
>> k = string.format("%q", k)
>> else
>> k = tostring(k)
>> end
>> if type(v) == 'string' then
>> v = string.format("%q", v)
>> else
>> v = tostring(v)
>> end
>> output:write(string.format("[%s] = %s,\n", k, v)
>> end
>> end
>> output:close()
>> end
>>
>>
>> NFF
>
>
--
-- serialize.lua
-- 20091024
--
-- supports tables with arbitrary topology, and numbers, strings, booleans
-- and functions (without upvales but with environments) either as keys or
-- values
--
--require 'extensive testing'
local table = table
local type = type
local tostring = tostring
local pairs = pairs
local string = string
local setmetatable = setmetatable
local getmetatable = getmetatable
local getfenv = getfenv
local _G = _G
-- _export is added to the module to facilitate exporting the (other) functions
-- to the global namespace; one can also choose which ones by providing their
-- names when calling _export
local function export(m)
m._export = function(...)
if ... then
for _,name in ipairs({...}) do
if m[name] then
_G[name] = m[name]
else
error(name ..' not in '..m._NAME)
end
end
else
for name, object in pairs(m) do
if string.sub(name,1,1) ~= '_' then
_G[name] = object
end
end
end
end
end
module('serialize',export)
_VERSION = 'serialize20091024'
local function addString(sb,...)
table.insert(sb,table.concat({...}))
end
local T
local s
local VISIT
local sb
local count
local useEnvs
local function getNewRef()
count = count + 1
return count
end
local function getRef(t)
local ref = T[t]
if not ref then
ref = getNewRef()
T[t] = ref
end
return ref
end
local function saveNonTable(o)
local o_type = type(o)
if o_type == "string" then
sb:add(string.format("%q", o))
elseif o_type == "function" then
local env = getfenv(o)
if env == _G then env = false end
env = useEnvs and env
local env_ref
if env then
s:put(env)
env_ref = getRef(env)
sb:add('setfenv(')
end
sb:add('loadstring(',string.format("%q",string.dump(o)),')')
if env then
sb:add(',T[',env_ref,'])\n')
end
else -- assume tostring will yield something decent
sb:add(tostring(o))
end
end
local function saveTable(input)
local seen = VISIT[input]
if seen then return end
local ref = getRef(input)
for key, value in pairs(input) do
sb:add('T[',ref,'][')
if type(key) == 'table' then
s:put(key)
local key_ref = getRef(key)
sb:add('T[',key_ref,']')
else
saveNonTable(key)
end
sb:add(']=')
if type(value) == 'table' then
s:put(value)
local value_ref = getRef(value)
sb:add('T[',value_ref,']')
else
saveNonTable(value)
end
sb:add('\n')
end
local mt = getmetatable(input)
if mt then
s:put(mt)
local mt_ref = getRef(mt)
sb:add('setmetatable(T[',ref,'],T[',mt_ref,'])\n')
end
end
function save(t, name, env_flag)
useEnvs = env_flag
sb = {add=addString}
count = 0
T={}
s = {
len = function(self) return #self end;
put = table.insert;
get = table.remove;
}
VISIT = setmetatable({},
{__index=function(t,k)
t[k] = true
return false
end})
local target = name and tostring(name) or 'data'
sb:add(string.format([=[
%s%s
do
local T = setmetatable({},
{__index=function(t,k)
local new = {}
t[k] = new
return new
end})
%s = T[1]
]=],name and '' or 'local ',target,target))
s:put(t)
while(s:len() > 0) do
saveTable(s:get())
end
sb:add('end\n')
sb:add(string.format('return %s\n',target))
local ret = table.concat(sb)
T = nil
s = nil
VISIT = nil
sb = nil
count = nil
useEnvs = nil
return ret
end