The Battle for Wesnoth  1.15.9+dev
config.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Definitions for the interface to Wesnoth Markup Language (WML).
18  *
19  * This module defines the interface to Wesnoth Markup Language (WML). WML is
20  * a simple hierarchical text-based file format. The format is defined in
21  * Wiki, under BuildingScenariosWML
22  *
23  * All configuration files are stored in this format, and data is sent across
24  * the network in this format. It is thus used extensively throughout the
25  * game.
26  */
27 
28 #pragma once
29 
31 #include "exceptions.hpp"
32 
33 #include <climits>
34 #include <ctime>
35 #include <functional>
36 #include <iosfwd>
37 #include <iterator>
38 #include <map>
39 #include <memory>
40 #include <string>
41 #include <string_view>
42 #include <type_traits>
43 #include <utility>
44 #include <vector>
45 
46 #include <boost/range/iterator_range.hpp>
47 
48 using config_key_type = std::string_view;
49 
50 class config;
51 class enum_tag;
52 
53 bool operator==(const config &, const config &);
54 inline bool operator!=(const config &a, const config &b) { return !operator==(a, b); }
55 std::ostream &operator << (std::ostream &, const config &);
56 
57 /** A config object defines a single node in a WML file, with access to child nodes. */
58 class config
59 {
60  friend bool operator==(const config& a, const config& b);
61  friend struct config_implementation;
62 
63  static config invalid;
64 
65  /**
66  * Raises an exception if @a this is not valid.
67  */
68  void check_valid() const;
69 
70  /**
71  * Raises an exception if @a this or @a cfg is not valid.
72  */
73  void check_valid(const config &cfg) const;
74 
75 public:
76  // Create an empty node.
77  config();
78 
79  config(const config &);
80  config &operator=(const config &);
81 
82  config(config &&);
83  config &operator=(config &&);
84 
85  /**
86  * Creates a config object with an empty child of name @a child.
87  */
88  explicit config(config_key_type child);
89 
90  /**
91  * Creates a config with several attributes and children.
92  * Pass the keys/tags and values/children alternately.
93  * For example: config("key", 42, "value", config())
94  */
95  template<typename... T>
96  explicit config(config_key_type first, T&&... args);
97 
98  ~config();
99 
100  // Verifies that the string can be used as a tag name
101  static bool valid_tag(config_key_type name);
102 
103  // Verifies that the string can be used as an attribute name
104  static bool valid_attribute(config_key_type name);
105 
106  explicit operator bool() const
107  { return this != &invalid; }
108 
109  static config& get_invalid()
110  { return invalid; }
111 
112  typedef std::vector<std::unique_ptr<config>> child_list;
113  typedef std::map<std::string, child_list, std::less<>> child_map;
114 
115  struct const_child_iterator;
116 
118  {
120  typedef std::random_access_iterator_tag iterator_category;
121  typedef int difference_type;
122  typedef config *pointer;
123  typedef config &reference;
126  explicit child_iterator(const Itor &i): i_(i) {}
127 
128  child_iterator &operator++() { ++i_; return *this; }
130  child_iterator &operator--() { --i_; return *this; }
132 
133  reference operator*() const { return **i_; }
134  pointer operator->() const { return &**i_; }
135 
136  bool operator==(const child_iterator &i) const { return i_ == i.i_; }
137  bool operator!=(const child_iterator &i) const { return i_ != i.i_; }
138  bool operator==(const const_child_iterator &i) const { return i == *this; }
139  bool operator!=(const const_child_iterator &i) const { return i != *this; }
140 
141  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
142  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
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 
146  this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
147  this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
148 
149  config &operator[](Itor::difference_type n) const { return *i_[n]; }
150  friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
151  friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
152  friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
153  friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
154  private:
155  Itor i_;
156  friend struct const_child_iterator;
157  };
158 
160  {
161  typedef const config value_type;
162  typedef std::random_access_iterator_tag iterator_category;
163  typedef int difference_type;
164  typedef const config *pointer;
165  typedef const config &reference;
166  typedef child_list::const_iterator Itor;
168  explicit const_child_iterator(const Itor &i): i_(i) {}
170 
171  const_child_iterator &operator++() { ++i_; return *this; }
173  const_child_iterator &operator--() { --i_; return *this; }
175 
176  reference operator*() const { return **i_; }
177  pointer operator->() const { return &**i_; }
178 
179  bool operator==(const const_child_iterator &i) const { return i_ == i.i_; }
180  bool operator!=(const const_child_iterator &i) const { return i_ != i.i_; }
181  bool operator==(const child_iterator &i) const { return i_ == i.i_; }
182  bool operator!=(const child_iterator &i) const { return i_ != i.i_; }
183 
184  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
185  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
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 
189  this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
190  this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
191 
192  const config &operator[](Itor::difference_type n) const { return *i_[n]; }
193  friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
194  friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
195  friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
196  friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
197 
198  private:
199  Itor i_;
200  };
201 
202  typedef boost::iterator_range<child_iterator> child_itors;
203  typedef boost::iterator_range<const_child_iterator> const_child_itors;
204 
205  /**
206  * Variant for storing WML attributes.
207  * The most efficient type is used when assigning a value. For instance,
208  * strings "yes", "no", "true", "false" will be detected and stored as boolean.
209  * @note The blank variant is only used when querying missing attributes.
210  * It is not stored in config objects.
211  */
213 
214  typedef std::map<
215  std::string
217  , std::less<>
219  typedef attribute_map::value_type attribute;
221 
223  {
224  typedef attribute value_type;
225  typedef std::bidirectional_iterator_tag iterator_category;
226  typedef int difference_type;
227  typedef attribute *pointer;
228  typedef attribute &reference;
230  explicit attribute_iterator(const Itor &i): i_(i) {}
231 
232  attribute_iterator &operator++() { ++i_; return *this; }
234  attribute_iterator &operator--() { --i_; return *this; }
236 
237  reference operator*() const { return *i_; }
238  pointer operator->() const { return &*i_; }
239 
240  bool operator==(const attribute_iterator &i) const { return i_ == i.i_; }
241  bool operator!=(const attribute_iterator &i) const { return i_ != i.i_; }
242  bool operator==(const const_attribute_iterator &i) const { return i == *this; }
243  bool operator!=(const const_attribute_iterator &i) const { return i != *this; }
244 
245  private:
247  Itor i_;
248  };
249 
251  {
252  typedef const attribute value_type;
253  typedef std::bidirectional_iterator_tag iterator_category;
254  typedef int difference_type;
255  typedef const attribute *pointer;
256  typedef const attribute &reference;
257  typedef attribute_map::const_iterator Itor;
258  explicit const_attribute_iterator(const Itor &i): i_(i) {}
260 
261  const_attribute_iterator &operator++() { ++i_; return *this; }
263 
264  const_attribute_iterator &operator--() { --i_; return *this; }
266 
267  reference operator*() const { return *i_; }
268  pointer operator->() const { return &*i_; }
269 
270  bool operator==(const const_attribute_iterator &i) const { return i_ == i.i_; }
271  bool operator!=(const const_attribute_iterator &i) const { return i_ != i.i_; }
272  bool operator==(const attribute_iterator &i) const { return i_ == i.i_; }
273  bool operator!=(const attribute_iterator &i) const { return i_ != i.i_; }
274 
275  private:
276  Itor i_;
277  };
278 
279  typedef boost::iterator_range<const_attribute_iterator> const_attr_itors;
280  typedef boost::iterator_range<attribute_iterator> attr_itors;
281 
282  child_itors child_range(config_key_type key);
283  const_child_itors child_range(config_key_type key) const;
284  unsigned child_count(config_key_type key) const;
285  unsigned all_children_count() const;
286  /** Count the number of non-blank attributes */
287  unsigned attribute_count() const;
288 
289  /**
290  * Determine whether a config has a child or not.
291  *
292  * @param key The key of the child to find.
293  *
294  * @returns Whether a child is available.
295  */
296  bool has_child(config_key_type key) const;
297 
298  /**
299  * Returns the first child with the given @a key, or an empty config if there is none.
300  */
301  const config & child_or_empty(config_key_type key) const;
302 
303  /**
304  * Returns the nth child with the given @a key, or
305  * a reference to an invalid config if there is none.
306  * @note A negative @a n accesses from the end of the object.
307  * For instance, -1 is the index of the last child.
308  */
309  config &child(config_key_type key, int n = 0);
310 
311  /**
312  * Returns the nth child with the given @a key, or
313  * a reference to an invalid config if there is none.
314  * @note A negative @a n accesses from the end of the object.
315  * For instance, -1 is the index of the last child.
316  */
317  const config& child(config_key_type key, int n = 0) const
318  { return const_cast<config *>(this)->child(key, n); }
319  /**
320  * Returns a mandatory child node.
321  *
322  * If the child is not found a @ref wml_exception is thrown.
323  *
324  * @pre parent[0] == '['
325  * @pre parent[parent.size() - 1] == ']'
326  *
327  * @param key The key of the child item to return.
328  * @param parent The section in which the child should reside.
329  * This is only used for error reporting.
330  *
331  * @returns The wanted child node.
332  */
333  config& child(config_key_type key, const std::string& parent);
334 
335  /**
336  * Returns a mandatory child node.
337  *
338  * If the child is not found a @ref wml_exception is thrown.
339  *
340  * @pre parent[0] == '['
341  * @pre parent[parent.size() - 1] == ']'
342  *
343  * @param key The key of the child item to return.
344  * @param parent The section in which the child should reside.
345  * This is only used for error reporting.
346  *
347  * @returns The wanted child node.
348  */
349  const config& child(
350  config_key_type key
351  , const std::string& parent) const;
352 
354  config& add_child(config_key_type key, const config& val);
355  /**
356  * @param key the tag name
357  * @param val the contents of the tag
358  * @param index is the index of the new child within all children of type key.
359  */
360  config& add_child_at(config_key_type key, const config &val, unsigned index);
361 
362  config &add_child(config_key_type key, config &&val);
363 
364  /**
365  * Returns a reference to the attribute with the given @a key.
366  * Creates it if it does not exist.
367  */
368  attribute_value& operator[](config_key_type key);
369 
370  /**
371  * Returns a reference to the attribute with the given @a key
372  * or to a dummy empty attribute if it does not exist.
373  */
374  const attribute_value& operator[](config_key_type key) const;
375 
376  /**
377  * Returns a reference to the attribute with the given @a key.
378  * Creates it if it does not exist.
379  */
380  attribute_value& operator[](const std::string& key)
381  {
382  return operator[](config_key_type(key));
383  }
384 
385  /**
386  * Returns a reference to the attribute with the given @a key
387  * or to a dummy empty attribute if it does not exist.
388  */
389  const attribute_value& operator[](const std::string& key) const
390  {
391  return operator[](config_key_type(key));
392  }
393 
394  /**
395  * Returns a reference to the attribute with the given @a key.
396  * Creates it if it does not exist.
397  */
398  attribute_value& operator[](const char* key)
399  {
400  return operator[](config_key_type(key));
401  }
402 
403  /**
404  * Returns a reference to the attribute with the given @a key
405  * or to a dummy empty attribute if it does not exist.
406  */
407  const attribute_value& operator[](const char* key) const
408  {
409  return operator[](config_key_type(key));
410  }
411 
412  /**
413  * Returns a pointer to the attribute with the given @a key
414  * or nullptr if it does not exist.
415  */
416  const attribute_value *get(config_key_type key) const;
417 
418  /**
419  * Function to handle backward compatibility
420  * Get the value of key and if missing try old_key
421  * and log msg as a WML error (if not empty)
422  */
423  const attribute_value &get_old_attribute(config_key_type key, const std::string &old_key, const std::string& in_tag = "") const;
424  /**
425  * Returns a reference to the first child with the given @a key.
426  * Creates the child if it does not yet exist.
427  */
428 
429  /**
430  * Inserts an attribute into the config
431  * @param key The name of the attribute
432  * @param value The attribute value
433  */
434  template<typename T>
435  void insert(config_key_type key, T&& value)
436  {
437  operator[](key) = std::forward<T>(value);
438  }
439 
441 
442  bool has_attribute(config_key_type key) const;
443  /**
444  * Function to handle backward compatibility
445  * Check if has key or old_key
446  * and log msg as a WML error (if not empty)
447  */
448  bool has_old_attribute(config_key_type key, const std::string &old_key, const std::string& msg = "") const;
449 
451  void merge_attributes(const config &);
452  template<typename... T>
453  void remove_attributes(T... keys) {
454  for(const std::string& key : {keys...}) {
455  remove_attribute(key);
456  }
457  }
458 
459  template<typename... T>
460  void copy_attributes(const config& from, T... keys)
461  {
462  for(const std::string& key : {keys...}) {
463  auto* attr = from.get(key);
464  if(attr) {
465  (*this)[key] = *attr;
466  }
467  }
468  }
469 
470  const_attr_itors attribute_range() const;
471  attr_itors attribute_range();
472 
473  /**
474  * Returns the first child of tag @a key with a @a name attribute
475  * containing @a value.
476  */
477  config& find_child(config_key_type key, const std::string &name,
478  const std::string &value);
479 
480  const config& find_child(config_key_type key, const std::string &name,
481  const std::string &value) const
482  { return const_cast<config *>(this)->find_child(key, name, value); }
483 
484 private:
486 public:
487  template<typename... T>
488  void clear_children(T... keys) {
489  for(auto key : {keys...}) {
490  clear_children_impl(key);
491  }
492  }
493 
494  /**
495  * Moves all the children with tag @a key from @a src to this.
496  */
497  void splice_children(config &src, const std::string &key);
498 
499  void remove_child(config_key_type key, unsigned index);
500  /**
501  * Removes all children with tag @a key for which @a p returns true.
502  */
503  void remove_children(config_key_type key, std::function<bool(const config&)> p);
505 
506  void clear();
507  void clear_all_children();
508  void clear_attributes();
509  bool empty() const;
510 
511  std::string debug() const;
512  std::string hash() const;
513 
514  struct error : public game::error {
515  error(const std::string& message) : game::error(message) {}
516  };
517 
518  struct child_pos
519  {
520  child_pos(child_map::iterator p, unsigned i) : pos(p), index(i) {}
522  unsigned index;
523 
524  bool operator==(const child_pos& o) const { return pos == o.pos && index == o.index; }
525  bool operator!=(const child_pos& o) const { return !operator==(o); }
526  };
527 
528  struct any_child
529  {
530  const child_map::key_type &key;
532  any_child(const child_map::key_type *k, config *c): key(*k), cfg(*c) {}
533  };
534 
536 
538  {
540  {
542  arrow_helper(const all_children_iterator &i): data(*i) {}
543  const any_child *operator->() const { return &data; }
544  };
545 
547  typedef std::random_access_iterator_tag iterator_category;
548  typedef int difference_type;
553  explicit all_children_iterator(const Itor &i): i_(i) {}
554 
555  all_children_iterator &operator++() { ++i_; return *this; }
557  this_type &operator--() { --i_; return *this; }
558  this_type operator--(int) { return this_type(i_--); }
559 
560  reference operator*() const;
561  pointer operator->() const { return *this; }
562 
563  bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
564  bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
565  bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
566  bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
567 
568  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
569  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
570  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
571  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
572 
573  this_type& operator+=(difference_type n) { i_ += n; return *this; }
574  this_type& operator-=(difference_type n) { i_ -= n; return *this; }
575 
576  reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
577  friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
578  friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
579  friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
580  friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
581 
582  private:
583  Itor i_;
584 
585  friend class config;
587  };
588 
590  {
592  {
595  const any_child *operator->() const { return &data; }
596  };
597 
598  typedef const any_child value_type;
599  typedef std::random_access_iterator_tag iterator_category;
600  typedef int difference_type;
601  typedef const arrow_helper pointer;
602  typedef const any_child reference;
603  typedef std::vector<child_pos>::const_iterator Itor;
605  explicit const_all_children_iterator(const Itor &i): i_(i) {}
607 
608  const_all_children_iterator &operator++() { ++i_; return *this; }
610  this_type &operator--() { --i_; return *this; }
611  this_type operator--(int) { return this_type(i_--); }
612 
613  reference operator*() const;
614  pointer operator->() const { return *this; }
615 
616  bool operator==(const const_all_children_iterator &i) const { return i_ == i.i_; }
617  bool operator!=(const const_all_children_iterator &i) const { return i_ != i.i_; }
618  bool operator==(const all_children_iterator &i) const { return i_ == i.i_; }
619  bool operator!=(const all_children_iterator &i) const { return i_ != i.i_; }
620 
621  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
622  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
623  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
624  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
625 
626  this_type& operator+=(difference_type n) { i_ += n; return *this; }
627  this_type& operator-=(difference_type n) { i_ -= n; return *this; }
628 
629  reference operator[](difference_type n) const { return any_child(&i_[n].pos->first, i_[n].pos->second[i_->index].get()); }
630  friend difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
631  friend this_type operator-(const this_type& a, difference_type n) { return this_type(a.i_ - n); }
632  friend this_type operator+(const this_type& a, difference_type n) { return this_type(a.i_ + n); }
633  friend this_type operator+(difference_type n, const this_type& a) { return this_type(a.i_ + n); }
634 
635  private:
636  Itor i_;
637 
638  friend class config;
639  };
640 
641  /**
642  * @param key the tag name
643  * @param val the contents of the tag
644  * @param pos is the index of the new child in _all_ children.
645  */
646  config& add_child_at_total(config_key_type key, const config &val, size_t pos);
647  size_t find_total_first_of(config_key_type key, size_t start = 0);
648 
649  typedef boost::iterator_range<all_children_iterator> all_children_itors;
650  typedef boost::iterator_range<const_all_children_iterator> const_all_children_itors;
651 
652  /** In-order iteration over all children. */
653  const_all_children_itors all_children_range() const;
654  all_children_itors all_children_range();
655 
663 
664  /**
665  * A function to get the differences between this object,
666  * and 'c', as another config object.
667  * I.e. calling cfg2.apply_diff(cfg1.get_diff(cfg2))
668  * will make cfg2 identical to cfg1.
669  */
670  config get_diff(const config& c) const;
671  void get_diff(const config& c, config& res) const;
672 
673  /**
674  * The name of the attribute used for tracking diff changes
675  */
676  static const char* diff_track_attribute;
677 
678  /**
679  * A function to apply a diff config onto this config object.
680  *
681  * If the "track" parameter is true, the changes made will be marked in a
682  * magic attribute (defined above) of this and child nodes of this config,
683  * with "new" value indicating an added child, "modified" a modified one,
684  * and "deleted" for the deleted items, *which will not be actually
685  * deleted* (so calling code can easily see what they are).
686  * Use clear_diff_track with the same diff object to clear the tracking
687  * info and actually delete the nodes.
688  */
689  void apply_diff(const config& diff, bool track = false); //throw error
690 
691  /**
692  * Clear any tracking info from a previous apply_diff call with tracking.
693  * This also removes the nodes that are to be deleted, in effect making
694  * apply_diff(c, true); clear_diff_tracking(c);
695  * equivalent to apply_diff(c, false);
696  */
697  void clear_diff_track(const config& diff);
698 
699  /**
700  * Merge config 'c' into this config, overwriting this config's values.
701  */
702  void merge_with(const config& c);
703 
704  /**
705  * Merge config 'c' into this config, preserving this config's values.
706  */
707  void inherit_from(const config& c);
708  /**
709  * Merge the attributes of config 'c' into this config, preserving this config's values.
710  */
711  void inherit_attributes(const config& c);
712 
713  bool matches(const config &filter) const;
714 
715  /**
716  * Append data from another config object to this one.
717  * Attributes in the latter config object will clobber attributes in this one.
718  */
719  void append(const config& cfg);
720  void append(config&& cfg);
721 
722  /**
723  * Adds children from @a cfg.
724  */
725  void append_children(const config &cfg);
726  void append_children(config&& cfg);
727 
728  /**
729  * Adds children from @a cfg.
730  */
731  void append_children(const config &cfg, const std::string& key);
732 
733  /** Moves children with the given name from the given config to this one. */
734  void append_children_by_move(config& cfg, const std::string& key);
735 
736  /**
737  * Adds attributes from @a cfg.
738  */
739  void append_attributes(const config &cfg);
740 
741  /**
742  * All children with the given key will be merged
743  * into the first element with that key.
744  */
745  void merge_children(const std::string& key);
746 
747  /**
748  * All children with the given key and with equal values
749  * of the specified attribute will be merged into the
750  * element with that key and that value of the attribute
751  */
752  void merge_children_by_attribute(const std::string& key, const std::string& attribute);
753 
754  //this is a cheap O(1) operation
755  void swap(config& cfg);
756 
757  /**
758  * Returns true if this object represents valid WML,
759  * i.e. can be saved to disk and again loaded by the WML parser.
760  */
761  bool validate_wml() const;
762 
763 private:
764  /**
765  * Removes the child at position @a pos of @a l.
766  */
768 
769  /** All the attributes of this node. */
771 
772  /** A list of all children of this node. */
773  child_map children_;
774 
775  std::vector<child_pos> ordered_children;
776 };
777 
778 /** Implement non-member swap function for std::swap (calls @ref config::swap). */
779 void swap(config& lhs, config& rhs);
780 
781 namespace detail {
782  template<typename... T>
784 
785  template<>
787  {
788  void visit(config&) {}
789  };
790 
791  template<typename K, typename V, typename... Rest>
792  struct config_construct_unpacker<K, V, Rest...>
793  {
794  template<typename K2 = K, typename V2 = V>
795  void visit(config& cfg, K2&& key, V2&& val, Rest... fwd)
796  {
797  cfg.insert(std::forward<K>(key), std::forward<V>(val));
799  unpack.visit(cfg, std::forward<Rest>(fwd)...);
800  }
801  };
802 
803  template<typename T, typename... Rest>
804  struct config_construct_unpacker<T, config, Rest...>
805  {
806  template<typename T2 = T, typename C = config>
807  void visit(config& cfg, T2&& tag, C&& child, Rest... fwd)
808  {
809  cfg.add_child(std::forward<T>(tag), std::forward<config>(child));
811  unpack.visit(cfg, std::forward<Rest>(fwd)...);
812  }
813  };
814 
815  template<typename T, typename... Rest>
816  struct config_construct_unpacker<T, config&, Rest...>
817  {
818  template<typename T2 = T>
819  void visit(config& cfg, T2&& tag, config& child, Rest... fwd)
820  {
821  cfg.add_child(std::forward<T>(tag), std::forward<config>(child));
823  unpack.visit(cfg, std::forward<Rest>(fwd)...);
824  }
825  };
826 }
827 
828 template<typename... T>
829 inline config::config(config_key_type first, T&&... args)
830 {
832  unpack.visit(*this, first, std::forward<T>(args)...);
833 }
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition: config.hpp:195
reference operator*() const
Definition: config.hpp:133
std::bidirectional_iterator_tag iterator_category
Definition: config.hpp:253
std::vector< child_pos >::iterator Itor
Definition: config.hpp:551
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition: config.hpp:151
static bool valid_tag(config_key_type name)
Definition: config.cpp:180
void check_valid() const
Raises an exception if this is not valid.
Definition: config.cpp:113
child_map::iterator pos
Definition: config.hpp:521
const_child_iterator & operator--()
Definition: config.hpp:173
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:415
bool matches(const config &filter) const
Definition: config.cpp:1237
error(const std::string &message)
Definition: config.hpp:515
const_all_children_iterator operator++(int)
Definition: config.hpp:609
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:570
attribute_iterator & operator++()
Definition: config.hpp:232
const_all_children_iterator ordered_cbegin() const
Definition: config.cpp:901
const_all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:916
bool operator==(const const_child_iterator &i) const
Definition: config.hpp:138
bool operator==(const all_children_iterator &i) const
Definition: config.hpp:563
void append_attributes(const config &cfg)
Adds attributes from cfg.
Definition: config.cpp:265
void visit(config &cfg, T2 &&tag, C &&child, Rest... fwd)
Definition: config.hpp:807
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:185
reference operator*() const
Definition: config.hpp:237
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:187
void clear_children(T... keys)
Definition: config.hpp:488
void recursive_clear_value(config_key_type key)
Definition: config.cpp:647
bool operator==(const config &, const config &)
Definition: config.cpp:1413
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:389
const_child_iterator(const Itor &i)
Definition: config.hpp:168
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:282
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:150
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:307
boost::iterator_range< const_all_children_iterator > const_all_children_itors
Definition: config.hpp:650
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:831
const_attribute_iterator operator--(int)
Definition: config.hpp:265
Variant for storing WML attributes.
attribute_iterator & operator--()
Definition: config.hpp:234
friend this_type operator+(difference_type n, const this_type &a)
Definition: config.hpp:633
bool operator!=(const attribute_iterator &i) const
Definition: config.hpp:273
friend this_type operator-(const this_type &a, difference_type n)
Definition: config.hpp:631
std::map< std::string, child_list, std::less<> > child_map
Definition: config.hpp:113
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:320
bool has_attribute(config_key_type key) const
Definition: config.cpp:208
#define a
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:144
bool operator!=(const child_iterator &i) const
Definition: config.hpp:137
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
Definition: config.cpp:407
attribute_iterator operator++(int)
Definition: config.hpp:233
unsigned child_count(config_key_type key) const
Definition: config.cpp:385
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:142
attribute_value & operator[](const std::string &key)
Returns a reference to the attribute with the given key.
Definition: config.hpp:380
config & add_child_at_total(config_key_type key, const config &val, size_t pos)
Definition: config.cpp:551
friend bool operator==(const config &a, const config &b)
Definition: config.cpp:1413
child_itors child_range(config_key_type key)
Definition: config.cpp:357
void remove_attributes(T... keys)
Definition: config.hpp:453
reference operator[](difference_type n) const
Definition: config.hpp:629
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition: config.hpp:152
attribute_map::value_type attribute
Definition: config.hpp:219
config & operator[](Itor::difference_type n) const
Definition: config.hpp:149
child_iterator(const Itor &i)
Definition: config.hpp:126
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:737
this_type operator--(int)
Definition: config.hpp:558
const_child_iterator operator++(int)
Definition: config.hpp:172
std::random_access_iterator_tag iterator_category
Definition: config.hpp:599
child_list::iterator Itor
Definition: config.hpp:124
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:571
size_t find_total_first_of(config_key_type key, size_t start=0)
Definition: config.cpp:537
const_all_children_iterator this_type
Definition: config.hpp:604
const attribute_value & get_old_attribute(config_key_type key, const std::string &old_key, const std::string &in_tag="") const
Function to handle backward compatibility Get the value of key and if missing try old_key and log msg...
Definition: config.cpp:757
const config * pointer
Definition: config.hpp:164
void insert(config_key_type key, T &&value)
Returns a reference to the first child with the given key.
Definition: config.hpp:435
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition: config.hpp:196
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
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:407
static bool valid_attribute(config_key_type name)
Definition: config.cpp:203
config & child_or_add(config_key_type key)
Definition: config.cpp:461
void clear()
Definition: config.cpp:858
attribute_map::const_iterator Itor
Definition: config.hpp:257
void append_children(const config &cfg)
Adds children from cfg.
Definition: config.cpp:236
bool operator==(const const_all_children_iterator &i) const
Definition: config.hpp:565
bool operator!=(const config &a, const config &b)
Definition: config.hpp:54
void clear_diff_track(const config &diff)
Clear any tracking info from a previous apply_diff call with tracking.
Definition: config.cpp:1126
const config & reference
Definition: config.hpp:165
friend this_type operator-(const this_type &a, difference_type n)
Definition: config.hpp:578
void remove_attribute(config_key_type key)
Definition: config.cpp:230
bool operator==(const child_iterator &i) const
Definition: config.hpp:136
const_attribute_iterator & operator++()
Definition: config.hpp:261
const_attr_itors attribute_range() const
Definition: config.cpp:804
void visit(config &cfg, T2 &&tag, config &child, Rest... fwd)
Definition: config.hpp:819
bool operator!=(const attribute_iterator &i) const
Definition: config.hpp:241
child_iterator this_type
Definition: config.hpp:125
std::string_view config_key_type
Definition: config.hpp:48
const_attribute_iterator(const Itor &i)
Definition: config.hpp:258
bool operator!=(const const_attribute_iterator &i) const
Definition: config.hpp:243
this_type & operator-=(difference_type n)
Definition: config.hpp:627
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:942
#define b
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:143
void merge_with(const config &c)
Merge config &#39;c&#39; into this config, overwriting this config&#39;s values.
Definition: config.cpp:1162
void inherit_from(const config &c)
Merge config &#39;c&#39; into this config, preserving this config&#39;s values.
Definition: config.cpp:1215
child_list::const_iterator Itor
Definition: config.hpp:166
this_type & operator-=(Itor::difference_type n)
Definition: config.hpp:147
bool operator!=(const const_child_iterator &i) const
Definition: config.hpp:139
static config invalid
Definition: config.hpp:63
unsigned attribute_count() const
Count the number of non-blank attributes.
Definition: config.cpp:402
const_all_children_iterator ordered_end() const
Definition: config.cpp:906
Definitions for the interface to Wesnoth Markup Language (WML).
void swap(config &cfg)
Definition: config.cpp:1385
std::random_access_iterator_tag iterator_category
Definition: config.hpp:547
all_children_iterator(const Itor &i)
Definition: config.hpp:553
const_child_iterator(const child_iterator &i)
Definition: config.hpp:169
child_iterator & operator++()
Definition: config.hpp:128
bool operator==(const child_iterator &i) const
Definition: config.hpp:181
friend this_type operator+(difference_type n, const this_type &a)
Definition: config.hpp:580
pointer operator->() const
Definition: config.hpp:134
void splice_children(config &src, const std::string &key)
Moves all the children with tag key from src to this.
Definition: config.cpp:621
const_attribute_iterator(attribute_iterator &i)
Definition: config.hpp:259
this_type & operator+=(Itor::difference_type n)
Definition: config.hpp:189
void clear_children_impl(config_key_type key)
Definition: config.cpp:606
bool operator==(const attribute_iterator &i) const
Definition: config.hpp:272
arrow_helper(const const_all_children_iterator &i)
Definition: config.hpp:594
static int unpack(lua_State *L)
Definition: ltablib.cpp:207
bool operator==(const const_all_children_iterator &i) const
Definition: config.hpp:616
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:569
std::bidirectional_iterator_tag iterator_category
Definition: config.hpp:225
friend struct const_child_iterator
Definition: config.hpp:156
bool operator!=(const const_all_children_iterator &i) const
Definition: config.hpp:566
child_iterator & operator--()
Definition: config.hpp:130
const_child_iterator this_type
Definition: config.hpp:167
bool operator==(const const_attribute_iterator &i) const
Definition: config.hpp:242
config & add_child_at(config_key_type key, const config &val, unsigned index)
Definition: config.cpp:503
pointer operator->() const
Definition: config.hpp:238
const child_map::key_type & key
Definition: config.hpp:530
bool validate_wml() const
Returns true if this object represents valid WML, i.e.
Definition: config.cpp:1399
unsigned all_children_count() const
Definition: config.cpp:397
bool operator!=(const child_iterator &i) const
Definition: config.hpp:182
reference operator[](difference_type n) const
Definition: config.hpp:576
this_type & operator-=(Itor::difference_type n)
Definition: config.hpp:190
const_child_iterator & operator++()
Definition: config.hpp:171
bool operator==(const attribute_iterator &i) const
Definition: config.hpp:240
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:568
unsigned index
Definition: config.hpp:522
bool operator!=(const const_child_iterator &i) const
Definition: config.hpp:180
std::vector< child_pos > ordered_children
Definition: config.hpp:775
void visit(config &cfg, K2 &&key, V2 &&val, Rest... fwd)
Definition: config.hpp:795
config()
Definition: config.cpp:127
bool operator==(const all_children_iterator &i) const
Definition: config.hpp:618
this_type & operator+=(difference_type n)
Definition: config.hpp:573
bool operator==(const child_pos &o) const
Definition: config.hpp:524
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:193
const any_child * operator->() const
Definition: config.hpp:543
boost::iterator_range< const_attribute_iterator > const_attr_itors
Definition: config.hpp:279
const_attribute_iterator operator++(int)
Definition: config.hpp:262
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
Definition: config.cpp:1063
pointer operator->() const
Definition: config.hpp:561
std::map< std::string, attribute_value, std::less<> > attribute_map
Definition: config.hpp:218
all_children_iterator erase(const all_children_iterator &i)
Definition: config.cpp:684
bool operator!=(const all_children_iterator &i) const
Definition: config.hpp:619
all_children_iterator operator++(int)
Definition: config.hpp:556
attribute_value & operator[](const char *key)
Returns a reference to the attribute with the given key.
Definition: config.hpp:398
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:1227
boost::iterator_range< const_child_iterator > const_child_itors
Definition: config.hpp:203
friend this_type operator+(const this_type &a, difference_type n)
Definition: config.hpp:632
const_all_children_iterator & operator++()
Definition: config.hpp:608
const config & find_child(config_key_type key, const std::string &name, const std::string &value) const
Definition: config.hpp:480
static config & get_invalid()
Definition: config.hpp:109
bool operator!=(const child_pos &o) const
Definition: config.hpp:525
std::size_t i
Definition: function.cpp:934
this_type & operator-=(difference_type n)
Definition: config.hpp:574
reference operator*() const
Definition: config.hpp:176
this_type & operator+=(Itor::difference_type n)
Definition: config.hpp:146
attribute_map values_
All the attributes of this node.
Definition: config.hpp:770
mock_party p
child_iterator operator--(int)
Definition: config.hpp:131
bool operator==(const const_child_iterator &i) const
Definition: config.hpp:179
boost::iterator_range< attribute_iterator > attr_itors
Definition: config.hpp:280
boost::iterator_range< all_children_iterator > all_children_itors
Definition: config.hpp:649
void copy_attributes(const config &from, T... keys)
Definition: config.hpp:460
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:623
std::string name
Definition: sdl_ttf.cpp:70
const attribute & reference
Definition: config.hpp:256
friend difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:630
child_pos(child_map::iterator p, unsigned i)
Definition: config.hpp:520
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition: config.hpp:194
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:621
bool operator!=(const const_all_children_iterator &i) const
Definition: config.hpp:617
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:71
std::vector< std::unique_ptr< config > > child_list
Definition: config.hpp:112
bool operator!=(const all_children_iterator &i) const
Definition: config.hpp:564
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:317
config & add_child(config_key_type key)
Definition: config.cpp:471
any_child(const child_map::key_type *k, config *c)
Definition: config.hpp:532
void merge_attributes(const config &)
Definition: config.cpp:783
this_type & operator+=(difference_type n)
Definition: config.hpp:626
const_all_children_iterator ordered_begin() const
Definition: config.cpp:896
const config & operator[](Itor::difference_type n) const
Definition: config.hpp:192
std::vector< child_pos >::const_iterator Itor
Definition: config.hpp:603
config & cfg
Definition: config.hpp:531
static const char * diff_track_attribute
The name of the attribute used for tracking diff changes.
Definition: config.hpp:676
attribute_iterator operator--(int)
Definition: config.hpp:235
arrow_helper(const all_children_iterator &i)
Definition: config.hpp:542
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:624
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:27
void clear_all_children()
Definition: config.cpp:866
boost::iterator_range< child_iterator > child_itors
Definition: config.hpp:202
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:141
const_all_children_iterator(const all_children_iterator &i)
Definition: config.hpp:606
friend difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:577
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:28
reference operator*() const
Definition: config.hpp:267
bool has_old_attribute(config_key_type key, const std::string &old_key, const std::string &msg="") const
Function to handle backward compatibility Check if has key or old_key and log msg as a WML error (if ...
Definition: config.cpp:214
std::random_access_iterator_tag iterator_category
Definition: config.hpp:162
const_child_iterator operator--(int)
Definition: config.hpp:174
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:186
const attribute * pointer
Definition: config.hpp:255
pointer operator->() const
Definition: config.hpp:177
void clear_attributes()
Definition: config.cpp:873
const_all_children_iterator(const Itor &i)
Definition: config.hpp:605
const config & child_or_empty(config_key_type key) const
Returns the first child with the given key, or an empty config if there is none.
Definition: config.cpp:448
child_iterator operator++(int)
Definition: config.hpp:129
std::random_access_iterator_tag iterator_category
Definition: config.hpp:120
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:622
config_attribute_value attribute_value
Variant for storing WML attributes.
Definition: config.hpp:212
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:58
mock_char c
std::ostream & operator<<(std::ostream &, const config &)
Definition: config.cpp:1294
static map_location::DIRECTION n
config & operator=(const config &)
Definition: config.cpp:155
~config()
Definition: config.cpp:150
attribute_iterator(const Itor &i)
Definition: config.hpp:230
void remove_child(config_key_type key, unsigned index)
Definition: config.cpp:689
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:184
friend this_type operator+(const this_type &a, difference_type n)
Definition: config.hpp:579
std::string hash() const
Definition: config.cpp:1330
const_all_children_iterator ordered_cend() const
Definition: config.cpp:911
bool operator==(const const_attribute_iterator &i) const
Definition: config.hpp:270
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
bool empty() const
Definition: config.cpp:879
child_map children_
A list of all children of this node.
Definition: config.hpp:773
std::string debug() const
Definition: config.cpp:1285
attribute_map::iterator Itor
Definition: config.hpp:229
const_attribute_iterator & operator--()
Definition: config.hpp:264
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:337
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:702
bool operator!=(const const_attribute_iterator &i) const
Definition: config.hpp:271
all_children_iterator & operator++()
Definition: config.hpp:555
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition: config.hpp:153
all_children_iterator this_type
Definition: config.hpp:552