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