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