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