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