Split tag.hpp into three files

This commit is contained in:
Celtic Minstrel 2018-11-04 19:05:21 -05:00
parent df4413ae66
commit a32e279b7c
10 changed files with 510 additions and 367 deletions

View file

@ -2809,7 +2809,21 @@
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)SDL\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\seed_rng.cpp" />
<ClCompile Include="..\..\src\serialization\tag.cpp">
<ClCompile Include="..\..\src\serialization\schema\key.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)Serialization\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\serialization\schema\tag.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)Serialization\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\serialization\schema\type.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)Serialization\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)Serialization\</ObjectFileName>
@ -4033,7 +4047,9 @@
<ClInclude Include="..\..\src\theme.hpp" />
<ClInclude Include="..\..\src\time_of_day.hpp" />
<ClInclude Include="..\..\src\tod_manager.hpp" />
<ClInclude Include="..\..\src\serialization\tag.hpp" />
<ClInclude Include="..\..\src\serialization\schema\key.hpp" />
<ClInclude Include="..\..\src\serialization\schema\tag.hpp" />
<ClInclude Include="..\..\src\serialization\schema\type.hpp" />
<ClInclude Include="..\..\src\tooltips.hpp" />
<ClInclude Include="..\..\src\units\abilities.hpp" />
<ClInclude Include="..\..\src\units\animation.hpp" />

View file

@ -1010,7 +1010,13 @@
<ClCompile Include="..\..\src\utils\name_generator_factory.cpp">
<Filter>utils</Filter>
</ClCompile>
<ClCompile Include="..\..\src\serialization\tag.cpp">
<ClCompile Include="..\..\src\serialization\schema\key.cpp">
<Filter>serialization</Filter>
</ClCompile>
<ClCompile Include="..\..\src\serialization\schema\tag.cpp">
<Filter>serialization</Filter>
</ClCompile>
<ClCompile Include="..\..\src\serialization\schema\type.cpp">
<Filter>serialization</Filter>
</ClCompile>
<ClCompile Include="..\..\src\tests\main.cpp">
@ -2513,7 +2519,13 @@
<ClInclude Include="..\..\src\utils\scope_exit.hpp">
<Filter>utils</Filter>
</ClInclude>
<ClInclude Include="..\..\src\serialization\tag.hpp">
<ClInclude Include="..\..\src\serialization\schema\key.hpp">
<Filter>serialization</Filter>
</ClInclude>
<ClInclude Include="..\..\src\serialization\schema\tag.hpp">
<Filter>serialization</Filter>
</ClInclude>
<ClInclude Include="..\..\src\serialization\schema\type.hpp">
<Filter>serialization</Filter>
</ClInclude>
<ClInclude Include="..\..\src\actions\advancement.hpp">

View file

@ -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

View file

@ -0,0 +1,63 @@
/*
Copyright (C) 2011 - 2018 by Sytyi Nick <nsytyi@gmail.com>
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

View file

@ -0,0 +1,143 @@
/*
Copyright (C) 2011 - 2018 by Sytyi Nick <nsytyi@gmail.com>
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 <iosfwd>
#include <string>
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_;
};
}

View file

@ -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> class_type::from_config(const config& cfg)
{
boost::optional<config::const_child_itors> composite_range;
std::shared_ptr<class_type> type;
if(cfg.has_child("union")) {
type = std::make_shared<class_type_union>(cfg["name"]);
composite_range.emplace(cfg.child("union").child_range("type"));
} else if(cfg.has_child("intersection")) {
type = std::make_shared<class_type_intersection>(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<class_type_list>(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<class_type_simple>(cfg["name"], cfg["value"]);
} else if(cfg.has_attribute("link")) {
type = std::make_shared<class_type_alias>(cfg["name"], cfg["link"]);
}
if(composite_range) {
auto composite_type = std::dynamic_pointer_cast<class_type_composite>(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

View file

@ -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 <algorithm>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <boost/regex.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator.hpp>
#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<class_type>;
using map = std::map<std::string, ptr>;
virtual bool matches(const std::string& value, const map& type_map) const = 0;
static std::shared_ptr<class_type> 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<class_type> 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<std::shared_ptr<class_type>> subtypes_;
public:
explicit class_type_composite(const std::string& name) : class_type(name) {}
void add_type(std::shared_ptr<class_type> 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 @@ public:
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)
{

View file

@ -0,0 +1,123 @@
/*
Copyright (C) 2011 - 2018 by Sytyi Nick <nsytyi@gmail.com>
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> class_type::from_config(const config& cfg)
{
boost::optional<config::const_child_itors> composite_range;
std::shared_ptr<class_type> type;
if(cfg.has_child("union")) {
type = std::make_shared<class_type_union>(cfg["name"]);
composite_range.emplace(cfg.child("union").child_range("type"));
} else if(cfg.has_child("intersection")) {
type = std::make_shared<class_type_intersection>(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<class_type_list>(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<class_type_simple>(cfg["name"], cfg["value"]);
} else if(cfg.has_attribute("link")) {
type = std::make_shared<class_type_alias>(cfg["name"], cfg["link"]);
}
if(composite_range) {
auto composite_type = std::dynamic_pointer_cast<class_type_composite>(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

View file

@ -0,0 +1,120 @@
/*
Copyright (C) 2011 - 2018 by Sytyi Nick <nsytyi@gmail.com>
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 <boost/regex.hpp>
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<class_type>;
using map = std::map<std::string, ptr>;
virtual bool matches(const std::string& value, const map& type_map) const = 0;
static std::shared_ptr<class_type> 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<class_type> 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<std::shared_ptr<class_type>> subtypes_;
public:
explicit class_type_composite(const std::string& name) : class_type(name) {}
void add_type(std::shared_ptr<class_type> 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;
};
}

View file

@ -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 <iostream>