The Battle for Wesnoth  1.17.0-dev
type.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2021
3  by Sytyi Nick <nsytyi@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Implementation of type.hpp.
19  */
20 
22 
23 #include "config.hpp"
24 #include <optional>
25 
27 {
28  bool empty;
29  is_translatable(bool b) : empty(b) {}
30  bool operator()(const std::string& str) const
31  {
32  return str.empty() ? empty : false;
33  }
34  bool operator()(const t_string&) const
35  {
36  return true;
37  }
38  bool operator()(const std::monostate&) const
39  {
40  return true;
41  }
42  template<typename T>
43  bool operator()(const T&) const
44  {
45  return false;
46  }
47 };
48 
49 namespace schema_validation
50 {
51 
52 std::shared_ptr<wml_type> wml_type::from_config(const config& cfg)
53 {
54  std::optional<config::const_child_itors> composite_range;
55  std::shared_ptr<wml_type> type;
56  if(cfg.has_child("union")) {
57  type = std::make_shared<wml_type_union>(cfg["name"]);
58  composite_range.emplace(cfg.child("union").child_range("type"));
59  } else if(cfg.has_child("intersection")) {
60  type = std::make_shared<wml_type_intersection>(cfg["name"]);
61  composite_range.emplace(cfg.child("intersection").child_range("type"));
62  } else if(cfg.has_child("list")) {
63  const config& list_cfg = cfg.child("list");
64  int list_min = list_cfg["min"].to_int();
65  int list_max = list_cfg["max"].str() == "infinite" ? -1 : list_cfg["max"].to_int(-1);
66  if(list_max < 0) list_max = INT_MAX;
67  type = std::make_shared<wml_type_list>(cfg["name"], list_cfg["split"].str("\\s*,\\s*"), list_min, list_max);
68  composite_range.emplace(list_cfg.child_range("element"));
69  } else if(cfg.has_attribute("value")) {
70  auto t = std::make_shared<wml_type_simple>(cfg["name"], cfg["value"]);
71  if(cfg["allow_translatable"].to_bool()) t->allow_translatable();
72  type = t;
73  } else if(cfg.has_attribute("link")) {
74  type = std::make_shared<wml_type_alias>(cfg["name"], cfg["link"]);
75  }
76  if(composite_range) {
77  auto composite_type = std::dynamic_pointer_cast<wml_type_composite>(type);
78  for(const config& elem : *composite_range) {
79  composite_type->add_type(wml_type::from_config(elem));
80  }
81  }
82  return type;
83 }
84 
85 bool wml_type_simple::matches(const config_attribute_value& value, const map&) const
86 {
87  if(!allow_translatable_ && value.apply_visitor(is_translatable(false))) return false;
88  boost::smatch sub;
89  return boost::regex_match(value.str(), sub, pattern_);
90 }
91 
92 bool wml_type_alias::matches(const config_attribute_value& value, const map& type_map) const
93 {
94  if(!cached_) {
95  auto it = type_map.find(link_);
96  if(it == type_map.end()) {
97  // TODO: Error message about the invalid type?
98  return false;
99  }
100  cached_ = it->second;
101  }
102  return cached_->matches(value, type_map);
103 }
104 
105 bool wml_type_union::matches(const config_attribute_value& value, const map& type_map) const
106 {
107  for(const auto& type : subtypes_) {
108  if(type->matches(value, type_map)) {
109  return true;
110  }
111  }
112  return false;
113 }
114 
115 bool wml_type_intersection::matches(const config_attribute_value& value, const map& type_map) const
116 {
117  for(const auto& type : subtypes_) {
118  if(!type->matches(value, type_map)) {
119  return false;
120  }
121  }
122  return true;
123 }
124 
125 bool wml_type_list::matches(const config_attribute_value& value_attr, const map& type_map) const
126 {
127  auto value = value_attr.str();
128  boost::sregex_token_iterator it(value.begin(), value.end(), split_, -1), end;
129  int n = 0;
130  bool result = std::all_of(it, end, [this, &type_map, &n](const boost::ssub_match& match){
131  // Not sure if this is necessary?
132  if(!match.matched) return true;
133  n++;
135  elem = std::string(match.first, match.second);
136  return this->wml_type_union::matches(elem, type_map);
137  });
138  return result && n >= min_ && n <= max_;
139 }
140 
141 bool wml_type_tstring::matches(const config_attribute_value& value, const map&) const
142 {
143  return value.apply_visitor(is_translatable(true));
144 }
145 
146 } // 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:402
bool operator()(const t_string &) const
Definition: type.cpp:34
This file contains object "type", which is used to store information about types while annotation par...
Variant for storing WML attributes.
bool has_attribute(config_key_type key) const
Definition: config.cpp:211
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
Definition: config.cpp:394
child_itors child_range(config_key_type key)
Definition: config.cpp:344
Definitions for the interface to Wesnoth Markup Language (WML).
std::map< std::string, ptr > map
Definition: type.hpp:43
#define b
bool operator()(const std::string &str) const
Definition: type.cpp:30
bool operator()(const std::monostate &) const
Definition: type.cpp:38
bool empty
Definition: type.cpp:28
is_translatable(bool b)
Definition: type.cpp:29
double t
Definition: astarsearch.cpp:65
auto apply_visitor(const V &visitor) const
Visitor support: Applies a visitor to the underlying variant.
static const char * match(MatchState *ms, const char *s, const char *p)
Definition: lstrlib.cpp:567
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
bool operator()(const T &) const
Definition: type.cpp:43
static map_location::DIRECTION n
Stores information about a schema type.
Definition: type.hpp:78
void add_type(std::shared_ptr< wml_type > type)
Definition: type.hpp:83
std::string str(const std::string &fallback="") const