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