Scheme parsing optimizations

This commit is contained in:
Steven Barth 2008-09-09 15:39:10 +00:00
parent 68ecfaf698
commit c287c8ca7e

View file

@ -362,6 +362,7 @@ function UVL.read_scheme( self, scheme, alias )
local files = luci.fs.glob(self.schemedir .. '/*/' .. scheme)
if files then
local ok, err
for i, file in ipairs( files ) do
if not luci.fs.access(file) then
return false, so:error(ERR.SME_READ(so,file))
@ -369,18 +370,32 @@ function UVL.read_scheme( self, scheme, alias )
local uci = luci.model.uci.cursor( luci.fs.dirname(file), default_savedir )
local sd, err = uci:get_all( luci.fs.basename(file) )
local sname = luci.fs.basename(file)
local sd, err = uci:load( sname )
if not sd then
return false, ERR.UCILOAD(so, err)
end
table.insert( schemes, sd )
ok, err = pcall(function()
uci:foreach(sname, "package", function(s)
self:_parse_package(so, s[".name"], s)
end)
uci:foreach(sname, "section", function(s)
self:_parse_section(so, s[".name"], s)
end)
uci:foreach(sname, "variable", function(s)
self:_parse_var(so, s[".name"], s)
end)
uci:foreach(sname, "enum", function(s)
self:_parse_enum(so, s[".name"], s)
end)
end)
end
local ok, err = self:_read_scheme_parts( so, schemes )
if ok and alias then self.packages[alias] = self.packages[scheme] end
return ok, err
return ok and self, err
else
return false, so:error(ERR.SME_FIND(so, self.schemedir))
end
@ -395,9 +410,6 @@ function UVL.read_scheme( self, scheme, alias )
end
end
-- Process all given parts and construct validation tree
function UVL._read_scheme_parts( self, scheme, schemes )
-- helper function to check for required fields
local function _req( t, n, c, r )
for i, v in ipairs(r) do
@ -447,50 +459,37 @@ function UVL._read_scheme_parts( self, scheme, schemes )
return ( v == "true" or v == "yes" or v == "on" or v == "1" )
end
local ok, err
-- Step 0: get package meta information
for i, conf in ipairs( schemes ) do
for k, v in pairs( conf ) do
if v['.type'] == 'package' then
self.packages[scheme:sid()] =
self.packages[scheme:sid()] or {
["name"] = scheme:sid();
function UVL._parse_package(self, scheme, k, v)
local sid = scheme:sid()
local pkg = self.packages[sid] or {
["name"] = sid;
["sections"] = { };
["variables"] = { };
}
for k, v2 in pairs(v) do
if k == "title" or k == "description" then
self.packages[scheme:sid()][k] = v2
end
end
end
end
pkg.title = v.title
pkg.description = v.description
self.packages[sid] = pkg
end
-- Step 1: get all sections
for i, conf in ipairs( schemes ) do
for k, v in pairs( conf ) do
if v['.type'] == 'section' then
ok, err = _req( TYPE_SECTION, k, v, { "name", "package" } )
if err then return false, scheme:error(err) end
function UVL._parse_section(self, scheme, k, v)
local ok, err = _req( TYPE_SECTION, k, v, { "name", "package" } )
if err then error(scheme:error(err)) end
local r, err = _ref( TYPE_SECTION, v )
if err then return false, scheme:error(err) end
if err then error(scheme:error(err)) end
self.packages[r[1]] =
self.packages[r[1]] or {
local p = self.packages[r[1]] or {
["name"] = r[1];
["sections"] = { };
["variables"] = { };
}
local p = self.packages[r[1]]
p.sections[v.name] = p.sections[v.name] or { }
p.variables[v.name] = p.variables[v.name] or { }
self.packages[r[1]] = p
local s = p.sections[v.name]
local so = scheme:section(v.name)
@ -519,32 +518,28 @@ function UVL._read_scheme_parts( self, scheme, schemes )
s.required = s.required or false
s.named = s.named or false
end
end
end
-- Step 2: get all variables
for i, conf in ipairs( schemes ) do
for k, v in pairs( conf ) do
if v['.type'] == "variable" then
ok, err = _req( TYPE_OPTION, k, v, { "name", "section" } )
if err then return false, scheme:error(err) end
function UVL._parse_var(self, scheme, k, v)
local ok, err = _req( TYPE_OPTION, k, v, { "name", "section" } )
if err then error(scheme:error(err)) end
local r, err = _ref( TYPE_OPTION, v )
if err then return false, scheme:error(err) end
if err then error(scheme:error(err)) end
local p = self.packages[r[1]]
if not p then
return false, scheme:error(
error(scheme:error(
ERR.SME_VBADPACK({scheme:sid(), '', v.name}, r[1])
)
))
end
local s = p.variables[r[2]]
if not s then
return false, scheme:error(
error(scheme:error(
ERR.SME_VBADSECT({scheme:sid(), '', v.name}, r[2])
)
))
end
s[v.name] = s[v.name] or { }
@ -558,23 +553,23 @@ function UVL._read_scheme_parts( self, scheme, schemes )
if k == "depends" then
t.depends = self:_read_dependency( v2, t.depends )
if not t.depends then
return false, scheme:error(so:error(
error(scheme:error(so:error(
ERR.SME_BADDEP(to, luci.util.serialize_data(v2))
))
)))
end
elseif k == "validator" then
t.validators = self:_read_validator( v2, t.validators )
if not t.validators then
return false, scheme:error(so:error(
error(scheme:error(so:error(
ERR.SME_BADVAL(to, luci.util.serialize_data(v2))
))
)))
end
elseif k == "valueof" then
local values, err = self:_read_reference( v2 )
if err then
return false, scheme:error(so:error(
error(scheme:error(so:error(
ERR.REFERENCE(to, luci.util.serialize_data(v2)):child(err)
))
)))
end
t.type = "reference"
t.values = values
@ -590,39 +585,34 @@ function UVL._read_scheme_parts( self, scheme, schemes )
t.datatype = t.datatype or "string"
t.required = t.required or false
end
end
end
-- Step 3: get all enums
for i, conf in ipairs( schemes ) do
for k, v in pairs( conf ) do
if v['.type'] == "enum" then
ok, err = _req( TYPE_ENUM, k, v, { "value", "variable" } )
if err then return false, scheme:error(err) end
function UVL._parse_enum(self, scheme, k, v)
local ok, err = _req( TYPE_ENUM, k, v, { "value", "variable" } )
if err then error(scheme:error(err)) end
local r, err = _ref( TYPE_ENUM, v )
if err then return false, scheme:error(err) end
if err then error(scheme:error(err)) end
local p = self.packages[r[1]]
if not p then
return false, scheme:error(
error(scheme:error(
ERR.SME_EBADPACK({scheme:sid(), '', '', v.value}, r[1])
)
))
end
local s = p.variables[r[2]]
if not s then
return false, scheme:error(
error(scheme:error(
ERR.SME_EBADSECT({scheme:sid(), '', '', v.value}, r[2])
)
))
end
local t = s[r[3]]
if not t then
return false, scheme:error(
error(scheme:error(
ERR.SME_EBADOPT({scheme:sid(), '', '', v.value}, r[3])
)
))
end
@ -631,7 +621,7 @@ function UVL._read_scheme_parts( self, scheme, schemes )
local eo = oo:enum(v.value)
if t.type ~= "enum" and t.type ~= "reference" then
return false, scheme:error(ERR.SME_EBADTYPE(eo))
error(scheme:error(ERR.SME_EBADTYPE(eo)))
end
if not t.values then
@ -646,7 +636,7 @@ function UVL._read_scheme_parts( self, scheme, schemes )
if v.default then
if t.default then
return false, scheme:error(ERR.SME_EBADDEF(eo))
error(scheme:error(ERR.SME_EBADDEF(eo)))
end
t.default = v.value
end
@ -657,17 +647,12 @@ function UVL._read_scheme_parts( self, scheme, schemes )
)
if not t.enum_depends[v.value] then
return false, scheme:error(so:error(oo:error(
error(scheme:error(so:error(oo:error(
ERR.SME_BADDEP(eo, luci.util.serialize_data(v.depends))
)))
))))
end
end
end
end
end
return self
end
-- Read a dependency specification
function UVL._read_dependency( self, values, deps )