Aadvert

Vault (Alpha)

Mar 31st, 2012
826
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.91 KB | None | 0 0
  1. -- (C) 2012 Sandre S. (firstname at gmail)
  2. --
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License at
  6. --
  7. --     http://www.apache.org/licenses/LICENSE-2.0
  8. --
  9. -- Unless required by applicable law or agreed to in writing, software
  10. -- distributed under the License is distributed on an "AS IS" BASIS,
  11. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. -- See the License for the specific language governing permissions and
  13. -- limitations under the License.
  14. --
  15.  
  16. -- Default configuration
  17.  
  18. local BaseDirectory = "/.vault"
  19. local DefaultMode = "append"
  20. local DefaultHybridN = 200
  21.  
  22. -- data -> Lua conversion
  23. local validTypes = {}
  24.  
  25. validTypes['string'] = function(str)
  26.     return string.format("%q", str)
  27. end
  28.  
  29. validTypes['number'] = function(num)
  30.     local srep = tostring(num)
  31.     if srep == "inf" then
  32.         return "math.huge"
  33.     end
  34.     return srep
  35. end
  36.  
  37. validTypes['boolean'] = tostring
  38. validTypes['nil'] =  function() return 'nil' end
  39.  
  40.  
  41. --- Converts stuff to a Lua representation
  42. -- @param obj The object to turn into Lua code
  43. local function toLua(val)
  44.     local sType = type(val)
  45.     if validTypes[sType] then
  46.         return validTypes[sType](val)
  47.     end
  48. end
  49.  
  50. local LineTemplate = "t[%s] = %s"
  51. local FileTemplate = [[
  52. local arg = {...}
  53. local t = arg[1]
  54. if type(t) ~= "table" then
  55.  error("Data script didn't recieve a table to transfer values to!")
  56. end
  57.  
  58. -- Begin data
  59.  
  60. ]]
  61.  
  62. local function genLine(k, v)
  63.     return string.format(LineTemplate, toLua(k), toLua(v))
  64. end
  65.  
  66. local function genWhole(tData)
  67.     local cData = {FileTemplate }
  68.  
  69.     for k, v in pairs(tData) do
  70.         table.insert(cData, genLine(k, v))
  71.     end
  72.  
  73.     return table.concat(cData, "\n")
  74. end -- /Data -> Lua conversion
  75.  
  76. -- Proxy management
  77.  
  78. local Proxies = {}
  79. local ProxyNames = {} -- Reverse lookup
  80. local ProxyConf = {} -- Configuration (HybridN, Mode, File, CurrentHybridN, ???)
  81. local ProxyRaw = {} -- Raw tables
  82.  
  83. do
  84.     local weakKey, weakValue = {__mode = "k"}, {__mode = "v"}
  85.     setmetatable(Proxies, weakValue)
  86.     setmetatable(ProxyNames, weakKey)
  87.     setmetatable(ProxyConf, weakKey)
  88.     setmetatable(ProxyRaw, weakKey)
  89. end -- Allow unreferenced proxies to be GC'd, even if they are registered here.
  90.  
  91. local function registerProxy(sName, proxy, conf, raw)
  92.     Proxies[sName] = proxy
  93.     ProxyNames[proxy] = sName
  94.     ProxyConf[proxy] = conf
  95.     ProxyRaw[proxy] = raw
  96. end -- /Proxy management
  97.  
  98.  
  99. -- File functions
  100. local function validateDirectory(sDir)
  101.     if not fs.exists(sDir) then
  102.         return fs.makeDir(sDir)
  103.     end
  104. end
  105.  
  106. local function resolveFile(sName)
  107.     return BaseDirectory .. "/" .. sName
  108. end
  109.  
  110. local function dumpFile(sFile)
  111.     local handle = fs.open(sFile, "r")
  112.     local sData = handle.readAll()
  113.     handle.close()
  114.     return sData
  115. end
  116.  
  117. local function createFile(sFile)
  118.     local handle = fs.open(sFile, "w")
  119.     handle.write(FileTemplate)
  120.     handle.close()
  121. end
  122.  
  123. local function loadRaw(conf)
  124.     local sData = dumpFile(conf.File)
  125.     return loadstring(sData)(conf.raw)
  126. end
  127.  
  128. local writeModes = {}
  129.  
  130. function writeModes.none() end -- Empty function for ignoring
  131.  
  132. local function dsFlush(conf)
  133.     local sData = genWhole(conf.raw)
  134.     local handle = fs.open(conf.File, "w")
  135.     handle.write(sData)
  136.     handle.close()
  137. end
  138.  
  139. local function wmAppend(conf, k, v)
  140.     local handle = fs.open(conf.File, "a")
  141.     handle.writeLine(genLine(k, v))
  142.     handle.close()
  143. end
  144. writeModes.append = wmAppend
  145.  
  146. function writeModes.hybrid(conf, k, v)
  147.     local n = conf.CurrentHybridN
  148.     if n >= conf.HybridN then
  149.         conf.CurrentHybridN = 0
  150.         dsFlush(conf)
  151.         return
  152.     end
  153.  
  154.     conf.CurrentHybridN = n + 1
  155.     return wmAppend(conf, k, v)
  156. end
  157. -- dsObject functions
  158.  
  159. local function dsNewIndex(self, k, v)
  160.     local conf, raw = ProxyConf[self], ProxyRaw[self]
  161.     -- Some type checking
  162.     if not validTypes[type(k)] or not validTypes[type(v)] then
  163.         error("Attempting to put invalid type in vault table", 2)
  164.     end
  165.     if raw[k] == v then
  166.         -- Avoid some needless writing
  167.         return
  168.     end
  169.     raw[k] = v
  170.     return writeModes[conf.Mode](conf, k, v)
  171. end
  172.  
  173. local function cloneConfig(sFile, raw, proxy)
  174.     return {Mode = DefaultMode, HybridN = DefaultHybridN, CurrentHybridN = 0, File = sFile, raw = raw, proxy = proxy}
  175. end
  176.  
  177. local function newdsObject(sName, sFile)
  178.     if not sFile then
  179.         sFile = resolveFile(sName)
  180.     end
  181.     local raw = {}
  182.     local proxy = {}
  183.     local conf = cloneConfig(sFile, raw, proxy)
  184.     registerProxy(sName, proxy, conf, raw)
  185.     -- Load data or create a new file if it doesn't exist
  186.     if fs.exists(conf.File) then
  187.         loadRaw(conf)
  188.     else
  189.         createFile(conf.File)
  190.     end
  191.  
  192.     setmetatable(proxy, {__index = raw, __newindex = dsNewIndex})
  193.  
  194.     return proxy
  195. end
  196.  
  197.  
  198. function open(sName)
  199.     if Proxies[sName] then
  200.         return Proxies[sName]
  201.     end
  202.     return newdsObject(sName)
  203. end
  204.  
  205. --- The name the handle will be referenced by
  206. -- @param sName
  207. -- @param sFile The specific file name to open
  208. --
  209. function openFile(sName, sFile)
  210.     if Proxies[sName] then
  211.         if ProxyConf[Proxies[sName]].File == sFile then
  212.             return Proxies[sName]
  213.         end
  214.         return false, "name taken"
  215.     end
  216.     return newdsObject(sName, sFile)
  217. end
  218.  
  219. function setMode(dsObj, sMode)
  220.     if not writeModes[sMode] then
  221.         error("vault.setMode(): Invalid mode")
  222.     end
  223.     ProxyConf[dsObj].Mode = sMode
  224. end
  225.  
  226. function getRaw(dsObj)
  227.     return ProxyRaw[dsObj]
  228. end
  229.  
  230. function setDir(sDirectory)
  231.     validateDirectory(sDirectory)
  232.     BaseDirectory = sDirectory
  233. end
  234.  
  235. function setHybridN(dsObj, n)
  236.     local conf = ProxyConf[dsObj]
  237.     conf.HybridN = n
  238. end
  239.  
  240. function getDir()
  241.     return BaseDirectory
  242. end
  243.  
  244. function getFile(dsObj)
  245.     return ProxyConf[dsObj].File
  246. end
  247.  
  248. function flush(dsObj)
  249.     local conf = ProxyConf[dsObj]
  250.     conf.CurrentHybridN = 0
  251.     dsFlush(conf)
  252. end
  253.  
  254. function reload(dsObj)
  255.     local conf = ProxyConf[dsObj]
  256.     local raw = conf.raw
  257.     local temp = {}
  258.     for k, v in pairs(raw) do
  259.         temp[k] = true
  260.     end
  261.     for k, v in pairs(temp) do
  262.         raw[k] = nil
  263.     end
  264.     loadRaw(conf)
  265. end
Advertisement
Add Comment
Please, Sign In to add comment