Advertisement
theoriginalbit

ccConfig

Feb 4th, 2013
468
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.78 KB | None | 0 0
  1. --[[
  2.   ccConfig v3.0.2 [Updated: 27 March 2014]
  3.  
  4.   Copyright © 2014 Joshua Asbury a.k.a. theoriginalbit [theoriginalbit@gmail.com]
  5.  
  6.   Permission is hereby granted, free of charge, to any person obtaining a copy
  7.   of this software and associated documentation files (the "Software"), to deal
  8.   in the Software without restriction, including without limitation the rights
  9.   to use, copy, modify, merge, publish, distribute, and/or sublicense copies
  10.   of the Software, and to permit persons to whom the Software is furnished to
  11.   do so, subject to the following conditions:
  12.  
  13.   - The above copyright notice and this permission notice shall be included in
  14.     all copies or substantial portions of the Software;
  15.   - Visible credit is given to the original author;
  16.   - The software is distributed in a non-profit way;
  17.  
  18.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. THE SOFTWARE.
  25. --]]
  26.  
  27. local function startsWith(str, prefix)
  28.   return str:sub( 1, #tostring(prefix)) == tostring(prefix)
  29. end
  30.  
  31. local function contains(str, seq)
  32.   return (str:find(seq, 1)) ~= nil
  33. end
  34.  
  35. local function split(str, patt)
  36.   local t = {}
  37.  
  38.   for s in str:gmatch("[^"..patt.."]+") do
  39.     t[#t+1] = s
  40.   end
  41.  
  42.   return t
  43. end
  44.  
  45. local function trim(str)
  46.   return (str:gsub("^%s*(.-)%s*$", "%1"))
  47. end
  48.  
  49. local function assert(cdn, msg, lvl)
  50.   if not cdn then
  51.     error(msg or "assertion failed!", (lvl == 0 and 0 or lvl and (lvl + 1) or 2))
  52.   end
  53.   return cdn
  54. end
  55.  
  56. local Configuration = {}
  57.  
  58. Configuration.__index = Configuration
  59.  
  60. local function validateParam(param, value)
  61.   return type(param) == value
  62. end
  63.  
  64. local function validateBoolean(b)
  65.   return (b == "true" or b == "false" or b == "1" or b == "0" or b == 1 or b == 0 or b == true or b == false or b == "yes" or b == "no")
  66. end
  67.  
  68. local function validateColor(source)
  69.   --# parse number inputs
  70.   if tonumber(source) then
  71.     local shifted = math.floor(math.log(tonumber(source))/math.log(2))
  72.     if shifted >= 0 and shifted <= 15 then
  73.       return col
  74.     end
  75.     return false, "colour out of range"
  76.   --# parse string inputs
  77.   elseif type(source) == "string" then
  78.     source =  source:lower()
  79.                     :gsub("%s*", "")
  80.                     :gsub("colou?rs?%.?", "")
  81.                     :gsub("lightb(.+)", "lightB%1")
  82.                     :gsub("lightg(.+)", "lightG%1")
  83.     source = colors[source] or colours[source]
  84.     return source, (not source and "invalid string input")
  85.   end
  86.   --# reject other inputs
  87.   return false, "expected number/string, got "..type(source)
  88. end
  89.  
  90. local function get(self, key, default)
  91.   if type(self.properties[key]) == "table" then
  92.     self.properties[key].default = default
  93.     return self.properties[key].value
  94.   end
  95.   --# the key doesn't exist in the table, create it now
  96.   self.properties[key] = {}
  97.   self.properties[key].value = default
  98.   self.properties[key].default = default
  99.   return default
  100. end
  101.  
  102. local function set(self, key, value)
  103.   assert(self.properties[key], "Invalid parameter #1: The key '"..tostring(key).."' does not exist in the configuration file.", 3)
  104.  
  105.   self.properties[key].value = value
  106. end
  107.  
  108. function Configuration:getBoolean(key, default)
  109.   --# validate parameters
  110.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  111.   assert(validateBoolean(default), "Invalid parameter #2: Expected boolean, got "..tostring(default).." of type "..type(default), 2)
  112.  
  113.   --# get the value from the config
  114.   local value = get(self, key, default)
  115.  
  116.   --# validate the config boolean
  117.   assert(validateBoolean(value), "Configuration error: No boolean value found under the key \""..key.."\", found "..tostring(value).." of type "..type(value), 2)
  118.  
  119.   --# return a boolean
  120.   return v == "true" or v == true or v == "1" or v == 1 or v == "yes"
  121. end
  122.  
  123. function Configuration:setBoolean(key, value)
  124.   --# validate parameters
  125.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  126.   assert(validateBoolean(value), "Invalid parameter #2: Expected boolean, got "..tostring(default).." of type "..type(value), 2)
  127.  
  128.   --# set the value
  129.   set(self, key, value)
  130. end
  131.  
  132. function Configuration:getNumber(key, default)
  133.   --# validate parameters
  134.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  135.   assert(validateParam(default, "number"), "Invalid parameter #2: Expected number, got "..tostring(default).." of type "..type(default), 2)
  136.  
  137.   --# get the number from the config
  138.   local value = tonumber(get(self, key, default))
  139.  
  140.   --# validate the number
  141.   assert(validateParam(value, "number"), "Configuration error: No number found under the key \""..key.."\", found "..tostring(value).." of type "..type(value), 2)
  142.  
  143.   --# return the number
  144.   return value
  145. end
  146.  
  147. function Configuration:setNumber(key, value)
  148.   --# validate parameters
  149.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  150.   assert(validateParam(value, "number"), "Invalid parameter #2: Expected number, got "..tostring(default).." of type "..type(value), 2)
  151.  
  152.   --# set the value
  153.   set(self, key, value)
  154. end
  155.  
  156. function Configuration:getString(key, default)
  157.   --# validate parameters
  158.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  159.   assert(validateParam(default, "string"), "Invalid parameter #2: Expected string, got "..tostring(default).." of type "..type(default), 2)
  160.  
  161.   --# get the string from the config
  162.   local value = get(self, key, default)
  163.  
  164.   --# return the string
  165.   return value
  166. end
  167.  
  168. function Configuration:setString(key, value)
  169.   --# validate parameters
  170.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  171.   assert(validateParam(value, "string"), "Invalid parameter #2: Expected string, got "..tostring(default).." of type "..type(value), 2)
  172.  
  173.   --# set the value
  174.   set(self, key, value)
  175. end
  176.  
  177. function Configuration:getColor(key, default)
  178.   --# validate parameters
  179.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  180.   local ok, value = validateColor(default)
  181.   assert(ok, "Invalid parameter #2: Expected number/color, got "..tostring(default).." of type "..type(default), 2)
  182.  
  183.   --# get the colour from the config
  184.   ok, value = validateColor(get(self, key, default))
  185.  
  186.   --# validate the colour
  187.   assert(ok, "Configuration error: No number/color found under the key\""..key.."\", found "..tostring(value).." of type "..type(value), 2)
  188.  
  189.   --# add the restriction comment
  190.   self.properties[key].restrict = "A number between 1 and 32768 or the string colors.<color>"
  191.  
  192.   return value
  193. end
  194.  
  195. function Configuration:setColor(key, value)
  196.   --# validate parameters
  197.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  198.   local ok, value = validateColor(value)
  199.   assert(ok, "Invalid parameter #2: Expected number/color, got "..tostring(default).." of type "..type(default), 2)
  200.  
  201.   --# set the value
  202.   set(self, key, value)
  203. end
  204.  
  205. --# add the non-English (US) function
  206. Configuration.getColour = Configuration.getColor
  207.  
  208. function Configuration:containsKey(key)
  209.   return (self.properties[key] ~= nil)
  210. end
  211.  
  212. function Configuration:load()
  213.   --# make sure the file exists
  214.   if not fs.exists(self.path) then
  215.     return false
  216.   end
  217.  
  218.   --# read the file
  219.   local h = fs.open(self.path, 'r')
  220.   assert(h, "Cannot open configuration file \'"..self.path.."\' for read")
  221.   local contents = h.readAll()
  222.   h.close()
  223.  
  224.   --# make sure there are contents of the file
  225.   if not contents then
  226.     return
  227.   end
  228.  
  229.   local count = 1
  230.  
  231.   contents = split(contents, '\n')
  232.  
  233.   for i = 1, #contents do
  234.     local v = trim(contents[i])
  235.     if v and v ~= "" and not startsWith(v, "+--") and contains(v, '=') then
  236.       local prop = split(v, '=')
  237.       local key = trim(prop[1])
  238.       local value = trim(prop[2])
  239.       self.properties[key] = {}
  240.       self.properties[key]["value"]   = value
  241.       self.properties[key]["default"] = value
  242.     elseif v and v ~= "" and not startsWith(v,"+--") and not contains(v, '=') then
  243.       error("[\""..self.path.."\"] Cannot parse line #"..i.." in configuration file", 0)
  244.     end
  245.   end
  246.   return true
  247. end
  248.  
  249. function Configuration:reset(key)
  250.   assert(type(self) == "table" and type(self.properties) == "table", "Cannot resetting config, have you forgotten to load the config?", 2)
  251.   assert((key and self.properties[key]) or not key, "No property for key "..tostring(key)..", have you forgotten to load the config?", 2)
  252.  
  253.   if key then
  254.     self.properties[key].value = self.properties[key].default
  255.   else
  256.     for k,_ in pairs(self.properties) do
  257.       self.properties[k].value = self.properties[k].default
  258.     end
  259.   end
  260. end
  261.  
  262. function Configuration:save()
  263.   --# open the config file
  264.   local h = fs.open(self.path, 'w')
  265.  
  266.   --# write the header
  267.   h.write(string.format("\n+-- %s CONFIGURATION FILE\n+-- Generated by theoriginalbit's ccConfig\n\n\n", self.name))
  268.  
  269.   --# loop through the properties
  270.   for k,v in pairs(self.properties) do
  271.     --# write the properties info to file
  272.     h.write(string.format("+-- %s restrictions: %s; default: %s;\n%s=%s\n\n\n", v.comment or "", v.restrict or "none", tostring(v.default), tostring(k), tostring(v.value)))
  273.  
  274.     --# flush the file
  275.     h.flush()
  276.   end
  277.  
  278.   --# close the file
  279.   h.close()
  280. end
  281.  
  282. function Configuration:addCommentForKey(key, value)
  283.   --# validate parameters
  284.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  285.   assert(self.properties[key], "Invalid parameter #1: No property with key \""..tostring(key).."\" to add comment", 2)
  286.  
  287.   --# add the comment
  288.   self.properties[key].comment = value
  289. end
  290.  
  291. function Configuration:addRestrictionForKey(key, value)
  292.   --# validate parameters
  293.   assert(validateParam(key, "string"), "Invalid parameter #1: Expected string, got "..type(key), 2)
  294.   assert(self.properties[key], "No property with key \""..tostring(key).."\" to add comment", 2)
  295.  
  296.   --# add the restriction comment
  297.   self.properties[key].restrict = value
  298. end
  299.  
  300. function Configuration:debug(toFile)
  301.   toFile = (toFile == true)
  302.   local h = toFile and fs.open("debug", 'w') or nil
  303.   for k,v in pairs(self.properties) do
  304.     if toFile then
  305.       h.write(k..":"..v.value.."\n")
  306.     else
  307.       print(k..":"..v.value)
  308.     end
  309.   end
  310.   if toFile then
  311.     h.close()
  312.   end
  313. end
  314.  
  315. local function instantiate(path, name)
  316.   assert(validateParam(path, "string"), "Invalid parameter #1: Expected string, got "..type(path), 3)
  317.   assert(validateParam(name, "string"), "Invalid parameter #2: Expected string, got "..type(name), 3)
  318.  
  319.   local obj = setmetatable({}, {
  320.     __newindex = function(self, key, value)
  321.       if type(value) == "function" then
  322.         local func = setmetatable({}, {
  323.           __call = function(_, ...)
  324.             if rawequal(self, ({...})[1]) then
  325.               return value(...)
  326.             end
  327.             return value(self, ...)
  328.           end;
  329.         })
  330.         rawset(self, key, func)
  331.       else
  332.         rawset(self, key, value)
  333.       end
  334.     end;
  335.   })
  336.  
  337.   obj.name = name:upper()
  338.   obj.path = path
  339.   obj.properties = {}
  340.  
  341.   for k,v in pairs(Configuration) do
  342.     obj[k] = v
  343.   end
  344.  
  345.   return obj
  346. end
  347.  
  348. function new(path, name)
  349.   return instantiate(path, name)
  350. end
  351.  
  352. function init(path, name)
  353.   return instantiate(path, name)
  354. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement