The Battle for Wesnoth  1.19.0+dev
type.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2024
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 #include "utils/variant.hpp"
26 
28 {
29  bool empty;
30  is_translatable(bool b) : empty(b) {}
31  bool operator()(const std::string& str) const
32  {
33  return str.empty() ? empty : false;
34  }
35  bool operator()(const t_string&) const
36  {
37  return true;
38  }
39  bool operator()(const utils::monostate&) const
40  {
41  return true;
42  }
43  template<typename T>
44  bool operator()(const T&) const
45  {
46  return false;
47  }
48 };
49 
50 namespace schema_validation
51 {
52 
53 std::shared_ptr<wml_type> wml_type::from_config(const config& cfg)
54 {
55  std::optional<config::const_child_itors> composite_range;
56  std::shared_ptr<wml_type> type;
57  if(cfg.has_child("union")) {
58  type = std::make_shared<wml_type_union>(cfg["name"]);
59  composite_range.emplace(cfg.mandatory_child("union").child_range("type"));
60  } else if(cfg.has_child("intersection")) {
61  type = std::make_shared<wml_type_intersection>(cfg["name"]);
62  composite_range.emplace(cfg.mandatory_child("intersection").child_range("type"));
63  } else if(cfg.has_child("list")) {
64  const config& list_cfg = cfg.mandatory_child("list");
65  int list_min = list_cfg["min"].to_int();
66  int list_max = list_cfg["max"].str() == "infinite" ? -1 : list_cfg["max"].to_int(-1);
67  if(list_max < 0) list_max = INT_MAX;
68  type = std::make_shared<wml_type_list>(cfg["name"], list_cfg["split"].str("\\s*,\\s*"), list_min, list_max);
69  composite_range.emplace(list_cfg.child_range("element"));
70  } else if(cfg.has_attribute("value")) {
71  auto t = std::make_shared<wml_type_simple>(cfg["name"], cfg["value"]);
72  if(cfg["allow_translatable"].to_bool()) t->allow_translatable();
73  type = t;
74  } else if(cfg.has_attribute("link")) {
75  type = std::make_shared<wml_type_alias>(cfg["name"], cfg["link"]);
76  }
77  if(composite_range) {
78  auto composite_type = std::dynamic_pointer_cast<wml_type_composite>(type);
79  for(const config& elem : *composite_range) {
80  composite_type->add_type(wml_type::from_config(elem));
81  }
82  }
83  return type;
84 }
85 
86 bool wml_type_simple::matches(const config_attribute_value& value, const map&) const
87 {
88  if(!allow_translatable_ && value.apply_visitor(is_translatable(false))) return false;
89  boost::smatch sub;
90  return boost::regex_match(value.str(), sub, pattern_);
91 }
92 
93 bool wml_type_alias::matches(const config_attribute_value& value, const map& type_map) const
94 {
95  if(!cached_) {
96  auto it = type_map.find(link_);
97  if(it == type_map.end()) {
98  // TODO: Error message about the invalid type?
99  return false;
100  }
101  cached_ = it->second;
102  }
103  return cached_->matches(value, type_map);
104 }
105 
106 bool wml_type_union::matches(const config_attribute_value& value, const map& type_map) const
107 {
108  for(const auto& type : subtypes_) {
109  if(type->matches(value, type_map)) {
110  return true;
111  }
112  }
113  return false;
114 }
115 
116 bool wml_type_intersection::matches(const config_attribute_value& value, const map& type_map) const
117 {
118  for(const auto& type : subtypes_) {
119  if(!type->matches(value, type_map)) {
120  return false;
121  }
122  }
123  return true;
124 }
125 
126 bool wml_type_list::matches(const config_attribute_value& value_attr, const map& type_map) const
127 {
128  auto value = value_attr.str();
129  boost::sregex_token_iterator it(value.begin(), value.end(), split_, -1), end;
130  int n = 0;
131  bool result = std::all_of(it, end, [this, &type_map, &n](const boost::ssub_match& match){
132  // Not sure if this is necessary?
133  if(!match.matched) return true;
134  n++;
136  elem = std::string(match.first, match.second);
137  return this->wml_type_union::matches(elem, type_map);
138  });
139  return result && n >= min_ && n <= max_;
140 }
141 
142 bool wml_type_tstring::matches(const config_attribute_value& value, const map&) const
143 {
144  return value.apply_visitor(is_translatable(true));
145 }
146 
147 } // namespace schema_validation
double t
Definition: astarsearch.cpp:63
Variant for storing WML attributes.
std::string str(const std::string &fallback="") const
auto apply_visitor(const V &visitor) const
Visitor support: Applies a visitor to the underlying variant.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
Definition: config.cpp:367
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
Definition: config.cpp:317
bool has_attribute(config_key_type key) const
Definition: config.cpp:155
child_itors child_range(config_key_type key)
Definition: config.cpp:273
std::shared_ptr< wml_type > cached_
Definition: type.hpp:67
bool matches(const config_attribute_value &value, const map &type_map) const override
Definition: type.cpp:93
std::vector< std::shared_ptr< wml_type > > subtypes_
Definition: type.hpp:81
bool matches(const config_attribute_value &value, const map &type_map) const override
Definition: type.cpp:116
bool matches(const config_attribute_value &value, const map &type_map) const override
Definition: type.cpp:126
bool matches(const config_attribute_value &value, const map &type_map) const override
Definition: type.cpp:86
bool matches(const config_attribute_value &value, const map &type_map) const override
Definition: type.cpp:142
bool matches(const config_attribute_value &value, const map &type_map) const override
Definition: type.cpp:106
static std::shared_ptr< wml_type > from_config(const config &cfg)
Definition: type.cpp:53
std::map< std::string, ptr > map
Definition: type.hpp:43
bool operator()(const utils::monostate &) const
Definition: type.cpp:39
is_translatable(bool b)
Definition: type.cpp:30
bool operator()(const t_string &) const
Definition: type.cpp:35
bool empty
Definition: type.cpp:29
bool operator()(const T &) const
Definition: type.cpp:44
bool operator()(const std::string &str) const
Definition: type.cpp:31
static map_location::DIRECTION n
This file contains object "type", which is used to store information about types while annotation par...
MacOS doesn't support std::visit when targing MacOS < 10.14 (currently we target 10....
#define b