require("hook") local hook = hook /*--------------------------------------------------------- utilx module Useful and common functions ---------------------------------------------------------*/ module("utilx") function KeyValuesToTable( kv, internal ) -- Expected: -- * "name" "value" -- * name value -- * // -- * { ... } -- * whitespace local ST_NAME = 0 local ST_VALUE = 1 local ST_VALUE_OR_CHILD = 2 local ST_CHILD = 3 local name = nil local value = nil local current_pos = 1 local current_contents = kv local state = ST_NAME local result = {} local first_name = nil while (true) do local c = string.sub(current_contents, current_pos, current_pos) current_pos = current_pos + 1 if (c == "") then break elseif (string.byte(c,1) <= 32) then -- continue (do nothing) elseif (c == "/" and string.sub(current_contents, current_pos, current_pos) == "/") then -- scan till EOL while (c != "\n") do c = string.sub(current_contents, current_pos, current_pos) current_pos = current_pos + 1 if (c == "") then break end end elseif (c == "}") then break elseif (c == "{") then state = ST_CHILD local inc_pos = 0 result[name],inc_pos = KeyValuesToTable( string.sub(current_contents, current_pos), true ) current_pos = current_pos + inc_pos state = ST_NAME elseif (c != "" or c == "\"") then if (state == ST_VALUE_OR_CHILD) then state = ST_VALUE end local quoted = (c == "\"") local thing = "" if (not quoted) then thing = c end while (true) do c = string.sub(current_contents, current_pos, current_pos) current_pos = current_pos + 1 if (quoted) then if (c == "\\") then c = string.sub(current_contents, current_pos, current_pos) current_pos = current_pos + 1 if (c == "n") then c = "\n" elseif (c == "r") then c = "\r" elseif (c == "t") then c = "\t" elseif (c == "\"") then c = "\"" elseif (c == "\\") then c = "\\" else c = "" end elseif (c == "\"") then break end else if (string.byte(c,1) <= 32) then break end end thing = thing .. c end current_pos = current_pos + 1 if tonumber(thing) then thing = tonumber(thing) end if (state == ST_NAME) then name = thing if (first_name == nil) then first_name = name end state = ST_VALUE_OR_CHILD elseif (state == ST_VALUE) then value = thing result[name] = value state = ST_NAME end end end if (not internal) then return result[first_name], first_name else return result, current_pos end end function TableToKeyValues( val, key, level ) local tabs = level or 0 // Return a string so that it doesn't bug out later if ( tabs > 8 ) then return "" end if ( type( val ) != "table" ) then return "" end local name = key or "Out" local str str = string.rep("\t", tabs) .. "\""..name.."\"\n" str = str .. string.rep("\t", tabs) .. "{\n" for k,v in pairs(val) do k = stringx.Replace(k, "\\", "\\\\") k = stringx.Replace(k, "\"", "\\\"") k = stringx.Replace(k, "\t", "\\t") k = stringx.Replace(k, "\n", "\\n") k = stringx.Replace(k, "\r", "\\r") if ( type( v ) == "table" ) then str = str .. TableToKeyValues(v,k,tabs+1) else v = stringx.Replace(v, "\\", "\\\\") v = stringx.Replace(v, "\"", "\\\"") v = stringx.Replace(v, "\t", "\\t") v = stringx.Replace(v, "\n", "\\r") v = stringx.Replace(v, "\r", "\\n") str = str .. string.rep("\t", tabs+1) .. "\""..k.."\"\t\""..v.."\"\n" end end str = str .. string.rep("\t", tabs) .. "}\n" return str end