# HG changeset patch # User Kim Alvefur # Date 1507847500 -7200 # Node ID 6a7b7cb7148ecb63b7716f1b9c92ade08388ad7d # Parent 226693a22fc9e914d07e743e910abb80bd48259c mod_storage_appendmap: Factor out serialization into reusable functions diff -r 226693a22fc9 -r 6a7b7cb7148e mod_storage_appendmap/mod_storage_appendmap.lua --- a/mod_storage_appendmap/mod_storage_appendmap.lua Wed Oct 11 13:56:03 2017 +0100 +++ b/mod_storage_appendmap/mod_storage_appendmap.lua Fri Oct 13 00:31:40 2017 +0200 @@ -2,11 +2,62 @@ local load = require "util.envload".envloadfile; local dm = require "core.storagemanager".olddm; +local REMOVE = {}; -- Special value for removing keys + local driver = {}; -local map = {}; + +local keywords = { + ["do"] = true; ["and"] = true; ["else"] = true; ["break"] = true; + ["if"] = true; ["end"] = true; ["goto"] = true; ["false"] = true; + ["in"] = true; ["for"] = true; ["then"] = true; ["local"] = true; + ["or"] = true; ["nil"] = true; ["true"] = true; ["until"] = true; + ["elseif"] = true; ["function"] = true; ["not"] = true; + ["repeat"] = true; ["return"] = true; ["while"] = true; + + -- _ENV is not technically a keyword but we need to treat it as such + ["_ENV"] = true; +}; + +local function is_usable_identifier(s) + return type(s) == "string" and not keywords[s] and s:find("^[%a_][%w_]*$"); +end + +local function serialize_key(key) + if is_usable_identifier(key) then + return key; + else + return "_ENV[" .. dump(key) .. "]"; + end +end + +local function serialize_value(value) + if value == REMOVE then + return "nil"; + else + return dump(value); + end +end + +local function serialize_pair(key, value) + key = serialize_key(key); + value = serialize_value(value); + return key .. " = " .. value .. ";\n"; +end + +local function serialize_map(keyvalues) + local keys, values = {}, {}; + for key, value in pairs(keyvalues) do + key = serialize_key(key); + value = serialize_value(value); + table.insert(keys, key); + table.insert(values, value); + end + return table.concat(keys, ", ") .. " = " .. table.concat(values, ", ") .. ";\n"; +end + +local map = { remove = REMOVE }; local map_mt = { __index = map }; -map.remove = {}; function map:get(user, key) module:log("debug", "map:get(%s, %s)", tostring(user), tostring(key)) @@ -29,36 +80,8 @@ return env[key]; end -local keywords = { - ["do"] = true; ["and"] = true; ["else"] = true; ["break"] = true; - ["if"] = true; ["end"] = true; ["goto"] = true; ["false"] = true; - ["in"] = true; ["for"] = true; ["then"] = true; ["local"] = true; - ["or"] = true; ["nil"] = true; ["true"] = true; ["until"] = true; - ["elseif"] = true; ["function"] = true; ["not"] = true; - ["repeat"] = true; ["return"] = true; ["while"] = true; - - -- _ENV is not technically a keyword but we need to treat it as such - ["_ENV"] = true; -}; - function map:set_keys(user, keyvalues) - local keys, values = {}, {}; - if _VERSION == "Lua 5.1" then - assert(keyvalues._ENV == nil, "'_ENV' is a restricted key"); - end - for key, value in pairs(keyvalues) do - module:log("debug", "user %s sets %q to %s", user, key, tostring(value)) - if type(key) ~= "string" or not key:find("^[%a_][%w_]*$") or keywords[key] then - key = "_ENV[" .. dump(key) .. "]"; - end - table.insert(keys, key); - if value == self.remove then - table.insert(values, "nil") - else - table.insert(values, dump(value)) - end - end - local data = table.concat(keys, ", ") .. " = " .. table.concat(values, ", ") .. ";\n"; + local data = serialize_map(keyvalues); return dm.append_raw(user, module.host, self.store, "map", data); end @@ -68,31 +91,22 @@ end if key == nil then local filename = dm.getpath(user, module.host, self.store, "map"); - os.remove(filename); - return true; + return os.remove(filename); end - if type(key) ~= "string" or not key:find("^[%w_][%w%d_]*$") or key == "_ENV" then - key = "_ENV[" .. dump(key) .. "]"; - end - local data = key .. " = " .. dump(value) .. ";\n"; + local data = serialize_pair(key, value); return dm.append_raw(user, module.host, self.store, "map", data); end -local keyval = {}; +local keyval = { remove = REMOVE }; local keyval_mt = { __index = keyval }; function keyval:get(user) - return map.get(self, user); + return map.get(self, user, nil); end -function keyval:set(user, data) - map.set(self, user); - if data then - for k, v in pairs(data) do - map.set(self, user, k, v); - end - end - return true; +function keyval:set(user, keyvalues) + local data = serialize_map(keyvalues); + return dm.store_raw(user, module.host, self.store, "map", data); end -- TODO some kind of periodic compaction thing?