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