diff options
Diffstat (limited to 'acf2/persistence/backends/json.lua')
-rw-r--r-- | acf2/persistence/backends/json.lua | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/acf2/persistence/backends/json.lua b/acf2/persistence/backends/json.lua new file mode 100644 index 0000000..809d947 --- /dev/null +++ b/acf2/persistence/backends/json.lua @@ -0,0 +1,79 @@ +--[[ +Copyright (c) 2012-2013 Kaarle Ritvanen +See LICENSE file for license details +--]] + +local pth = require('acf2.path') +local Cache = require('acf2.persistence.backends.volatile') +local util = require('acf2.persistence.util') +local copy = require('acf2.util').copy + +local json = require('cjson') +local posix = require('posix') + + +local backend = require('acf2.object').class() + +function backend:init() + -- TODO cache expiration + self.cache = {} + self.dirty = {} +end + +function backend:split_path(path) + local fpath = copy(path) + local jpath = {} + local res + + while #fpath > 0 do + local fp = pth.join('/', unpack(fpath)) + if self.cache[fp] then return fp, jpath end + table.insert(jpath, 1, fpath[#fpath]) + table.remove(fpath) + end + + fpath = '/' + + while true do + fpath = pth.join(fpath, jpath[1]) + table.remove(jpath, 1) + + local t = posix.stat(fpath, 'type') + if t == 'link' then t = posix.stat(posix.readlink(fpath), 'type') end + if not t or not ({directory=true, regular=true})[t] then + error('File or directory does not exist: '..fpath) + end + + if t == 'regular' then return fpath, jpath end + + assert(#jpath > 0) + end +end + +function backend:get(path, top) + local fpath, jpath = self:split_path(path) + if not self.cache[fpath] then + self.cache[fpath] = Cache(json.decode(util.read_file(fpath))) + end + return self.cache[fpath]:get(jpath, top) +end + +function backend:set(mods) + local dirty = {} + + for _, mod in ipairs(mods) do + local path, value = unpack(mod) + local fpath, jpath = self:split_path(path) + self.cache[fpath]:_set(jpath, value) + dirty[fpath] = true + end + + for path, _ in pairs(dirty) do + local file = util.open_file(path, 'w') + file:write(json.encode(self.cache[path]:_get{})) + file:close() + end +end + + +return backend |