mirror of
https://github.com/libretro/lutro-iyfct.git
synced 2024-11-26 17:50:25 +00:00
180 lines
5.6 KiB
Lua
180 lines
5.6 KiB
Lua
--[[
|
|
Save Table to File/Stringtable
|
|
Load Table from File/Stringtable
|
|
v 0.94
|
|
|
|
Lua 5.1 compatible
|
|
|
|
Userdata and indices of these are not saved
|
|
Functions are saved via string.dump, so make sure it has no upvalues
|
|
References are saved
|
|
----------------------------------------------------
|
|
table.save( table [, filename] )
|
|
|
|
Saves a table so it can be called via the table.load function again
|
|
table must a object of type 'table'
|
|
filename is optional, and may be a string representing a filename or true/1
|
|
|
|
table.save( table )
|
|
on success: returns a string representing the table (stringtable)
|
|
(uses a string as buffer, ideal for smaller tables)
|
|
table.save( table, true or 1 )
|
|
on success: returns a string representing the table (stringtable)
|
|
(uses io.tmpfile() as buffer, ideal for bigger tables)
|
|
table.save( table, "filename" )
|
|
on success: returns 1
|
|
(saves the table to file "filename")
|
|
on failure: returns as second argument an error msg
|
|
----------------------------------------------------
|
|
table.load( filename or stringtable )
|
|
|
|
Loads a table that has been saved via the table.save function
|
|
|
|
on success: returns a previously saved table
|
|
on failure: returns as second argument an error msg
|
|
----------------------------------------------------
|
|
|
|
chillcode, http://lua-users.org/wiki/SaveTableToFile
|
|
Licensed under the same terms as Lua itself.
|
|
]]--
|
|
do
|
|
-- declare local variables
|
|
--// exportstring( string )
|
|
--// returns a "Lua" portable version of the string
|
|
local function exportstring( s )
|
|
s = string.format( "%q",s )
|
|
-- to replace
|
|
s = string.gsub( s,"\\\n","\\n" )
|
|
s = string.gsub( s,"\r","\\r" )
|
|
s = string.gsub( s,string.char(26),"\"..string.char(26)..\"" )
|
|
return s
|
|
end
|
|
--// The Save Function
|
|
function table.save( tbl,filename )
|
|
local charS,charE = " ","\n"
|
|
local file,err
|
|
-- create a pseudo file that writes to a string and return the string
|
|
if not filename then
|
|
file = { write = function( self,newstr ) self.str = self.str..newstr end, str = "" }
|
|
charS,charE = "",""
|
|
-- write table to tmpfile
|
|
elseif filename == true or filename == 1 then
|
|
charS,charE,file = "","",io.tmpfile()
|
|
-- write table to file
|
|
-- use io.open here rather than io.output, since in windows when clicking on a file opened with io.output will create an error
|
|
else
|
|
file,err = io.open( filename, "w" )
|
|
if err then return _,err end
|
|
end
|
|
-- initiate variables for save procedure
|
|
local tables,lookup = { tbl },{ [tbl] = 1 }
|
|
file:write( "return {"..charE )
|
|
for idx,t in ipairs( tables ) do
|
|
if filename and filename ~= true and filename ~= 1 then
|
|
file:write( "-- Table: {"..idx.."}"..charE )
|
|
end
|
|
file:write( "{"..charE )
|
|
local thandled = {}
|
|
for i,v in ipairs( t ) do
|
|
thandled[i] = true
|
|
-- escape functions and userdata
|
|
if type( v ) ~= "userdata" then
|
|
-- only handle value
|
|
if type( v ) == "table" then
|
|
if not lookup[v] then
|
|
table.insert( tables, v )
|
|
lookup[v] = #tables
|
|
end
|
|
file:write( charS.."{"..lookup[v].."},"..charE )
|
|
elseif type( v ) == "function" then
|
|
file:write( charS.."loadstring("..exportstring(string.dump( v )).."),"..charE )
|
|
else
|
|
local value = ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
|
|
file:write( charS..value..","..charE )
|
|
end
|
|
end
|
|
end
|
|
for i,v in pairs( t ) do
|
|
-- escape functions and userdata
|
|
if (not thandled[i]) and type( v ) ~= "userdata" then
|
|
-- handle index
|
|
if type( i ) == "table" then
|
|
if not lookup[i] then
|
|
table.insert( tables,i )
|
|
lookup[i] = #tables
|
|
end
|
|
file:write( charS.."[{"..lookup[i].."}]=" )
|
|
else
|
|
local index = ( type( i ) == "string" and "["..exportstring( i ).."]" ) or string.format( "[%d]",i )
|
|
file:write( charS..index.."=" )
|
|
end
|
|
-- handle value
|
|
if type( v ) == "table" then
|
|
if not lookup[v] then
|
|
table.insert( tables,v )
|
|
lookup[v] = #tables
|
|
end
|
|
file:write( "{"..lookup[v].."},"..charE )
|
|
elseif type( v ) == "function" then
|
|
file:write( "loadstring("..exportstring(string.dump( v )).."),"..charE )
|
|
else
|
|
local value = ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
|
|
file:write( value..","..charE )
|
|
end
|
|
end
|
|
end
|
|
file:write( "},"..charE )
|
|
end
|
|
file:write( "}" )
|
|
-- Return Values
|
|
-- return stringtable from string
|
|
if not filename then
|
|
-- set marker for stringtable
|
|
return file.str.."--|"
|
|
-- return stringttable from file
|
|
elseif filename == true or filename == 1 then
|
|
file:seek ( "set" )
|
|
-- no need to close file, it gets closed and removed automatically
|
|
-- set marker for stringtable
|
|
return file:read( "*a" ).."--|"
|
|
-- close file and return 1
|
|
else
|
|
file:close()
|
|
return 1
|
|
end
|
|
end
|
|
|
|
--// The Load Function
|
|
function table.load( sfile )
|
|
-- catch marker for stringtable
|
|
if string.sub( sfile,-3,-1 ) == "--|" then
|
|
tables,err = loadstring( sfile )
|
|
else
|
|
tables,err = loadfile( sfile )
|
|
end
|
|
if err then return _,err
|
|
end
|
|
tables = tables()
|
|
for idx = 1,#tables do
|
|
local tolinkv,tolinki = {},{}
|
|
for i,v in pairs( tables[idx] ) do
|
|
if type( v ) == "table" and tables[v[1]] then
|
|
table.insert( tolinkv,{ i,tables[v[1]] } )
|
|
end
|
|
if type( i ) == "table" and tables[i[1]] then
|
|
table.insert( tolinki,{ i,tables[i[1]] } )
|
|
end
|
|
end
|
|
-- link values, first due to possible changes of indices
|
|
for _,v in ipairs( tolinkv ) do
|
|
tables[idx][v[1]] = v[2]
|
|
end
|
|
-- link indices
|
|
for _,v in ipairs( tolinki ) do
|
|
tables[idx][v[2]],tables[idx][v[1]] = tables[idx][v[1]],nil
|
|
end
|
|
end
|
|
return tables[1]
|
|
end
|
|
-- close do
|
|
end |