The Battle for Wesnoth  1.15.2+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  , super_("")
117  , tags_()
118  , keys_()
119  , links_()
120  , fuzzy_(false)
121  , any_tag_(false)
122  {
123  }
124 
125  wml_tag(const std::string& name, int min, int max, const std::string& super = "", bool any = false)
126  : name_(name)
127  , min_(min)
128  , max_(max)
129  , super_(super)
130  , tags_()
131  , keys_()
132  , links_()
133  , fuzzy_(name.find_first_of("*?") != std::string::npos)
134  , any_tag_(any)
135  {
136  }
137 
138  wml_tag(const config&);
139 
141  {
142  }
143 
144  /** Prints information about tag to outputstream, recursively
145  * is used to print tag info
146  * the format is next
147  * [tag]
148  * subtags
149  * keys
150  * name="name"
151  * min="min"
152  * max="max"
153  * [/tag]
154  */
155  void print(std::ostream& os);
156 
157  const std::string& get_name() const
158  {
159  return name_;
160  }
161 
162  int get_min() const
163  {
164  return min_;
165  }
166 
167  int get_max() const
168  {
169  return max_;
170  }
171 
172  const std::string& get_super() const
173  {
174  return super_;
175  }
176 
177  bool is_extension() const
178  {
179  return !super_.empty();
180  }
181 
182  bool is_fuzzy() const {
183  return fuzzy_;
184  }
185 
186  bool accepts_any_tag() const {
187  return any_tag_;
188  }
189 
190  void set_name(const std::string& name)
191  {
192  name_ = name;
193  }
194 
195  void set_min(int o)
196  {
197  min_ = o;
198  }
199 
200  void set_max(int o)
201  {
202  max_ = o;
203  }
204 
205  void set_min(const std::string& s);
206  void set_max(const std::string& s);
207 
208  void set_super(const std::string& s)
209  {
210  super_ = s;
211  }
212 
213  void set_fuzzy(bool f) {
214  fuzzy_ = f;
215  }
216 
217  void set_any_tag(bool any) {
218  any_tag_ = any;
219  }
220 
221  void add_key(const wml_key& new_key)
222  {
223  keys_.emplace(new_key.get_name(), new_key);
224  }
225 
226  void add_tag(const wml_tag& new_tag)
227  {
228  tags_.emplace(new_tag.name_, new_tag);
229  }
230 
231  void add_link(const std::string& link);
232 
233  void add_switch(const config& switch_cfg);
234 
235  void add_filter(const config& cond_cfg);
236 
237  /**
238  * Tags are usually organized in tree.
239  * This function helps to add a tag to his exact place in tree
240  * @param path - path in subtree to exact place of tag
241  * @param tag - tag to add
242  * @param root - root of schema tree - use to support of adding to link.
243  * Path is getting shotter and shoter with each call.
244  * Path should look like tag1/tag2/parent/ Slash at end is mandatory.
245  */
246  void add_tag(const std::string& path, const wml_tag& tag, wml_tag& root);
247 
248  bool operator<(const wml_tag& t) const
249  {
250  return name_ < t.name_;
251  }
252 
253  bool operator==(const wml_tag& other) const
254  {
255  return name_ == other.name_;
256  }
257 
258  /** Returns pointer to child key. */
259  const wml_key* find_key(const std::string& name, const config& match, bool ignore_super = false) const;
260 
261  /** Returns pointer to child link. */
262  const std::string* find_link(const std::string& name) const;
263 
264  /**
265  * Returns pointer to tag using full path to it.
266  * Also work with links
267  */
268  const wml_tag* find_tag(const std::string& fullpath, const wml_tag& root, const config& match, bool ignore_super = false) const;
269 
270  /** Calls the expansion on each child. */
271  void expand_all(wml_tag& root);
272 
273  boost::iterator_range<tag_iterator> tags(const config& cfg_match) const
274  {
275  return {tag_iterator(*this, cfg_match), tag_iterator()};
276  }
277 
278  boost::iterator_range<key_iterator> keys(const config& cfg_match) const
279  {
280  return {key_iterator(*this, cfg_match), key_iterator()};
281  }
282 
283  const link_map& links() const
284  {
285  return links_;
286  }
287 
288  const condition_list& conditions() const
289  {
290  return conditions_;
291  }
292 
293  void remove_key_by_name(const std::string& name)
294  {
295  keys_.erase(name);
296  }
297 
298  /** Removes all keys with this type. Works recursively */
299  void remove_keys_by_type(const std::string& type);
300 
301 private:
302  /** name of tag. */
303  std::string name_;
304 
305  /** number of minimum occasions. */
306  int min_;
307 
308  /** number of maximum occasions. */
309  int max_;
310 
311  /**
312  * name of tag to extend "super-tag"
313  * Extension is smth like inheritance and is used in case
314  * when you need to use another tag with all his
315  * keys, children, etc. But you also want to allow extra subtags of that tags,
316  * so just linking that tag wouldn't help at all.
317  */
318  std::string super_;
319 
320  /** children tags*/
322 
323  /** keys*/
325 
326  /** links to possible children. */
328 
329  /** conditional partial matches */
331 
332  /** super-tag references */
334 
335  /** whether this is a "fuzzy" tag. */
336  bool fuzzy_;
337 
338  /** whether this tag allows arbitrary subtags. */
339  bool any_tag_;
340 
341  /**
342  * the same as wml_tag::print(std::ostream&)
343  * but indents different levels with step space.
344  * @param os stream to print
345  * @param level current level of indentation
346  * @param step step to next indent
347  */
348  void printl(std::ostream& os, int level, int step = 4);
349 
350  wml_tag* find_tag(const std::string & fullpath, wml_tag & root, const config& match)
351  {
352  return const_cast<wml_tag*>(const_cast<const wml_tag*>(this)->find_tag(fullpath, root, match));
353  }
354 
355  void add_tags(const tag_map& list)
356  {
357  tags_.insert(list.begin(), list.end());
358  }
359 
360  void add_keys(const key_map& list)
361  {
362  keys_.insert(list.begin(), list.end());
363  }
364 
365  void add_links(const link_map& list)
366  {
367  links_.insert(list.begin(), list.end());
368  }
369 
370  void add_conditions(const condition_list& list);
371 
372  /** Expands all "super", storing direct references for easier access. */
373  void expand(wml_tag& root);
374 };
375 
376 /**
377  * Stores information about a conditional portion of a tag.
378  * Format is the same as wml_tag.
379  */
380 class wml_condition : public wml_tag {
382 public:
383  wml_condition(const config& info, const config& filter) : wml_tag(info), filter_(filter) {}
384  bool matches(const config& cfg) const;
385 };
386 }
const std::string & get_super() const
Definition: tag.hpp:172
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:90
void add_switch(const config &switch_cfg)
Definition: tag.cpp:390
wml_condition(const config &info, const config &filter)
Definition: tag.hpp:383
Stores information about tag.
Definition: tag.hpp:46
void add_filter(const config &cond_cfg)
Definition: tag.cpp:435
STL namespace.
bool operator<(const wml_tag &t) const
Definition: tag.hpp:248
void remove_keys_by_type(const std::string &type)
Removes all keys with this type.
Definition: tag.cpp:249
Definitions for the interface to Wesnoth Markup Language (WML).
bool is_fuzzy() const
Definition: tag.hpp:182
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:103
void set_min(int o)
Definition: tag.hpp:195
wml_tag(const std::string &name, int min, int max, const std::string &super="", bool any=false)
Definition: tag.hpp:125
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:278
bool equal(const iterator< T, Map > &other) const
Definition: tag.hpp:86
const std::string & get_name() const
Definition: key.hpp:58
Map::const_iterator current
Definition: tag.hpp:60
void set_fuzzy(bool f)
Definition: tag.hpp:213
bool accepts_any_tag() const
Definition: tag.hpp:186
void add_keys(const key_map &list)
Definition: tag.hpp:360
void set_max(int o)
Definition: tag.hpp:200
void add_link(const std::string &link)
Definition: tag.cpp:95
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:159
super_list super_refs_
super-tag references
Definition: tag.hpp:333
void set_super(const std::string &s)
Definition: tag.hpp:208
std::string path
Definition: game_config.cpp:39
void add_key(const wml_key &new_key)
Definition: tag.hpp:221
int get_min() const
Definition: tag.hpp:162
std::queue< const wml_tag * > condition_queue
Definition: tag.hpp:59
tag_map tags_
children tags
Definition: tag.hpp:321
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:380
void add_links(const link_map &list)
Definition: tag.hpp:365
std::string name_
name of tag.
Definition: tag.hpp:303
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:517
void add_tag(const wml_tag &new_tag)
Definition: tag.hpp:226
boost::iterator_range< tag_iterator > tags(const config &cfg_match) const
Definition: tag.hpp:273
std::map< std::string, wml_tag > tag_map
Definition: tag.hpp:49
condition_list conditions_
conditional partial matches
Definition: tag.hpp:330
void init(const wml_tag &base_tag)
Definition: tag.cpp:478
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:290
int min_
number of minimum occasions.
Definition: tag.hpp:306
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:74
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:327
static map_location::DIRECTION s
int max_
number of maximum occasions.
Definition: tag.hpp:309
bool any_tag_
whether this tag allows arbitrary subtags.
Definition: tag.hpp:339
int get_max() const
Definition: tag.hpp:167
void set_any_tag(bool any)
Definition: tag.hpp:217
void set_name(const std::string &name)
Definition: tag.hpp:190
void expand(wml_tag &root)
Expands all "super", storing direct references for easier access.
Definition: tag.cpp:374
void add_tags(const tag_map &list)
Definition: tag.hpp:355
wml_tag * find_tag(const std::string &fullpath, wml_tag &root, const config &match)
Definition: tag.hpp:350
void expand_all(wml_tag &root)
Calls the expansion on each child.
Definition: tag.cpp:237
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:157
void add_conditions(const condition_list &list)
Definition: tag.cpp:369
iterator< wml_tag > tag_iterator
Definition: tag.hpp:108
void remove_key_by_name(const std::string &name)
Definition: tag.hpp:293
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:318
static const char * match(MatchState *ms, const char *s, const char *p)
Definition: lstrlib.cpp:425
bool fuzzy_
whether this is a "fuzzy" tag.
Definition: tag.hpp:336
key_map keys_
keys
Definition: tag.hpp:324
const condition_list & conditions() const
Definition: tag.hpp:288
const link_map & links() const
Definition: tag.hpp:283
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
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:149
bool operator==(const wml_tag &other) const
Definition: tag.hpp:253
bool is_extension() const
Definition: tag.hpp:177