The Battle for Wesnoth  1.15.1+dev
type.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2018 by Sytyi Nick <nsytyi@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Implementation of type.hpp.
18  */
19 
21 #include "boost/optional.hpp"
22 
23 #include "config.hpp"
24 
25 namespace schema_validation
26 {
27 
28 /*WIKI
29  * @begin{parent}{name="wml_schema/tag/"}
30  * @begin{tag}{name="key"}{min=0}{max=-1}
31  * @begin{table}{config}
32  * name & string & & The name of key. $
33  * type & string & & The type of key value. $
34  * default & string & & The default value of the key. $
35  * mandatory & string & & Shows if key is mandatory $
36  * @end{table}
37  * @end{tag}{name="key"}
38  * @end{parent}{name="wml_schema/tag/"}
39  */
40 std::shared_ptr<wml_type> wml_type::from_config(const config& cfg)
41 {
42  boost::optional<config::const_child_itors> composite_range;
43  std::shared_ptr<wml_type> type;
44  if(cfg.has_child("union")) {
45  type = std::make_shared<wml_type_union>(cfg["name"]);
46  composite_range.emplace(cfg.child("union").child_range("type"));
47  } else if(cfg.has_child("intersection")) {
48  type = std::make_shared<wml_type_intersection>(cfg["name"]);
49  composite_range.emplace(cfg.child("intersection").child_range("type"));
50  } else if(cfg.has_child("list")) {
51  const config& list_cfg = cfg.child("list");
52  int list_min = list_cfg["min"].to_int();
53  int list_max = list_cfg["max"].str() == "infinite" ? -1 : list_cfg["max"].to_int(-1);
54  if(list_max < 0) list_max = INT_MAX;
55  type = std::make_shared<wml_type_list>(cfg["name"], list_cfg["split"].str("\\s*,\\s*"), list_min, list_max);
56  composite_range.emplace(list_cfg.child_range("element"));
57  } else if(cfg.has_attribute("value")) {
58  type = std::make_shared<wml_type_simple>(cfg["name"], cfg["value"]);
59  } else if(cfg.has_attribute("link")) {
60  type = std::make_shared<wml_type_alias>(cfg["name"], cfg["link"]);
61  }
62  if(composite_range) {
63  auto composite_type = std::dynamic_pointer_cast<wml_type_composite>(type);
64  for(const config& elem : *composite_range) {
65  composite_type->add_type(wml_type::from_config(elem));
66  }
67  }
68  return type;
69 }
70 
71 bool wml_type_simple::matches(const std::string& value, const map&) const
72 {
73  boost::smatch sub;
74  return boost::regex_match(value, sub, pattern_);
75 }
76 
77 bool wml_type_alias::matches(const std::string& value, const map& type_map) const
78 {
79  if(!cached_) {
80  auto it = type_map.find(link_);
81  if(it == type_map.end()) {
82  // TODO: Error message about the invalid type?
83  return false;
84  }
85  cached_ = it->second;
86  }
87  return cached_->matches(value, type_map);
88 }
89 
90 bool wml_type_union::matches(const std::string& value, const map& type_map) const
91 {
92  for(const auto& type : subtypes_) {
93  if(type->matches(value, type_map)) {
94  return true;
95  }
96  }
97  return false;
98 }
99 
100 bool wml_type_intersection::matches(const std::string& value, const map& type_map) const
101 {
102  for(const auto& type : subtypes_) {
103  if(!type->matches(value, type_map)) {
104  return false;
105  }
106  }
107  return true;
108 }
109 
110 bool wml_type_list::matches(const std::string& value, const map& type_map) const
111 {
112  boost::sregex_token_iterator it(value.begin(), value.end(), split_, -1), end;
113  int n = 0;
114  bool result = std::all_of(it, end, [this, &type_map, &n](const boost::ssub_match& match){
115  // Not sure if this is necessary?
116  if(!match.matched) return true;
117  n++;
118  return this->wml_type_union::matches(std::string(match.first, match.second), type_map);
119  });
120  return result && n >= min_ && n <= max_;
121 }
122 
123 } // namespace schema_validation
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:420
This file contains object "type", which is used to store information about types while annotation par...
bool has_attribute(config_key_type key) const
Definition: config.cpp:213
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
Definition: config.cpp:412
child_itors child_range(config_key_type key)
Definition: config.cpp:362
Definitions for the interface to Wesnoth Markup Language (WML).
std::map< std::string, ptr > map
Definition: type.hpp:41
static std::shared_ptr< wml_type > from_config(const config &cfg)
Definition: type.cpp:40
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:110
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:90
static const char * match(MatchState *ms, const char *s, const char *p)
Definition: lstrlib.cpp:425
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:100
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:77
static map_location::DIRECTION n
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:71
Stores information about a schema type.
Definition: type.hpp:74
void add_type(std::shared_ptr< wml_type > type)
Definition: type.hpp:79