The Battle for Wesnoth  1.19.6+dev
tag.hpp
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  * This file contains object "tag", which is used to store
19  * information about tags while annotation parsing.
20  */
21 
22 #pragma once
23 
24 #include <functional>
25 #include <map>
26 #include <string>
27 #include <vector>
28 #include <queue>
29 
30 #include <boost/iterator/iterator_facade.hpp>
31 #include "config.hpp"
33 
34 namespace schema_validation
35 {
36 
37 class wml_condition;
38 
39 /**
40  * Stores information about tag.
41  * Each tags is an element of great tag tree. This tree is close to filesystem:
42  * you can use links and special include directory global/
43  * Normally root is not mentioned in path.
44  * Each tag has name, minimum and maximum occasions number,
45  * and lists of subtags, keys and links.
46  */
47 class wml_tag
48 {
49 public:
50  using tag_map = std::map<std::string, wml_tag>;
51  using key_map = std::map<std::string, wml_key>;
52  using link_map = std::map<std::string, std::string>;
53  using condition_list = std::vector<wml_condition>;
54  using super_list = std::map<std::string, const wml_tag*>;
55 private:
56  static void push_new_tag_conditions(std::queue<const wml_tag*>& q, const config& match, const wml_tag& tag);
57  template<typename T, typename Map = std::map<std::string, T>>
58  class iterator : public boost::iterator_facade<iterator<T, Map>, const typename Map::value_type, std::forward_iterator_tag>
59  {
60  std::queue<const wml_tag*> condition_queue;
61  typename Map::const_iterator current;
62  std::reference_wrapper<const config> match;
63  public:
64  // Construct a begin iterator
65  iterator(const wml_tag& base_tag, const config& match) : match(match)
66  {
67  init(base_tag);
68  push_new_tag_conditions(base_tag);
70  }
71  // Construct an end iterator
72  iterator() : match(config().child_or_empty("fsdfsdf")) {}
73  private:
75  void init(const wml_tag& base_tag);
76  void ensure_valid_or_end();
77  void increment()
78  {
79  ++current;
81  }
83  {
85  }
86  bool equal(const iterator<T, Map>& other) const
87  {
88  if(condition_queue.empty() && other.condition_queue.empty()) {
89  return true;
90  }
91  if(condition_queue.empty() || other.condition_queue.empty()) {
92  return false;
93  }
94  if(condition_queue.front() != other.condition_queue.front()) {
95  return false;
96  }
97  if(current != other.current) {
98  return false;
99  }
100  return true;
101  }
103  {
104  return *current;
105  }
106  };
107  template<typename T, typename Map> friend class iterator;
111 public:
112 
113  wml_tag() = default;
114 
115  wml_tag(const std::string& name, int min, int max, const std::string& super = "", bool any = false);
116 
117  wml_tag(const config&);
118 
119  /** Prints information about tag to outputstream, recursively
120  * is used to print tag info
121  * the format is next
122  * [tag]
123  * subtags
124  * keys
125  * name="name"
126  * min="min"
127  * max="max"
128  * [/tag]
129  */
130  void print(std::ostream& os);
131 
132  const std::string& get_name() const
133  {
134  return name_;
135  }
136 
137  int get_min() const
138  {
139  return min_;
140  }
141 
142  int get_max() const
143  {
144  return max_;
145  }
146 
147  int get_min_children() const
148  {
149  return min_children_;
150  }
151 
152  int get_max_children() const
153  {
154  return max_children_;
155  }
156 
157  const std::string& get_super() const
158  {
159  return super_;
160  }
161 
162  bool is_extension() const
163  {
164  return !super_.empty();
165  }
166 
167  bool is_fuzzy() const {
168  return fuzzy_;
169  }
170 
171  bool accepts_any_tag() const {
172  return any_tag_;
173  }
174 
175  void set_name(const std::string& name)
176  {
177  name_ = name;
178  }
179 
180  void set_min(int o)
181  {
182  min_ = o;
183  }
184 
185  void set_max(int o)
186  {
187  max_ = o;
188  }
189 
190  void set_min_children(int o)
191  {
192  min_children_ = o;
193  }
194 
195  void set_max_children(int o)
196  {
197  max_children_ = o;
198  }
199 
200  void set_min(const std::string& s);
201  void set_max(const std::string& s);
202 
203  void set_min_children(const std::string& s);
204  void set_max_children(const std::string& s);
205 
206  void set_super(const std::string& s)
207  {
208  super_ = s;
209  }
210 
211  void set_fuzzy(bool f) {
212  fuzzy_ = f;
213  }
214 
215  void set_any_tag(bool any) {
216  any_tag_ = any;
217  }
218 
219  void add_key(const wml_key& new_key)
220  {
221  keys_.emplace(new_key.get_name(), new_key);
222  }
223 
224  void add_tag(const wml_tag& new_tag)
225  {
226  tags_.emplace(new_tag.name_, new_tag);
227  }
228 
229  void add_link(const std::string& link);
230 
231  void add_switch(const config& switch_cfg);
232 
233  void add_filter(const config& cond_cfg);
234 
235  /**
236  * Tags are usually organized in tree.
237  * This function helps to add a tag to his exact place in tree
238  * @param path - path in subtree to exact place of tag
239  * @param tag - tag to add
240  * @param root - root of schema tree - use to support of adding to link.
241  * Path is getting shotter and shoter with each call.
242  * Path should look like tag1/tag2/parent/ Slash at end is mandatory.
243  */
244  void add_tag(const std::string& path, const wml_tag& tag, wml_tag& root);
245 
246  bool operator<(const wml_tag& t) const
247  {
248  return name_ < t.name_;
249  }
250 
251  bool operator==(const wml_tag& other) const
252  {
253  return name_ == other.name_;
254  }
255 
256  /** Returns pointer to child key. */
257  const wml_key* find_key(const std::string& name, const config& match, bool ignore_super = false) const;
258 
259  /** Returns pointer to child link. */
260  const std::string* find_link(const std::string& name) const;
261 
262  /**
263  * Returns pointer to tag using full path to it.
264  * Also work with links
265  */
266  const wml_tag* find_tag(const std::string& fullpath, const wml_tag& root, const config& match, bool ignore_super = false) const;
267 
268  /** Calls the expansion on each child. */
269  void expand_all(wml_tag& root);
270 
271  boost::iterator_range<tag_iterator> tags(const config& cfg_match) const
272  {
273  return {tag_iterator(*this, cfg_match), tag_iterator()};
274  }
275 
276  boost::iterator_range<key_iterator> keys(const config& cfg_match) const
277  {
278  return {key_iterator(*this, cfg_match), key_iterator()};
279  }
280 
281  boost::iterator_range<super_iterator> super(const config& cfg_match) const {
282  return {super_iterator(*this, cfg_match), super_iterator()};
283  }
284 
285  const link_map& links() const
286  {
287  return links_;
288  }
289 
290  const condition_list& conditions() const
291  {
292  return conditions_;
293  }
294 
295  void remove_key_by_name(const std::string& name)
296  {
297  keys_.erase(name);
298  }
299 
300  /** Removes all keys with this type. Works recursively */
301  void remove_keys_by_type(const std::string& type);
302 
303 private:
304  /** name of tag. */
305  std::string name_ = "";
306 
307  /** minimum number of occurrences. */
308  int min_ = 0;
309 
310  /** maximum number of occurrences. */
311  int max_ = 0;
312 
313  /** minimum number of children. */
314  int min_children_ = 0;
315 
316  /** maximum number of children. */
317  int max_children_ = std::numeric_limits<int>::max();
318 
319  /**
320  * name of tag to extend "super-tag"
321  * Extension is smth like inheritance and is used in case
322  * when you need to use another tag with all his
323  * keys, children, etc. But you also want to allow extra subtags of that tags,
324  * so just linking that tag wouldn't help at all.
325  */
326  std::string super_ = "";
327 
328  /** children tags*/
330 
331  /** keys*/
333 
334  /** links to possible children. */
336 
337  /** conditional partial matches */
339 
340  /** super-tag references */
342 
343  /** whether this is a "fuzzy" tag. */
344  bool fuzzy_ = false;
345 
346  /** whether this tag allows arbitrary subtags. */
347  bool any_tag_ = false;
348 
349  /**
350  * the same as wml_tag::print(std::ostream&)
351  * but indents different levels with step space.
352  * @param os stream to print
353  * @param level current level of indentation
354  * @param step step to next indent
355  */
356  void printl(std::ostream& os, int level, int step = 4);
357 
358  wml_tag* find_tag(const std::string & fullpath, wml_tag & root, const config& match)
359  {
360  return const_cast<wml_tag*>(const_cast<const wml_tag*>(this)->find_tag(fullpath, root, match));
361  }
362 
363  void add_tags(const tag_map& list)
364  {
365  tags_.insert(list.begin(), list.end());
366  }
367 
368  void add_keys(const key_map& list)
369  {
370  keys_.insert(list.begin(), list.end());
371  }
372 
373  void add_links(const link_map& list)
374  {
375  links_.insert(list.begin(), list.end());
376  }
377 
378  void add_conditions(const condition_list& list);
379 
380  /** Expands all "super", storing direct references for easier access. */
381  void expand(wml_tag& root);
382 
383  /** Finds a key with super bookkeeping to handle super cycles. */
384  const wml_key* find_key(const std::string& name, const config& match, bool ignore_super, std::vector<const wml_tag*>& visited) const;
385 
386  /** Finds a tag with super bookkeeping to handle super cycles. */
387  const wml_tag* find_tag(const std::string& fullpath, const wml_tag& root, const config& match, bool ignore_super, std::vector<const wml_tag*>& visited) const;
388 };
389 
390 /**
391  * Stores information about a conditional portion of a tag.
392  * Format is the same as wml_tag.
393  */
394 class wml_condition : public wml_tag {
396 public:
397  wml_condition(const config& info, const config& filter) : wml_tag(info), filter_(filter) {}
398  bool matches(const config& cfg) const;
399 };
400 }
double t
Definition: astarsearch.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
Stores information about a conditional portion of a tag.
Definition: tag.hpp:394
wml_condition(const config &info, const config &filter)
Definition: tag.hpp:397
bool matches(const config &cfg) const
Definition: tag.cpp:481
wml_key is used to save the information about one key.
Definition: key.hpp:37
const std::string & get_name() const
Definition: key.hpp:59
std::reference_wrapper< const config > match
Definition: tag.hpp:62
iterator< T, Map >::reference dereference() const
Definition: tag.hpp:102
bool equal(const iterator< T, Map > &other) const
Definition: tag.hpp:86
iterator(const wml_tag &base_tag, const config &match)
Definition: tag.hpp:65
void push_new_tag_conditions(const wml_tag &tag)
Definition: tag.hpp:82
friend class boost::iterator_core_access
Definition: tag.hpp:74
std::queue< const wml_tag * > condition_queue
Definition: tag.hpp:60
Map::const_iterator current
Definition: tag.hpp:61
void init(const wml_tag &base_tag)
Definition: tag.cpp:494
Stores information about tag.
Definition: tag.hpp:48
void add_link(const std::string &link)
Definition: tag.cpp:111
boost::iterator_range< super_iterator > super(const config &cfg_match) const
Definition: tag.hpp:281
int get_min_children() const
Definition: tag.hpp:147
int get_min() const
Definition: tag.hpp:137
const link_map & links() const
Definition: tag.hpp:285
void expand(wml_tag &root)
Expands all "super", storing direct references for easier access.
Definition: tag.cpp:394
void set_super(const std::string &s)
Definition: tag.hpp:206
const std::string & get_name() const
Definition: tag.hpp:132
std::string super_
name of tag to extend "super-tag" Extension is smth like inheritance and is used in case when you nee...
Definition: tag.hpp:326
bool operator<(const wml_tag &t) const
Definition: tag.hpp:246
const wml_tag * find_tag(const std::string &fullpath, const wml_tag &root, const config &match, bool ignore_super=false) const
Returns pointer to tag using full path to it.
Definition: tag.cpp:189
const condition_list & conditions() const
Definition: tag.hpp:290
iterator< const wml_tag * > super_iterator
Definition: tag.hpp:110
void set_max(int o)
Definition: tag.hpp:185
std::map< std::string, const wml_tag * > super_list
Definition: tag.hpp:54
std::map< std::string, std::string > link_map
Definition: tag.hpp:52
void remove_key_by_name(const std::string &name)
Definition: tag.hpp:295
void add_tags(const tag_map &list)
Definition: tag.hpp:363
int get_max_children() const
Definition: tag.hpp:152
bool operator==(const wml_tag &other) const
Definition: tag.hpp:251
void set_name(const std::string &name)
Definition: tag.hpp:175
void add_filter(const config &cond_cfg)
Definition: tag.cpp:451
int min_children_
minimum number of children.
Definition: tag.hpp:314
super_list super_refs_
super-tag references
Definition: tag.hpp:341
void set_fuzzy(bool f)
Definition: tag.hpp:211
void add_keys(const key_map &list)
Definition: tag.hpp:368
void add_tag(const wml_tag &new_tag)
Definition: tag.hpp:224
const std::string * find_link(const std::string &name) const
Returns pointer to child link.
Definition: tag.cpp:179
void set_min(int o)
Definition: tag.hpp:180
void set_any_tag(bool any)
Definition: tag.hpp:215
std::map< std::string, wml_key > key_map
Definition: tag.hpp:51
void set_min_children(const std::string &s)
void print(std::ostream &os)
Prints information about tag to outputstream, recursively is used to print tag info the format is nex...
Definition: tag.cpp:90
link_map links_
links to possible children.
Definition: tag.hpp:335
iterator< wml_tag > tag_iterator
Definition: tag.hpp:108
std::string name_
name of tag.
Definition: tag.hpp:305
void add_conditions(const condition_list &list)
Definition: tag.cpp:389
boost::iterator_range< key_iterator > keys(const config &cfg_match) const
Definition: tag.hpp:276
boost::iterator_range< tag_iterator > tags(const config &cfg_match) const
Definition: tag.hpp:271
bool fuzzy_
whether this is a "fuzzy" tag.
Definition: tag.hpp:344
void remove_keys_by_type(const std::string &type)
Removes all keys with this type.
Definition: tag.cpp:294
iterator< wml_key > key_iterator
Definition: tag.hpp:109
void add_links(const link_map &list)
Definition: tag.hpp:373
int min_
minimum number of occurrences.
Definition: tag.hpp:308
std::map< std::string, wml_tag > tag_map
Definition: tag.hpp:50
bool accepts_any_tag() const
Definition: tag.hpp:171
bool any_tag_
whether this tag allows arbitrary subtags.
Definition: tag.hpp:347
int get_max() const
Definition: tag.hpp:142
bool is_fuzzy() const
Definition: tag.hpp:167
void add_switch(const config &switch_cfg)
Definition: tag.cpp:406
void set_max_children(const std::string &s)
static void push_new_tag_conditions(std::queue< const wml_tag * > &q, const config &match, const wml_tag &tag)
Definition: tag.cpp:554
bool is_extension() const
Definition: tag.hpp:162
condition_list conditions_
conditional partial matches
Definition: tag.hpp:338
std::vector< wml_condition > condition_list
Definition: tag.hpp:53
const wml_key * find_key(const std::string &name, const config &match, bool ignore_super=false) const
Returns pointer to child key.
Definition: tag.cpp:119
void set_min_children(int o)
Definition: tag.hpp:190
void expand_all(wml_tag &root)
Calls the expansion on each child.
Definition: tag.cpp:282
const std::string & get_super() const
Definition: tag.hpp:157
tag_map tags_
children tags
Definition: tag.hpp:329
wml_tag * find_tag(const std::string &fullpath, wml_tag &root, const config &match)
Definition: tag.hpp:358
void add_key(const wml_key &new_key)
Definition: tag.hpp:219
int max_
maximum number of occurrences.
Definition: tag.hpp:311
void printl(std::ostream &os, int level, int step=4)
the same as wml_tag::print(std::ostream&) but indents different levels with step space.
Definition: tag.cpp:310
int max_children_
maximum number of children.
Definition: tag.hpp:317
void set_max_children(int o)
Definition: tag.hpp:195
Definitions for the interface to Wesnoth Markup Language (WML).
std::string path
Definition: filesystem.cpp:91
logger & info()
Definition: log.cpp:319
std::string tag(const std::string &tag_name, Args &&... contents)
Definition: markup.hpp:45
This file contains object "key", which is used to store information about keys while annotation parsi...
static map_location::direction s
#define f