summaryrefslogtreecommitdiffstats
path: root/acf2/persistence/backends/json.lua
diff options
context:
space:
mode:
Diffstat (limited to 'acf2/persistence/backends/json.lua')
-rw-r--r--acf2/persistence/backends/json.lua79
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