summaryrefslogtreecommitdiffstats
path: root/include/dnsjit/lib/parseconf.lua
diff options
context:
space:
mode:
Diffstat (limited to 'include/dnsjit/lib/parseconf.lua')
-rw-r--r--include/dnsjit/lib/parseconf.lua181
1 files changed, 181 insertions, 0 deletions
diff --git a/include/dnsjit/lib/parseconf.lua b/include/dnsjit/lib/parseconf.lua
new file mode 100644
index 0000000..638763b
--- /dev/null
+++ b/include/dnsjit/lib/parseconf.lua
@@ -0,0 +1,181 @@
+-- Copyright (c) 2018-2021, OARC, Inc.
+-- All rights reserved.
+--
+-- This file is part of dnsjit.
+--
+-- dnsjit is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- dnsjit is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
+
+-- dnsjit.lib.parseconf
+-- Parse simple config files
+-- local conf = require("dnsjit.lib.parseconf").new()
+-- .
+-- conf:func("config_name", function(k,...)
+-- print(k,...)
+-- end)
+-- .
+-- conf:file(file)
+-- .
+-- print(conf:val("another_config_name"))
+--
+-- This module parses simple config files that are based on the config
+-- syntax of DSC, drool and parseconf helper library.
+-- Each config begins with a
+-- .B name
+-- followed by
+-- .B options
+-- and ends with a
+-- .BR ; .
+-- Multiple configs can be given on the same line.
+-- Valid option types are
+-- .IR number ,
+-- .IR float ,
+-- .IR string ,
+-- .IR "quoted string" .
+-- Comments can be added by prefixing the comment with
+-- .BR # .
+-- .SS Example
+-- # Comment
+-- number 12345;
+-- float 123.456;
+-- string string string;
+-- quoted_string "string string string";
+-- multi config; on one line;
+module(...,package.seeall)
+
+local log = require("dnsjit.core.log")
+
+local module_log = log.new("lib.parseconf")
+Parseconf = {}
+
+-- Create a new Parseconf object.
+function Parseconf.new()
+ local self = setmetatable({
+ conf = {},
+ cf = {},
+ _log = log.new("lib.parseconf", module_log),
+ }, { __index = Parseconf })
+
+ self._log:debug("new()")
+
+ return self
+end
+
+-- Return the Log object to control logging of this instance or module.
+function Parseconf:log()
+ if self == nil then
+ return module_log
+ end
+ return self._log
+end
+
+-- Set a function to call when config
+-- .I name
+-- is found.
+function Parseconf:func(name, func)
+ self.cf[name] = func
+end
+
+function Parseconf:part(l, n)
+ local p
+ p = l:match("^(%d+)[%s;]", n)
+ if p then
+ return p, tonumber(p)
+ end
+ p = l:match("^(%d+%.%d+)[%s;]", n)
+ if p then
+ return p, tonumber(p)
+ end
+ p = l:match("^(\"[^\"]+\")[%s;]", n)
+ if p then
+ return p, p:sub(2, -2)
+ end
+ p = l:match("^([^%s;]+)[%s;]", n)
+ if p then
+ return p, p
+ end
+end
+
+function Parseconf:next(l, n)
+ local eol = l:match("^%s*;%s*", n)
+ if eol then
+ return true, eol
+ end
+ local ws = l:match("^%s+", n)
+ if ws then
+ return ws
+ end
+ return false
+end
+
+-- Parse the given file.
+function Parseconf:file(fn)
+ local ln, l
+ ln = 1
+ for l in io.lines(fn) do
+ local c = l:find("#")
+ if c then
+ l = l:sub(1, c - 1)
+ end
+ local e, m = pcall(self.line, self, l)
+ if e == false then
+ error("parse error in "..fn.."["..ln.."]: "..m)
+ end
+ ln = ln + 1
+ end
+end
+
+-- Parse the given line.
+function Parseconf:line(l)
+ local n
+ n = 1
+ while n <= l:len() do
+ local c = nil
+ local va = {}
+ while true do
+ local p, v = self:part(l, n)
+ if not p then
+ error("invalid config at character "..n..": "..l:sub(n))
+ end
+ if not c then
+ c = p
+ else
+ table.insert(va, v)
+ end
+ n = n + p:len()
+ local ws, eol = self:next(l, n)
+ if ws == true then
+ if eol then
+ n = n + eol:len()
+ end
+ break
+ elseif ws == false then
+ error("invalid config at character "..n..": "..l:sub(n))
+ end
+ n = n + ws:len()
+ end
+ if self.cf[c] then
+ self.cf[c](c, unpack(va))
+ else
+ self.conf[c] = va
+ end
+ end
+end
+
+-- Get the value of a config
+-- .IR name .
+function Parseconf:val(name)
+ return self.conf[name]
+end
+
+return Parseconf