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