Advertisement
partyboy1a

tablehandling.lua

Sep 2nd, 2011
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.38 KB | None | 0 0
  1. --[[
  2.    Save Table to File/Stringtable
  3.    Load Table from File/Stringtable
  4.    v 0.94
  5.    
  6.    Lua 5.1 compatible
  7.    
  8.    Userdata and indices of these are not saved
  9.    Functions are saved via string.dump, so make sure it has no upvalues
  10.    References are saved
  11.    ----------------------------------------------------
  12.    table.save( table [, filename] )
  13.    
  14.    Saves a table so it can be called via the table.load function again
  15.    table must a object of type 'table'
  16.    filename is optional, and may be a string representing a filename or true/1
  17.    
  18.    table.save( table )
  19.       on success: returns a string representing the table (stringtable)
  20.       (uses a string as buffer, ideal for smaller tables)
  21.    table.save( table, true or 1 )
  22.       on success: returns a string representing the table (stringtable)
  23.       (uses io.tmpfile() as buffer, ideal for bigger tables)
  24.    table.save( table, "filename" )
  25.       on success: returns 1
  26.       (saves the table to file "filename")
  27.    on failure: returns as second argument an error msg
  28.    ----------------------------------------------------
  29.    table.load( filename or stringtable )
  30.    
  31.    Loads a table that has been saved via the table.save function
  32.    
  33.    on success: returns a previously saved table
  34.    on failure: returns as second argument an error msg
  35.    ----------------------------------------------------
  36.    
  37.    chillcode, http://lua-users.org/wiki/SaveTableToFile
  38.    Licensed under the same terms as Lua itself.
  39. ]]--
  40.  
  41.    -- declare local variables
  42.    --// exportstring( string )
  43.    --// returns a "Lua" portable version of the string
  44.    local function exportstring( s )
  45.       s = string.format( "%q",s )
  46.       -- to replace
  47.       s = string.gsub( s,"\\\n","\\n" )
  48.       s = string.gsub( s,"\r","\\r" )
  49.       s = string.gsub( s,string.char(26),"\"..string.char(26)..\"" )
  50.       return s
  51.    end
  52. --// The Save Function
  53. function table.save(  tbl,filename )
  54.    local charS,charE = "   ","\n"
  55.    local file,err
  56.    -- create a pseudo file that writes to a string and return the string
  57.    if not filename then
  58.       file =  { write = function( self,newstr ) self.str = self.str..newstr end, str = "" }
  59.       charS,charE = "",""
  60.    -- write table to tmpfile
  61.    elseif filename == true or filename == 1 then
  62.       charS,charE,file = "","",io.tmpfile()
  63.    -- write table to file
  64.    -- use io.open here rather than io.output, since in windows when clicking on a file opened with io.output will create an error
  65.    else
  66.       file,err = io.open( filename, "w" )
  67.       if err then return _,err end
  68.    end
  69.    -- initiate variables for save procedure
  70.    local tables,lookup = { tbl },{ [tbl] = 1 }
  71.    file:write( "return {"..charE )
  72.    for idx,t in ipairs( tables ) do
  73.       if filename and filename ~= true and filename ~= 1 then
  74.          file:write( "-- Table: {"..idx.."}"..charE )
  75.       end
  76.       file:write( "{"..charE )
  77.       local thandled = {}
  78.       for i,v in ipairs( t ) do
  79.          thandled[i] = true
  80.          -- escape functions and userdata
  81.          if type( v ) ~= "userdata" then
  82.             -- only handle value
  83.             if type( v ) == "table" then
  84.                if not lookup[v] then
  85.                   table.insert( tables, v )
  86.                   lookup[v] = #tables
  87.                end
  88.                file:write( charS.."{"..lookup[v].."},"..charE )
  89.             elseif type( v ) == "function" then
  90.                file:write( charS.."loadstring("..exportstring(string.dump( v )).."),"..charE )
  91.             else
  92.                local value =  ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
  93.                file:write(  charS..value..","..charE )
  94.             end
  95.          end
  96.       end
  97.       for i,v in pairs( t ) do
  98.          -- escape functions and userdata
  99.          if (not thandled[i]) and type( v ) ~= "userdata" then
  100.             -- handle index
  101.             if type( i ) == "table" then
  102.                if not lookup[i] then
  103.                   table.insert( tables,i )
  104.                   lookup[i] = #tables
  105.                end
  106.                file:write( charS.."[{"..lookup[i].."}]=" )
  107.             else
  108.                local index = ( type( i ) == "string" and "["..exportstring( i ).."]" ) or string.format( "[%d]",i )
  109.                file:write( charS..index.."=" )
  110.             end
  111.             -- handle value
  112.             if type( v ) == "table" then
  113.                if not lookup[v] then
  114.                   table.insert( tables,v )
  115.                   lookup[v] = #tables
  116.                end
  117.                file:write( "{"..lookup[v].."},"..charE )
  118.             elseif type( v ) == "function" then
  119.                file:write( "loadstring("..exportstring(string.dump( v )).."),"..charE )
  120.             else
  121.                local value =  ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
  122.                file:write( value..","..charE )
  123.             end
  124.          end
  125.       end
  126.       file:write( "},"..charE )
  127.    end
  128.    file:write( "}" )
  129.    -- Return Values
  130.    -- return stringtable from string
  131.    if not filename then
  132.       -- set marker for stringtable
  133.       return file.str.."--|"
  134.    -- return stringttable from file
  135.    elseif filename == true or filename == 1 then
  136.       file:seek ( "set" )
  137.       -- no need to close file, it gets closed and removed automatically
  138.       -- set marker for stringtable
  139.       return file:read( "*a" ).."--|"
  140.    -- close file and return 1
  141.    else
  142.       file:close()
  143.       return 1
  144.    end
  145. end
  146.  
  147. --// The Load Function
  148. function table.load( sfile )
  149.    -- catch marker for stringtable
  150.    if string.sub( sfile,-3,-1 ) == "--|" then
  151.       tables,err = loadstring( sfile )
  152.    else
  153.       tables,err = loadfile( sfile )
  154.    end
  155.    if err then return _,err
  156.    end
  157.    tables = tables()
  158.    for idx = 1,#tables do
  159.       local tolinkv,tolinki = {},{}
  160.       for i,v in pairs( tables[idx] ) do
  161.          if type( v ) == "table" and tables[v[1]] then
  162.             table.insert( tolinkv,{ i,tables[v[1]] } )
  163.          end
  164.          if type( i ) == "table" and tables[i[1]] then
  165.             table.insert( tolinki,{ i,tables[i[1]] } )
  166.          end
  167.       end
  168.       -- link values, first due to possible changes of indices
  169.       for _,v in ipairs( tolinkv ) do
  170.          tables[idx][v[1]] = v[2]
  171.       end
  172.       -- link indices
  173.       for _,v in ipairs( tolinki ) do
  174.          tables[idx][v[2]],tables[idx][v[1]] =  tables[idx][v[1]],nil
  175.       end
  176.    end
  177.    return tables[1]
  178. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement