From a32e279b7cf13c23499dfb28dd6d83c1b2de8de7 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sun, 4 Nov 2018 19:05:21 -0500 Subject: [PATCH] Split tag.hpp into three files --- projectfiles/VC14/wesnoth.vcxproj | 20 +- projectfiles/VC14/wesnoth.vcxproj.filters | 16 +- source_lists/libwesnoth_core | 4 +- src/serialization/schema/key.cpp | 63 ++++++ src/serialization/schema/key.hpp | 143 ++++++++++++++ src/serialization/{ => schema}/tag.cpp | 154 ++------------- src/serialization/{ => schema}/tag.hpp | 230 +--------------------- src/serialization/schema/type.cpp | 123 ++++++++++++ src/serialization/schema/type.hpp | 120 +++++++++++ src/serialization/schema_validator.hpp | 4 +- 10 files changed, 510 insertions(+), 367 deletions(-) create mode 100644 src/serialization/schema/key.cpp create mode 100644 src/serialization/schema/key.hpp rename src/serialization/{ => schema}/tag.cpp (76%) rename src/serialization/{ => schema}/tag.hpp (63%) create mode 100644 src/serialization/schema/type.cpp create mode 100644 src/serialization/schema/type.hpp diff --git a/projectfiles/VC14/wesnoth.vcxproj b/projectfiles/VC14/wesnoth.vcxproj index 6890b90d57ad..6290378d3cee 100644 --- a/projectfiles/VC14/wesnoth.vcxproj +++ b/projectfiles/VC14/wesnoth.vcxproj @@ -2809,7 +2809,21 @@ $(IntDir)SDL\ - + + $(IntDir)Serialization\ + $(IntDir)Serialization\ + $(IntDir)Serialization\ + $(IntDir)Serialization\ + $(IntDir)Serialization\ + + + $(IntDir)Serialization\ + $(IntDir)Serialization\ + $(IntDir)Serialization\ + $(IntDir)Serialization\ + $(IntDir)Serialization\ + + $(IntDir)Serialization\ $(IntDir)Serialization\ $(IntDir)Serialization\ @@ -4033,7 +4047,9 @@ - + + + diff --git a/projectfiles/VC14/wesnoth.vcxproj.filters b/projectfiles/VC14/wesnoth.vcxproj.filters index d6553a1b8d32..ddc499513830 100644 --- a/projectfiles/VC14/wesnoth.vcxproj.filters +++ b/projectfiles/VC14/wesnoth.vcxproj.filters @@ -1010,7 +1010,13 @@ utils - + + serialization + + + serialization + + serialization @@ -2513,7 +2519,13 @@ utils - + + serialization + + + serialization + + serialization diff --git a/source_lists/libwesnoth_core b/source_lists/libwesnoth_core index 09be2246904c..f307650580e1 100644 --- a/source_lists/libwesnoth_core +++ b/source_lists/libwesnoth_core @@ -21,7 +21,9 @@ serialization/parser.cpp serialization/preprocessor.cpp serialization/schema_validator.cpp serialization/string_utils.cpp -serialization/tag.cpp +serialization/schema/key.cpp +serialization/schema/tag.cpp +serialization/schema/type.cpp serialization/tokenizer.cpp serialization/unicode.cpp serialization/validator.cpp diff --git a/src/serialization/schema/key.cpp b/src/serialization/schema/key.cpp new file mode 100644 index 000000000000..dd312441b2f5 --- /dev/null +++ b/src/serialization/schema/key.cpp @@ -0,0 +1,63 @@ +/* + Copyright (C) 2011 - 2018 by Sytyi Nick + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program 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 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +/** + * @file + * Implementation of key.hpp. + */ + +#include "serialization/schema/key.hpp" + +#include "config.hpp" + +namespace schema_validation +{ + +class_key::class_key(const config& cfg) + : name_(cfg["name"].str()) + , type_(cfg["type"].str()) + , default_() + , mandatory_(false) + , fuzzy_(name_.find_first_of("*?") != std::string::npos) +{ + if(cfg.has_attribute("mandatory")) { + mandatory_ = cfg["mandatory"].to_bool(); + } else { + if(cfg.has_attribute("default")) { + default_ = cfg["default"].str(); + } + } +} + +void class_key::print(std::ostream& os, int level) const +{ + std::string s; + for(int j = 0; j < level; j++) { + s.append(" "); + } + + os << s << "[key]\n" << s << " name=\"" << name_ << "\"\n" << s << " type=\"" << type_ << "\"\n"; + + if(is_mandatory()) { + os << s << " mandatory=\"true\"\n"; + } else { + os << s << " default=" << default_ << "\n"; + } + + // TODO: Other attributes + + os << s << "[/key]\n"; +} + +} // namespace schema_validation diff --git a/src/serialization/schema/key.hpp b/src/serialization/schema/key.hpp new file mode 100644 index 000000000000..63043e4567c7 --- /dev/null +++ b/src/serialization/schema/key.hpp @@ -0,0 +1,143 @@ +/* + Copyright (C) 2011 - 2018 by Sytyi Nick + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program 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 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +/** + * @file + * This file contains object "key", which is used to store + * information about keys while annotation parsing. + */ + +#pragma once + +#include +#include + +class config; + +namespace schema_validation +{ + +/** + * class_key is used to save the information about one key. + * Key has next info: name, type, default value or key is mandatory. + */ +class class_key +{ +public: + class_key() + : name_("") + , type_("") + , default_("\"\"") + , mandatory_(false) + , fuzzy_(false) + { + } + + class_key(const std::string& name, const std::string& type, const std::string& def = "\"\"") + : name_(name) + , type_(type) + , default_(def) + , mandatory_(def.empty()) + , fuzzy_(name.find_first_of("*?") != std::string::npos) + { + } + + class_key(const config&); + + const std::string& get_name() const + { + return name_; + } + + const std::string& get_type() const + { + return type_; + } + + const std::string& get_default() const + { + return default_; + } + + bool is_mandatory() const + { + return mandatory_; + } + + bool is_fuzzy() const { + return fuzzy_; + } + + void set_name(const std::string& name) + { + name_ = name; + } + + void set_type(const std::string& type) + { + type_ = type; + } + + void set_default(const std::string& def) + { + default_ = def; + if(def.empty()) { + mandatory_ = true; + } + } + + void set_mandatory(bool mandatory) + { + mandatory_ = mandatory; + } + + void set_fuzzy(bool f) + { + fuzzy_ = f; + } + + /** is used to print key info + * the format is next + * [key] + * name="name" + * type="type" + * default="default" + * mandatory="true/false" + * [/key] + */ + void print(std::ostream& os, int level) const; + + /** Compares keys by name. Used in std::sort, i.e. */ + bool operator<(const class_key& k) const + { + return (get_name() < k.get_name()); + } + +private: + /** Name of key. */ + std::string name_; + + /** Type of key. */ + std::string type_; + + /** Default value. */ + std::string default_; + + /** Shows, if key is a mandatory key. */ + bool mandatory_; + + /** Whether the key is a fuzzy match. */ + bool fuzzy_; +}; +} diff --git a/src/serialization/tag.cpp b/src/serialization/schema/tag.cpp similarity index 76% rename from src/serialization/tag.cpp rename to src/serialization/schema/tag.cpp index 0f1e7c92ed95..4995b03316aa 100644 --- a/src/serialization/tag.cpp +++ b/src/serialization/schema/tag.cpp @@ -17,149 +17,15 @@ * Implementation of tag.hpp. */ -#include "serialization/tag.hpp" +#include "serialization/schema/tag.hpp" #include "serialization/string_utils.hpp" -#include "boost/optional.hpp" #include "formatter.hpp" -#include "config.hpp" - namespace schema_validation { class_tag any_tag("", 0, -1, "", true); -/*WIKI - * @begin{parent}{name="wml_schema/tag/"} - * @begin{tag}{name="key"}{min=0}{max=-1} - * @begin{table}{config} - * name & string & & The name of key. $ - * type & string & & The type of key value. $ - * default & string & & The default value of the key. $ - * mandatory & string & & Shows if key is mandatory $ - * @end{table} - * @end{tag}{name="key"} - * @end{parent}{name="wml_schema/tag/"} - */ -std::shared_ptr class_type::from_config(const config& cfg) -{ - boost::optional composite_range; - std::shared_ptr type; - if(cfg.has_child("union")) { - type = std::make_shared(cfg["name"]); - composite_range.emplace(cfg.child("union").child_range("type")); - } else if(cfg.has_child("intersection")) { - type = std::make_shared(cfg["name"]); - composite_range.emplace(cfg.child("intersection").child_range("type")); - } else if(cfg.has_child("list")) { - const config& list_cfg = cfg.child("list"); - int list_min = list_cfg["min"].to_int(); - int list_max = list_cfg["max"].str() == "infinite" ? -1 : list_cfg["max"].to_int(-1); - if(list_max < 0) list_max = INT_MAX; - type = std::make_shared(cfg["name"], list_cfg["split"].str("\\s*,\\s*"), list_min, list_max); - composite_range.emplace(list_cfg.child_range("element")); - } else if(cfg.has_attribute("value")) { - type = std::make_shared(cfg["name"], cfg["value"]); - } else if(cfg.has_attribute("link")) { - type = std::make_shared(cfg["name"], cfg["link"]); - } - if(composite_range) { - auto composite_type = std::dynamic_pointer_cast(type); - for(const config& elem : *composite_range) { - composite_type->add_type(class_type::from_config(elem)); - } - } - return type; -} - -bool class_type_simple::matches(const std::string& value, const map&) const -{ - boost::smatch sub; - return boost::regex_match(value, sub, pattern_); -} - -bool class_type_alias::matches(const std::string& value, const map& type_map) const -{ - if(!cached_) { - auto it = type_map.find(link_); - if(it == type_map.end()) { - // TODO: Error message about the invalid type? - return false; - } - cached_ = it->second; - } - return cached_->matches(value, type_map); -} - -bool class_type_union::matches(const std::string& value, const map& type_map) const -{ - for(const auto& type : subtypes_) { - if(type->matches(value, type_map)) { - return true; - } - } - return false; -} - -bool class_type_intersection::matches(const std::string& value, const map& type_map) const -{ - for(const auto& type : subtypes_) { - if(!type->matches(value, type_map)) { - return false; - } - } - return true; -} - -bool class_type_list::matches(const std::string& value, const map& type_map) const -{ - boost::sregex_token_iterator it(value.begin(), value.end(), split_, -1), end; - int n = 0; - bool result = std::all_of(it, end, [this, &type_map, &n](const boost::ssub_match& match){ - // Not sure if this is necessary? - if(!match.matched) return true; - n++; - return this->class_type_union::matches(std::string(match.first, match.second), type_map); - }); - return result && n >= min_ && n <= max_; -} - -class_key::class_key(const config& cfg) - : name_(cfg["name"].str()) - , type_(cfg["type"].str()) - , default_() - , mandatory_(false) - , fuzzy_(name_.find_first_of("*?") != std::string::npos) -{ - if(cfg.has_attribute("mandatory")) { - mandatory_ = cfg["mandatory"].to_bool(); - } else { - if(cfg.has_attribute("default")) { - default_ = cfg["default"].str(); - } - } -} - -void class_key::print(std::ostream& os, int level) const -{ - std::string s; - for(int j = 0; j < level; j++) { - s.append(" "); - } - - os << s << "[key]\n" << s << " name=\"" << name_ << "\"\n" << s << " type=\"" << type_ << "\"\n"; - - if(is_mandatory()) { - os << s << " mandatory=\"true\"\n"; - } else { - os << s << " default=" << default_ << "\n"; - } - - // TODO: Other attributes - - os << s << "[/key]\n"; -} - class_tag::class_tag(const config& cfg) : name_(cfg["name"].str()) , min_(cfg["min"].to_int()) @@ -208,6 +74,22 @@ void class_tag::print(std::ostream& os) printl(os, 4, 4); } +void class_tag::set_min(const std::string& s) +{ + std::istringstream i(s); + if(!(i >> min_)) { + min_ = 0; + } +} + +void class_tag::set_max(const std::string& s) +{ + std::istringstream i(s); + if(!(i >> max_)) { + max_ = 0; + } +} + void class_tag::add_link(const std::string& link) { std::string::size_type pos_last = link.rfind('/'); @@ -491,7 +373,7 @@ void class_tag::expand(class_tag& root) super_refs_.push_back(super_tag); } else { // TODO: Detect super cycles too! - std::cerr << "the same" << super_tag->name_ << "\n"; + //std::cerr << "the same" << super_tag->name_ << "\n"; } } // TODO: Warn if the super doesn't exist diff --git a/src/serialization/tag.hpp b/src/serialization/schema/tag.hpp similarity index 63% rename from src/serialization/tag.hpp rename to src/serialization/schema/tag.hpp index 3f0069867c75..e583c18bb464 100644 --- a/src/serialization/tag.hpp +++ b/src/serialization/schema/tag.hpp @@ -14,232 +14,25 @@ /** * @file - * This file contains objects "tag" and "key", which are used to store - * information about tags and keys while annotation parsing. + * This file contains object "tag", which is used to store + * information about tags while annotation parsing. */ #pragma once -#include -#include #include -#include #include #include #include -#include #include #include #include "config.hpp" +#include "serialization/schema/key.hpp" namespace schema_validation { -/** - * Stores information about a schema type. - * This is an abstract base class for several variants of schema type. - */ -class class_type { -protected: - std::string name_; -public: - class_type() = delete; - explicit class_type(const std::string& name) : name_(name) {} - using ptr = std::shared_ptr; - using map = std::map; - virtual bool matches(const std::string& value, const map& type_map) const = 0; - static std::shared_ptr from_config(const config& cfg); -}; - -/** - * Stores information about a schema type. - * This type represents a simple pattern match. - */ -class class_type_simple : public class_type { - boost::regex pattern_; -public: - class_type_simple(const std::string& name, const std::string& pattern) : class_type(name), pattern_(pattern) {} - bool matches(const std::string& value, const map& type_map) const override; -}; - -/** - * Stores information about a schema type. - * This type represents a name alias for another type. - */ -class class_type_alias : public class_type { - mutable std::shared_ptr cached_; - std::string link_; -public: - class_type_alias(const std::string& name, const std::string& link) : class_type(name), link_(link) {} - bool matches(const std::string& value, const map& type_map) const override; -}; - -/** - * Stores information about a schema type. - * This is an abstract base class for composite types. - */ -class class_type_composite : public class_type { -protected: - std::vector> subtypes_; -public: - explicit class_type_composite(const std::string& name) : class_type(name) {} - void add_type(std::shared_ptr type) - { - subtypes_.push_back(type); - } -}; - -/** - * Stores information about a schema type. - * Represents a union type, which matches if any of its subtypes match. - */ -class class_type_union : public class_type_composite { -public: - explicit class_type_union(const std::string& name) : class_type_composite(name) {} - bool matches(const std::string& value, const map& type_map) const override; -}; - -/** - * Stores information about a schema type. - * Represents an intersection type, which matches if all of its subtypes match. - */ -class class_type_intersection : public class_type_composite { -public: - explicit class_type_intersection(const std::string& name) : class_type_composite(name) {} - bool matches(const std::string& value, const map& type_map) const override; -}; - -/** - * Stores information about a schema type. - * Represents a list type, where each list element is itself a union. - */ -class class_type_list : public class_type_union { - boost::regex split_; - int min_ = 0, max_ = -1; -public: - class_type_list(const std::string& name, const std::string& pattern, int min, int max) - : class_type_union(name) - , split_(pattern) - , min_(min) - , max_(max) - {} - bool matches(const std::string& value, const map& type_map) const override; -}; - -/** - * class_key is used to save the information about one key. - * Key has next info: name, type, default value or key is mandatory. - */ -class class_key -{ -public: - class_key() - : name_("") - , type_("") - , default_("\"\"") - , mandatory_(false) - , fuzzy_(false) - { - } - - class_key(const std::string& name, const std::string& type, const std::string& def = "\"\"") - : name_(name) - , type_(type) - , default_(def) - , mandatory_(def.empty()) - , fuzzy_(name.find_first_of("*?") != std::string::npos) - { - } - - class_key(const config&); - - const std::string& get_name() const - { - return name_; - } - - const std::string& get_type() const - { - return type_; - } - - const std::string& get_default() const - { - return default_; - } - - bool is_mandatory() const - { - return mandatory_; - } - - bool is_fuzzy() const { - return fuzzy_; - } - - void set_name(const std::string& name) - { - name_ = name; - } - - void set_type(const std::string& type) - { - type_ = type; - } - - void set_default(const std::string& def) - { - default_ = def; - if(def.empty()) { - mandatory_ = true; - } - } - - void set_mandatory(bool mandatory) - { - mandatory_ = mandatory; - } - - void set_fuzzy(bool f) - { - fuzzy_ = f; - } - - /** is used to print key info - * the format is next - * [key] - * name="name" - * type="type" - * default="default" - * mandatory="true/false" - * [/key] - */ - void print(std::ostream& os, int level) const; - - /** Compares keys by name. Used in std::sort, i.e. */ - bool operator<(const class_key& k) const - { - return (get_name() < k.get_name()); - } - -private: - /** Name of key. */ - std::string name_; - - /** Type of key. */ - std::string type_; - - /** Default value. */ - std::string default_; - - /** Shows, if key is a mandatory key. */ - bool mandatory_; - - /** Whether the key is a fuzzy match. */ - bool fuzzy_; -}; - class class_condition; /** @@ -413,21 +206,8 @@ class class_tag max_ = o; } - void set_min(const std::string& s) - { - std::istringstream i(s); - if(!(i >> min_)) { - min_ = 0; - } - } - - void set_max(const std::string& s) - { - std::istringstream i(s); - if(!(i >> max_)) { - max_ = 0; - } - } + void set_min(const std::string& s); + void set_max(const std::string& s); void set_super(const std::string& s) { diff --git a/src/serialization/schema/type.cpp b/src/serialization/schema/type.cpp new file mode 100644 index 000000000000..1515e8d698c2 --- /dev/null +++ b/src/serialization/schema/type.cpp @@ -0,0 +1,123 @@ +/* + Copyright (C) 2011 - 2018 by Sytyi Nick + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program 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 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +/** + * @file + * Implementation of type.hpp. + */ + +#include "serialization/schema/type.hpp" +#include "boost/optional.hpp" + +#include "config.hpp" + +namespace schema_validation +{ + +/*WIKI + * @begin{parent}{name="wml_schema/tag/"} + * @begin{tag}{name="key"}{min=0}{max=-1} + * @begin{table}{config} + * name & string & & The name of key. $ + * type & string & & The type of key value. $ + * default & string & & The default value of the key. $ + * mandatory & string & & Shows if key is mandatory $ + * @end{table} + * @end{tag}{name="key"} + * @end{parent}{name="wml_schema/tag/"} + */ +std::shared_ptr class_type::from_config(const config& cfg) +{ + boost::optional composite_range; + std::shared_ptr type; + if(cfg.has_child("union")) { + type = std::make_shared(cfg["name"]); + composite_range.emplace(cfg.child("union").child_range("type")); + } else if(cfg.has_child("intersection")) { + type = std::make_shared(cfg["name"]); + composite_range.emplace(cfg.child("intersection").child_range("type")); + } else if(cfg.has_child("list")) { + const config& list_cfg = cfg.child("list"); + int list_min = list_cfg["min"].to_int(); + int list_max = list_cfg["max"].str() == "infinite" ? -1 : list_cfg["max"].to_int(-1); + if(list_max < 0) list_max = INT_MAX; + type = std::make_shared(cfg["name"], list_cfg["split"].str("\\s*,\\s*"), list_min, list_max); + composite_range.emplace(list_cfg.child_range("element")); + } else if(cfg.has_attribute("value")) { + type = std::make_shared(cfg["name"], cfg["value"]); + } else if(cfg.has_attribute("link")) { + type = std::make_shared(cfg["name"], cfg["link"]); + } + if(composite_range) { + auto composite_type = std::dynamic_pointer_cast(type); + for(const config& elem : *composite_range) { + composite_type->add_type(class_type::from_config(elem)); + } + } + return type; +} + +bool class_type_simple::matches(const std::string& value, const map&) const +{ + boost::smatch sub; + return boost::regex_match(value, sub, pattern_); +} + +bool class_type_alias::matches(const std::string& value, const map& type_map) const +{ + if(!cached_) { + auto it = type_map.find(link_); + if(it == type_map.end()) { + // TODO: Error message about the invalid type? + return false; + } + cached_ = it->second; + } + return cached_->matches(value, type_map); +} + +bool class_type_union::matches(const std::string& value, const map& type_map) const +{ + for(const auto& type : subtypes_) { + if(type->matches(value, type_map)) { + return true; + } + } + return false; +} + +bool class_type_intersection::matches(const std::string& value, const map& type_map) const +{ + for(const auto& type : subtypes_) { + if(!type->matches(value, type_map)) { + return false; + } + } + return true; +} + +bool class_type_list::matches(const std::string& value, const map& type_map) const +{ + boost::sregex_token_iterator it(value.begin(), value.end(), split_, -1), end; + int n = 0; + bool result = std::all_of(it, end, [this, &type_map, &n](const boost::ssub_match& match){ + // Not sure if this is necessary? + if(!match.matched) return true; + n++; + return this->class_type_union::matches(std::string(match.first, match.second), type_map); + }); + return result && n >= min_ && n <= max_; +} + +} // namespace schema_validation diff --git a/src/serialization/schema/type.hpp b/src/serialization/schema/type.hpp new file mode 100644 index 000000000000..5bef2f7331d9 --- /dev/null +++ b/src/serialization/schema/type.hpp @@ -0,0 +1,120 @@ +/* + Copyright (C) 2011 - 2018 by Sytyi Nick + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program 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 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +/** + * @file + * This file contains object "type", which is used to store + * information about types while annotation parsing. + */ + +#pragma once + +#include + +class config; + +namespace schema_validation +{ + +/** + * Stores information about a schema type. + * This is an abstract base class for several variants of schema type. + */ +class class_type { +protected: + std::string name_; +public: + class_type() = delete; + explicit class_type(const std::string& name) : name_(name) {} + using ptr = std::shared_ptr; + using map = std::map; + virtual bool matches(const std::string& value, const map& type_map) const = 0; + static std::shared_ptr from_config(const config& cfg); +}; + +/** + * Stores information about a schema type. + * This type represents a simple pattern match. + */ +class class_type_simple : public class_type { + boost::regex pattern_; +public: + class_type_simple(const std::string& name, const std::string& pattern) : class_type(name), pattern_(pattern) {} + bool matches(const std::string& value, const map& type_map) const override; +}; + +/** + * Stores information about a schema type. + * This type represents a name alias for another type. + */ +class class_type_alias : public class_type { + mutable std::shared_ptr cached_; + std::string link_; +public: + class_type_alias(const std::string& name, const std::string& link) : class_type(name), link_(link) {} + bool matches(const std::string& value, const map& type_map) const override; +}; + +/** + * Stores information about a schema type. + * This is an abstract base class for composite types. + */ +class class_type_composite : public class_type { +protected: + std::vector> subtypes_; +public: + explicit class_type_composite(const std::string& name) : class_type(name) {} + void add_type(std::shared_ptr type) + { + subtypes_.push_back(type); + } +}; + +/** + * Stores information about a schema type. + * Represents a union type, which matches if any of its subtypes match. + */ +class class_type_union : public class_type_composite { +public: + explicit class_type_union(const std::string& name) : class_type_composite(name) {} + bool matches(const std::string& value, const map& type_map) const override; +}; + +/** + * Stores information about a schema type. + * Represents an intersection type, which matches if all of its subtypes match. + */ +class class_type_intersection : public class_type_composite { +public: + explicit class_type_intersection(const std::string& name) : class_type_composite(name) {} + bool matches(const std::string& value, const map& type_map) const override; +}; + +/** + * Stores information about a schema type. + * Represents a list type, where each list element is itself a union. + */ +class class_type_list : public class_type_union { + boost::regex split_; + int min_ = 0, max_ = -1; +public: + class_type_list(const std::string& name, const std::string& pattern, int min, int max) + : class_type_union(name) + , split_(pattern) + , min_(min) + , max_(max) + {} + bool matches(const std::string& value, const map& type_map) const override; +}; +} diff --git a/src/serialization/schema_validator.hpp b/src/serialization/schema_validator.hpp index df3f024158b4..b993695688c3 100644 --- a/src/serialization/schema_validator.hpp +++ b/src/serialization/schema_validator.hpp @@ -16,7 +16,9 @@ #include "config_cache.hpp" #include "serialization/parser.hpp" -#include "serialization/tag.hpp" +#include "serialization/schema/type.hpp" +#include "serialization/schema/tag.hpp" +#include "serialization/schema/key.hpp" #include "serialization/validator.hpp" #include