The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
tag.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2011 - 2025
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
34namespace schema_validation
35{
36
37class 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 */
48{
49public:
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*>;
55private:
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);
70 }
71 // Construct an end iterator
72 iterator() : match(config().child_or_empty("fsdfsdf")) {}
73 private:
75 void init(const wml_tag& base_tag);
77 void increment()
78 {
79 ++current;
81 }
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;
111public:
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
148 {
149 return min_children_;
150 }
151
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
191 {
192 min_children_ = o;
193 }
194
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
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
303private:
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. */
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 */
394class wml_condition : public wml_tag {
396public:
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
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
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:482
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:495
Stores information about tag.
Definition tag.hpp:48
void add_link(const std::string &link)
Definition tag.cpp:112
int get_min_children() const
Definition tag.hpp:147
void expand(wml_tag &root)
Expands all "super", storing direct references for easier access.
Definition tag.cpp:395
void set_super(const std::string &s)
Definition tag.hpp:206
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
const std::string & get_super() const
Definition tag.hpp:157
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:190
iterator< const wml_tag * > super_iterator
Definition tag.hpp:110
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
boost::iterator_range< key_iterator > keys(const config &cfg_match) const
Definition tag.hpp:276
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:452
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
boost::iterator_range< tag_iterator > tags(const config &cfg_match) const
Definition tag.hpp:271
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:180
void set_any_tag(bool any)
Definition tag.hpp:215
const condition_list & conditions() const
Definition tag.hpp:290
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:91
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
const std::string & get_name() const
Definition tag.hpp:132
wml_tag * find_tag(const std::string &fullpath, wml_tag &root, const config &match)
Definition tag.hpp:358
void add_conditions(const condition_list &list)
Definition tag.cpp:390
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:295
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
const link_map & links() const
Definition tag.hpp:285
bool accepts_any_tag() const
Definition tag.hpp:171
bool any_tag_
whether this tag allows arbitrary subtags.
Definition tag.hpp:347
bool is_fuzzy() const
Definition tag.hpp:167
void add_switch(const config &switch_cfg)
Definition tag.cpp:407
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:555
bool is_extension() const
Definition tag.hpp:162
condition_list conditions_
conditional partial matches
Definition tag.hpp:338
boost::iterator_range< super_iterator > super(const config &cfg_match) const
Definition tag.hpp:281
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:120
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:283
tag_map tags_
children tags
Definition tag.hpp:329
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:311
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).
const config * cfg
This file contains object "key", which is used to store information about keys while annotation parsi...
static map_location::direction s
#define f