Posted by
| Nick Gammon
Australia (22,975 posts) bio
Forum Administrator |
Message
| Hmmm. I reworked the idea a bit. First to remove multiple calls to GetVariable, which would slow it down. Second to add a couple more features:
- Also convert "true" and "false" back to booleans
- Handle bad compile when attempting to convert tables back
- Table checks now for "{ xxx }" not just "{" and "}" somewhere in the string
- Loadstring done in a restricted environment to stop data injection like:
var = "{ hello }; os.remove 'mushclient.exe'; b = {}"
-- tvar.lua
-- ----------------------------------------------------------
-- Accessing MUSHclient variables through the 'var' table.
-- See forum thread:
-- http://www.gammon.com.au/forum/?id=4904
-- Improvements suggested:
-- http://www.gammon.com.au/forum/?id=10980
-- Date: 6th Marh 2011
--[[
* Set a variable by assigning something to it.
* Delete a variable by assigning nil to it.
* Get a variable by retrieving its value, will return nil if the variable does not exist.
Improvements in this version:
* Automatically turns things that look like numbers into numbers
* Automatically turns "true" and "false" into booleans
* Saves amd restores tables by using serialize
Examples:
require "tvar"
var.target = "kobold" -- set MUSHclient variable 'target' to kobold
print (var.target) -- print contents of MUSHclient variable
-- table
var.t1 = { "fish", "chips", "steak", { "subtable", "foo" }, drink = "beer" }
Limitations:
1. Things that look like numbers will become numbers, perhaps unintentionally
2. Things that look like tables will become tables, perhaps unintentionally
3. The words "true" and "false" will become booleans even if they were not before
4. Slightly slower than the "var" module because of the extra tests
--]]
-- ----------------------------------------------------------
require "serialize"
var = {} -- variables table
setmetatable (var,
{
-- called to access an entry
__index =
function (t, key)
local v = GetVariable (key) -- find the variable in MUSHclient variable space
-- no such variable returns nil
if v == nil then
return nil
end -- if
-- convert true and false back into booleans
if v == "true" then
return true
end -- if true
if v == "false" then
return false
end -- if false
-- if can be converted into a number return that number
local n = tonumber (v)
if n then
return n
end -- if a number
-- if variable is in the form {xxx} treat as a table
if string.sub (v, 1, 1) == "{" and string.sub (v, -1, -1) == "}" then
local t = {} -- local environment
local f = loadstring ("ret = " .. v)
-- if loadstring fails, just return as a string
if f then
setfenv (f, t) -- local environment
-- if pcall fails, just return as a string
if pcall (f) then
return t.ret
end -- if executed ok
end -- if loadstring worked
end -- if looks like a table
return v -- return "normal" variable
end, -- function __index
-- called to change or delete an entry
__newindex =
function (t, key, value)
local result -- of SetVariable
if value == nil then -- nil deletes it
result = DeleteVariable (key)
elseif type (value) == 'table' then
result = SetVariable (key, serialize.save_simple (value))
else
result = SetVariable (key, tostring (value))
end -- if
-- warn if they are using bad variable keys
if result == error_code.eInvalidObjectLabel then
error ("Bad variable key '" .. key .. "'", 2)
end -- bad variable
end -- function __newindex
}) -- end metatable
return var
I should point out that this new module is not necessarily symmetrical.
For example, something that you wanted to be a string, but happens to look like a number (eg. "5e6") now actually becomes a number (eg. 5000000).
Similarly the strings "true" and "false" become booleans, when you might not want that.
Similarly something that looks like a table now becomes one (eg. "{nick}" becomes an empty table because the variable nick is nil).
Still, if you can live with that, you may find it useful. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|