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