The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
config.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://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 #ifndef CONFIG_HPP_INCLUDED
29 #define CONFIG_HPP_INCLUDED
30 
31 #include "global.hpp"
32 
33 #include <climits>
34 #include <ctime>
35 #include <iosfwd>
36 #include <iterator>
37 #include <map>
38 #include <string>
39 #include <utility>
40 #include <vector>
41 
42 #include <boost/exception/exception.hpp>
43 #include <boost/variant/apply_visitor.hpp>
44 #include <boost/variant/variant.hpp>
45 
46 #include <boost/utility/enable_if.hpp>
47 #include <boost/type_traits/is_same.hpp>
48 #include <boost/type_traits/add_const.hpp>
49 #include <boost/type_traits/is_base_of.hpp>
50 
51 #include "exceptions.hpp"
52 #include "tstring.hpp"
53 #include "utils/iterable_pair.hpp"
54 
55 #ifdef HAVE_CXX14
56 # ifdef __clang__ // Check this first, because clang also defines __GNUC__
57 # ifdef __apple_build_version__ // Apple clang
58 # if (__clang_major__ == 5 && __clang_minor__ >= 1) || __clang_major__ > 5 // Apple clang 5.1+
59 # define USE_HETEROGENOUS_LOOKUPS
60 # endif
61 # else // Non-Apple clang
62 # if (__clang_major__ == 3 && __clang_minor__ >= 4) || __clang_major__ > 3 // clang 3.4+
63 # define USE_HETEROGENOUS_LOOKUPS
64 # endif
65 # endif
66 # elif defined(__GNUC__) && __GNUC__ >= 5 // GCC 5.0+
67 # define USE_HETEROGENOUS_LOOKUPS
68 # endif
69 #endif
70 
71 #if defined(_MSC_VER) && _MSC_VER >= 1900 // MSVC 2015
72 # define USE_HETEROGENOUS_LOOKUPS
73 #endif
74 
75 class config;
76 class enum_tag;
77 
78 bool operator==(const config &, const config &);
79 inline bool operator!=(const config &a, const config &b) { return !operator==(a, b); }
80 std::ostream &operator << (std::ostream &, const config &);
81 
82 /** A config object defines a single node in a WML file, with access to child nodes. */
83 class config
84 {
85  friend bool operator==(const config& a, const config& b);
86  friend struct tconfig_implementation;
87 
88  static config invalid;
89 
90  /**
91  * Raises an exception if @a this is not valid.
92  */
93  void check_valid() const;
94 
95  /**
96  * Raises an exception if @a this or @a cfg is not valid.
97  */
98  void check_valid(const config &cfg) const;
99 
100 public:
101  // Create an empty node.
102  config();
103 
104  config(const config &);
105  config &operator=(const config &);
106 
107  config(config &&);
108  config &operator=(config &&);
109 
110  /**
111  * Creates a config object with an empty child of name @a child.
112  */
113  explicit config(const std::string &child);
114 
115  ~config();
116 
117  // Verifies that the string can be used as an attribute or tag name
118  static bool valid_id(const std::string& id);
119 
120  explicit operator bool() const
121  { return this != &invalid; }
122 
123  typedef std::vector<config*> child_list;
124  typedef std::map<std::string, child_list
125 #ifdef USE_HETEROGENOUS_LOOKUPS
126  , std::less<>
127 #endif
129 
130  struct const_child_iterator;
131 
133  {
135  typedef std::random_access_iterator_tag iterator_category;
136  typedef int difference_type;
137  typedef config *pointer;
138  typedef config &reference;
141  explicit child_iterator(const Itor &i): i_(i) {}
142 
143  child_iterator &operator++() { ++i_; return *this; }
145  child_iterator &operator--() { --i_; return *this; }
147 
148  config &operator*() const { return **i_; }
149  config *operator->() const { return &**i_; }
150 
151  bool operator==(const child_iterator &i) const { return i_ == i.i_; }
152  bool operator!=(const child_iterator &i) const { return i_ != i.i_; }
153 
154  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
155  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
156  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
157  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
158 
159  this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
160  this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
161 
162  config &operator[](Itor::difference_type n) const { return *i_[n]; }
163  friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
164  friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
165  friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
166  friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
167  private:
168  Itor i_;
169  friend struct const_child_iterator;
170  };
171 
173  {
175  typedef std::random_access_iterator_tag iterator_category;
176  typedef int difference_type;
177  typedef const config *pointer;
178  typedef const config &reference;
179  typedef child_list::const_iterator Itor;
181  explicit const_child_iterator(const Itor &i): i_(i) {}
183 
184  const_child_iterator &operator++() { ++i_; return *this; }
186  const_child_iterator &operator--() { --i_; return *this; }
188 
189  const config &operator*() const { return **i_; }
190  const config *operator->() const { return &**i_; }
191 
192  bool operator==(const const_child_iterator &i) const { return i_ == i.i_; }
193  bool operator!=(const const_child_iterator &i) const { return i_ != i.i_; }
194 
195  friend bool operator<(const this_type& a, const this_type& b) { return a.i_ < b.i_; }
196  friend bool operator<=(const this_type& a, const this_type& b) { return a.i_ <= b.i_; }
197  friend bool operator>=(const this_type& a, const this_type& b) { return a.i_ >= b.i_; }
198  friend bool operator>(const this_type& a, const this_type& b) { return a.i_ > b.i_; }
199 
200  this_type& operator+=(Itor::difference_type n) { i_ += n; return *this; }
201  this_type& operator-=(Itor::difference_type n) { i_ -= n; return *this; }
202 
203  const config &operator[](Itor::difference_type n) const { return *i_[n]; }
204  friend Itor::difference_type operator-(const this_type& a, const this_type& b) { return a.i_ - b.i_; }
205  friend this_type operator-(const this_type& a, Itor::difference_type n) { return this_type(a.i_ - n); }
206  friend this_type operator+(const this_type& a, Itor::difference_type n) { return this_type(a.i_ + n); }
207  friend this_type operator+(Itor::difference_type n, const this_type& a) { return this_type(a.i_ + n); }
208 
209  private:
210  Itor i_;
211  };
212 
213  typedef std::pair<child_iterator,child_iterator> child_itors;
214  typedef std::pair<const_child_iterator,const_child_iterator> const_child_itors;
215 
216  /**
217  * Variant for storing WML attributes.
218  * The most efficient type is used when assigning a value. For instance,
219  * strings "yes", "no", "true", "false" will be detected and stored as boolean.
220  * @note The blank variant is only used when querying missing attributes.
221  * It is not stored in config objects.
222  */
224  {
225  /// A wrapper for bool to get the correct streaming ("true"/"false").
226  /// Most visitors can simply treat this as bool.
227  public:
229  {
230  bool value_;
231  public:
232  explicit true_false(bool value = false) : value_(value) {}
233  operator bool() const { return value_; }
234 
235  const std::string & str() const
236  { return value_ ? config::attribute_value::s_true :
238  };
239  friend std::ostream& operator<<(std::ostream &os, const true_false &v);
240 
241  /// A wrapper for bool to get the correct streaming ("yes"/"no").
242  /// Most visitors can simply treat this as bool.
243  class yes_no
244  {
245  bool value_;
246  public:
247  explicit yes_no(bool value = false) : value_(value) {}
248  operator bool() const { return value_; }
249 
250  const std::string & str() const
251  { return value_ ? config::attribute_value::s_yes :
253  };
254  friend std::ostream& operator<<(std::ostream &os, const yes_no &v);
255  private:
256  /// Visitor for checking equality.
257  class equality_visitor;
258  /// Visitor for converting a variant to a string.
260 
261  // Data will be stored in a variant, allowing for the possibility of
262  // boolean, numeric, and translatable data in addition to basic string
263  // data. For most purposes, int is the preferred type for numeric data
264  // as it is fast (often natural word size). While it is desirable to
265  // use few types (to keep the overhead low), we do have use cases for
266  // fractions (double) and huge numbers (up to the larger of LLONG_MAX
267  // and SIZE_MAX).
268  typedef boost::variant<boost::blank,
270  int, unsigned long long, double,
272  > value_type;
273  /// The stored value will always use the first type from the variant
274  /// definition that can represent it and that can be streamed to the
275  /// correct string representation (if applicable).
276  /// This is enforced upon assignment.
277  value_type value_;
278 
279  public:
280  /// Default implementation, but defined out-of-line for efficiency reasons.
281  attribute_value();
282  /// Default implementation, but defined out-of-line for efficiency reasons.
284  /// Default implementation, but defined out-of-line for efficiency reasons.
286  /// Default implementation, but defined out-of-line for efficiency reasons.
288 
289  // Numeric assignments:
290  attribute_value &operator=(bool v);
292  attribute_value &operator=(long v) { return operator=(static_cast<long long>(v)); }
293  attribute_value &operator=(long long v);
294  attribute_value &operator=(unsigned v) { return operator=(static_cast<unsigned long long>(v)); }
295  attribute_value &operator=(unsigned long v) { return operator=(static_cast<unsigned long long>(v)); }
296  attribute_value &operator=(unsigned long long v);
297  attribute_value &operator=(double v);
298 
299  // String assignments:
300  attribute_value &operator=(const char *v) { return operator=(std::string(v)); }
301  attribute_value &operator=(const std::string &v);
303  template<typename T>
304  typename boost::enable_if<boost::is_base_of<enum_tag, T>, attribute_value &>::type operator=(const T &v)
305  {
306  return operator=(T::enum_to_string(v));
307  }
308  // Extracting as a specific type:
309  bool to_bool(bool def = false) const;
310  int to_int(int def = 0) const;
311  long long to_long_long(long long def = 0) const;
312  unsigned to_unsigned(unsigned def = 0) const;
313  size_t to_size_t(size_t def = 0) const;
314  time_t to_time_t(time_t def = 0) const;
315  double to_double(double def = 0.) const;
316  std::string str() const;
317  t_string t_str() const;
318  /**
319  @param T a type created with MAKE_ENUM macro
320  NOTE: since T::VALUE constants is not of type T but of the underlying enum type you must specify the template parameter explicitly
321  TODO: Fix this in c++11 using constexpr types.
322  */
323  template<typename T>
324  typename boost::enable_if<boost::is_base_of<enum_tag, T>, T>::type to_enum(const T &v) const
325  {
326  return T::string_to_enum(this->str(), v);
327  }
328 
329  // Implicit conversions:
330  operator int() const { return to_int(); }
331  operator std::string() const { return str(); }
332  operator t_string() const { return t_str(); }
333 
334  /// Tests for an attribute that was never set.
335  bool blank() const;
336  /// Tests for an attribute that either was never set or was set to "".
337  bool empty() const;
338 
339 
340  // Comparisons:
341  bool operator==(const attribute_value &other) const;
342  bool operator!=(const attribute_value &other) const
343  { return !operator==(other); }
344 
345  bool equals(const std::string& str) const;
346  // These function prevent t_string creation in case of c["a"] == "b" comparisons.
347  // The templates are needed to prevent using these function in case of c["a"] == 0 comparisons.
348  template<typename T>
350  friend operator==(const attribute_value &val, const T &str)
351  { return val.equals(str); }
352 
353  template<typename T>
354  typename boost::enable_if<boost::is_same<const char*, T>, bool>::type
355  friend operator==(const attribute_value &val, T str)
356  { return val.equals(std::string(str)); }
357 
358  template<typename T>
359  bool friend operator==(const T &str, const attribute_value &val)
360  { return val == str; }
361 
362  template<typename T>
363  bool friend operator!=(const attribute_value &val, const T &str)
364  { return !(val == str); }
365 
366  template<typename T>
367  bool friend operator!=(const T &str, const attribute_value &val)
368  { return !(val == str); }
369 
370  // Streaming:
371  friend std::ostream& operator<<(std::ostream &os, const attribute_value &v);
372 
373  // Visitor support:
374  /// Applies a visitor to the underlying variant.
375  /// (See the documentation for Boost.Variant.)
376  template <typename V>
377  typename V::result_type apply_visitor(const V & visitor) const
378  { return boost::apply_visitor(visitor, value_); }
379 
380  private:
381  // Special strings.
382  static const std::string s_yes, s_no;
383  static const std::string s_true, s_false;
384  };
385 
386  typedef std::map<
389 #ifdef USE_HETEROGENOUS_LOOKUPS
390  , std::less<>
391 #endif
393  typedef attribute_map::value_type attribute;
394 
396  {
397  typedef attribute value_type;
398  typedef std::forward_iterator_tag iterator_category;
399  typedef int difference_type;
400  typedef const attribute *pointer;
401  typedef const attribute &reference;
402  typedef attribute_map::const_iterator Itor;
403  explicit const_attribute_iterator(const Itor &i): i_(i) {}
404 
405  const_attribute_iterator &operator++() { ++i_; return *this; }
407 
408  const attribute &operator*() const { return *i_; }
409  const attribute *operator->() const { return &*i_; }
410 
411  bool operator==(const const_attribute_iterator &i) const { return i_ == i.i_; }
412  bool operator!=(const const_attribute_iterator &i) const { return i_ != i.i_; }
413 
414  private:
415  Itor i_;
416  };
417 
418  typedef std::pair<const_attribute_iterator,const_attribute_iterator> const_attr_itors;
419 
420  child_itors child_range(const std::string& key);
421  const_child_itors child_range(const std::string& key) const;
422  unsigned child_count(const std::string &key) const;
423  unsigned all_children_count() const;
424  /** Note: this function also counts the 'blank' attributes, so it might return more than one might expect */
425  unsigned attribute_count() const
426  { return values.size(); }
427 
428  /**
429  * Determine whether a config has a child or not.
430  *
431  * @param key The key of the child to find.
432  *
433  * @returns Whether a child is available.
434  */
435  bool has_child(const std::string& key) const;
436 
437  /**
438  * Returns the first child with the given @a key, or an empty config if there is none.
439  */
440  const config & child_or_empty(const std::string &key) const;
441 
442  /**
443  * Returns the nth child with the given @a key, or
444  * a reference to an invalid config if there is none.
445  * @note A negative @a n accesses from the end of the object.
446  * For instance, -1 is the index of the last child.
447  */
448  config &child(const std::string& key, int n = 0);
449 
450 #ifdef USE_HETEROGENOUS_LOOKUPS
451  template<int N>
452  config &child(const char(&key)[N], int n = 0)
453  { return child_impl(key, N - 1, n); }
454 private:
455  config &child_impl(const char* key, int len, int n = 0);
456 public:
457 #endif
458  /**
459  * Returns the nth child with the given @a key, or
460  * a reference to an invalid config if there is none.
461  * @note A negative @a n accesses from the end of the object.
462  * For instance, -1 is the index of the last child.
463  */
464  const config &child(const std::string& key, int n = 0) const
465  { return const_cast<config *>(this)->child(key, n); }
466 
467 #ifdef USE_HETEROGENOUS_LOOKUPS
468  template<int N>
469  const config &child(const char(&key)[N], int n = 0) const
470  { return const_cast<config *>(this)->child_impl(key, N- 1, n); }
471 #endif
472  /**
473  * Returns a mandatory child node.
474  *
475  * If the child is not found a @ref wml_exception is thrown.
476  *
477  * @pre parent[0] == '['
478  * @pre parent[parent.size() - 1] == ']'
479  *
480  * @param key The key of the child item to return.
481  * @param parent The section in which the child should reside.
482  * This is only used for error reporting.
483  *
484  * @returns The wanted child node.
485  */
486  config& child(const std::string& key, const std::string& parent);
487 
488  /**
489  * Returns a mandatory child node.
490  *
491  * If the child is not found a @ref wml_exception is thrown.
492  *
493  * @pre parent[0] == '['
494  * @pre parent[parent.size() - 1] == ']'
495  *
496  * @param key The key of the child item to return.
497  * @param parent The section in which the child should reside.
498  * This is only used for error reporting.
499  *
500  * @returns The wanted child node.
501  */
502  const config& child(
503  const std::string& key
504  , const std::string& parent) const;
505 
506  config& add_child(const std::string& key);
507  config& add_child(const std::string& key, const config& val);
508  config& add_child_at(const std::string &key, const config &val, unsigned index);
509 
510  config &add_child(const std::string &key, config &&val);
511 
512  /**
513  * Returns a reference to the attribute with the given @a key.
514  * Creates it if it does not exist.
515  */
516  attribute_value &operator[](const std::string &key);
517 
518  /**
519  * Returns a reference to the attribute with the given @a key
520  * or to a dummy empty attribute if it does not exist.
521  */
522  const attribute_value &operator[](const std::string &key) const;
523 
524 #ifdef USE_HETEROGENOUS_LOOKUPS
525  /**
526  * Returns a reference to the attribute with the given @a key
527  * or to a dummy empty attribute if it does not exist.
528  */
529  template<int N>
530  inline const attribute_value &operator[](const char (&key)[N]) const
531  {
532  //-1 for the terminating null character.
533  return get_attribute(key, N - 1);
534  }
535 
536  template<int N>
537  inline attribute_value& operator[](const char (&key)[N])
538  {
539  return (*this)[std::string(key)];
540  }
541 #endif
542  /**
543  * Returns a pointer to the attribute with the given @a key
544  * or nullptr if it does not exist.
545  */
546  const attribute_value *get(const std::string &key) const;
547 
548  /**
549  * Function to handle backward compatibility
550  * Get the value of key and if missing try old_key
551  * and log msg as a WML error (if not empty)
552  */
553  const attribute_value &get_old_attribute(const std::string &key, const std::string &old_key, const std::string& msg = "") const;
554  /**
555  * Returns a reference to the first child with the given @a key.
556  * Creates the child if it does not yet exist.
557  */
558  config &child_or_add(const std::string &key);
559 
560  bool has_attribute(const std::string &key) const;
561  /**
562  * Function to handle backward compatibility
563  * Check if has key or old_key
564  * and log msg as a WML error (if not empty)
565  */
566  bool has_old_attribute(const std::string &key, const std::string &old_key, const std::string& msg = "") const;
567 
568  void remove_attribute(const std::string &key);
569  void merge_attributes(const config &);
570  template<typename... T>
571  void remove_attributes(T... keys) {
572  for(const std::string& key : {keys...}) {
573  remove_attribute(key);
574  }
575  }
576 
577  const_attr_itors attribute_range() const;
578 
579  /**
580  * Returns the first child of tag @a key with a @a name attribute
581  * containing @a value.
582  */
583  config &find_child(const std::string &key, const std::string &name,
584  const std::string &value);
585 
586  const config &find_child(const std::string &key, const std::string &name,
587  const std::string &value) const
588  { return const_cast<config *>(this)->find_child(key, name, value); }
589 
590  void clear_children(const std::string& key);
591  template<typename... T>
592  void clear_children(T... keys) {
593  for(std::string key : {keys...}) {
594  clear_children(key);
595  }
596  }
597 
598  /**
599  * Moves all the children with tag @a key from @a src to this.
600  */
601  void splice_children(config &src, const std::string &key);
602 
603  void remove_child(const std::string &key, unsigned index);
604  void recursive_clear_value(const std::string& key);
605 
606  void clear();
607  bool empty() const;
608 
609  std::string debug() const;
610  std::string hash() const;
611 
612  struct error : public game::error, public boost::exception {
613  error(const std::string& message) : game::error(message) {}
614  };
615 
616  struct child_pos
617  {
618  child_pos(child_map::iterator p, unsigned i) : pos(p), index(i) {}
620  unsigned index;
621 
622  bool operator==(const child_pos& o) const { return pos == o.pos && index == o.index; }
623  bool operator!=(const child_pos& o) const { return !operator==(o); }
624  };
625 
626  struct any_child
627  {
628  const child_map::key_type &key;
629  const config &cfg;
630  any_child(const child_map::key_type *k, const config *c): key(*k), cfg(*c) {}
631  };
632 
634  {
636  {
638  arrow_helper(const all_children_iterator &i): data(*i) {}
639  const any_child *operator->() const { return &data; }
640  };
641 
643  typedef std::forward_iterator_tag iterator_category;
644  typedef int difference_type;
645  typedef const arrow_helper pointer;
646  typedef const any_child reference;
647  typedef std::vector<child_pos>::const_iterator Itor;
648  explicit all_children_iterator(const Itor &i): i_(i) {}
649 
650  all_children_iterator &operator++() { ++i_; return *this; }
652 
653  reference operator*() const;
654  pointer operator->() const { return *this; }
655 
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  private:
660  Itor i_;
661 
662  friend class config;
663  };
664 
665  typedef std::pair<all_children_iterator, all_children_iterator> all_children_itors;
666 
667  /** In-order iteration over all children. */
668  all_children_itors all_children_range() const;
669 
673 
674  /**
675  * A function to get the differences between this object,
676  * and 'c', as another config object.
677  * I.e. calling cfg2.apply_diff(cfg1.get_diff(cfg2))
678  * will make cfg2 identical to cfg1.
679  */
680  config get_diff(const config& c) const;
681  void get_diff(const config& c, config& res) const;
682 
683  /**
684  * The name of the attribute used for tracking diff changes
685  */
686  static const char* diff_track_attribute;
687 
688  /**
689  * A function to apply a diff config onto this config object.
690  *
691  * If the "track" parameter is true, the changes made will be marked in a
692  * magic attribute (defined above) of this and child nodes of this config,
693  * with "new" value indicating an added child, "modified" a modified one,
694  * and "deleted" for the deleted items, *which will not be actually
695  * deleted* (so calling code can easily see what they are).
696  * Use clear_diff_track with the same diff object to clear the tracking
697  * info and actually delete the nodes.
698  */
699  void apply_diff(const config& diff, bool track = false); //throw error
700 
701  /**
702  * Clear any tracking info from a previous apply_diff call with tracking.
703  * This also removes the nodes that are to be deleted, in effect making
704  * apply_diff(c, true); clear_diff_tracking(c);
705  * equivalent to apply_diff(c, false);
706  */
707  void clear_diff_track(const config& diff);
708 
709  /**
710  * Merge config 'c' into this config, overwriting this config's values.
711  */
712  void merge_with(const config& c);
713 
714  /**
715  * Merge config 'c' into this config, preserving this config's values.
716  */
717  void inherit_from(const config& c);
718 
719  bool matches(const config &filter) const;
720 
721  /**
722  * Append data from another config object to this one.
723  * Attributes in the latter config object will clobber attributes in this one.
724  */
725  void append(const config& cfg);
726 
727  /**
728  * Adds children from @a cfg.
729  */
730  void append_children(const config &cfg);
731 
732  /**
733  * Adds children from @a cfg.
734  */
735  void append_children(const config &cfg, const std::string& key);
736 
737  /**
738  * Adds attributes from @a cfg.
739  */
740  void append_attributes(const config &cfg);
741 
742  /**
743  * All children with the given key will be merged
744  * into the first element with that key.
745  */
746  void merge_children(const std::string& key);
747 
748  /**
749  * All children with the given key and with equal values
750  * of the specified attribute will be merged into the
751  * element with that key and that value of the attribute
752  */
753  void merge_children_by_attribute(const std::string& key, const std::string& attribute);
754 
755  //this is a cheap O(1) operation
756  void swap(config& cfg);
757 
758 private:
759 #ifdef USE_HETEROGENOUS_LOOKUPS
760  const attribute_value& get_attribute(const char* key, int len) const;
761 #endif
762  /**
763  * Removes the child at position @a pos of @a l.
764  */
766 
767  /** All the attributes of this node. */
769 
770  /** A list of all children of this node. */
772 
773  std::vector<child_pos> ordered_children;
774 };
775 
777 {
778 public:
779  virtual ~variable_set() {}
780  virtual config::attribute_value get_variable_const(const std::string &id) const = 0;
781 };
782 
783 inline std::ostream &operator<<(std::ostream &os, const config::attribute_value::true_false &v) { return os << v.str(); }
784 inline std::ostream &operator<<(std::ostream &os, const config::attribute_value::yes_no &v) { return os << v.str(); }
785 
786 #endif
const attribute_value & get_old_attribute(const std::string &key, const std::string &old_key, const std::string &msg="") const
Function to handle backward compatibility Get the value of key and if missing try old_key and log msg...
Definition: config.cpp:948
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition: config.hpp:206
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition: config.hpp:164
child_itors child_range(const std::string &key)
Definition: config.cpp:613
attribute_value & operator=(unsigned v)
Definition: config.hpp:294
double to_double(double def=0.) const
Definition: config.cpp:333
void remove_attribute(const std::string &key)
Definition: config.cpp:534
bool friend operator!=(const attribute_value &val, const T &str)
Definition: config.hpp:363
std::string str() const
Definition: config.cpp:353
~attribute_value()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: config.cpp:121
child_map::iterator pos
Definition: config.hpp:619
const_child_iterator & operator--()
Definition: config.hpp:186
error(const std::string &message)
Definition: config.hpp:613
static const std::string s_no
Definition: config.hpp:382
bool matches(const config &filter) const
Definition: config.cpp:1410
static const std::string s_false
Definition: config.hpp:383
void append_attributes(const config &cfg)
Adds attributes from cfg.
Definition: config.cpp:549
boost::enable_if< boost::is_base_of< enum_tag, T >, T >::type to_enum(const T &v) const
Definition: config.hpp:324
const std::string & str() const
Definition: config.hpp:250
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:196
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:198
all_children_iterator ordered_end() const
Definition: config.cpp:1122
std::pair< const_attribute_iterator, const_attribute_iterator > const_attr_itors
Definition: config.hpp:418
bool operator==(const config &, const config &)
Definition: config.cpp:1527
const_child_iterator(const Itor &i)
Definition: config.hpp:181
size_t to_size_t(size_t def=0) const
Definition: config.cpp:323
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:566
config & operator[](Itor::difference_type n) const
Definition: config.hpp:162
bool operator!=(const const_child_iterator &i) const
Definition: config.hpp:193
const config * operator->() const
Definition: config.hpp:190
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:163
unsigned attribute_count() const
Note: this function also counts the 'blank' attributes, so it might return more than one might expect...
Definition: config.hpp:425
const GLfloat * c
Definition: glew.h:12741
int pos
Definition: formula.cpp:800
std::vector< child_pos >::const_iterator Itor
Definition: config.hpp:647
bool operator!=(const child_iterator &i) const
Definition: config.hpp:152
bool to_bool(bool def=false) const
Definition: config.cpp:275
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
t_string t_str() const
Definition: config.cpp:358
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:574
bool operator==(const const_child_iterator &i) const
Definition: config.hpp:192
friend bool operator>(const this_type &a, const this_type &b)
Definition: config.hpp:157
config & child_or_add(const std::string &key)
Returns a reference to the first child with the given key.
Definition: config.cpp:734
friend bool operator<=(const this_type &a, const this_type &b)
Definition: config.hpp:155
bool operator==(const const_attribute_iterator &i) const
Definition: config.hpp:411
friend bool operator==(const config &a, const config &b)
Definition: config.cpp:1527
Visitor for converting a variant to a string.
Definition: config.cpp:339
friend this_type operator+(const this_type &a, Itor::difference_type n)
Definition: config.hpp:165
attribute_map::value_type attribute
Definition: config.hpp:393
const config & child(const std::string &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:464
child_iterator(const Itor &i)
Definition: config.hpp:141
const_child_iterator operator++(int)
Definition: config.hpp:185
child_list::iterator Itor
Definition: config.hpp:139
const any_child * operator->() const
Definition: config.hpp:639
bool operator==(const child_pos &o) const
Definition: config.hpp:622
GLuint const GLfloat * val
Definition: glew.h:2614
const config * pointer
Definition: config.hpp:177
value_type value_
The stored value will always use the first type from the variant definition that can represent it and...
Definition: config.hpp:277
reference operator*() const
Definition: config.cpp:1112
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition: config.hpp:207
V::result_type apply_visitor(const V &visitor) const
Applies a visitor to the underlying variant.
Definition: config.hpp:377
GLenum src
Definition: glew.h:2392
void clear()
Definition: config.cpp:1055
attribute_map::const_iterator Itor
Definition: config.hpp:402
void append_children(const config &cfg)
Adds children from cfg.
Definition: config.cpp:540
const config & child_or_empty(const std::string &key) const
Returns the first child with the given key, or an empty config if there is none.
Definition: config.cpp:722
bool operator!=(const config &a, const config &b)
Definition: config.hpp:79
void clear_diff_track(const config &diff)
Clear any tracking info from a previous apply_diff call with tracking.
Definition: config.cpp:1314
std::string debug() const
Definition: config.cpp:1438
const config & reference
Definition: config.hpp:178
void clear_children(const std::string &key)
Definition: config.cpp:820
bool empty() const
Definition: config.cpp:1105
bool empty() const
Tests for an attribute that either was never set or was set to "".
Definition: config.cpp:375
friend std::ostream & operator<<(std::ostream &os, const true_false &v)
Definition: config.hpp:783
std::pair< const_child_iterator, const_child_iterator > const_child_itors
Definition: config.hpp:214
const_attribute_iterator & operator++()
Definition: config.hpp:405
const config & cfg
Definition: config.hpp:629
Variant for storing WML attributes.
Definition: config.hpp:223
child_iterator this_type
Definition: config.hpp:140
GLboolean GLenum GLenum GLvoid * values
Definition: glew.h:3799
const_attribute_iterator(const Itor &i)
Definition: config.hpp:403
GLdouble l
Definition: glew.h:6966
bool operator==(const child_iterator &i) const
Definition: config.hpp:151
bool blank() const
Tests for an attribute that was never set.
Definition: config.cpp:367
boost::variant< boost::blank, true_false, yes_no, int, unsigned long long, double, std::string, t_string > value_type
Definition: config.hpp:259
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:156
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
static bool valid_id(const std::string &id)
Definition: config.cpp:498
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
Definition: config.cpp:1350
void inherit_from(const config &c)
Merge config 'c' into this config, preserving this config's values.
Definition: config.cpp:1401
child_list::const_iterator Itor
Definition: config.hpp:179
this_type & operator-=(Itor::difference_type n)
Definition: config.hpp:160
bool has_child(const std::string &key) const
Determine whether a config has a child or not.
Definition: config.cpp:651
bool operator!=(const attribute_value &other) const
Definition: config.hpp:342
static config invalid
Definition: config.hpp:88
void swap(config &cfg)
Definition: config.cpp:1518
all_children_iterator(const Itor &i)
Definition: config.hpp:648
const_child_iterator(const child_iterator &i)
Definition: config.hpp:182
child_iterator & operator++()
Definition: config.hpp:143
void splice_children(config &src, const std::string &key)
Moves all the children with tag key from src to this.
Definition: config.cpp:837
void check_valid() const
Raises an exception if this is not valid.
Definition: config.cpp:443
boost::enable_if< boost::is_base_of< enum_tag, T >, attribute_value & >::type operator=(const T &v)
Definition: config.hpp:304
this_type & operator+=(Itor::difference_type n)
Definition: config.hpp:200
static const std::string s_yes
Definition: config.hpp:382
void clear_children(T...keys)
Definition: config.hpp:592
child_iterator & operator--()
Definition: config.hpp:145
const_child_iterator this_type
Definition: config.hpp:180
const GLdouble * v
Definition: glew.h:1359
GLsizei const GLfloat * value
Definition: glew.h:1817
all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:1127
const child_map::key_type & key
Definition: config.hpp:628
GLenum GLsizei len
Definition: glew.h:5662
attribute_value & operator=(const char *v)
Definition: config.hpp:300
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
void remove_child(const std::string &key, unsigned index)
Definition: config.cpp:899
this_type & operator-=(Itor::difference_type n)
Definition: config.hpp:201
bool friend operator!=(const T &str, const attribute_value &val)
Definition: config.hpp:367
const_child_iterator & operator++()
Definition: config.hpp:184
std::pair< all_children_iterator, all_children_iterator > all_children_itors
Definition: config.hpp:665
unsigned index
Definition: config.hpp:620
config & add_child(const std::string &key)
Definition: config.cpp:743
std::forward_iterator_tag iterator_category
Definition: config.hpp:643
std::vector< child_pos > ordered_children
Definition: config.hpp:773
A wrapper for bool to get the correct streaming ("yes"/"no").
Definition: config.hpp:243
config()
Definition: config.cpp:455
attribute_map values
All the attributes of this node.
Definition: config.hpp:768
const config & operator*() const
Definition: config.hpp:189
friend Itor::difference_type operator-(const this_type &a, const this_type &b)
Definition: config.hpp:204
const attribute & operator*() const
Definition: config.hpp:408
const_attribute_iterator operator++(int)
Definition: config.hpp:406
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
Definition: config.cpp:1252
const attribute * operator->() const
Definition: config.hpp:409
GLfloat GLfloat p
Definition: glew.h:12766
bool operator==(const all_children_iterator &i) const
Definition: config.hpp:656
const any_child reference
Definition: config.hpp:646
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
bool friend operator==(const T &str, const attribute_value &val)
Definition: config.hpp:359
all_children_iterator erase(const all_children_iterator &i)
Definition: config.cpp:894
yes_no(bool value=false)
Definition: config.hpp:247
all_children_iterator operator++(int)
Definition: config.hpp:651
const arrow_helper pointer
Definition: config.hpp:645
GLuint res
Definition: glew.h:9258
config get_diff(const config &c) const
A function to get the differences between this object, and 'c', as another config object...
Definition: config.cpp:1134
bool operator!=(const child_pos &o) const
Definition: config.hpp:623
attribute_value()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: config.cpp:115
this_type & operator+=(Itor::difference_type n)
Definition: config.hpp:159
boost::enable_if< boost::is_same< const std::string, typename boost::add_const< T >::type >, bool >::type friend operator==(const attribute_value &val, const T &str)
Definition: config.hpp:350
std::forward_iterator_tag iterator_category
Definition: config.hpp:398
config & operator*() const
Definition: config.hpp:148
child_iterator operator--(int)
Definition: config.hpp:146
boost::enable_if< boost::is_same< const char *, T >, bool >::type friend operator==(const attribute_value &val, T str)
Definition: config.hpp:355
const_attr_itors attribute_range() const
Definition: config.cpp:984
GLuint index
Definition: glew.h:1782
child_map children
A list of all children of this node.
Definition: config.hpp:771
bool operator!=(const all_children_iterator &i) const
Definition: config.hpp:657
attribute_value & operator[](const std::string &key)
Returns a reference to the attribute with the given key.
Definition: config.cpp:942
std::pair< child_iterator, child_iterator > child_itors
Definition: config.hpp:213
const attribute & reference
Definition: config.hpp:401
child_pos(child_map::iterator p, unsigned i)
Definition: config.hpp:618
friend this_type operator-(const this_type &a, Itor::difference_type n)
Definition: config.hpp:205
size_t i
Definition: function.cpp:1057
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:112
std::map< std::string, child_list > child_map
Definition: config.hpp:128
pointer operator->() const
Definition: config.hpp:654
config * operator->() const
Definition: config.hpp:149
unsigned child_count(const std::string &key) const
Definition: config.cpp:635
void merge_attributes(const config &)
Definition: config.cpp:968
GLuint const GLchar * name
Definition: glew.h:1782
attribute_value & operator=(const attribute_value &)
Default implementation, but defined out-of-line for efficiency reasons.
Definition: config.cpp:132
std::string hash() const
Definition: config.cpp:1468
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:3448
static const char * diff_track_attribute
The name of the attribute used for tracking diff changes.
Definition: config.hpp:686
virtual config::attribute_value get_variable_const(const std::string &id) const =0
GLclampd n
Definition: glew.h:5903
bool equals(const std::string &str) const
Checks for equality of the attribute values when viewed as strings.
Definition: config.cpp:417
arrow_helper(const all_children_iterator &i)
Definition: config.hpp:638
bool has_attribute(const std::string &key) const
Definition: config.cpp:514
long long to_long_long(long long def=0) const
Definition: config.cpp:313
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:27
config & child(const std::string &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:658
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:154
bool operator!=(const const_attribute_iterator &i) const
Definition: config.hpp:412
unsigned all_children_count() const
Definition: config.cpp:646
config & find_child(const std::string &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:1010
void recursive_clear_value(const std::string &key)
Definition: config.cpp:860
time_t to_time_t(time_t def=0) const
Definition: config.cpp:328
GLsizei GLenum GLuint GLuint GLsizei char * message
Definition: glew.h:2499
int to_int(int def=0) const
Definition: config.cpp:308
std::vector< config * > child_list
Definition: config.hpp:123
std::random_access_iterator_tag iterator_category
Definition: config.hpp:175
const_child_iterator operator--(int)
Definition: config.hpp:187
friend bool operator>=(const this_type &a, const this_type &b)
Definition: config.hpp:197
const config & operator[](Itor::difference_type n) const
Definition: config.hpp:203
const attribute * pointer
Definition: config.hpp:400
const config & find_child(const std::string &key, const std::string &name, const std::string &value) const
Definition: config.hpp:586
unsigned to_unsigned(unsigned def=0) const
Definition: config.cpp:318
any_child(const child_map::key_type *k, const config *c)
Definition: config.hpp:630
bool operator==(const attribute_value &other) const
Checks for equality of the attribute values when viewed as strings.
Definition: config.cpp:406
child_iterator operator++(int)
Definition: config.hpp:144
void remove_attributes(T...keys)
Definition: config.hpp:571
std::random_access_iterator_tag iterator_category
Definition: config.hpp:135
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
std::map< std::string, attribute_value > attribute_map
Definition: config.hpp:392
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
attribute_value & operator=(unsigned long v)
Definition: config.hpp:295
std::ostream & operator<<(std::ostream &, const config &)
Definition: config.cpp:1447
config & operator=(const config &)
Definition: config.cpp:474
~config()
Definition: config.cpp:469
static const std::string s_true
Definition: config.hpp:383
friend bool operator<(const this_type &a, const this_type &b)
Definition: config.hpp:195
GLsizei const GLcharARB ** string
Definition: glew.h:4503
bool has_old_attribute(const std::string &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:520
config & add_child_at(const std::string &key, const config &val, unsigned index)
Definition: config.cpp:773
attribute_value & operator=(long v)
Definition: config.hpp:292
A wrapper for bool to get the correct streaming ("true"/"false").
Definition: config.hpp:228
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:589
all_children_iterator ordered_begin() const
Definition: config.cpp:1117
virtual ~variable_set()
Definition: config.hpp:779
all_children_iterator & operator++()
Definition: config.hpp:650
friend this_type operator+(Itor::difference_type n, const this_type &a)
Definition: config.hpp:166
const std::string & str() const
Definition: config.hpp:235