Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Persistant storage: single long string or key-value?

edited September 2013 in Questions Posts: 11

I'd like to save user-created objects that each have a handful of properties. There are two ways I can think of to do this. One is to give each object an id, and then store each property as a key-value using something like objectID_propertyName, property. The other is to make a long string similar to how CargoBot handles level solutions. Objects each have their own line and properties are enclosed in ().

Which solution makes more sense in terms of memory and speed? I like the first solution because accessing the property is more intuitive and assuming the underlying storage is a hash table, it should be faster than string manipulations, right? But I am not thrilled about assigning each object an ID. It's not hard to generate, but doesn't have much to do with the object except for data storage. And I still have to scrape the id to get the property name, which might take as long as processing one long string.

Which approach is better? Is there a third, more sensible way to handle it?

And, while I'm worrying about memory usage, is there a tool to track memory used by my app?

Thanks!

Comments

  • So, thinking about this some more, I'm now leaning toward using an object id for the key and a single string for the properties: objectID, "property1, property2, property3". I'll still have to process the string to get individual properties, but this likely would only happen at the beginning of the app. This way, I can save object data when the user creates the object. If I have one long, multiple line string with properties for all the objects, I'd either have to keep rewriting the whole thing; or wait until the game exits to save it. I'll still have to give each object having an id though.

  • Jmv38Jmv38 Mod
    Posts: 3,297

    This tells you memory usage:

    function showMem()   
        local kb = gcinfo()
        print(tostring(kb).." kb")
    end
    
  • Jmv38Jmv38 Mod
    edited September 2013 Posts: 3,297

    I think i would save an executable string:


    -- test loadstring -- Use this function to perform your initial setup function setup()     -- object to load     obj = {}     -- string saving obj properties     str =  [[     obj.color = color(255, 0, 0, 255)     obj.size = 100 ]]     parameter.action("show properties",         function()             print("properties:")             for i,v in pairs(obj) do              print(tostring(i).." : "..tostring(v))             end             print("end")         end     )     parameter.action("load properties",         function()             loadstring(str)()         end     ) end

    This programs shows the properties are undefined until you load them. Then they are there. Check the [[ syntax for multiline strings. Also check the special syntaxt for loadstring! You can save the string either in one local variable, or in a tab (better for exchanging your program with others).

  • Posts: 1,255

    I don't tend to save executable code, but save properties to delineated strings. Often I find the easiest thing to do when reading them in is populate a table of string segments using something like this for semicolon delimited values

    i = 0
    for t in string.gmatch(s,"([^;]+)") do
        i = i + 1
        bits[i] = t
    end
    

    and so on...

    Then come back to that table and figure out what goes where based on some index values.

  • Thanks for the suggestions. Very helpful!

    So it sounds like you would both recommend saving one key-value per object, but Jvm would go with an executable string and Mark would use a regular string and then parse it out. I hadn't considered using an executable - kind of new to Lua and wasn't even clear on whether Codea used a subset of Lua or the whole thing. It does nicely avoid having to assign an order to the properties. Either way, I would still need to use some sort of object ID to use as the key, right?

    Jvm, when you say 'tabs', are you referring to the tabs in the coding environment? The documentation for readProjectData mentions sharing projects. I had assumed that meant between developers, like for code sharing. Someone who downloads the app wouldn't have access to the tabs, would they? Also, can I programmatically write to a tab?

  • Jmv38Jmv38 Mod
    edited October 2013 Posts: 3,297

    I thought you were knew to lua, this is why i showed an example with some aspects it took me some time to learn. You can save into a tab with saveProjectTab, see the doc of codea for details. 'yes' to your other questions.

  • BriarfoxBriarfox Mod
    Posts: 1,542

    I found this online and it has worked rather well. It will save the table to a string then I just loadstring it into a table,

    function table.val_to_str ( v )
      if "string" == type( v ) then
        v = string.gsub( v, "\n", "\\n" )
        if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
          return "'" .. v .. "'"
        end
        return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
      else
        return "table" == type( v ) and table.tostring( v ) or
          tostring( v )
      end
    end
    
    function table.key_to_str ( k )
      if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
        return k
      else
        return "[" .. table.val_to_str( k ) .. "]"
      end
    end
    
    function table.tostring( tbl )
      local result, done = {}, {}
      for k, v in ipairs( tbl ) do
        table.insert( result, table.val_to_str( v ) )
        done[ k ] = true
      end
      for k, v in pairs( tbl ) do
        if not done[ k ] then
          table.insert( result,
            table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
        end
      end
      return "{" .. table.concat( result, "," ) .. "}"
    end
    
Sign In or Register to comment.