The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
config.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
3 by David White <dave@whitevine.net>
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 * Definitions for the interface to Wesnoth Markup Language (WML).
19 *
20 * This module defines the interface to Wesnoth Markup Language (WML). WML is
21 * a simple hierarchical text-based file format. The format is defined in
22 * Wiki, under BuildingScenariosWML
23 *
24 * All configuration files are stored in this format, and data is sent across
25 * the network in this format. It is thus used extensively throughout the
26 * game.
27 */
28
29#pragma once
30
32#include "exceptions.hpp"
33#include "utils/const_clone.hpp"
35#include "utils/ranges.hpp"
36
37#include <functional>
38#include <iosfwd>
39#include <map>
40#include <memory>
41#include <string>
42#include <string_view>
43#include <utility>
44#include <vector>
45
46#include <boost/range/iterator_range.hpp>
47
48enum class DEP_LEVEL : uint8_t;
49
50class config;
51
52template<class T>
54{
55public:
57
59 : opt_(&ref)
60 {
61 }
62
63 optional_config_impl(utils::nullopt_t)
64 : opt_()
65 {
66 }
67
68 T& value() const
69 {
70 if(opt_) {
71 return *opt_;
72 } else {
73 // We're going to drop this codepath once we can use optional::value anyway, but just
74 // noting we want this function to ultimately throw utils::bad_optional_access.
75 throw std::runtime_error("Optional reference has no value");
76 }
77 }
78
80 {
81 opt_ = &new_ref;
82 return *this;
83 }
84
85 bool has_value() const
86 {
87#ifdef DEBUG_CONFIG
88 tested_ = true;
89#endif
90 return opt_ != nullptr;
91
92 }
93
94 explicit operator bool() const
95 {
96 return has_value();
97 }
98
103
104 /** Returns a pointer to the referenced object or nullptr if no reference is held. */
105 T* ptr() const
106 {
107 if(opt_) {
108 return &value();
109 } else {
110 return nullptr;
111 }
112 }
113
114 T* operator->() const
115 {
116 assert(tested());
117 return &value();
118 }
119
120 T& operator*() const
121 {
122 assert(tested());
123 return value();
124 }
125
127 {
128 assert(tested());
129 return value()[key];
130 }
131
136 bool tested() const
137 {
138#ifdef DEBUG_CONFIG
139 return tested_;
140#else
141 return true;
142#endif
143 }
144private:
146#ifdef DEBUG_CONFIG
147 mutable bool tested_;
148#endif
149};
150
151bool operator==(const config &, const config &);
152inline bool operator!=(const config &a, const config &b) { return !operator==(a, b); }
153std::ostream &operator << (std::ostream &, const config &);
154
155/** A config object defines a single node in a WML file, with access to child nodes. */
157{
158 friend bool operator==(const config& a, const config& b);
159public:
160 // Create an empty node.
161 config();
162
163 config(const config &);
164 config &operator=(const config &);
165
166 config(config &&) noexcept;
167 config &operator=(config &&) noexcept;
168
169 /**
170 * Creates a config object with an empty child of name @a child.
171 */
172 explicit config(std::string_view child);
173
174 /**
175 * Creates a config with several attributes and children.
176 * Pass the keys/tags and values/children alternately.
177 * For example: config("key", 42, "value", config())
178 */
179 template<typename... Args>
180 explicit config(std::string_view first, Args&&... args);
181
182 ~config();
183
184 // Verifies that the string can be used as a tag name
185 static bool valid_tag(std::string_view name);
186
187 // Verifies that the string can be used as an attribute name
188 static bool valid_attribute(std::string_view name);
189
190 typedef std::vector<std::unique_ptr<config>> child_list;
191 typedef std::map<std::string, child_list, std::less<>> child_map;
192
194
196 {
198 typedef std::random_access_iterator_tag iterator_category;
199 typedef config *pointer;
201 typedef child_list::iterator Itor;
202 typedef Itor::difference_type difference_type;
204 explicit child_iterator(const Itor &i): i_(i) {}
205
206 child_iterator &operator++() { ++i_; return *this; }
208 child_iterator &operator--() { --i_; return *this; }
210
211 reference operator*() const { return **i_; }
212 pointer operator->() const { return &**i_; }
213
214 bool operator==(const child_iterator &i) const { return i_ == i.i_; }
215 bool operator!=(const child_iterator &i) const { return i_ != i.i_; }
216 bool operator==(const const_child_iterator &i) const { return i == *this; }
217 bool operator!=(const const_child_iterator &i) const { return i != *this; }
218
219 friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
220 friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
221 friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
222 friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
223
224 this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
225 this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
226
227 config &operator[](Itor::difference_type n) const { return *i_[n]; }
228 friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
229 friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
230 friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
231 friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
232 private:
234 friend struct const_child_iterator;
235 };
236
238 {
239 typedef const config value_type;
240 typedef std::random_access_iterator_tag iterator_category;
241 typedef const config *pointer;
242 typedef const config &reference;
243 typedef child_list::const_iterator Itor;
244 typedef Itor::difference_type difference_type;
246 explicit const_child_iterator(const Itor &i): i_(i) {}
248
249 const_child_iterator &operator++() { ++i_; return *this; }
251 const_child_iterator &operator--() { --i_; return *this; }
253
254 reference operator*() const { return **i_; }
255 pointer operator->() const { return &**i_; }
256
257 bool operator==(const const_child_iterator &i) const { return i_ == i.i_; }
258 bool operator!=(const const_child_iterator &i) const { return i_ != i.i_; }
259 bool operator==(const child_iterator &i) const { return i_ == i.i_; }
260 bool operator!=(const child_iterator &i) const { return i_ != i.i_; }
261
262 friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
263 friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
264 friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
265 friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
266
267 this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
268 this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
269
270 const config &operator[](Itor::difference_type n) const { return *i_[n]; }
271 friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
272 friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
273 friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
274 friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
275
276 private:
278 };
279
280 typedef boost::iterator_range<child_iterator> child_itors;
281 typedef boost::iterator_range<const_child_iterator> const_child_itors;
282
283 /**
284 * Variant for storing WML attributes.
285 * The most efficient type is used when assigning a value. For instance,
286 * strings "yes", "no", "true", "false" will be detected and stored as boolean.
287 * @note The blank variant is only used when querying missing attributes.
288 * It is not stored in config objects.
289 */
291
292 typedef std::map<
293 std::string
295 , std::less<>
297 typedef attribute_map::value_type attribute;
299
301 {
303 typedef std::bidirectional_iterator_tag iterator_category;
306 typedef attribute_map::iterator Itor;
307 typedef Itor::difference_type difference_type;
308 explicit attribute_iterator(const Itor &i): i_(i) {}
309
310 attribute_iterator &operator++() { ++i_; return *this; }
312 attribute_iterator &operator--() { --i_; return *this; }
314
315 reference operator*() const { return *i_; }
316 pointer operator->() const { return &*i_; }
317
318 bool operator==(const attribute_iterator &i) const { return i_ == i.i_; }
319 bool operator!=(const attribute_iterator &i) const { return i_ != i.i_; }
320 bool operator==(const const_attribute_iterator &i) const { return i == *this; }
321 bool operator!=(const const_attribute_iterator &i) const { return i != *this; }
322
323 private:
326 };
327
329 {
330 typedef const attribute value_type;
331 typedef std::bidirectional_iterator_tag iterator_category;
332 typedef const attribute *pointer;
333 typedef const attribute &reference;
334 typedef attribute_map::const_iterator Itor;
335 typedef Itor::difference_type difference_type;
336 explicit const_attribute_iterator(const Itor &i): i_(i) {}
338
339 const_attribute_iterator &operator++() { ++i_; return *this; }
341
342 const_attribute_iterator &operator--() { --i_; return *this; }
344
345 reference operator*() const { return *i_; }
346 pointer operator->() const { return &*i_; }
347
348 bool operator==(const const_attribute_iterator &i) const { return i_ == i.i_; }
349 bool operator!=(const const_attribute_iterator &i) const { return i_ != i.i_; }
350 bool operator==(const attribute_iterator &i) const { return i_ == i.i_; }
351 bool operator!=(const attribute_iterator &i) const { return i_ != i.i_; }
352
353 private:
355 };
356
357 typedef boost::iterator_range<const_attribute_iterator> const_attr_itors;
358 typedef boost::iterator_range<attribute_iterator> attr_itors;
359
360 child_itors child_range(std::string_view key);
361 const_child_itors child_range(std::string_view key) const;
362 std::size_t child_count(std::string_view key) const;
363 std::size_t all_children_count() const;
364 /** Count the number of non-blank attributes */
365 std::size_t attribute_count() const;
366
367 /**
368 * Determine whether a config has a child or not.
369 *
370 * @param key The key of the child to find.
371 *
372 * @returns Whether a child is available.
373 */
374 bool has_child(std::string_view key) const;
375
376 /**
377 * Returns the first child with the given @a key, or an empty config if there is none.
378 */
379 const config & child_or_empty(std::string_view key) const;
380
381 /**
382 * Returns the nth child with the given @a key, or
383 * throws an error if there is none.
384 * @note A negative @a n accesses from the end of the object.
385 * For instance, -1 is the index of the last child.
386 */
387
388 config& mandatory_child(std::string_view key, int n = 0);
389 /**
390 * Returns the nth child with the given @a key, or
391 * throws an error if there is none.
392 * @note A negative @a n accesses from the end of the object.
393 * For instance, -1 is the index of the last child.
394 */
395 const config& mandatory_child(std::string_view key, int n = 0) const;
396
397 /** Equivalent to @ref mandatory_child, but returns an empty optional if the nth child was not found. */
398 optional_config_impl<config> optional_child(std::string_view key, int n = 0);
399
400 /** Equivalent to @ref mandatory_child, but returns an empty optional if the nth child was not found. */
401 optional_config_impl<const config> optional_child(std::string_view key, int n = 0) const;
402
403 /**
404 * Returns a mandatory child node.
405 *
406 * If the child is not found a @ref wml_exception is thrown.
407 *
408 * @pre parent[0] == '['
409 * @pre parent[parent.size() - 1] == ']'
410 *
411 * @param key The key of the child item to return.
412 * @param parent The section in which the child should reside.
413 * This is only used for error reporting.
414 *
415 * @returns The wanted child node.
416 */
417 config& mandatory_child(std::string_view key, const std::string& parent);
418
419 /**
420 * Returns a mandatory child node.
421 *
422 * If the child is not found a @ref wml_exception is thrown.
423 *
424 * @pre parent[0] == '['
425 * @pre parent[parent.size() - 1] == ']'
426 *
427 * @param key The key of the child item to return.
428 * @param parent The section in which the child should reside.
429 * This is only used for error reporting.
430 *
431 * @returns The wanted child node.
432 */
433 const config& mandatory_child(std::string_view key, const std::string& parent) const;
434
435 /**
436 * Get a deprecated child and log a deprecation message
437 * @param old_key The deprecated child to return if present
438 * @param in_tag The name of the tag this child appears in
439 * @param level The deprecation level
440 * @param message An explanation of the deprecation, possibly mentioning an alternative
441 * @note The deprecation message will be a level 3 deprecation.
442 */
443 optional_config_impl<const config> get_deprecated_child(std::string_view old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
444
445 /**
446 * Get a deprecated child range and log a deprecation message
447 * @param old_key The deprecated child to return if present
448 * @param in_tag The name of the tag this child appears in
449 * @param level The deprecation level
450 * @param message An explanation of the deprecation, possibly mentioning an alternative
451 * @note The deprecation message will be a level 3 deprecation.
452 */
453 const_child_itors get_deprecated_child_range(std::string_view old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
454
455 config& add_child(std::string_view key);
456 config& add_child(std::string_view key, const config& val);
457 /**
458 * @param key the tag name
459 * @param val the contents of the tag
460 * @param index is the index of the new child within all children of type key.
461 */
462 config& add_child_at(std::string_view key, const config &val, std::size_t index);
463
464 config &add_child(std::string_view key, config &&val);
465
466 /**
467 * Returns a reference to the attribute with the given @a key.
468 * Creates it if it does not exist.
469 */
470 attribute_value& operator[](std::string_view key);
471
472 /**
473 * Returns a reference to the attribute with the given @a key
474 * or to a dummy empty attribute if it does not exist.
475 */
476 const attribute_value& operator[](std::string_view key) const;
477
478 /**
479 * Returns a pointer to the attribute with the given @a key
480 * or nullptr if it does not exist.
481 */
482 const attribute_value *get(std::string_view key) const;
483
484 /**
485 * Chooses a value. If the value specified by @a key is
486 * blank, then @a default_key is chosen instead.
487 * If both values are blank or not set, then an empty value is returned.
488 */
489 const attribute_value& get_or(const std::string_view key, const std::string_view default_key) const;
490
491 /**
492 * Function to handle backward compatibility
493 * Get the value of key and if missing try old_key
494 * and log a deprecation message
495 * @param key The non-deprecated attribute to return
496 * @param old_key The deprecated attribute to return if @a key is missing
497 * @param in_tag The name of the tag these attributes appear in
498 * @param message An explanation of the deprecation, to be output if @a old_key is present.
499 * @note The deprecation message will be a level 1 deprecation.
500 */
501 const attribute_value &get_old_attribute(std::string_view key, const std::string &old_key, const std::string& in_tag, const std::string& message = "") const;
502
503 /**
504 * Get a deprecated attribute without a direct substitute,
505 * and log a deprecation message
506 * @param old_key The deprecated attribute to return if present
507 * @param in_tag The name of the tag this attribute appears in
508 * @param level The deprecation level
509 * @param message An explanation of the deprecation, possibly mentioning an alternative
510 */
511 const attribute_value& get_deprecated_attribute(std::string_view old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
512
513 /**
514 * Inserts an attribute into the config
515 * @param key The name of the attribute
516 * @param value The attribute value
517 */
518 template<typename T>
519 void insert(std::string_view key, T&& value)
520 {
521 operator[](key) = std::forward<T>(value);
522 }
523
524 /**
525 * Returns a reference to the first child with the given @a key.
526 * Creates the child if it does not yet exist.
527 */
528 config &child_or_add(std::string_view key);
529
530 bool has_attribute(std::string_view key) const;
531
532 void remove_attribute(std::string_view key);
533 void merge_attributes(const config &);
534
535 template<typename... T>
536 void remove_attributes(T... keys) { (remove_attribute(keys), ...); }
537
538 /**
539 * Copies attributes that exist in the source config.
540 *
541 * @param from Source config to copy attributes from.
542 * @param keys Attribute names.
543 */
544 template<typename... T>
545 void copy_attributes(const config& from, T... keys)
546 {
547 for(const auto& key : {keys...}) {
548 auto* attr = from.get(key);
549 if(attr) {
550 (*this)[key] = *attr;
551 }
552 }
553 }
554
555 /**
556 * Copies or deletes attributes to match the source config.
557 *
558 * Attributes that do not exist in the source are fully erased rather than
559 * set to the unspecified/default attribute value.
560 *
561 * @param from Source config to copy attributes from.
562 * @param keys Attribute names.
563 */
564 template<typename... T>
565 void copy_or_remove_attributes(const config& from, T... keys)
566 {
567 for(const auto& key : {keys...}) {
568 if(from.has_attribute(key)) {
569 (*this)[key] = from[key];
570 } else {
571 remove_attribute(key);
572 }
573 }
574 }
575
578
579 /**
580 * Returns the first child of tag @a key with a @a name attribute
581 * containing @a value.
582 */
583 optional_config_impl<config> find_child(std::string_view key, const std::string &name,
584 const std::string &value);
585
586 optional_config_impl<const config> find_child(std::string_view key, const std::string &name,
587 const std::string &value) const
588 { return const_cast<config *>(this)->find_child(key, name, value); }
589
590 config& find_mandatory_child(std::string_view key, const std::string &name,
591 const std::string &value);
592
593 const config& find_mandatory_child(std::string_view key, const std::string &name,
594 const std::string &value) const;
595
596private:
597 void clear_children_impl(std::string_view key);
598
599public:
600 template<typename... T>
601 void clear_children(T... keys) { (clear_children_impl(keys), ...); }
602
603 /**
604 * Moves all the children with tag @a key from @a src to this.
605 */
606 void splice_children(config& src, std::string_view key);
607
608 void remove_child(std::string_view key, std::size_t index);
609
610 /**
611 * Removes all children with tag @a key for which @a p returns true.
612 * If no predicate is provided, all @a key tags will be removed.
613 */
614 void remove_children(std::string_view key, const std::function<bool(const config&)>& p = {});
615
616 void recursive_clear_value(std::string_view key);
617
618 void clear();
619 void clear_all_children();
620 void clear_attributes();
621 bool empty() const;
622
623 std::string debug() const;
624 std::string hash() const;
625
626 struct error : public game::error {
627 error(const std::string& message) : game::error(message) {}
628 };
629
631 {
632 child_pos(child_map::iterator p, std::size_t i) : pos(p), index(i) {}
633 child_map::iterator pos;
634 std::size_t index;
635
636 bool operator==(const child_pos& o) const { return pos == o.pos && index == o.index; }
637 bool operator!=(const child_pos& o) const { return !operator==(o); }
638 };
639
641 {
642 const child_map::key_type &key;
644 any_child(const child_map::key_type *k, config *c): key(*k), cfg(*c) {}
645 };
646
647 struct const_all_children_iterator;
648
650 {
652 {
655 const any_child *operator->() const { return &data; }
656 };
657
659 typedef std::random_access_iterator_tag iterator_category;
662 typedef std::vector<child_pos>::iterator Itor;
663 typedef Itor::difference_type difference_type;
665 explicit all_children_iterator(const Itor &i): i_(i) {}
666
667 all_children_iterator &operator++() { ++i_; return *this; }
669 this_type &operator--() { --i_; return *this; }
670 this_type operator--(int) { return this_type(i_--); }
671
672 reference operator*() const;
673 pointer operator->() const { return *this; }
674
675 bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
676 bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
677 bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
678 bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
679
680 friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
681 friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
682 friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
683 friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
684
685 this_type& operator+=(difference_type n) { i_ += n; return *this; }
686 this_type& operator-=(difference_type n) { i_ -= n; return *this; }
687
688 reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
689 friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
690 friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
691 friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
692 friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
693
694 private:
696
697 friend class config;
699 };
700
702 {
704 {
707 const any_child *operator->() const { return &data; }
708 };
709
710 typedef const any_child value_type;
711 typedef std::random_access_iterator_tag iterator_category;
712 typedef const arrow_helper pointer;
713 typedef const any_child reference;
714 typedef std::vector<child_pos>::const_iterator Itor;
715 typedef Itor::difference_type difference_type;
717 explicit const_all_children_iterator(const Itor &i): i_(i) {}
719
722 this_type &operator--() { --i_; return *this; }
723 this_type operator--(int) { return this_type(i_--); }
724
725 reference operator*() const;
726 pointer operator->() const { return *this; }
727
728 bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
729 bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
730 bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
731 bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
732
733 friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
734 friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
735 friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
736 friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
737
738 this_type& operator+=(difference_type n) { i_ += n; return *this; }
739 this_type& operator-=(difference_type n) { i_ -= n; return *this; }
740
741 reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
742 friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
743 friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
744 friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
745 friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
746
747 private:
749
750 friend class config;
751 };
752
753 /**
754 * @param key the tag name
755 * @param val the contents of the tag
756 * @param pos is the index of the new child in _all_ children.
757 */
758 config& add_child_at_total(std::string_view key, const config &val, std::size_t pos);
759 std::size_t find_total_first_of(std::string_view key, std::size_t start = 0);
760
761 typedef boost::iterator_range<all_children_iterator> all_children_itors;
762 typedef boost::iterator_range<const_all_children_iterator> const_all_children_itors;
763
764 /** In-order iteration over all children. */
767
775
776private:
777 template<typename Res>
778 static auto any_tag_view(const child_pos& elem) -> std::pair<const child_map::key_type&, Res>
779 {
780 const auto& [key, list] = *elem.pos;
781 return { key, *list[elem.index] };
782 }
783
784public:
785#ifdef __cpp_explicit_this_parameter // C++23
786
787 /** In-order iteration over all children. */
788 template<typename Self>
789 auto all_children_view(this Self&& self)
790 { return self.ordered_children_ | std::views::transform(&config::any_tag_view<Self>); }
791
792#else
793
794 /** In-order iteration over all children. */
795 auto all_children_view() const
796 { return ordered_children_ | utils::views::transform(&config::any_tag_view<const config&>); }
797
798 /** In-order iteration over all children. */
800 { return ordered_children_ | utils::views::transform(&config::any_tag_view<config&>); }
801
802#endif // __cpp_explicit_this_parameter
803
804 /**
805 * A function to get the differences between this object,
806 * and 'c', as another config object.
807 * I.e. calling cfg2.apply_diff(cfg1.get_diff(cfg2))
808 * will make cfg2 identical to cfg1.
809 */
810 config get_diff(const config& c) const;
811 void get_diff(const config& c, config& res) const;
812
813 /**
814 * The name of the attribute used for tracking diff changes
815 */
816 static const char* diff_track_attribute;
817
818 /**
819 * A function to apply a diff config onto this config object.
820 *
821 * If the "track" parameter is true, the changes made will be marked in a
822 * magic attribute (defined above) of this and child nodes of this config,
823 * with "new" value indicating an added child, "modified" a modified one,
824 * and "deleted" for the deleted items, *which will not be actually
825 * deleted* (so calling code can easily see what they are).
826 * Use clear_diff_track with the same diff object to clear the tracking
827 * info and actually delete the nodes.
828 */
829 void apply_diff(const config& diff, bool track = false); //throw error
830
831 /**
832 * Clear any tracking info from a previous apply_diff call with tracking.
833 * This also removes the nodes that are to be deleted, in effect making
834 * apply_diff(c, true); clear_diff_tracking(c);
835 * equivalent to apply_diff(c, false);
836 */
837 void clear_diff_track(const config& diff);
838
839 /**
840 * Merge config 'c' into this config, overwriting this config's values.
841 */
842 void merge_with(const config& c);
843
844 /**
845 * Merge config 'c' into this config, preserving this config's values.
846 */
847 void inherit_from(const config& c);
848 /**
849 * Merge the attributes of config 'c' into this config, preserving this config's values.
850 */
851 void inherit_attributes(const config& c);
852
853 bool matches(const config &filter) const;
854
855 /**
856 * Append data from another config object to this one.
857 * Attributes in the latter config object will clobber attributes in this one.
858 */
859 void append(const config& cfg);
860 void append(config&& cfg);
861
862 /**
863 * Adds children from @a cfg.
864 */
865 void append_children(const config &cfg);
866
867 /**
868 * Adds children from @a cfg.
869 */
870 void append_children(const config &cfg, std::string_view key);
871
872 /** Moves children with the given name from the given config to this one. */
873 void append_children_by_move(config& cfg, std::string_view key);
874
875 /**
876 * Adds attributes from @a cfg.
877 */
878 void append_attributes(const config &cfg);
879
880 /**
881 * All children with the given key will be merged
882 * into the first element with that key.
883 */
884 void merge_children(std::string_view key);
885
886 /**
887 * All children with the given key and with equal values
888 * of the specified attribute will be merged into the
889 * element with that key and that value of the attribute
890 */
891 void merge_children_by_attribute(std::string_view key, std::string_view attribute);
892
893 //this is a cheap O(1) operation
894 void swap(config& cfg) noexcept;
895
896 /**
897 * Returns true if this object represents valid WML,
898 * i.e. can be saved to disk and again loaded by the WML parser.
899 */
900 bool validate_wml() const;
901
902 /** A non-owning view over all child tag names. */
903 auto child_name_view() const
904 {
906 }
907
908private:
909 /**
910 * Removes the child at position @a pos of @a l.
911 */
912 std::vector<child_pos>::iterator remove_child(const child_map::iterator &l, std::size_t pos);
913
914 /** All the attributes of this node. */
916
917 /** A list of all children of this node. */
919
920 std::vector<child_pos> ordered_children_;
921};
922
923
926/** Implement non-member swap function for std::swap (calls @ref config::swap). */
927void swap(config& lhs, config& rhs) noexcept;
928
929namespace detail
930{
931 template<typename Key, typename Value, typename... Rest>
932 inline void config_construct_unpack(config& cfg, Key&& key, Value&& val, Rest... fwd)
933 {
934 if constexpr(std::is_same_v<std::decay_t<Value>, config>) {
935 cfg.add_child(std::forward<Key>(key), std::forward<Value>(val));
936 } else {
937 cfg.insert(std::forward<Key>(key), std::forward<Value>(val));
938 }
939
940 if constexpr(sizeof...(Rest) > 0) {
941 config_construct_unpack(cfg, std::forward<Rest>(fwd)...);
942 }
943 }
944}
945
946template<typename... Args>
947inline config::config(std::string_view first, Args&&... args)
948{
949 detail::config_construct_unpack(*this, first, std::forward<Args>(args)...);
950}
Variant for storing WML attributes.
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
void remove_attribute(std::string_view key)
Definition config.cpp:162
void copy_or_remove_attributes(const config &from, T... keys)
Copies or deletes attributes to match the source config.
Definition config.hpp:565
static bool valid_tag(std::string_view name)
Definition config.cpp:129
optional_config_impl< const config > find_child(std::string_view key, const std::string &name, const std::string &value) const
Definition config.hpp:586
config & add_child(std::string_view key)
Definition config.cpp:436
void merge_children_by_attribute(std::string_view key, std::string_view attribute)
All children with the given key and with equal values of the specified attribute will be merged into ...
Definition config.cpp:250
void append(const config &cfg)
Append data from another config object to this one.
Definition config.cpp:188
void insert(std::string_view key, T &&value)
Inserts an attribute into the config.
Definition config.hpp:519
const attribute_value & get_or(const std::string_view key, const std::string_view default_key) const
Chooses a value.
Definition config.cpp:671
void remove_attributes(T... keys)
Definition config.hpp:536
all_children_iterator erase(const all_children_iterator &i)
Definition config.cpp:618
const_all_children_iterator ordered_begin() const
Definition config.cpp:838
void merge_children(std::string_view key)
All children with the given key will be merged into the first element with that key.
Definition config.cpp:235
static auto any_tag_view(const child_pos &elem) -> std::pair< const child_map::key_type &, Res >
Definition config.hpp:778
boost::iterator_range< const_all_children_iterator > const_all_children_itors
Definition config.hpp:762
std::size_t attribute_count() const
Count the number of non-blank attributes.
Definition config.cpp:307
void copy_attributes(const config &from, T... keys)
Copies attributes that exist in the source config.
Definition config.hpp:545
optional_config_impl< config > optional_child(std::string_view key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
Definition config.cpp:380
bool matches(const config &filter) const
Definition config.cpp:1168
const attribute_value & get_old_attribute(std::string_view key, const std::string &old_key, const std::string &in_tag, const std::string &message="") const
Function to handle backward compatibility Get the value of key and if missing try old_key and log a d...
Definition config.cpp:688
void append_children_by_move(config &cfg, std::string_view key)
Moves children with the given name from the given config to this one.
Definition config.cpp:224
void recursive_clear_value(std::string_view key)
Definition config.cpp:583
const_attr_itors attribute_range() const
Definition config.cpp:740
config_attribute_value attribute_value
Variant for storing WML attributes.
Definition config.hpp:290
attribute_map values_
All the attributes of this node.
Definition config.hpp:915
bool validate_wml() const
Returns true if this object represents valid WML, i.e.
Definition config.cpp:1292
config & child_or_add(std::string_view key)
Returns a reference to the first child with the given key.
Definition config.cpp:401
auto all_children_view() const
In-order iteration over all children.
Definition config.hpp:795
void merge_attributes(const config &)
Definition config.cpp:722
const_all_children_iterator ordered_end() const
Definition config.cpp:848
boost::iterator_range< child_iterator > child_itors
Definition config.hpp:280
config & find_mandatory_child(std::string_view key, const std::string &name, const std::string &value)
Definition config.cpp:784
std::vector< std::unique_ptr< config > > child_list
Definition config.hpp:190
const attribute_value & get_deprecated_attribute(std::string_view old_key, const std::string &in_tag, DEP_LEVEL level, const std::string &message) const
Get a deprecated attribute without a direct substitute, and log a deprecation message.
Definition config.cpp:710
child_itors child_range(std::string_view key)
Definition config.cpp:268
const attribute_value * get(std::string_view key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition config.cpp:665
boost::iterator_range< attribute_iterator > attr_itors
Definition config.hpp:358
const_all_children_iterator ordered_cbegin() const
Definition config.cpp:843
static bool valid_attribute(std::string_view name)
Definition config.cpp:152
void clear_children(T... keys)
Definition config.hpp:601
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
Definition config.cpp:1097
config & add_child_at_total(std::string_view key, const config &val, std::size_t pos)
Definition config.cpp:512
void swap(config &cfg) noexcept
Definition config.cpp:1280
std::map< std::string, child_list, std::less<> > child_map
Definition config.hpp:191
optional_config_impl< config > find_child(std::string_view key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition config.cpp:764
void clear_all_children()
Definition config.cpp:810
void inherit_from(const config &c)
Merge config 'c' into this config, preserving this config's values.
Definition config.cpp:1147
const_all_children_itors all_children_range() const
In-order iteration over all children.
Definition config.cpp:858
static const char * diff_track_attribute
The name of the attribute used for tracking diff changes.
Definition config.hpp:816
boost::iterator_range< all_children_iterator > all_children_itors
Definition config.hpp:761
void append_attributes(const config &cfg)
Adds attributes from cfg.
Definition config.cpp:174
boost::iterator_range< const_attribute_iterator > const_attr_itors
Definition config.hpp:357
void splice_children(config &src, std::string_view key)
Moves all the children with tag key from src to this.
Definition config.cpp:558
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
Definition config.cpp:1000
~config()
Definition config.cpp:99
std::size_t all_children_count() const
Definition config.cpp:302
child_map children_
A list of all children of this node.
Definition config.hpp:918
attribute_value & operator[](std::string_view key)
Returns a reference to the attribute with the given key.
Definition config.cpp:677
const_all_children_iterator ordered_cend() const
Definition config.cpp:853
bool has_attribute(std::string_view key) const
Definition config.cpp:157
config get_diff(const config &c) const
A function to get the differences between this object, and 'c', as another config object.
Definition config.cpp:884
config()
Definition config.cpp:76
std::string debug() const
Definition config.cpp:1214
std::vector< child_pos > ordered_children_
Definition config.hpp:920
attribute_map::value_type attribute
Definition config.hpp:297
void inherit_attributes(const config &c)
Merge the attributes of config 'c' into this config, preserving this config's values.
Definition config.cpp:1159
void remove_child(std::string_view key, std::size_t index)
Definition config.cpp:623
std::size_t child_count(std::string_view key) const
Definition config.cpp:292
optional_config_impl< const config > get_deprecated_child(std::string_view old_key, const std::string &in_tag, DEP_LEVEL level, const std::string &message) const
Get a deprecated child and log a deprecation message.
Definition config.cpp:411
auto child_name_view() const
A non-owning view over all child tag names.
Definition config.hpp:903
bool has_child(std::string_view key) const
Determine whether a config has a child or not.
Definition config.cpp:312
void clear_diff_track(const config &diff)
Clear any tracking info from a previous apply_diff call with tracking.
Definition config.cpp:1061
const config & child_or_empty(std::string_view key) const
Returns the first child with the given key, or an empty config if there is none.
Definition config.cpp:390
config & add_child_at(std::string_view key, const config &val, std::size_t index)
Definition config.cpp:465
std::map< std::string, attribute_value, std::less<> > attribute_map
Definition config.hpp:296
std::size_t find_total_first_of(std::string_view key, std::size_t start=0)
Definition config.cpp:498
boost::iterator_range< const_child_iterator > const_child_itors
Definition config.hpp:281
void append_children(const config &cfg)
Adds children from cfg.
Definition config.cpp:167
auto all_children_view()
In-order iteration over all children.
Definition config.hpp:799
void clear_attributes()
Definition config.cpp:817
bool empty() const
Definition config.cpp:823
config & mandatory_child(std::string_view key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
Definition config.cpp:362
void clear()
Definition config.cpp:802
void clear_children_impl(std::string_view key)
Definition config.cpp:548
std::string hash() const
Definition config.cpp:1227
friend bool operator==(const config &a, const config &b)
Definition config.cpp:1306
config & operator=(const config &)
Definition config.cpp:104
const_child_itors get_deprecated_child_range(std::string_view old_key, const std::string &in_tag, DEP_LEVEL level, const std::string &message) const
Get a deprecated child range and log a deprecation message.
Definition config.cpp:422
void remove_children(std::string_view key, const std::function< bool(const config &)> &p={})
Removes all children with tag key for which p returns true.
Definition config.cpp:634
optional_config_impl()=default
T & value() const
Definition config.hpp:68
optional_config_impl(utils::nullopt_t)
Definition config.hpp:63
optional_config_impl< T > & operator=(T &new_ref)
Definition config.hpp:79
T * operator->() const
Definition config.hpp:114
T * ptr() const
Returns a pointer to the referenced object or nullptr if no reference is held.
Definition config.hpp:105
T & operator*() const
Definition config.hpp:120
bool has_value() const
Definition config.hpp:85
optional_config_impl(T &ref)
Definition config.hpp:58
bool tested() const
Definition config.hpp:136
utils::const_clone_t< config_attribute_value, T > & operator[](std::string_view key)
Definition config.hpp:126
A simple wrapper class for optional reference types.
std::ostream & operator<<(std::ostream &, const config &)
Definition config.cpp:1221
void swap(config &lhs, config &rhs) noexcept
Implement non-member swap function for std::swap (calls config::swap).
Definition config.cpp:1287
bool operator!=(const config &a, const config &b)
Definition config.hpp:152
bool operator==(const config &, const config &)
Definition config.cpp:1306
Definitions for the interface to Wesnoth Markup Language (WML).
DEP_LEVEL
See https://wiki.wesnoth.org/CompatibilityStandards for more info.
const config * cfg
void config_construct_unpack(config &cfg, Key &&key, Value &&val, Rest... fwd)
Definition config.hpp:932
constexpr auto transform
Definition ranges.hpp:45
constexpr auto keys
Definition ranges.hpp:43
typename const_clone< D, S >::type const_clone_t
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
Definition sound.cpp:139
rect src
Non-transparent portion of the surface to compose.
const any_child * operator->() const
Definition config.hpp:655
arrow_helper(const all_children_iterator &i)
Definition config.hpp:654
friend difference_type operator-(const this_type &a, const this_type &b)
Definition config.hpp:689
all_children_iterator this_type
Definition config.hpp:664
this_type & operator-=(difference_type n)
Definition config.hpp:686
pointer operator->() const
Definition config.hpp:673
std::vector< child_pos >::iterator Itor
Definition config.hpp:662
this_type & operator+=(difference_type n)
Definition config.hpp:685
reference operator[](difference_type n) const
Definition config.hpp:688
reference operator*() const
Definition config.cpp:828
bool operator==(const all_children_iterator &i) const
Definition config.hpp:675
friend this_type operator-(const this_type &a, difference_type n)
Definition config.hpp:690
bool operator==(const const_all_children_iterator &i) const
Definition config.hpp:677
all_children_iterator & operator++()
Definition config.hpp:667
std::random_access_iterator_tag iterator_category
Definition config.hpp:659
friend bool operator>=(const this_type &a, const this_type &b)
Definition config.hpp:682
friend bool operator>(const this_type &a, const this_type &b)
Definition config.hpp:683
friend this_type operator+(const this_type &a, difference_type n)
Definition config.hpp:691
friend bool operator<=(const this_type &a, const this_type &b)
Definition config.hpp:681
friend bool operator<(const this_type &a, const this_type &b)
Definition config.hpp:680
bool operator!=(const all_children_iterator &i) const
Definition config.hpp:676
all_children_iterator(const Itor &i)
Definition config.hpp:665
bool operator!=(const const_all_children_iterator &i) const
Definition config.hpp:678
all_children_iterator operator++(int)
Definition config.hpp:668
friend this_type operator+(difference_type n, const this_type &a)
Definition config.hpp:692
Itor::difference_type difference_type
Definition config.hpp:663
any_child(const child_map::key_type *k, config *c)
Definition config.hpp:644
const child_map::key_type & key
Definition config.hpp:642
bool operator!=(const attribute_iterator &i) const
Definition config.hpp:319
attribute_iterator & operator--()
Definition config.hpp:312
attribute_iterator & operator++()
Definition config.hpp:310
attribute_iterator operator--(int)
Definition config.hpp:313
std::bidirectional_iterator_tag iterator_category
Definition config.hpp:303
bool operator==(const attribute_iterator &i) const
Definition config.hpp:318
bool operator!=(const const_attribute_iterator &i) const
Definition config.hpp:321
reference operator*() const
Definition config.hpp:315
Itor::difference_type difference_type
Definition config.hpp:307
pointer operator->() const
Definition config.hpp:316
bool operator==(const const_attribute_iterator &i) const
Definition config.hpp:320
attribute_map::iterator Itor
Definition config.hpp:306
attribute_iterator operator++(int)
Definition config.hpp:311
attribute_iterator(const Itor &i)
Definition config.hpp:308
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition config.hpp:228
std::random_access_iterator_tag iterator_category
Definition config.hpp:198
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition config.hpp:229
bool operator==(const const_child_iterator &i) const
Definition config.hpp:216
Itor::difference_type difference_type
Definition config.hpp:202
bool operator==(const child_iterator &i) const
Definition config.hpp:214
child_iterator & operator++()
Definition config.hpp:206
this_type & operator+=(Itor::difference_type n)
Definition config.hpp:224
child_list::iterator Itor
Definition config.hpp:201
child_iterator(const Itor &i)
Definition config.hpp:204
reference operator*() const
Definition config.hpp:211
bool operator!=(const const_child_iterator &i) const
Definition config.hpp:217
pointer operator->() const
Definition config.hpp:212
child_iterator & operator--()
Definition config.hpp:208
child_iterator operator--(int)
Definition config.hpp:209
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition config.hpp:231
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition config.hpp:230
child_iterator operator++(int)
Definition config.hpp:207
friend bool operator>=(const this_type &a, const this_type &b)
Definition config.hpp:221
friend bool operator>(const this_type &a, const this_type &b)
Definition config.hpp:222
bool operator!=(const child_iterator &i) const
Definition config.hpp:215
config & operator[](Itor::difference_type n) const
Definition config.hpp:227
this_type & operator-=(Itor::difference_type n)
Definition config.hpp:225
friend bool operator<=(const this_type &a, const this_type &b)
Definition config.hpp:220
friend bool operator<(const this_type &a, const this_type &b)
Definition config.hpp:219
child_iterator this_type
Definition config.hpp:203
bool operator==(const child_pos &o) const
Definition config.hpp:636
std::size_t index
Definition config.hpp:634
bool operator!=(const child_pos &o) const
Definition config.hpp:637
child_pos(child_map::iterator p, std::size_t i)
Definition config.hpp:632
child_map::iterator pos
Definition config.hpp:633
arrow_helper(const const_all_children_iterator &i)
Definition config.hpp:706
const_all_children_iterator this_type
Definition config.hpp:716
friend difference_type operator-(const this_type &a, const this_type &b)
Definition config.hpp:742
const_all_children_iterator(const all_children_iterator &i)
Definition config.hpp:718
const_all_children_iterator(const Itor &i)
Definition config.hpp:717
const_all_children_iterator operator++(int)
Definition config.hpp:721
this_type & operator+=(difference_type n)
Definition config.hpp:738
Itor::difference_type difference_type
Definition config.hpp:715
reference operator[](difference_type n) const
Definition config.hpp:741
std::vector< child_pos >::const_iterator Itor
Definition config.hpp:714
bool operator==(const const_all_children_iterator &i) const
Definition config.hpp:728
friend this_type operator-(const this_type &a, difference_type n)
Definition config.hpp:743
std::random_access_iterator_tag iterator_category
Definition config.hpp:711
bool operator!=(const const_all_children_iterator &i) const
Definition config.hpp:729
bool operator!=(const all_children_iterator &i) const
Definition config.hpp:731
bool operator==(const all_children_iterator &i) const
Definition config.hpp:730
friend bool operator>=(const this_type &a, const this_type &b)
Definition config.hpp:735
friend bool operator>(const this_type &a, const this_type &b)
Definition config.hpp:736
friend this_type operator+(const this_type &a, difference_type n)
Definition config.hpp:744
friend bool operator<=(const this_type &a, const this_type &b)
Definition config.hpp:734
friend bool operator<(const this_type &a, const this_type &b)
Definition config.hpp:733
this_type & operator-=(difference_type n)
Definition config.hpp:739
const_all_children_iterator & operator++()
Definition config.hpp:720
friend this_type operator+(difference_type n, const this_type &a)
Definition config.hpp:745
bool operator==(const attribute_iterator &i) const
Definition config.hpp:350
const_attribute_iterator operator--(int)
Definition config.hpp:343
const_attribute_iterator operator++(int)
Definition config.hpp:340
const_attribute_iterator & operator--()
Definition config.hpp:342
Itor::difference_type difference_type
Definition config.hpp:335
const attribute & reference
Definition config.hpp:333
const_attribute_iterator(const Itor &i)
Definition config.hpp:336
const_attribute_iterator(attribute_iterator &i)
Definition config.hpp:337
reference operator*() const
Definition config.hpp:345
attribute_map::const_iterator Itor
Definition config.hpp:334
std::bidirectional_iterator_tag iterator_category
Definition config.hpp:331
const_attribute_iterator & operator++()
Definition config.hpp:339
bool operator!=(const attribute_iterator &i) const
Definition config.hpp:351
bool operator!=(const const_attribute_iterator &i) const
Definition config.hpp:349
bool operator==(const const_attribute_iterator &i) const
Definition config.hpp:348
const config & operator[](Itor::difference_type n) const
Definition config.hpp:270
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition config.hpp:271
const_child_iterator(const Itor &i)
Definition config.hpp:246
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition config.hpp:272
bool operator==(const const_child_iterator &i) const
Definition config.hpp:257
std::random_access_iterator_tag iterator_category
Definition config.hpp:240
pointer operator->() const
Definition config.hpp:255
const_child_iterator operator++(int)
Definition config.hpp:250
const_child_iterator this_type
Definition config.hpp:245
bool operator==(const child_iterator &i) const
Definition config.hpp:259
const_child_iterator operator--(int)
Definition config.hpp:252
const_child_iterator & operator++()
Definition config.hpp:249
Itor::difference_type difference_type
Definition config.hpp:244
const_child_iterator(const child_iterator &i)
Definition config.hpp:247
this_type & operator-=(Itor::difference_type n)
Definition config.hpp:268
this_type & operator+=(Itor::difference_type n)
Definition config.hpp:267
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition config.hpp:274
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition config.hpp:273
bool operator!=(const child_iterator &i) const
Definition config.hpp:260
friend bool operator>=(const this_type &a, const this_type &b)
Definition config.hpp:264
friend bool operator>(const this_type &a, const this_type &b)
Definition config.hpp:265
reference operator*() const
Definition config.hpp:254
bool operator!=(const const_child_iterator &i) const
Definition config.hpp:258
friend bool operator<=(const this_type &a, const this_type &b)
Definition config.hpp:263
friend bool operator<(const this_type &a, const this_type &b)
Definition config.hpp:262
child_list::const_iterator Itor
Definition config.hpp:243
const_child_iterator & operator--()
Definition config.hpp:251
error(const std::string &message)
Definition config.hpp:627
Base class for all the errors encountered by the engine.
std::string message
mock_party p
static map_location::direction n
#define i
#define c
#define b