+--- Create a dynamic table which automatically creates subtables.
+-- @return Dynamic Table
+function dtable()
+ return setmetatable({}, { __index =
+ function(tbl, key)
+ return rawget(tbl, key)
+ or rawget(rawset(tbl, key, dtable()), key)
+ end
+ })
+end
+
+
+-- Serialize the contents of a table value.
+function _serialize_table(t)
+ local data = ""
+ for k, v in pairs(t) do
+ k = serialize_data(k)
+ v = serialize_data(v)
+ data = data .. ( #data > 0 and ", " or "" ) ..
+ '[' .. k .. '] = ' .. v
+ end
+ return data
+end
+
+--- Recursively serialize given data to lua code, suitable for restoring
+-- with loadstring().
+-- @param val Value containing the data to serialize
+-- @return String value containing the serialized code
+-- @see restore_data
+-- @see get_bytecode
+function serialize_data(val)
+ if val == nil then
+ return "nil"
+ elseif type(val) == "number" then
+ return val
+ elseif type(val) == "string" then
+ return string.format("%q", val)
+ elseif type(val) == "boolean" then
+ return val and "true" or "false"
+ elseif type(val) == "function" then
+ return string.format("loadstring(%q)", get_bytecode(val))
+ elseif type(val) == "table" then
+ return "{ " .. _serialize_table(val) .. " }"
+ else
+ return '"[unhandled data type:' .. type(val) .. ']"'
+ end
+end
+
+--- Restore data previously serialized with serialize_data().
+-- @param str String containing the data to restore
+-- @return Value containing the restored data structure
+-- @see serialize_data
+-- @see get_bytecode
+function restore_data(str)
+ return loadstring("return " .. str)()
+end
+
+