The Battle for Wesnoth  1.17.5+dev
config.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2022
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"
34 
35 #include <climits>
36 #include <ctime>
37 #include <functional>
38 #include <iosfwd>
39 #include <iterator>
40 #include <map>
41 #include <memory>
42 #include <string>
43 #include <string_view>
44 #include <type_traits>
45 #include <utility>
46 #include <vector>
47 
48 #include <boost/range/iterator_range.hpp>
49 
50 using config_key_type = std::string_view;
51 enum class DEP_LEVEL : uint8_t;
52 
53 class config;
54 
55 bool operator==(const config &, const config &);
56 inline bool operator!=(const config &a, const config &b) { return !operator==(a, b); }
57 std::ostream &operator << (std::ostream &, const config &);
58 
59 /** A config object defines a single node in a WML file, with access to child nodes. */
60 class config
61 {
62  friend bool operator==(const config& a, const config& b);
63  friend struct config_implementation;
64 
65  static config invalid;
66 
67  /**
68  * Raises an exception if @a this is not valid.
69  */
70  void check_valid() const;
71 
72  /**
73  * Raises an exception if @a this or @a cfg is not valid.
74  */
75  void check_valid(const config &cfg) const;
76 
77 public:
78  // Create an empty node.
79  config();
80 
81  config(const config &);
82  config &operator=(const config &);
83 
84  config(config &&);
85  config &operator=(config &&);
86 
87  /**
88  * Creates a config object with an empty child of name @a child.
89  */
90  explicit config(config_key_type child);
91 
92  /**
93  * Creates a config with several attributes and children.
94  * Pass the keys/tags and values/children alternately.
95  * For example: config("key", 42, "value", config())
96  */
97  template<typename... T>
98  explicit config(config_key_type first, T&&... args);
99 
100  ~config();
101 
102  // Verifies that the string can be used as a tag name
103  static bool valid_tag(config_key_type name);
104 
105  // Verifies that the string can be used as an attribute name
106  static bool valid_attribute(config_key_type name);
107 
108  explicit operator bool() const
109  { return this != &invalid; }
110 
111  static config& get_invalid()
112  { return invalid; }
113 
114  typedef std::vector<std::unique_ptr<config>> child_list;
115  typedef std::map<std::string, child_list, std::less<>> child_map;
116 
117  struct const_child_iterator;
118 
120  {
122  typedef std::random_access_iterator_tag iterator_category;
123  typedef int difference_type;
124  typedef config *pointer;
125  typedef config &reference;
128  explicit child_iterator(const Itor &i): i_(i) {}
129 
130  child_iterator &operator++() { ++i_; return *this; }
131  child_iterator operator++(int) { return child_iterator(i_++); }
132  child_iterator &operator--() { --i_; return *this; }
133  child_iterator operator--(int) { return child_iterator(i_--); }
134 
135  reference operator*() const { return **i_; }
136  pointer operator->() const { return &**i_; }
137 
138  bool operator==(const child_iterator &i) const { return i_ == i.i_; }
139  bool operator!=(const child_iterator &i) const { return i_ != i.i_; }
140  bool operator==(const const_child_iterator &i) const { return i == *this; }
141  bool operator!=(const const_child_iterator &i) const { return i != *this; }
142 
143  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
144  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
145  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
146  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
147 
148  this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
149  this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
150 
151  config &operator[](Itor::difference_type n) const { return *i_[n]; }
152  friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
153  friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
154  friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
155  friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
156  private:
157  Itor i_;
158  friend struct const_child_iterator;
159  };
160 
162  {
163  typedef const config value_type;
164  typedef std::random_access_iterator_tag iterator_category;
165  typedef int difference_type;
166  typedef const config *pointer;
167  typedef const config &reference;
168  typedef child_list::const_iterator Itor;
170  explicit const_child_iterator(const Itor &i): i_(i) {}
171  const_child_iterator(const child_iterator &i): i_(i.i_) {}
172 
173  const_child_iterator &operator++() { ++i_; return *this; }
175  const_child_iterator &operator--() { --i_; return *this; }
177 
178  reference operator*() const { return **i_; }
179  pointer operator->() const { return &**i_; }
180 
181  bool operator==(const const_child_iterator &i) const { return i_ == i.i_; }
182  bool operator!=(const const_child_iterator &i) const { return i_ != i.i_; }
183  bool operator==(const child_iterator &i) const { return i_ == i.i_; }
184  bool operator!=(const child_iterator &i) const { return i_ != i.i_; }
185 
186  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
187  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
188  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
189  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
190 
191  this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
192  this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
193 
194  const config &operator[](Itor::difference_type n) const { return *i_[n]; }
195  friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
196  friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
197  friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
198  friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
199 
200  private:
201  Itor i_;
202  };
203 
204  typedef boost::iterator_range<child_iterator> child_itors;
205  typedef boost::iterator_range<const_child_iterator> const_child_itors;
206 
207  /**
208  * Variant for storing WML attributes.
209  * The most efficient type is used when assigning a value. For instance,
210  * strings "yes", "no", "true", "false" will be detected and stored as boolean.
211  * @note The blank variant is only used when querying missing attributes.
212  * It is not stored in config objects.
213  */
215 
216  typedef std::map<
217  std::string
219  , std::less<>
221  typedef attribute_map::value_type attribute;
223 
225  {
226  typedef attribute value_type;
227  typedef std::bidirectional_iterator_tag iterator_category;
228  typedef int difference_type;
229  typedef attribute *pointer;
230  typedef attribute &reference;
232  explicit attribute_iterator(const Itor &i): i_(i) {}
233 
234  attribute_iterator &operator++() { ++i_; return *this; }
236  attribute_iterator &operator--() { --i_; return *this; }
238 
239  reference operator*() const { return *i_; }
240  pointer operator->() const { return &*i_; }
241 
242  bool operator==(const attribute_iterator &i) const { return i_ == i.i_; }
243  bool operator!=(const attribute_iterator &i) const { return i_ != i.i_; }
244  bool operator==(const const_attribute_iterator &i) const { return i == *this; }
245  bool operator!=(const const_attribute_iterator &i) const { return i != *this; }
246 
247  private:
249  Itor i_;
250  };
251 
253  {
254  typedef const attribute value_type;
255  typedef std::bidirectional_iterator_tag iterator_category;
256  typedef int difference_type;
257  typedef const attribute *pointer;
258  typedef const attribute &reference;
259  typedef attribute_map::const_iterator Itor;
260  explicit const_attribute_iterator(const Itor &i): i_(i) {}
262 
263  const_attribute_iterator &operator++() { ++i_; return *this; }
265 
266  const_attribute_iterator &operator--() { --i_; return *this; }
268 
269  reference operator*() const { return *i_; }
270  pointer operator->() const { return &*i_; }
271 
272  bool operator==(const const_attribute_iterator &i) const { return i_ == i.i_; }
273  bool operator!=(const const_attribute_iterator &i) const { return i_ != i.i_; }
274  bool operator==(const attribute_iterator &i) const { return i_ == i.i_; }
275  bool operator!=(const attribute_iterator &i) const { return i_ != i.i_; }
276 
277  private:
278  Itor i_;
279  };
280 
281  typedef boost::iterator_range<const_attribute_iterator> const_attr_itors;
282  typedef boost::iterator_range<attribute_iterator> attr_itors;
283 
284  child_itors child_range(config_key_type key);
285  const_child_itors child_range(config_key_type key) const;
286  unsigned child_count(config_key_type key) const;
287  unsigned all_children_count() const;
288  /** Count the number of non-blank attributes */
289  unsigned attribute_count() const;
290 
291  /**
292  * Determine whether a config has a child or not.
293  *
294  * @param key The key of the child to find.
295  *
296  * @returns Whether a child is available.
297  */
298  bool has_child(config_key_type key) const;
299 
300  /**
301  * Returns the first child with the given @a key, or an empty config if there is none.
302  */
303  const config & child_or_empty(config_key_type key) const;
304 
305  /**
306  * An object of this type will cause the following functions to throw a config::error instead
307  * of returning a reference to the invalid config for the duration of its lfetime. If multiple
308  * instances exist simultaneously, this behavior will persist until all objects are destroyed.
309  *
310  * - @c child
311  * - @c find_child
312  */
314  {
315  public:
316  friend class config;
317 
319  {
320  instances++;
321  }
322 
324  {
325  instances--;
326  }
327 
328  static bool do_throw()
329  {
330  return instances > 0;
331  }
332 
333  private:
334  static inline unsigned instances = 0;
335  };
336 
337  /**
338  * Returns the nth child with the given @a key, or
339  * a reference to an invalid config if there is none.
340  * @note A negative @a n accesses from the end of the object.
341  * For instance, -1 is the index of the last child.
342  */
343  config& child(config_key_type key, int n = 0);
344 
345  /**
346  * Returns the nth child with the given @a key, or
347  * a reference to an invalid config if there is none.
348  * @note A negative @a n accesses from the end of the object.
349  * For instance, -1 is the index of the last child.
350  */
351  const config& child(config_key_type key, int n = 0) const
352  { return const_cast<config*>(this)->child(key, n); }
353 
354  /** Euivalent to @ref child, but returns an empty optional if the nth child was not found. */
356 
357  /** Euivalent to @ref child, but returns an empty optional if the nth child was not found. */
359 
360  /**
361  * Returns a mandatory child node.
362  *
363  * If the child is not found a @ref wml_exception is thrown.
364  *
365  * @pre parent[0] == '['
366  * @pre parent[parent.size() - 1] == ']'
367  *
368  * @param key The key of the child item to return.
369  * @param parent The section in which the child should reside.
370  * This is only used for error reporting.
371  *
372  * @returns The wanted child node.
373  */
374  config& child(config_key_type key, const std::string& parent);
375 
376  /**
377  * Returns a mandatory child node.
378  *
379  * If the child is not found a @ref wml_exception is thrown.
380  *
381  * @pre parent[0] == '['
382  * @pre parent[parent.size() - 1] == ']'
383  *
384  * @param key The key of the child item to return.
385  * @param parent The section in which the child should reside.
386  * This is only used for error reporting.
387  *
388  * @returns The wanted child node.
389  */
390  const config& child(config_key_type key, const std::string& parent) const;
391 
392  /**
393  * Get a deprecated child and log a deprecation message
394  * @param old_key The deprecated child to return if present
395  * @param in_tag The name of the tag this child appears in
396  * @param level The deprecation level
397  * @param message An explanation of the deprecation, possibly mentioning an alternative
398  * @note The deprecation message will be a level 3 deprecation.
399  */
400  utils::optional_reference<const config> get_deprecated_child(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
401 
402  /**
403  * Get a deprecated child rangw and log a deprecation message
404  * @param old_key The deprecated child to return if present
405  * @param in_tag The name of the tag this child appears in
406  * @param level The deprecation level
407  * @param message An explanation of the deprecation, possibly mentioning an alternative
408  * @note The deprecation message will be a level 3 deprecation.
409  */
410  const_child_itors get_deprecated_child_range(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
411 
413  config& add_child(config_key_type key, const config& val);
414  /**
415  * @param key the tag name
416  * @param val the contents of the tag
417  * @param index is the index of the new child within all children of type key.
418  */
419  config& add_child_at(config_key_type key, const config &val, unsigned index);
420 
421  config &add_child(config_key_type key, config &&val);
422 
423  /**
424  * Returns a reference to the attribute with the given @a key.
425  * Creates it if it does not exist.
426  */
427  attribute_value& operator[](config_key_type key);
428 
429  /**
430  * Returns a reference to the attribute with the given @a key
431  * or to a dummy empty attribute if it does not exist.
432  */
433  const attribute_value& operator[](config_key_type key) const;
434 
435  /**
436  * Returns a reference to the attribute with the given @a key.
437  * Creates it if it does not exist.
438  */
439  attribute_value& operator[](const std::string& key)
440  {
441  return operator[](config_key_type(key));
442  }
443 
444  /**
445  * Returns a reference to the attribute with the given @a key
446  * or to a dummy empty attribute if it does not exist.
447  */
448  const attribute_value& operator[](const std::string& key) const
449  {
450  return operator[](config_key_type(key));
451  }
452 
453  /**
454  * Returns a reference to the attribute with the given @a key.
455  * Creates it if it does not exist.
456  */
457  attribute_value& operator[](const char* key)
458  {
459  return operator[](config_key_type(key));
460  }
461 
462  /**
463  * Returns a reference to the attribute with the given @a key
464  * or to a dummy empty attribute if it does not exist.
465  */
466  const attribute_value& operator[](const char* key) const
467  {
468  return operator[](config_key_type(key));
469  }
470 
471  /**
472  * Returns a pointer to the attribute with the given @a key
473  * or nullptr if it does not exist.
474  */
475  const attribute_value *get(config_key_type key) const;
476 
477  /**
478  * Function to handle backward compatibility
479  * Get the value of key and if missing try old_key
480  * and log a deprecation message
481  * @param key The non-deprecated attribute to return
482  * @param old_key The deprecated attribute to return if @a key is missing
483  * @param in_tag The name of the tag these attributes appear in
484  * @param message An explanation of the deprecation, to be output if @a old_key is present.
485  * @note The deprecation message will be a level 1 deprecation.
486  */
487  const attribute_value &get_old_attribute(config_key_type key, const std::string &old_key, const std::string& in_tag, const std::string& message = "") const;
488 
489  /**
490  * Get a deprecated attribute without a direct substitute,
491  * and log a deprecation message
492  * @param old_key The deprecated attribute to return if present
493  * @param in_tag The name of the tag this attribute appears in
494  * @param level The deprecation level
495  * @param message An explanation of the deprecation, possibly mentioning an alternative
496  */
497  const attribute_value& get_deprecated_attribute(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
498 
499  /**
500  * Inserts an attribute into the config
501  * @param key The name of the attribute
502  * @param value The attribute value
503  */
504  template<typename T>
505  void insert(config_key_type key, T&& value)
506  {
507  operator[](key) = std::forward<T>(value);
508  }
509 
510  /**
511  * Returns a reference to the first child with the given @a key.
512  * Creates the child if it does not yet exist.
513  */
515 
516  bool has_attribute(config_key_type key) const;
517 
519  void merge_attributes(const config &);
520  template<typename... T>
521  void remove_attributes(T... keys) {
522  for(const auto& key : {keys...}) {
523  remove_attribute(key);
524  }
525  }
526 
527  template<typename... T>
528  void copy_attributes(const config& from, T... keys)
529  {
530  for(const auto& key : {keys...}) {
531  auto* attr = from.get(key);
532  if(attr) {
533  (*this)[key] = *attr;
534  }
535  }
536  }
537 
538  const_attr_itors attribute_range() const;
539  attr_itors attribute_range();
540 
541  /**
542  * Returns the first child of tag @a key with a @a name attribute
543  * containing @a value.
544  */
545  config& find_child(config_key_type key, const std::string &name,
546  const std::string &value);
547 
548  const config& find_child(config_key_type key, const std::string &name,
549  const std::string &value) const
550  { return const_cast<config *>(this)->find_child(key, name, value); }
551 
552 private:
554 public:
555  template<typename... T>
556  void clear_children(T... keys) {
557  for(auto key : {keys...}) {
558  clear_children_impl(key);
559  }
560  }
561 
562  /**
563  * Moves all the children with tag @a key from @a src to this.
564  */
565  void splice_children(config &src, const std::string &key);
566 
567  void remove_child(config_key_type key, unsigned index);
568  /**
569  * Removes all children with tag @a key for which @a p returns true.
570  */
571  void remove_children(config_key_type key, std::function<bool(const config&)> p = [](config){return true;});
573 
574  void clear();
575  void clear_all_children();
576  void clear_attributes();
577  bool empty() const;
578 
579  std::string debug() const;
580  std::string hash() const;
581 
582  struct error : public game::error {
583  error(const std::string& message) : game::error(message) {}
584  };
585 
586  struct child_pos
587  {
588  child_pos(child_map::iterator p, unsigned i) : pos(p), index(i) {}
590  unsigned index;
591 
592  bool operator==(const child_pos& o) const { return pos == o.pos && index == o.index; }
593  bool operator!=(const child_pos& o) const { return !operator==(o); }
594  };
595 
596  struct any_child
597  {
598  const child_map::key_type &key;
600  any_child(const child_map::key_type *k, config *c): key(*k), cfg(*c) {}
601  };
602 
604 
606  {
608  {
610  arrow_helper(const all_children_iterator &i): data(*i) {}
611  const any_child *operator->() const { return &data; }
612  };
613 
615  typedef std::random_access_iterator_tag iterator_category;
616  typedef int difference_type;
621  explicit all_children_iterator(const Itor &i): i_(i) {}
622 
623  all_children_iterator &operator++() { ++i_; return *this; }
625  this_type &operator--() { --i_; return *this; }
626  this_type operator--(int) { return this_type(i_--); }
627 
628  reference operator*() const;
629  pointer operator->() const { return *this; }
630 
631  bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
632  bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
633  bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
634  bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
635 
636  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
637  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
638  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
639  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
640 
641  this_type& operator+=(difference_type n) { i_ += n; return *this; }
642  this_type& operator-=(difference_type n) { i_ -= n; return *this; }
643 
644  reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
645  friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
646  friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
647  friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
648  friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
649 
650  private:
651  Itor i_;
652 
653  friend class config;
655  };
656 
658  {
660  {
663  const any_child *operator->() const { return &data; }
664  };
665 
666  typedef const any_child value_type;
667  typedef std::random_access_iterator_tag iterator_category;
668  typedef int difference_type;
669  typedef const arrow_helper pointer;
670  typedef const any_child reference;
671  typedef std::vector<child_pos>::const_iterator Itor;
673  explicit const_all_children_iterator(const Itor &i): i_(i) {}
675 
676  const_all_children_iterator &operator++() { ++i_; return *this; }
678  this_type &operator--() { --i_; return *this; }
679  this_type operator--(int) { return this_type(i_--); }
680 
681  reference operator*() const;
682  pointer operator->() const { return *this; }
683 
684  bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
685  bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
686  bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
687  bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
688 
689  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
690  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
691  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
692  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
693 
694  this_type& operator+=(difference_type n) { i_ += n; return *this; }
695  this_type& operator-=(difference_type n) { i_ -= n; return *this; }
696 
697  reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
698  friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
699  friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
700  friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
701  friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
702 
703  private:
704  Itor i_;
705 
706  friend class config;
707  };
708 
709  /**
710  * @param key the tag name
711  * @param val the contents of the tag
712  * @param pos is the index of the new child in _all_ children.
713  */
714  config& add_child_at_total(config_key_type key, const config &val, size_t pos);
715  size_t find_total_first_of(config_key_type key, size_t start = 0);
716 
717  typedef boost::iterator_range<all_children_iterator> all_children_itors;
718  typedef boost::iterator_range<const_all_children_iterator> const_all_children_itors;
719 
720  /** In-order iteration over all children. */
721  const_all_children_itors all_children_range() const;
722  all_children_itors all_children_range();
723 
731 
732  /**
733  * A function to get the differences between this object,
734  * and 'c', as another config object.
735  * I.e. calling cfg2.apply_diff(cfg1.get_diff(cfg2))
736  * will make cfg2 identical to cfg1.
737  */
738  config get_diff(const config& c) const;
739  void get_diff(const config& c, config& res) const;
740 
741  /**
742  * The name of the attribute used for tracking diff changes
743  */
744  static const char* diff_track_attribute;
745 
746  /**
747  * A function to apply a diff config onto this config object.
748  *
749  * If the "track" parameter is true, the changes made will be marked in a
750  * magic attribute (defined above) of this and child nodes of this config,
751  * with "new" value indicating an added child, "modified" a modified one,
752  * and "deleted" for the deleted items, *which will not be actually
753  * deleted* (so calling code can easily see what they are).
754  * Use clear_diff_track with the same diff object to clear the tracking
755  * info and actually delete the nodes.
756  */
757  void apply_diff(const config& diff, bool track = false); //throw error
758 
759  /**
760  * Clear any tracking info from a previous apply_diff call with tracking.
761  * This also removes the nodes that are to be deleted, in effect making
762  * apply_diff(c, true); clear_diff_tracking(c);
763  * equivalent to apply_diff(c, false);
764  */
765  void clear_diff_track(const config& diff);
766 
767  /**
768  * Merge config 'c' into this config, overwriting this config's values.
769  */
770  void merge_with(const config& c);
771 
772  /**
773  * Merge config 'c' into this config, preserving this config's values.
774  */
775  void inherit_from(const config& c);
776  /**
777  * Merge the attributes of config 'c' into this config, preserving this config's values.
778  */
779  void inherit_attributes(const config& c);
780 
781  bool matches(const config &filter) const;
782 
783  /**
784  * Append data from another config object to this one.
785  * Attributes in the latter config object will clobber attributes in this one.
786  */
787  void append(const config& cfg);
788  void append(config&& cfg);
789 
790  /**
791  * Adds children from @a cfg.
792  */
793  void append_children(const config &cfg);
794  void append_children(config&& cfg);
795 
796  /**
797  * Adds children from @a cfg.
798  */
799  void append_children(const config &cfg, const std::string& key);
800 
801  /** Moves children with the given name from the given config to this one. */
802  void append_children_by_move(config& cfg, const std::string& key);
803 
804  /**
805  * Adds attributes from @a cfg.
806  */
807  void append_attributes(const config &cfg);
808 
809  /**
810  * All children with the given key will be merged
811  * into the first element with that key.
812  */
813  void merge_children(const std::string& key);
814 
815  /**
816  * All children with the given key and with equal values
817  * of the specified attribute will be merged into the
818  * element with that key and that value of the attribute
819  */
820  void merge_children_by_attribute(const std::string& key, const std::string& attribute);
821 
822  //this is a cheap O(1) operation
823  void swap(config& cfg);
824 
825  /**
826  * Returns true if this object represents valid WML,
827  * i.e. can be saved to disk and again loaded by the WML parser.
828  */
829  bool validate_wml() const;
830 
831 private:
832  /**
833  * Removes the child at position @a pos of @a l.
834  */
836 
837  /** All the attributes of this node. */
839 
840  /** A list of all children of this node. */
841  child_map children_;
842 
843  std::vector<child_pos> ordered_children;
844 };
845 
846 /** Implement non-member swap function for std::swap (calls @ref config::swap). */
847 void swap(config& lhs, config& rhs);
848 
849 namespace detail {
850  template<typename... T>
852 
853  template<>
855  {
856  void visit(config&) {}
857  };
858 
859  template<typename K, typename V, typename... Rest>
860  struct config_construct_unpacker<K, V, Rest...>
861  {
862  template<typename K2 = K, typename V2 = V>
863  void visit(config& cfg, K2&& key, V2&& val, Rest... fwd)
864  {
865  cfg.insert(std::forward<K>(key), std::forward<V>(val));
866  config_construct_unpacker<Rest...> unpack;
867  unpack.visit(cfg, std::forward<Rest>(fwd)...);
868  }
869  };
870 
871  template<typename T, typename... Rest>
872  struct config_construct_unpacker<T, config, Rest...>
873  {
874  template<typename T2 = T, typename C = config>
875  void visit(config& cfg, T2&& tag, C&& child, Rest... fwd)
876  {
877  cfg.add_child(std::forward<T>(tag), std::forward<config>(child));
878  config_construct_unpacker<Rest...> unpack;
879  unpack.visit(cfg, std::forward<Rest>(fwd)...);
880  }
881  };
882 
883  template<typename T, typename... Rest>
884  struct config_construct_unpacker<T, config&, Rest...>
885  {
886  template<typename T2 = T>
887  void visit(config& cfg, T2&& tag, config& child, Rest... fwd)
888  {
889  cfg.add_child(std::forward<T>(tag), std::forward<config>(child));
890  config_construct_unpacker<Rest...> unpack;
891  unpack.visit(cfg, std::forward<Rest>(fwd)...);
892  }
893  };
894 }
895 
896 template<typename... T>
897 inline config::config(config_key_type first, T&&... args)
898 {
900  unpack.visit(*this, first, std::forward<T>(args)...);
901 }
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition: config.hpp:197
reference operator*() const
Definition: config.hpp:135
std::bidirectional_iterator_tag iterator_category
Definition: config.hpp:255
std::vector< child_pos >::iterator Itor
Definition: config.hpp:619
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition: config.hpp:153
child_map::iterator pos
Definition: config.hpp:589
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:402
const_child_iterator & operator--()
Definition: config.hpp:175
bool matches(const config &filter) const
Definition: config.cpp:1299
An object of this type will cause the following functions to throw a config::error instead of returni...
Definition: config.hpp:313
error(const std::string &message)
Definition: config.hpp:583
const_all_children_iterator operator++(int)
Definition: config.hpp:677
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:638
attribute_iterator & operator++()
Definition: config.hpp:234
const_all_children_iterator ordered_cbegin() const
Definition: config.cpp:963
const_all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:978
bool operator==(const const_child_iterator &i) const
Definition: config.hpp:140
bool operator==(const all_children_iterator &i) const
Definition: config.hpp:631
void append_attributes(const config &cfg)
Adds attributes from cfg.
Definition: config.cpp:252
void visit(config &cfg, T2 &&tag, C &&child, Rest... fwd)
Definition: config.hpp:875
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:187
reference operator*() const
Definition: config.hpp:239
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:189
void clear_children(T... keys)
Definition: config.hpp:556
void recursive_clear_value(config_key_type key)
Definition: config.cpp:690
bool operator==(const config &, const config &)
Definition: config.cpp:1475
const attribute_value & operator[](const std::string &key) const
Returns a reference to the attribute with the given key or to a dummy empty attribute if it does not ...
Definition: config.hpp:448
const_child_iterator(const Itor &i)
Definition: config.hpp:170
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:269
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:152
void append_children_by_move(config &cfg, const std::string &key)
Moves children with the given name from the given config to this one.
Definition: config.cpp:294
boost::iterator_range< const_all_children_iterator > const_all_children_itors
Definition: config.hpp:718
config & find_child(config_key_type 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:885
const_attribute_iterator operator--(int)
Definition: config.hpp:267
Variant for storing WML attributes.
attribute_iterator & operator--()
Definition: config.hpp:236
friend this_type operator+(difference_type n, const this_type &a)
Definition: config.hpp:701
bool operator!=(const attribute_iterator &i) const
Definition: config.hpp:275
friend this_type operator-(const this_type &a, difference_type n)
Definition: config.hpp:699
std::map< std::string, child_list, std::less<> > child_map
Definition: config.hpp:115
void merge_children(const std::string &key)
All children with the given key will be merged into the first element with that key.
Definition: config.cpp:307
bool has_attribute(config_key_type key) const
Definition: config.cpp:211
#define a
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:146
bool operator!=(const child_iterator &i) const
Definition: config.hpp:139
attribute_iterator operator++(int)
Definition: config.hpp:235
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:144
attribute_value & operator[](const std::string &key)
Returns a reference to the attribute with the given key.
Definition: config.hpp:439
config & add_child_at_total(config_key_type key, const config &val, size_t pos)
Definition: config.cpp:594
friend bool operator==(const config &a, const config &b)
Definition: config.cpp:1475
void remove_attributes(T... keys)
Definition: config.hpp:521
reference operator[](difference_type n) const
Definition: config.hpp:697
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition: config.hpp:154
attribute_map::value_type attribute
Definition: config.hpp:221
config & operator[](Itor::difference_type n) const
Definition: config.hpp:151
child_iterator(const Itor &i)
Definition: config.hpp:128
std::string_view data
Definition: picture.cpp:208
void clear(const std::string &key)
Definition: general.cpp:190
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition: config.cpp:780
this_type operator--(int)
Definition: config.hpp:626
const_child_iterator operator++(int)
Definition: config.hpp:174
std::random_access_iterator_tag iterator_category
Definition: config.hpp:667
child_list::iterator Itor
Definition: config.hpp:126
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:639
size_t find_total_first_of(config_key_type key, size_t start=0)
Definition: config.cpp:580
const_all_children_iterator this_type
Definition: config.hpp:672
const attribute_value & get_old_attribute(config_key_type 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:800
const config * pointer
Definition: config.hpp:166
void insert(config_key_type key, T &&value)
Inserts an attribute into the config.
Definition: config.hpp:505
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition: config.hpp:198
const attribute_value & operator[](const char *key) const
Returns a reference to the attribute with the given key or to a dummy empty attribute if it does not ...
Definition: config.hpp:466
config & child_or_add(config_key_type key)
Returns a reference to the first child with the given key.
Definition: config.cpp:478
DEP_LEVEL
See https://wiki.wesnoth.org/CompatibilityStandards for more info.
Definition: deprecation.hpp:21
attribute_map::const_iterator Itor
Definition: config.hpp:259
void append_children(const config &cfg)
Adds children from cfg.
Definition: config.cpp:223
bool operator==(const const_all_children_iterator &i) const
Definition: config.hpp:633
void clear_diff_track(const config &diff)
Clear any tracking info from a previous apply_diff call with tracking.
Definition: config.cpp:1188
const config & reference
Definition: config.hpp:167
friend this_type operator-(const this_type &a, difference_type n)
Definition: config.hpp:646
void remove_attribute(config_key_type key)
Definition: config.cpp:217
bool operator==(const child_iterator &i) const
Definition: config.hpp:138
const_attribute_iterator & operator++()
Definition: config.hpp:263
const_attr_itors attribute_range() const
Definition: config.cpp:858
void visit(config &cfg, T2 &&tag, config &child, Rest... fwd)
Definition: config.hpp:887
bool operator!=(const attribute_iterator &i) const
Definition: config.hpp:243
child_iterator this_type
Definition: config.hpp:127
std::string_view config_key_type
Definition: config.hpp:50
const_attribute_iterator(const Itor &i)
Definition: config.hpp:260
bool operator!=(const const_attribute_iterator &i) const
Definition: config.hpp:245
this_type & operator-=(difference_type n)
Definition: config.hpp:695
config get_diff(const config &c) const
A function to get the differences between this object, and &#39;c&#39;, as another config object...
Definition: config.cpp:1004
#define b
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:145
void merge_with(const config &c)
Merge config &#39;c&#39; into this config, overwriting this config&#39;s values.
Definition: config.cpp:1224
void inherit_from(const config &c)
Merge config &#39;c&#39; into this config, preserving this config&#39;s values.
Definition: config.cpp:1277
child_list::const_iterator Itor
Definition: config.hpp:168
this_type & operator-=(Itor::difference_type n)
Definition: config.hpp:149
bool operator!=(const const_child_iterator &i) const
Definition: config.hpp:141
static config invalid
Definition: config.hpp:65
const_all_children_iterator ordered_end() const
Definition: config.cpp:968
Definitions for the interface to Wesnoth Markup Language (WML).
std::random_access_iterator_tag iterator_category
Definition: config.hpp:615
all_children_iterator(const Itor &i)
Definition: config.hpp:621
const_child_iterator(const child_iterator &i)
Definition: config.hpp:171
child_iterator & operator++()
Definition: config.hpp:130
bool operator==(const child_iterator &i) const
Definition: config.hpp:183
friend this_type operator+(difference_type n, const this_type &a)
Definition: config.hpp:648
pointer operator->() const
Definition: config.hpp:136
void splice_children(config &src, const std::string &key)
Moves all the children with tag key from src to this.
Definition: config.cpp:664
const_attribute_iterator(attribute_iterator &i)
Definition: config.hpp:261
this_type & operator+=(Itor::difference_type n)
Definition: config.hpp:191
void clear_children_impl(config_key_type key)
Definition: config.cpp:649
bool operator==(const attribute_iterator &i) const
Definition: config.hpp:274
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:30
arrow_helper(const const_all_children_iterator &i)
Definition: config.hpp:662
bool operator==(const const_all_children_iterator &i) const
Definition: config.hpp:684
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:637
std::bidirectional_iterator_tag iterator_category
Definition: config.hpp:227
bool operator!=(const const_all_children_iterator &i) const
Definition: config.hpp:634
child_iterator & operator--()
Definition: config.hpp:132
const_child_iterator this_type
Definition: config.hpp:169
bool operator==(const const_attribute_iterator &i) const
Definition: config.hpp:244
config & add_child_at(config_key_type key, const config &val, unsigned index)
Definition: config.cpp:546
pointer operator->() const
Definition: config.hpp:240
const child_map::key_type & key
Definition: config.hpp:598
bool validate_wml() const
Returns true if this object represents valid WML, i.e.
Definition: config.cpp:1461
bool operator!=(const child_iterator &i) const
Definition: config.hpp:184
reference operator[](difference_type n) const
Definition: config.hpp:644
this_type & operator-=(Itor::difference_type n)
Definition: config.hpp:192
const_child_iterator & operator++()
Definition: config.hpp:173
void erase(const std::string &key)
Definition: general.cpp:205
bool operator==(const attribute_iterator &i) const
Definition: config.hpp:242
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:636
unsigned index
Definition: config.hpp:590
bool operator!=(const const_child_iterator &i) const
Definition: config.hpp:182
std::vector< child_pos > ordered_children
Definition: config.hpp:843
void visit(config &cfg, K2 &&key, V2 &&val, Rest... fwd)
Definition: config.hpp:863
config()
Definition: config.cpp:130
bool operator==(const all_children_iterator &i) const
Definition: config.hpp:686
this_type & operator+=(difference_type n)
Definition: config.hpp:641
bool operator==(const child_pos &o) const
Definition: config.hpp:592
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:195
const any_child * operator->() const
Definition: config.hpp:611
utils::optional_reference< config > optional_child(config_key_type key, int n=0)
Euivalent to child, but returns an empty optional if the nth child was not found. ...
Definition: config.cpp:445
boost::iterator_range< const_attribute_iterator > const_attr_itors
Definition: config.hpp:281
const_attribute_iterator operator++(int)
Definition: config.hpp:264
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
Definition: config.cpp:1125
pointer operator->() const
Definition: config.hpp:629
std::map< std::string, attribute_value, std::less<> > attribute_map
Definition: config.hpp:220
bool operator!=(const all_children_iterator &i) const
Definition: config.hpp:687
all_children_iterator operator++(int)
Definition: config.hpp:624
attribute_value & operator[](const char *key)
Returns a reference to the attribute with the given key.
Definition: config.hpp:457
void inherit_attributes(const config &c)
Merge the attributes of config &#39;c&#39; into this config, preserving this config&#39;s values.
Definition: config.cpp:1289
boost::iterator_range< const_child_iterator > const_child_itors
Definition: config.hpp:205
friend this_type operator+(const this_type &a, difference_type n)
Definition: config.hpp:700
const_all_children_iterator & operator++()
Definition: config.hpp:676
attribute_value & operator[](config_key_type key)
Returns a reference to the attribute with the given key.
Definition: config.cpp:787
const config & find_child(config_key_type key, const std::string &name, const std::string &value) const
Definition: config.hpp:548
static config & get_invalid()
Definition: config.hpp:111
bool operator!=(const child_pos &o) const
Definition: config.hpp:593
std::size_t i
Definition: function.cpp:967
this_type & operator-=(difference_type n)
Definition: config.hpp:642
reference operator*() const
Definition: config.hpp:178
this_type & operator+=(Itor::difference_type n)
Definition: config.hpp:148
attribute_map values_
All the attributes of this node.
Definition: config.hpp:838
utils::optional_reference< const config > get_deprecated_child(config_key_type 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:488
mock_party p
child_iterator operator--(int)
Definition: config.hpp:133
bool operator==(const const_child_iterator &i) const
Definition: config.hpp:181
boost::iterator_range< attribute_iterator > attr_itors
Definition: config.hpp:282
boost::iterator_range< all_children_iterator > all_children_itors
Definition: config.hpp:717
void copy_attributes(const config &from, T... keys)
Definition: config.hpp:528
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:691
const attribute & reference
Definition: config.hpp:258
friend difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:698
child_pos(child_map::iterator p, unsigned i)
Definition: config.hpp:588
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition: config.hpp:196
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:689
bool operator!=(const const_all_children_iterator &i) const
Definition: config.hpp:685
#define debug(x)
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:72
std::vector< std::unique_ptr< config > > child_list
Definition: config.hpp:114
bool operator!=(const all_children_iterator &i) const
Definition: config.hpp:632
const config & child(config_key_type key, int n=0) const
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.hpp:351
config & add_child(config_key_type key)
Definition: config.cpp:514
any_child(const child_map::key_type *k, config *c)
Definition: config.hpp:600
void merge_attributes(const config &)
Definition: config.cpp:837
this_type & operator+=(difference_type n)
Definition: config.hpp:694
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
Definition: config.cpp:1456
const_all_children_iterator ordered_begin() const
Definition: config.cpp:958
const config & operator[](Itor::difference_type n) const
Definition: config.hpp:194
std::vector< child_pos >::const_iterator Itor
Definition: config.hpp:671
config & cfg
Definition: config.hpp:599
static const char * diff_track_attribute
The name of the attribute used for tracking diff changes.
Definition: config.hpp:744
attribute_iterator operator--(int)
Definition: config.hpp:237
arrow_helper(const all_children_iterator &i)
Definition: config.hpp:610
const_child_itors get_deprecated_child_range(config_key_type old_key, const std::string &in_tag, DEP_LEVEL level, const std::string &message) const
Get a deprecated child rangw and log a deprecation message.
Definition: config.cpp:500
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:692
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:28
void clear_all_children()
Definition: config.cpp:928
boost::iterator_range< child_iterator > child_itors
Definition: config.hpp:204
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:143
const_all_children_iterator(const all_children_iterator &i)
Definition: config.hpp:674
friend difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:645
reference operator*() const
Definition: config.hpp:269
std::random_access_iterator_tag iterator_category
Definition: config.hpp:164
const_child_iterator operator--(int)
Definition: config.hpp:176
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:188
const attribute * pointer
Definition: config.hpp:257
void remove_children(config_key_type key, std::function< bool(const config &)> p=[](config){return true;})
Removes all children with tag key for which p returns true.
Definition: config.cpp:745
pointer operator->() const
Definition: config.hpp:179
void clear_attributes()
Definition: config.cpp:935
const_all_children_iterator(const Itor &i)
Definition: config.hpp:673
child_iterator operator++(int)
Definition: config.hpp:131
std::random_access_iterator_tag iterator_category
Definition: config.hpp:122
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:690
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
mock_char c
std::ostream & operator<<(std::ostream &, const config &)
Definition: config.cpp:1356
const attribute_value & get_deprecated_attribute(config_key_type 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:824
static map_location::DIRECTION n
attribute_iterator(const Itor &i)
Definition: config.hpp:232
void remove_child(config_key_type key, unsigned index)
Definition: config.cpp:732
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:186
friend this_type operator+(const this_type &a, difference_type n)
Definition: config.hpp:647
std::string hash() const
Definition: config.cpp:1392
const_all_children_iterator ordered_cend() const
Definition: config.cpp:973
bool operator==(const const_attribute_iterator &i) const
Definition: config.hpp:272
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
bool empty() const
Definition: config.cpp:941
child_map children_
A list of all children of this node.
Definition: config.hpp:841
A simple wrapper class for optional reference types.
static utils::const_clone_ref< config, T > child(T config, config_key_type key, const std::string &parent)
Implementation for the wrappers for [const] config& child(const std::string& key, const std::string& ...
Definition: config.cpp:83
attribute_map::iterator Itor
Definition: config.hpp:231
const_attribute_iterator & operator--()
Definition: config.hpp:266
void merge_children_by_attribute(const std::string &key, const std::string &attribute)
All children with the given key and with equal values of the specified attribute will be merged into ...
Definition: config.cpp:324
bool operator!=(const const_attribute_iterator &i) const
Definition: config.hpp:273
all_children_iterator & operator++()
Definition: config.hpp:623
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition: config.hpp:155
all_children_iterator this_type
Definition: config.hpp:620