Scheme parsing optimizations
This commit is contained in:
parent
68ecfaf698
commit
c287c8ca7e
1 changed files with 226 additions and 241 deletions
|
@ -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 )
|
||||
|
|
Loading…
Reference in a new issue