Add a feature to the schema validator to limit the constrain number of subtags

This commit is contained in:
Celtic Minstrel 2020-10-24 15:40:25 -04:00
parent d53fc3036d
commit 8266e0fb86
5 changed files with 53 additions and 5 deletions

View file

@ -124,7 +124,7 @@
name="add"
max=infinite
super="theme/~content~"
#max_children=1
max_tags=1
[/tag]
[/tag]
[tag]

View file

@ -146,6 +146,8 @@
{SIMPLE_KEY super path_list}
{DEFAULT_KEY any_tag bool no}
{DEFAULT_KEY deprecated bool no}
{DEFAULT_KEY min_tags int 0}
{DEFAULT_KEY max_tags int,inf infinite}
[tag]
name="key"
max=infinite

View file

@ -30,6 +30,8 @@ wml_tag::wml_tag(const config& cfg)
: name_(cfg["name"].str())
, min_(cfg["min"].to_int())
, max_(cfg["max"].str() == "infinite" ? -1 : cfg["max"].to_int(1))
, min_children_(cfg["min_tags"].to_int())
, max_children_(cfg["max_tags"].str() == "infinite" ? -1 : cfg["max_tags"].to_int(-1))
, super_("")
, tags_()
, keys_()
@ -42,6 +44,9 @@ wml_tag::wml_tag(const config& cfg)
if(max_ < 0) {
max_ = INT_MAX;
}
if(max_children_ < 0) {
max_children_ = INT_MAX;
}
if(cfg.has_attribute("super")) {
super_ = cfg["super"].str();

View file

@ -126,6 +126,8 @@ public:
: name_(name)
, min_(min)
, max_(max)
, min_children_(0)
, max_children_(INT_MAX)
, super_(super)
, tags_()
, keys_()
@ -169,6 +171,16 @@ public:
return max_;
}
int get_min_children() const
{
return min_children_;
}
int get_max_children() const
{
return max_children_;
}
const std::string& get_super() const
{
return super_;
@ -202,9 +214,22 @@ public:
max_ = o;
}
void set_min_children(int o)
{
min_children_ = o;
}
void set_max_children(int o)
{
max_children_ = o;
}
void set_min(const std::string& s);
void set_max(const std::string& s);
void set_min_children(const std::string& s);
void set_max_children(const std::string& s);
void set_super(const std::string& s)
{
super_ = s;
@ -302,12 +327,18 @@ private:
/** name of tag. */
std::string name_;
/** number of minimum occasions. */
/** minimum number of occurrences. */
int min_;
/** number of maximum occasions. */
/** maximum number of occurrences. */
int max_;
/** minimum number of children. */
int min_children_;
/** maximum number of children. */
int max_children_;
/**
* name of tag to extend "super-tag"
* Extension is smth like inheritance and is used in case

View file

@ -231,6 +231,8 @@ void schema_validator::open_tag(const std::string& name, const config& parent, i
if(!addittion) {
counter& cnt = counter_.top()[name];
++cnt.cnt;
counter& total_cnt = counter_.top()[""];
++total_cnt.cnt;
}
}
}
@ -271,7 +273,8 @@ void schema_validator::validate(const config& cfg, const std::string& name, int
// Please note that validating unknown tag keys the result will be false
// Checking all elements counters.
if(have_active_tag() && is_valid()) {
for(const auto& tag : active_tag().tags(cfg)) {
const wml_tag& active = active_tag();
for(const auto& tag : active.tags(cfg)) {
int cnt = counter_.top()[tag.first].cnt;
if(tag.second.get_min() > cnt) {
@ -283,9 +286,16 @@ void schema_validator::validate(const config& cfg, const std::string& name, int
queue_message(cfg, EXTRA_TAG, file, start_line, tag.second.get_max(), tag.first, "", name);
}
}
int total_cnt = counter_.top()[""].cnt;
if(active.get_min_children() > total_cnt) {
queue_message(cfg, MISSING_TAG, file, start_line, active.get_min_children(), "*", "", active.get_name());
} else if(active_tag().get_max_children() < total_cnt) {
queue_message(cfg, EXTRA_TAG, file, start_line, active.get_max_children(), "*", "", active.get_name());
}
// Checking if all mandatory keys are present
for(const auto& key : active_tag().keys(cfg)) {
for(const auto& key : active.keys(cfg)) {
if(key.second.is_mandatory()) {
if(cfg.get(key.first) == nullptr) {
queue_message(cfg, MISSING_KEY, file, start_line, 0, name, key.first);