The Battle for Wesnoth  1.17.14+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  /**
528  * Copies attributes that exist in the source config.
529  *
530  * @param from Source config to copy attributes from.
531  * @param keys Attribute names.
532  */
533  template<typename... T>
534  void copy_attributes(const config& from, T... keys)
535  {
536  for(const auto& key : {keys...}) {
537  auto* attr = from.get(key);
538  if(attr) {
539  (*this)[key] = *attr;
540  }
541  }
542  }
543 
544  /**
545  * Copies or deletes attributes to match the source config.
546  *
547  * Attributes that do not exist in the source are fully erased rather than
548  * set to the unspecified/default attribute value.
549  *
550  * @param from Source config to copy attributes from.
551  * @param keys Attribute names.
552  */
553  template<typename... T>
554  void copy_or_remove_attributes(const config& from, T... keys)
555  {
556  for(const auto& key : {keys...}) {
557  if(from.has_attribute(key)) {
558  (*this)[key] = from[key];
559  } else {
560  remove_attribute(key);
561  }
562  }
563  }
564 
565  const_attr_itors attribute_range() const;
566  attr_itors attribute_range();
567 
568  /**
569  * Returns the first child of tag @a key with a @a name attribute
570  * containing @a value.
571  */
572  config& find_child(config_key_type key, const std::string &name,
573  const std::string &value);
574 
575  const config& find_child(config_key_type key, const std::string &name,
576  const std::string &value) const
577  { return const_cast<config *>(this)->find_child(key, name, value); }
578 
579 private:
581 public:
582  template<typename... T>
583  void clear_children(T... keys) {
584  for(auto key : {keys...}) {
585  clear_children_impl(key);
586  }
587  }
588 
589  /**
590  * Moves all the children with tag @a key from @a src to this.
591  */
592  void splice_children(config &src, const std::string &key);
593 
594  void remove_child(config_key_type key, unsigned index);
595  /**
596  * Removes all children with tag @a key for which @a p returns true.
597  */
598  void remove_children(config_key_type key, std::function<bool(const config&)> p = [](config){return true;});
600 
601  void clear();
602  void clear_all_children();
603  void clear_attributes();
604  bool empty() const;
605 
606  std::string debug() const;
607  std::string hash() const;
608 
609  struct error : public game::error {
610  error(const std::string& message) : game::error(message) {}
611  };
612 
613  struct child_pos
614  {
615  child_pos(child_map::iterator p, unsigned i) : pos(p), index(i) {}
617  unsigned index;
618 
619  bool operator==(const child_pos& o) const { return pos == o.pos && index == o.index; }
620  bool operator!=(const child_pos& o) const { return !operator==(o); }
621  };
622 
623  struct any_child
624  {
625  const child_map::key_type &key;
627  any_child(const child_map::key_type *k, config *c): key(*k), cfg(*c) {}
628  };
629 
631 
633  {
635  {
637  arrow_helper(const all_children_iterator &i): data(*i) {}
638  const any_child *operator->() const { return &data; }
639  };
640 
642  typedef std::random_access_iterator_tag iterator_category;
643  typedef int difference_type;
648  explicit all_children_iterator(const Itor &i): i_(i) {}
649 
650  all_children_iterator &operator++() { ++i_; return *this; }
652  this_type &operator--() { --i_; return *this; }
653  this_type operator--(int) { return this_type(i_--); }
654 
655  reference operator*() const;
656  pointer operator->() const { return *this; }
657 
658  bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
659  bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
660  bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
661  bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
662 
663  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
664  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
665  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
666  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
667 
668  this_type& operator+=(difference_type n) { i_ += n; return *this; }
669  this_type& operator-=(difference_type n) { i_ -= n; return *this; }
670 
671  reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
672  friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
673  friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
674  friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
675  friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
676 
677  private:
678  Itor i_;
679 
680  friend class config;
682  };
683 
685  {
687  {
690  const any_child *operator->() const { return &data; }
691  };
692 
693  typedef const any_child value_type;
694  typedef std::random_access_iterator_tag iterator_category;
695  typedef int difference_type;
696  typedef const arrow_helper pointer;
697  typedef const any_child reference;
698  typedef std::vector<child_pos>::const_iterator Itor;
700  explicit const_all_children_iterator(const Itor &i): i_(i) {}
702 
703  const_all_children_iterator &operator++() { ++i_; return *this; }
705  this_type &operator--() { --i_; return *this; }
706  this_type operator--(int) { return this_type(i_--); }
707 
708  reference operator*() const;
709  pointer operator->() const { return *this; }
710 
711  bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
712  bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
713  bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
714  bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
715 
716  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
717  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
718  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
719  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
720 
721  this_type& operator+=(difference_type n) { i_ += n; return *this; }
722  this_type& operator-=(difference_type n) { i_ -= n; return *this; }
723 
724  reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
725  friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
726  friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
727  friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
728  friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
729 
730  private:
731  Itor i_;
732 
733  friend class config;
734  };
735 
736  /**
737  * @param key the tag name
738  * @param val the contents of the tag
739  * @param pos is the index of the new child in _all_ children.
740  */
741  config& add_child_at_total(config_key_type key, const config &val, size_t pos);
742  size_t find_total_first_of(config_key_type key, size_t start = 0);
743 
744  typedef boost::iterator_range<all_children_iterator> all_children_itors;
745  typedef boost::iterator_range<const_all_children_iterator> const_all_children_itors;
746 
747  /** In-order iteration over all children. */
748  const_all_children_itors all_children_range() const;
749  all_children_itors all_children_range();
750 
758 
759  /**
760  * A function to get the differences between this object,
761  * and 'c', as another config object.
762  * I.e. calling cfg2.apply_diff(cfg1.get_diff(cfg2))
763  * will make cfg2 identical to cfg1.
764  */
765  config get_diff(const config& c) const;
766  void get_diff(const config& c, config& res) const;
767 
768  /**
769  * The name of the attribute used for tracking diff changes
770  */
771  static const char* diff_track_attribute;
772 
773  /**
774  * A function to apply a diff config onto this config object.
775  *
776  * If the "track" parameter is true, the changes made will be marked in a
777  * magic attribute (defined above) of this and child nodes of this config,
778  * with "new" value indicating an added child, "modified" a modified one,
779  * and "deleted" for the deleted items, *which will not be actually
780  * deleted* (so calling code can easily see what they are).
781  * Use clear_diff_track with the same diff object to clear the tracking
782  * info and actually delete the nodes.
783  */
784  void apply_diff(const config& diff, bool track = false); //throw error
785 
786  /**
787  * Clear any tracking info from a previous apply_diff call with tracking.
788  * This also removes the nodes that are to be deleted, in effect making
789  * apply_diff(c, true); clear_diff_tracking(c);
790  * equivalent to apply_diff(c, false);
791  */
792  void clear_diff_track(const config& diff);
793 
794  /**
795  * Merge config 'c' into this config, overwriting this config's values.
796  */
797  void merge_with(const config& c);
798 
799  /**
800  * Merge config 'c' into this config, preserving this config's values.
801  */
802  void inherit_from(const config& c);
803  /**
804  * Merge the attributes of config 'c' into this config, preserving this config's values.
805  */
806  void inherit_attributes(const config& c);
807 
808  bool matches(const config &filter) const;
809 
810  /**
811  * Append data from another config object to this one.
812  * Attributes in the latter config object will clobber attributes in this one.
813  */
814  void append(const config& cfg);
815  void append(config&& cfg);
816 
817  /**
818  * Adds children from @a cfg.
819  */
820  void append_children(const config &cfg);
821  void append_children(config&& cfg);
822 
823  /**
824  * Adds children from @a cfg.
825  */
826  void append_children(const config &cfg, const std::string& key);
827 
828  /** Moves children with the given name from the given config to this one. */
829  void append_children_by_move(config& cfg, const std::string& key);
830 
831  /**
832  * Adds attributes from @a cfg.
833  */
834  void append_attributes(const config &cfg);
835 
836  /**
837  * All children with the given key will be merged
838  * into the first element with that key.
839  */
840  void merge_children(const std::string& key);
841 
842  /**
843  * All children with the given key and with equal values
844  * of the specified attribute will be merged into the
845  * element with that key and that value of the attribute
846  */
847  void merge_children_by_attribute(const std::string& key, const std::string& attribute);
848 
849  //this is a cheap O(1) operation
850  void swap(config& cfg);
851 
852  /**
853  * Returns true if this object represents valid WML,
854  * i.e. can be saved to disk and again loaded by the WML parser.
855  */
856  bool validate_wml() const;
857 
858 private:
859  /**
860  * Removes the child at position @a pos of @a l.
861  */
863 
864  /** All the attributes of this node. */
866 
867  /** A list of all children of this node. */
868  child_map children_;
869 
870  std::vector<child_pos> ordered_children;
871 };
872 
873 /** Implement non-member swap function for std::swap (calls @ref config::swap). */
874 void swap(config& lhs, config& rhs);
875 
876 namespace detail {
877  template<typename... T>
879 
880  template<>
882  {
883  void visit(config&) {}
884  };
885 
886  template<typename K, typename V, typename... Rest>
887  struct config_construct_unpacker<K, V, Rest...>
888  {
889  template<typename K2 = K, typename V2 = V>
890  void visit(config& cfg, K2&& key, V2&& val, Rest... fwd)
891  {
892  cfg.insert(std::forward<K>(key), std::forward<V>(val));
893  config_construct_unpacker<Rest...> unpack;
894  unpack.visit(cfg, std::forward<Rest>(fwd)...);
895  }
896  };
897 
898  template<typename T, typename... Rest>
899  struct config_construct_unpacker<T, config, Rest...>
900  {
901  template<typename T2 = T, typename C = config>
902  void visit(config& cfg, T2&& tag, C&& child, Rest... fwd)
903  {
904  cfg.add_child(std::forward<T>(tag), std::forward<config>(child));
905  config_construct_unpacker<Rest...> unpack;
906  unpack.visit(cfg, std::forward<Rest>(fwd)...);
907  }
908  };
909 
910  template<typename T, typename... Rest>
911  struct config_construct_unpacker<T, config&, Rest...>
912  {
913  template<typename T2 = T>
914  void visit(config& cfg, T2&& tag, config& child, Rest... fwd)
915  {
916  cfg.add_child(std::forward<T>(tag), std::forward<config>(child));
917  config_construct_unpacker<Rest...> unpack;
918  unpack.visit(cfg, std::forward<Rest>(fwd)...);
919  }
920  };
921 }
922 
923 template<typename... T>
924 inline config::config(config_key_type first, T&&... args)
925 {
927  unpack.visit(*this, first, std::forward<T>(args)...);
928 }
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition: config.hpp:197
void copy_or_remove_attributes(const config &from, T... keys)
Copies or deletes attributes to match the source config.
Definition: config.hpp:554
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:646
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition: config.hpp:153
child_map::iterator pos
Definition: config.hpp:616
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:610
const_all_children_iterator operator++(int)
Definition: config.hpp:704
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:665
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:658
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:902
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:583
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:745
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:728
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:726
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:724
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:206
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:653
const_child_iterator operator++(int)
Definition: config.hpp:174
std::random_access_iterator_tag iterator_category
Definition: config.hpp:694
child_list::iterator Itor
Definition: config.hpp:126
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:666
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:699
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:660
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:673
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:914
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:722
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:642
all_children_iterator(const Itor &i)
Definition: config.hpp:648
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:675
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:689
bool operator==(const const_all_children_iterator &i) const
Definition: config.hpp:711
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:664
std::bidirectional_iterator_tag iterator_category
Definition: config.hpp:227
bool operator!=(const const_all_children_iterator &i) const
Definition: config.hpp:661
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:625
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:671
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:663
unsigned index
Definition: config.hpp:617
bool operator!=(const const_child_iterator &i) const
Definition: config.hpp:182
std::vector< child_pos > ordered_children
Definition: config.hpp:870
void visit(config &cfg, K2 &&key, V2 &&val, Rest... fwd)
Definition: config.hpp:890
config()
Definition: config.cpp:130
bool operator==(const all_children_iterator &i) const
Definition: config.hpp:713
this_type & operator+=(difference_type n)
Definition: config.hpp:668
bool operator==(const child_pos &o) const
Definition: config.hpp:619
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:638
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:656
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:714
all_children_iterator operator++(int)
Definition: config.hpp:651
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:727
const_all_children_iterator & operator++()
Definition: config.hpp:703
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:575
static config & get_invalid()
Definition: config.hpp:111
bool operator!=(const child_pos &o) const
Definition: config.hpp:620
std::size_t i
Definition: function.cpp:968
this_type & operator-=(difference_type n)
Definition: config.hpp:669
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:865
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:744
void copy_attributes(const config &from, T... keys)
Copies attributes that exist in the source config.
Definition: config.hpp:534
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:718
const attribute & reference
Definition: config.hpp:258
friend difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:725
child_pos(child_map::iterator p, unsigned i)
Definition: config.hpp:615
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:716
bool operator!=(const const_all_children_iterator &i) const
Definition: config.hpp:712
#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:659
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:627
void merge_attributes(const config &)
Definition: config.cpp:837
this_type & operator+=(difference_type n)
Definition: config.hpp:721
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:698
config & cfg
Definition: config.hpp:626
static const char * diff_track_attribute
The name of the attribute used for tracking diff changes.
Definition: config.hpp:771
attribute_iterator operator--(int)
Definition: config.hpp:237
arrow_helper(const all_children_iterator &i)
Definition: config.hpp:637
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:719
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:701
friend difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:672
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:700
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:717
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:674
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:868
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:650
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition: config.hpp:155
all_children_iterator this_type
Definition: config.hpp:647