]> git.mxchange.org Git - simgear.git/blob - simgear/props/props.hxx
SGPropertyNode: add removeAllChildren() method
[simgear.git] / simgear / props / props.hxx
1 /**
2  * \file props.hxx
3  * Interface definition for a property list.
4  * Started Fall 2000 by David Megginson, david@megginson.com
5  * This code is released into the Public Domain.
6  *
7  * See props.html for documentation [replace with URL when available].
8  *
9  * $Id$
10  */
11
12 #ifndef __PROPS_HXX
13 #define __PROPS_HXX
14
15 #ifndef PROPS_STANDALONE
16 #define PROPS_STANDALONE 0
17 #endif
18
19 #include <vector>
20 #include <string>
21 #include <iostream>
22 #include <sstream>
23 #include <typeinfo>
24
25 #include <boost/utility.hpp>
26 #include <boost/type_traits/is_enum.hpp>
27
28 #if PROPS_STANDALONE
29 #else
30 #include <simgear/compiler.h>
31 #include <simgear/debug/logstream.hxx>
32 #endif
33
34
35 #include <simgear/math/SGMathFwd.hxx>
36 #include <simgear/math/sg_types.hxx>
37 #include <simgear/structure/SGReferenced.hxx>
38 #include <simgear/structure/SGSharedPtr.hxx>
39
40 // XXX This whole file should be in the simgear namespace, but I don't
41 // have the guts yet...
42
43 namespace simgear
44 {
45
46   class PropertyInterpolationMgr;
47
48 template<typename T>
49 std::istream& readFrom(std::istream& stream, T& result)
50 {
51     stream >> result;
52     return stream;
53 }
54
55 /**
56  * Parse a string as an object of a given type.
57  * XXX no error behavior yet.
58  *
59  * @tparam T the return type
60  * @param str the string
61  * @return the object.
62  */
63 template<typename T>
64 inline T parseString(const std::string& str)
65 {
66     std::istringstream stream(str);
67     T result;
68     readFrom(stream, result);
69     return result;
70 }
71
72 /**
73  * Property value types.
74  */
75
76 #ifdef NONE
77 #pragma warn A sloppy coder has defined NONE as a macro!
78 #undef NONE
79 #endif
80
81 #ifdef ALIAS
82 #pragma warn A sloppy coder has defined ALIAS as a macro!
83 #undef ALIAS
84 #endif
85
86 #ifdef UNSPECIFIED
87 #pragma warn A sloppy coder has defined UNSPECIFIED as a macro!
88 #undef UNSPECIFIED
89 #endif
90
91 #ifdef BOOL
92 #pragma warn A sloppy coder has defined BOOL as a macro!
93 #undef BOOL
94 #endif
95
96 #ifdef INT
97 #pragma warn A sloppy coder has defined INT as a macro!
98 #undef INT
99 #endif
100
101 #ifdef LONG
102 #pragma warn A sloppy coder has defined LONG as a macro!
103 #undef LONG
104 #endif
105
106 #ifdef FLOAT
107 #pragma warn A sloppy coder has defined FLOAT as a macro!
108 #undef FLOAT
109 #endif
110
111 #ifdef DOUBLE
112 #pragma warn A sloppy coder has defined DOUBLE as a macro!
113 #undef DOUBLE
114 #endif
115
116 #ifdef STRING
117 #pragma warn A sloppy coder has defined STRING as a macro!
118 #undef STRING
119 #endif
120
121 namespace props
122 {
123 /**
124  * The possible types of an SGPropertyNode. Types that appear after
125  * EXTENDED are not stored in the SGPropertyNode itself.
126  */
127 enum Type {
128     NONE = 0, /**< The node hasn't been assigned a value yet. */
129     ALIAS, /**< The node "points" to another node. */
130     BOOL,
131     INT,
132     LONG,
133     FLOAT,
134     DOUBLE,
135     STRING,
136     UNSPECIFIED,
137     EXTENDED, /**< The node's value is not stored in the property;
138                * the actual value and type is retrieved from an
139                * SGRawValue node. This type is never returned by @see
140                * SGPropertyNode::getType.
141                */
142     // Extended properties
143     VEC3D,
144     VEC4D
145 };
146
147 template<typename T> struct PropertyTraits;
148
149 #define DEFINTERNALPROP(TYPE, PROP) \
150 template<> \
151 struct PropertyTraits<TYPE> \
152 { \
153     static const Type type_tag = PROP; \
154     enum  { Internal = 1 }; \
155 }
156
157 DEFINTERNALPROP(bool, BOOL);
158 DEFINTERNALPROP(int, INT);
159 DEFINTERNALPROP(long, LONG);
160 DEFINTERNALPROP(float, FLOAT);
161 DEFINTERNALPROP(double, DOUBLE);
162 DEFINTERNALPROP(const char *, STRING);
163 DEFINTERNALPROP(const char[], STRING);
164 #undef DEFINTERNALPROP
165
166 }
167 }
168
169
170
171 ////////////////////////////////////////////////////////////////////////
172 // A raw value.
173 //
174 // This is the mechanism that information-providing routines can
175 // use to link their own values to the property manager.  Any
176 // SGValue can be tied to a raw value and then untied again.
177 //
178 // Note: we are forced to use inlined methods here to ensure
179 // that the templates will be instantiated.  We're probably taking
180 // a small performance hit for that.
181 ////////////////////////////////////////////////////////////////////////
182
183 /**
184  * Base class for SGRawValue classes that holds no type
185  * information. This allows some generic manipulation of the
186  * SGRawValue object.
187  */
188 class SGRaw
189 {
190 public:
191     /**
192      * Get the type enumeration for the raw value.
193      *
194      * @return the type.
195      */
196     virtual simgear::props::Type getType() const = 0;
197     virtual ~SGRaw() {}
198     
199     /**
200      * Create a new deep copy of this raw value.
201      *
202      * The copy will contain its own version of the underlying value
203      * as well, and will be the same type.
204      *
205      * @return A deep copy of the current object.
206      */
207     virtual SGRaw* clone() const = 0;
208
209 };
210
211 class SGRawExtended : public SGRaw
212 {
213 public:
214     /**    
215      * Make an SGRawValueContainer from the SGRawValue.
216      *
217      * This is a virtual function of SGRawExtended so that
218      * SGPropertyNode::untie doesn't need to know the type of an
219      * extended property.
220      */
221     virtual SGRawExtended* makeContainer() const = 0;
222     /**
223      * Write value out to a stream
224      */
225     virtual std::ostream& printOn(std::ostream& stream) const = 0;
226     /**
227      * Read value from a stream and store it.
228      */
229     virtual std::istream& readFrom(std::istream& stream) = 0;
230 };
231
232 // Choose between different base classes based on whether the value is
233 // stored internal to the property node. This frees us from defining
234 // the virtual functions in the SGRawExtended interface where they
235 // don't make sense, e.g. readFrom for the const char* type.
236 template<typename T, int internal = simgear::props::PropertyTraits<T>::Internal>
237 class SGRawBase;
238
239 template<typename T>
240 class SGRawBase<T, 1> : public SGRaw
241 {
242 };
243
244 template<typename T>
245 class SGRawBase<T, 0> : public SGRawExtended
246 {
247     virtual SGRawExtended* makeContainer() const;
248     virtual std::ostream& printOn(std::ostream& stream) const;
249     virtual std::istream& readFrom(std::istream& stream);
250 };
251
252 /**
253  * Abstract base class for a raw value.
254  *
255  * <p>The property manager is implemented in two layers.  The {@link
256  * SGPropertyNode} is the highest and most abstract layer,
257  * representing an LValue/RValue pair: it records the position of the
258  * property in the property tree and contains facilities for
259  * navigation to other nodes.  It is guaranteed to be persistent: the
260  * {@link SGPropertyNode} will not change during a session, even if
261  * the property is bound and unbound multiple times.</p>
262  *
263  * <p>When the property value is not managed internally in the
264  * SGPropertyNode, the SGPropertyNode will contain a reference to an
265  * SGRawValue (this class), which provides an abstract way to get,
266  * set, and clone the underlying value.  The SGRawValue may change
267  * frequently during a session as a value is retyped or bound and
268  * unbound to various data source, but the abstract SGPropertyNode
269  * layer insulates the application from those changes.
270  *
271  * <p>The SGPropertyNode class always keeps a *copy* of a raw value,
272  * not the original one passed to it; if you override a derived class
273  * but do not replace the {@link #clone} method, strange things will
274  * happen.</p>
275  *
276  * <p>All derived SGRawValue classes must implement {@link #getValue},
277  * {@link #setValue}, and {@link #clone} for the appropriate type.</p>
278  *
279  * @see SGPropertyNode
280  * @see SGRawValuePointer
281  * @see SGRawValueFunctions
282  * @see SGRawValueFunctionsIndexed
283  * @see SGRawValueMethods
284  * @see SGRawValueMethodsIndexed
285  * @see SGRawValueContainer
286  */
287 template <class T>
288 class SGRawValue : public SGRawBase<T>
289 {
290 public:
291
292   /**
293    * The default underlying value for this type.
294    *
295    * Every raw value has a default; the default is false for a
296    * boolean, 0 for the various numeric values, and "" for a string.
297    * If additional types of raw values are added in the future, they
298    * may need different kinds of default values (such as epoch for a
299    * date type).  The default value is used when creating new values.
300    */
301   static T DefaultValue()
302   {
303     return T();
304   }
305
306
307   /**
308    * Constructor.
309    *
310    * Use the default value for this type.
311    */
312   SGRawValue () {}
313
314
315   /**
316    * Destructor.
317    */
318   virtual ~SGRawValue () {}
319
320
321   /**
322    * Return the underlying value.
323    *
324    * @return The actual value for the property.
325    * @see #setValue
326    */
327   virtual T getValue () const = 0;
328
329
330   /**
331    * Assign a new underlying value.
332    *
333    * If the new value cannot be set (because this is a read-only
334    * raw value, or because the new value is not acceptable for
335    * some reason) this method returns false and leaves the original
336    * value unchanged.
337    *
338    * @param value The actual value for the property.
339    * @return true if the value was set successfully, false otherwise.
340    * @see #getValue
341    */
342   virtual bool setValue (T value) = 0;
343
344
345   /**
346    * Return the type tag for this raw value type.
347    */
348   virtual simgear::props::Type getType() const
349   {
350     return simgear::props::PropertyTraits<T>::type_tag;
351   }
352 };
353
354
355
356 ////////////////////////////////////////////////////////////////////////
357 // Default values for every type.
358 ////////////////////////////////////////////////////////////////////////
359
360 template<> inline bool SGRawValue<bool>::DefaultValue()
361 {
362   return false;
363 }
364
365 template<> inline const char * SGRawValue<const char *>::DefaultValue()
366 {
367   return "";
368 }
369
370 /**
371  * A raw value bound to a pointer.
372  *
373  * This is the most efficient way to tie an external value, but also
374  * the most dangerous, because there is no way for the supplier to
375  * perform bounds checking and derived calculations except by polling
376  * the variable to see if it has changed.  There is no default
377  * constructor, because this class would be meaningless without a
378  * pointer.
379  */
380 template <class T>
381 class SGRawValuePointer : public SGRawValue<T>
382 {
383 public:
384
385   /**
386    * Explicit pointer constructor.
387    *
388    * Create a new raw value bound to the value of the variable
389    * referenced by the pointer.
390    *
391    * @param ptr The pointer to the variable to which this raw value
392    * will be bound.
393    */
394   SGRawValuePointer (T * ptr) : _ptr(ptr) {}
395
396   /**
397    * Destructor.
398    */
399   virtual ~SGRawValuePointer () {}
400
401   /**
402    * Get the underlying value.
403    *
404    * This method will dereference the pointer and return the
405    * variable's value.
406    */
407   virtual T getValue () const { return *_ptr; }
408
409   /**
410    * Set the underlying value.
411    *
412    * This method will dereference the pointer and change the
413    * variable's value.
414    */
415   virtual bool setValue (T value) { *_ptr = value; return true; }
416
417   /**
418    * Create a copy of this raw value.
419    *
420    * The copy will use the same external pointer as the original.
421    */
422   virtual SGRaw* clone () const {
423     return new SGRawValuePointer(_ptr);
424   }
425
426 private:
427   T * _ptr;
428 };
429
430
431 /**
432  * A value managed through static functions.
433  *
434  * A read-only value will not have a setter; a write-only value will
435  * not have a getter.
436  */
437 template <class T>
438 class SGRawValueFunctions : public SGRawValue<T>
439 {
440 public:
441
442   /**
443    * The template type of a static getter function.
444    */
445   typedef T (*getter_t)();
446
447   /**
448    * The template type of a static setter function.
449    */
450   typedef void (*setter_t)(T);
451
452   /**
453    * Explicit constructor.
454    *
455    * Create a new raw value bound to the getter and setter supplied.
456    *
457    * @param getter A static function for getting a value, or 0
458    * to read-disable the value.
459    * @param setter A static function for setting a value, or 0
460    * to write-disable the value.
461    */
462   SGRawValueFunctions (getter_t getter = 0, setter_t setter = 0)
463     : _getter(getter), _setter(setter) {}
464
465   /**
466    * Destructor.
467    */
468   virtual ~SGRawValueFunctions () {}
469
470   /**
471    * Get the underlying value.
472    *
473    * This method will invoke the getter function to get a value.
474    * If no getter function was supplied, this method will always
475    * return the default value for the type.
476    */
477   virtual T getValue () const {
478     if (_getter) return (*_getter)();
479     else return SGRawValue<T>::DefaultValue();
480   }
481
482   /**
483    * Set the underlying value.
484    *
485    * This method will invoke the setter function to change the
486    * underlying value.  If no setter function was supplied, this
487    * method will return false.
488    */
489   virtual bool setValue (T value) {
490     if (_setter) { (*_setter)(value); return true; }
491     else return false;
492   }
493
494   /**
495    * Create a copy of this raw value, bound to the same functions.
496    */
497   virtual SGRaw* clone () const {
498     return new SGRawValueFunctions(_getter,_setter);
499   }
500
501 private:
502   getter_t _getter;
503   setter_t _setter;
504 };
505
506
507 /**
508  * An indexed value bound to static functions.
509  *
510  * A read-only value will not have a setter; a write-only value will
511  * not have a getter.  An indexed value is useful for binding one
512  * of a list of possible values (such as multiple engines for a
513  * plane).  The index is hard-coded at creation time.
514  *
515  * @see SGRawValue
516  */
517 template <class T>
518 class SGRawValueFunctionsIndexed : public SGRawValue<T>
519 {
520 public:
521   typedef T (*getter_t)(int);
522   typedef void (*setter_t)(int,T);
523   SGRawValueFunctionsIndexed (int index, getter_t getter = 0, setter_t setter = 0)
524     : _index(index), _getter(getter), _setter(setter) {}
525   virtual ~SGRawValueFunctionsIndexed () {}
526   virtual T getValue () const {
527     if (_getter) return (*_getter)(_index);
528     else return SGRawValue<T>::DefaultValue();
529   }
530   virtual bool setValue (T value) {
531     if (_setter) { (*_setter)(_index, value); return true; }
532     else return false;
533   }
534   virtual SGRaw* clone () const {
535     return new SGRawValueFunctionsIndexed(_index, _getter, _setter);
536   }
537 private:
538   int _index;
539   getter_t _getter;
540   setter_t _setter;
541 };
542
543
544 /**
545  * A value managed through an object and access methods.
546  *
547  * A read-only value will not have a setter; a write-only value will
548  * not have a getter.
549  */
550 template <class C, class T>
551 class SGRawValueMethods : public SGRawValue<T>
552 {
553 public:
554   typedef T (C::*getter_t)() const;
555   typedef void (C::*setter_t)(T);
556   SGRawValueMethods (C &obj, getter_t getter = 0, setter_t setter = 0)
557     : _obj(obj), _getter(getter), _setter(setter) {}
558   virtual ~SGRawValueMethods () {}
559   virtual T getValue () const {
560     if (_getter) { return (_obj.*_getter)(); }
561     else { return SGRawValue<T>::DefaultValue(); }
562   }
563   virtual bool setValue (T value) {
564     if (_setter) { (_obj.*_setter)(value); return true; }
565     else return false;
566   }
567   virtual SGRaw* clone () const {
568     return new SGRawValueMethods(_obj, _getter, _setter);
569   }
570 private:
571   C &_obj;
572   getter_t _getter;
573   setter_t _setter;
574 };
575
576
577 /**
578  * An indexed value managed through an object and access methods.
579  *
580  * A read-only value will not have a setter; a write-only value will
581  * not have a getter.
582  */
583 template <class C, class T>
584 class SGRawValueMethodsIndexed : public SGRawValue<T>
585 {
586 public:
587   typedef T (C::*getter_t)(int) const;
588   typedef void (C::*setter_t)(int, T);
589   SGRawValueMethodsIndexed (C &obj, int index,
590                      getter_t getter = 0, setter_t setter = 0)
591     : _obj(obj), _index(index), _getter(getter), _setter(setter) {}
592   virtual ~SGRawValueMethodsIndexed () {}
593   virtual T getValue () const {
594     if (_getter) { return (_obj.*_getter)(_index); }
595     else { return SGRawValue<T>::DefaultValue(); }
596   }
597   virtual bool setValue (T value) {
598     if (_setter) { (_obj.*_setter)(_index, value); return true; }
599     else return false;
600   }
601   virtual SGRaw* clone () const {
602     return new SGRawValueMethodsIndexed(_obj, _index, _getter, _setter);
603   }
604 private:
605   C &_obj;
606   int _index;
607   getter_t _getter;
608   setter_t _setter;
609 };
610
611 /**
612  * A raw value that contains its value. This provides a way for
613  * property nodes to contain values that shouldn't be stored in the
614  * property node itself.
615  */
616 template <class T>
617 class SGRawValueContainer : public SGRawValue<T>
618 {
619 public:
620
621     /**
622      * Explicit constructor.
623      */
624     SGRawValueContainer(const T& obj) : _obj(obj) {}
625
626     /**
627      * Destructor.
628      */
629     virtual ~SGRawValueContainer() {}
630
631     /**
632      * Get the underlying value.
633      */
634     virtual T getValue() const { return _obj; }
635
636     /**
637      * Set the underlying value.
638      *
639      * This method will dereference the pointer and change the
640      * variable's value.
641      */
642     virtual bool setValue (T value) { _obj = value; return true; }
643
644     /**
645      * Create a copy of this raw value.
646      */
647     virtual SGRaw* clone () const {
648         return new SGRawValueContainer(_obj);
649     }
650
651 private:
652     T _obj;
653 };
654
655 template<typename T>
656 SGRawExtended* SGRawBase<T, 0>::makeContainer() const
657 {
658     return new SGRawValueContainer<T>(static_cast<const SGRawValue<T>*>(this)
659                                       ->getValue());
660 }
661
662 template<typename T>
663 std::ostream& SGRawBase<T, 0>::printOn(std::ostream& stream) const
664 {
665     return stream << static_cast<SGRawValue<T>*>(this)->getValue();
666 }
667
668 template<typename T>
669 std::istream& SGRawBase<T, 0>::readFrom(std::istream& stream)
670 {
671     T value;
672     simgear::readFrom(stream, value);
673     static_cast<SGRawValue<T>*>(this)->setValue(value);
674     return stream;
675 }
676
677 /**
678  * The smart pointer that manage reference counting
679  */
680 class SGPropertyNode;
681 typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
682 typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
683
684 namespace simgear
685 {
686 typedef std::vector<SGPropertyNode_ptr> PropertyList;
687 }
688
689 /**
690  * The property change listener interface.
691  *
692  * <p>Any class that needs to listen for property changes must implement
693  * this interface.</p>
694  */
695 class SGPropertyChangeListener
696 {
697 public:
698   virtual ~SGPropertyChangeListener ();
699   virtual void valueChanged (SGPropertyNode * node);
700   virtual void childAdded (SGPropertyNode * parent, SGPropertyNode * child);
701   virtual void childRemoved (SGPropertyNode * parent, SGPropertyNode * child);
702
703 protected:
704   friend class SGPropertyNode;
705   virtual void register_property (SGPropertyNode * node);
706   virtual void unregister_property (SGPropertyNode * node);
707
708 private:
709   std::vector<SGPropertyNode *> _properties;
710 };
711
712
713 /**
714  * A node in a property tree.
715  */
716 class SGPropertyNode : public SGReferenced
717 {
718 public:
719
720   /**
721    * Public constants.
722    */
723   enum {
724     MAX_STRING_LEN = 1024
725   };
726
727   /**
728    * Access mode attributes.
729    *
730    * <p>The ARCHIVE attribute is strictly advisory, and controls
731    * whether the property should normally be saved and restored.</p>
732    */
733   enum Attribute {
734     READ = 1,
735     WRITE = 2,
736     ARCHIVE = 4,
737     REMOVED = 8,
738     TRACE_READ = 16,
739     TRACE_WRITE = 32,
740     USERARCHIVE = 64,
741     PRESERVE = 128
742     // beware: if you add another attribute here,
743     // also update value of "LAST_USED_ATTRIBUTE".
744   };
745
746
747   /**
748    * Last used attribute
749    * Update as needed when enum Attribute is changed
750    */
751   static const int LAST_USED_ATTRIBUTE;
752
753   /**
754    * Default constructor.
755    */
756   SGPropertyNode ();
757
758
759   /**
760    * Copy constructor.
761    */
762   SGPropertyNode (const SGPropertyNode &node);
763
764
765   /**
766    * Destructor.
767    */
768   virtual ~SGPropertyNode ();
769
770
771
772   //
773   // Basic properties.
774   //
775
776   /**
777    * Test whether this node contains a primitive leaf value.
778    */
779     bool hasValue () const { return (_type != simgear::props::NONE); }
780
781
782   /**
783    * Get the node's simple (XML) name.
784    */
785   const char * getName () const { return _name.c_str(); }
786
787   /**
788    * Get the node's simple name as a string.
789    */
790   const std::string& getNameString () const { return _name; }
791
792   /**
793    * Get the node's pretty display name, with subscript when needed.
794    */
795     std::string getDisplayName (bool simplify = false) const;
796
797
798   /**
799    * Get the node's integer index.
800    */
801   int getIndex () const { return _index; }
802
803
804   /**
805    * Get a non-const pointer to the node's parent.
806    */
807   SGPropertyNode * getParent () { return _parent; }
808
809
810   /**
811    * Get a const pointer to the node's parent.
812    */
813   const SGPropertyNode * getParent () const { return _parent; }
814
815
816   //
817   // Children.
818   //
819
820
821   /**
822    * Get the number of child nodes.
823    */
824   int nChildren () const { return (int)_children.size(); }
825
826
827   /**
828    * Get a child node by position (*NOT* index).
829    */
830   SGPropertyNode * getChild (int position);
831
832
833   /**
834    * Get a const child node by position (*NOT* index).
835    */
836   const SGPropertyNode * getChild (int position) const;
837
838
839   /**
840    * Test whether a named child exists.
841    */
842   bool hasChild (const char * name, int index = 0) const
843   {
844     return (getChild(name, index) != 0);
845   }
846
847   /**
848    * Test whether a named child exists.
849    */
850   bool hasChild (const std::string& name, int index = 0) const
851   {
852     return (getChild(name, index) != 0);
853   }
854
855   /**
856    * Create a new child node with the given name and an unused index
857    *
858    * @param min_index Minimal index for new node (skips lower indices)
859    * @param append    Whether to simply use the index after the last used index
860    *                  or use a lower, unused index if it exists
861    */
862   SGPropertyNode * addChild ( const char* name,
863                               int min_index = 0,
864                               bool append = true );
865   SGPropertyNode * addChild ( const std::string& name,
866                               int min_index = 0,
867                               bool append = true )
868   { return addChild(name.c_str(), min_index, append); }
869
870   /**
871    * Create multiple child nodes with the given name an unused indices
872    *
873    * @param count     The number of nodes create
874    * @param min_index Minimal index for new nodes (skips lower indices)
875    * @param append    Whether to simply use the index after the last used index
876    *                  or use a lower, unused index if it exists
877    */
878   simgear::PropertyList addChildren ( const std::string& name,
879                                       size_t count,
880                                       int min_index = 0,
881                                       bool append = true );
882
883   /**
884    * Get a child node by name and index.
885    */
886   SGPropertyNode * getChild (const char* name, int index = 0,
887                              bool create = false);
888   SGPropertyNode * getChild (const std::string& name, int index = 0,
889                              bool create = false);
890   /**
891    * Get a const child node by name and index.
892    */
893   const SGPropertyNode * getChild (const char * name, int index = 0) const;
894
895   /**
896    * Get a const child node by name and index.
897    */
898   const SGPropertyNode * getChild (const std::string& name, int index = 0) const
899   { return getChild(name.c_str(), index); }
900
901
902   /**
903    * Get a vector of all children with the specified name.
904    */
905   simgear::PropertyList getChildren (const char * name) const;
906
907   /**
908    * Get a vector of all children with the specified name.
909    */
910   simgear::PropertyList getChildren (const std::string& name) const
911   { return getChildren(name.c_str()); }
912
913   // TODO do we need the removeXXX methods to return the deleted nodes?
914   /**
915    * Remove child by position.
916    */
917   SGPropertyNode_ptr removeChild (int pos, bool keep = true);
918
919
920   /**
921    * Remove a child node
922    */
923   SGPropertyNode_ptr removeChild (const char * name, int index = 0,
924                                   bool keep = true);
925
926   /**
927    * Remove a child node
928    */
929   SGPropertyNode_ptr removeChild (const std::string& name, int index = 0,
930                                   bool keep = true)
931   { return removeChild(name.c_str(), index, keep); }
932
933   /**
934    * Remove all children with the specified name.
935    */
936   simgear::PropertyList removeChildren (const char * name, bool keep = true);
937
938   /**
939    * Remove all children with the specified name.
940    */
941   simgear::PropertyList removeChildren (const std::string& name,
942                                         bool keep = true)
943   { return removeChildren(name.c_str(), keep); }
944
945   /**
946    * Remove all children (does not change the value of the node)
947    */
948   void removeAllChildren();
949
950   //
951   // Alias support.
952   //
953
954
955   /**
956    * Alias this node's leaf value to another's.
957    */
958   bool alias (SGPropertyNode * target);
959
960
961   /**
962    * Alias this node's leaf value to another's by relative path.
963    */
964   bool alias (const char * path);
965
966   /**
967    * Alias this node's leaf value to another's by relative path.
968    */
969   bool alias (const std::string& path)
970   { return alias(path.c_str()); }
971
972
973   /**
974    * Remove any alias for this node.
975    */
976   bool unalias ();
977
978
979   /**
980    * Test whether the node's leaf value is aliased to another's.
981    */
982   bool isAlias () const { return (_type == simgear::props::ALIAS); }
983
984
985   /**
986    * Get a non-const pointer to the current alias target, if any.
987    */
988   SGPropertyNode * getAliasTarget ();
989
990
991   /**
992    * Get a const pointer to the current alias target, if any.
993    */
994   const SGPropertyNode * getAliasTarget () const;
995
996
997   //
998   // Path information.
999   //
1000
1001
1002   /**
1003    * Get the path to this node from the root.
1004    */
1005   std::string getPath (bool simplify = false) const;
1006
1007
1008   /**
1009    * Get a pointer to the root node.
1010    */
1011   SGPropertyNode * getRootNode ();
1012
1013
1014   /**
1015    * Get a const pointer to the root node.
1016    */
1017   const SGPropertyNode * getRootNode () const;
1018
1019
1020   /**
1021    * Get a pointer to another node by relative path.
1022    */
1023   SGPropertyNode * getNode (const char * relative_path, bool create = false);
1024
1025   /**
1026    * Get a pointer to another node by relative path.
1027    */
1028   SGPropertyNode * getNode (const std::string& relative_path, bool create = false)
1029   { return getNode(relative_path.c_str(), create); }
1030
1031   /**
1032    * Get a pointer to another node by relative path.
1033    *
1034    * This method leaves the index off the last member of the path,
1035    * so that the user can specify it separately (and save some
1036    * string building).  For example, getNode("/bar[1]/foo", 3) is
1037    * exactly equivalent to getNode("bar[1]/foo[3]").  The index
1038    * provided overrides any given in the path itself for the last
1039    * component.
1040    */
1041   SGPropertyNode * getNode (const char * relative_path, int index,
1042                             bool create = false);
1043
1044   /**
1045    * Get a pointer to another node by relative path.
1046    *
1047    * This method leaves the index off the last member of the path,
1048    * so that the user can specify it separately (and save some
1049    * string building).  For example, getNode("/bar[1]/foo", 3) is
1050    * exactly equivalent to getNode("bar[1]/foo[3]").  The index
1051    * provided overrides any given in the path itself for the last
1052    * component.
1053    */
1054   SGPropertyNode * getNode (const std::string& relative_path, int index,
1055                             bool create = false)
1056   { return getNode(relative_path.c_str(), index, create); }
1057
1058   /**
1059    * Get a const pointer to another node by relative path.
1060    */
1061   const SGPropertyNode * getNode (const char * relative_path) const;
1062
1063   /**
1064    * Get a const pointer to another node by relative path.
1065    */
1066   const SGPropertyNode * getNode (const std::string& relative_path) const
1067   { return getNode(relative_path.c_str()); }
1068
1069
1070   /**
1071    * Get a const pointer to another node by relative path.
1072    *
1073    * This method leaves the index off the last member of the path,
1074    * so that the user can specify it separate.
1075    */
1076   const SGPropertyNode * getNode (const char * relative_path,
1077                                   int index) const;
1078
1079   /**
1080    * Get a const pointer to another node by relative path.
1081    *
1082    * This method leaves the index off the last member of the path,
1083    * so that the user can specify it separate.
1084    */
1085   const SGPropertyNode * getNode (const std::string& relative_path,
1086                                   int index) const
1087   { return getNode(relative_path.c_str(), index); }
1088
1089   //
1090   // Access Mode.
1091   //
1092
1093   /**
1094    * Check a single mode attribute for the property node.
1095    */
1096   bool getAttribute (Attribute attr) const { return ((_attr & attr) != 0); }
1097
1098
1099   /**
1100    * Set a single mode attribute for the property node.
1101    */
1102   void setAttribute (Attribute attr, bool state) {
1103     (state ? _attr |= attr : _attr &= ~attr);
1104   }
1105
1106
1107   /**
1108    * Get all of the mode attributes for the property node.
1109    */
1110   int getAttributes () const { return _attr; }
1111
1112
1113   /**
1114    * Set all of the mode attributes for the property node.
1115    */
1116   void setAttributes (int attr) { _attr = attr; }
1117   
1118
1119   //
1120   // Leaf Value (primitive).
1121   //
1122
1123
1124   /**
1125    * Get the type of leaf value, if any, for this node.
1126    */
1127   simgear::props::Type getType () const;
1128
1129
1130   /**
1131    * Get a bool value for this node.
1132    */
1133   bool getBoolValue () const;
1134
1135
1136   /**
1137    * Get an int value for this node.
1138    */
1139   int getIntValue () const;
1140
1141
1142   /**
1143    * Get a long int value for this node.
1144    */
1145   long getLongValue () const;
1146
1147
1148   /**
1149    * Get a float value for this node.
1150    */
1151   float getFloatValue () const;
1152
1153
1154   /**
1155    * Get a double value for this node.
1156    */
1157   double getDoubleValue () const;
1158
1159
1160   /**
1161    * Get a string value for this node.
1162    */
1163   const char * getStringValue () const;
1164
1165   /**
1166    * Get a value from a node. If the actual type of the node doesn't
1167    * match the desired type, a conversion isn't guaranteed.
1168    */
1169   template<typename T>
1170   T getValue(typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
1171              ::type* dummy = 0) const;
1172   // Getter for extended property
1173   template<typename T>
1174   T getValue(typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
1175              ::type* dummy = 0) const;
1176
1177   /**
1178    * Get a list of values from all children with the given name
1179    */
1180   template<typename T, typename T_get /* = T */> // TODO use C++11 or traits
1181   std::vector<T> getChildValues(const std::string& name) const;
1182
1183   /**
1184    * Get a list of values from all children with the given name
1185    */
1186   template<typename T>
1187   std::vector<T> getChildValues(const std::string& name) const;
1188
1189   /**
1190    * Set a bool value for this node.
1191    */
1192   bool setBoolValue (bool value);
1193
1194
1195   /**
1196    * Set an int value for this node.
1197    */
1198   bool setIntValue (int value);
1199
1200
1201   /**
1202    * Set a long int value for this node.
1203    */
1204   bool setLongValue (long value);
1205
1206
1207   /**
1208    * Set a float value for this node.
1209    */
1210   bool setFloatValue (float value);
1211
1212
1213   /**
1214    * Set a double value for this node.
1215    */
1216   bool setDoubleValue (double value);
1217
1218
1219   /**
1220    * Set a string value for this node.
1221    */
1222   bool setStringValue (const char * value);
1223
1224   /**
1225    * Set a string value for this node.
1226    */
1227   bool setStringValue (const std::string& value)
1228   { return setStringValue(value.c_str()); }
1229
1230
1231   /**
1232    * Set a value of unspecified type for this node.
1233    */
1234   bool setUnspecifiedValue (const char * value);
1235
1236   template<typename T>
1237   bool setValue(const T& val,
1238                 typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
1239                 ::type* dummy = 0);
1240
1241   template<typename T>
1242   bool setValue(const T& val,
1243                 typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
1244                 ::type* dummy = 0);
1245
1246   template<int N>
1247   bool setValue(const char (&val)[N])
1248   {
1249     return setValue(&val[0]);
1250   }
1251   
1252   /**
1253    * Set relative node to given value and afterwards make read only.
1254    *
1255    * @param relative_path   Path to node
1256    * @param value           Value to set
1257    *
1258    * @return whether value could be set
1259    */
1260   template<typename T>
1261   bool setValueReadOnly(const std::string& relative_path, const T& value)
1262   {
1263     SGPropertyNode* node = getNode(relative_path, true);
1264     bool ret = node->setValue(value);
1265     node->setAttributes(READ);
1266     return ret;
1267   }
1268
1269   /**
1270    * Interpolate current value to target value within given time.
1271    *
1272    * @param type        Type of interpolation ("numeric", "color", etc.)
1273    * @param target      Node containing target value
1274    * @param duration    Duration of interpolation (in seconds)
1275    * @param easing      Easing function (http://easings.net/)
1276    */
1277   bool interpolate( const std::string& type,
1278                     const SGPropertyNode& target,
1279                     double duration = 0.6,
1280                     const std::string& easing = "swing" );
1281
1282   /**
1283    * Interpolate current value to a series of values within given durations.
1284    *
1285    * @param type        Type of interpolation ("numeric", "color", etc.)
1286    * @param values      Nodes containing intermediate and target values
1287    * @param duration    Durations for each interpolation step (in seconds)
1288    * @param easing      Easing function (http://easings.net/)
1289    */
1290   bool interpolate( const std::string& type,
1291                     const simgear::PropertyList& values,
1292                     const double_list& deltas,
1293                     const std::string& easing = "swing" );
1294
1295   /**
1296    * Set the interpolation manager used by the interpolate methods.
1297    */
1298   static void setInterpolationMgr(simgear::PropertyInterpolationMgr* mgr);
1299
1300   /**
1301    * Print the value of the property to a stream.
1302    */
1303   std::ostream& printOn(std::ostream& stream) const;
1304   
1305   //
1306   // Data binding.
1307   //
1308
1309
1310   /**
1311    * Test whether this node is bound to an external data source.
1312    */
1313   bool isTied () const { return _tied; }
1314
1315     /**
1316      * Bind this node to an external source.
1317      */
1318     template<typename T>
1319     bool tie(const SGRawValue<T> &rawValue, bool useDefault = true);
1320
1321   /**
1322    * Unbind this node from any external data source.
1323    */
1324   bool untie ();
1325
1326
1327   //
1328   // Convenience methods using paths.
1329   // TODO: add attribute methods
1330   //
1331
1332
1333   /**
1334    * Get another node's type.
1335    */
1336   simgear::props::Type getType (const char * relative_path) const;
1337
1338   /**
1339    * Get another node's type.
1340    */
1341   simgear::props::Type getType (const std::string& relative_path) const
1342   { return getType(relative_path.c_str()); }
1343
1344   /**
1345    * Test whether another node has a leaf value.
1346    */
1347   bool hasValue (const char * relative_path) const;
1348
1349   /**
1350    * Test whether another node has a leaf value.
1351    */
1352   bool hasValue (const std::string& relative_path) const
1353   { return hasValue(relative_path.c_str()); }
1354
1355   /**
1356    * Get another node's value as a bool.
1357    */
1358   bool getBoolValue (const char * relative_path,
1359                      bool defaultValue = false) const;
1360
1361   /**
1362    * Get another node's value as a bool.
1363    */
1364   bool getBoolValue (const std::string& relative_path,
1365                      bool defaultValue = false) const
1366   { return getBoolValue(relative_path.c_str(), defaultValue); }
1367
1368   /**
1369    * Get another node's value as an int.
1370    */
1371   int getIntValue (const char * relative_path,
1372                    int defaultValue = 0) const;
1373
1374   /**
1375    * Get another node's value as an int.
1376    */
1377   int getIntValue (const std::string& relative_path,
1378                    int defaultValue = 0) const
1379   { return getIntValue(relative_path.c_str(), defaultValue); }
1380
1381
1382   /**
1383    * Get another node's value as a long int.
1384    */
1385   long getLongValue (const char * relative_path,
1386                      long defaultValue = 0L) const;
1387
1388   /**
1389    * Get another node's value as a long int.
1390    */
1391   long getLongValue (const std::string& relative_path,
1392                      long defaultValue = 0L) const
1393   { return getLongValue(relative_path.c_str(), defaultValue); }
1394
1395   /**
1396    * Get another node's value as a float.
1397    */
1398   float getFloatValue (const char * relative_path,
1399                        float defaultValue = 0.0f) const;
1400
1401   /**
1402    * Get another node's value as a float.
1403    */
1404   float getFloatValue (const std::string& relative_path,
1405                        float defaultValue = 0.0f) const
1406   { return getFloatValue(relative_path.c_str(), defaultValue); }
1407
1408
1409   /**
1410    * Get another node's value as a double.
1411    */
1412   double getDoubleValue (const char * relative_path,
1413                          double defaultValue = 0.0) const;
1414
1415   /**
1416    * Get another node's value as a double.
1417    */
1418   double getDoubleValue (const std::string& relative_path,
1419                          double defaultValue = 0.0) const
1420   { return getDoubleValue(relative_path.c_str(), defaultValue); }
1421
1422   /**
1423    * Get another node's value as a string.
1424    */
1425   const char * getStringValue (const char * relative_path,
1426                                const char * defaultValue = "") const;
1427
1428
1429   /**
1430    * Get another node's value as a string.
1431    */
1432   const char * getStringValue (const std::string& relative_path,
1433                                const char * defaultValue = "") const
1434   { return getStringValue(relative_path.c_str(), defaultValue); }
1435
1436
1437   /**
1438    * Set another node's value as a bool.
1439    */
1440   bool setBoolValue (const char * relative_path, bool value);
1441
1442   /**
1443    * Set another node's value as a bool.
1444    */
1445   bool setBoolValue (const std::string& relative_path, bool value)
1446   { return setBoolValue(relative_path.c_str(), value); }
1447
1448
1449   /**
1450    * Set another node's value as an int.
1451    */
1452   bool setIntValue (const char * relative_path, int value);
1453
1454   /**
1455    * Set another node's value as an int.
1456    */
1457   bool setIntValue (const std::string& relative_path, int value)
1458   { return setIntValue(relative_path.c_str(), value); }
1459
1460
1461   /**
1462    * Set another node's value as a long int.
1463    */
1464   bool setLongValue (const char * relative_path, long value);
1465
1466   /**
1467    * Set another node's value as a long int.
1468    */
1469   bool setLongValue (const std::string& relative_path, long value)
1470   { return setLongValue(relative_path.c_str(), value); }
1471
1472
1473   /**
1474    * Set another node's value as a float.
1475    */
1476   bool setFloatValue (const char * relative_path, float value);
1477
1478   /**
1479    * Set another node's value as a float.
1480    */
1481   bool setFloatValue (const std::string& relative_path, float value)
1482   { return setFloatValue(relative_path.c_str(), value); }
1483
1484
1485   /**
1486    * Set another node's value as a double.
1487    */
1488   bool setDoubleValue (const char * relative_path, double value);
1489
1490   /**
1491    * Set another node's value as a double.
1492    */
1493   bool setDoubleValue (const std::string& relative_path, double value)
1494   { return setDoubleValue(relative_path.c_str(), value); }
1495
1496
1497   /**
1498    * Set another node's value as a string.
1499    */
1500   bool setStringValue (const char * relative_path, const char * value);
1501
1502   bool setStringValue(const char * relative_path, const std::string& value)
1503   { return setStringValue(relative_path, value.c_str()); }
1504   /**
1505    * Set another node's value as a string.
1506    */
1507   bool setStringValue (const std::string& relative_path, const char * value)
1508   { return setStringValue(relative_path.c_str(), value); }
1509
1510   bool setStringValue (const std::string& relative_path,
1511                        const std::string& value)
1512   { return setStringValue(relative_path.c_str(), value.c_str()); }
1513
1514   /**
1515    * Set another node's value with no specified type.
1516    */
1517   bool setUnspecifiedValue (const char * relative_path, const char * value);
1518
1519
1520   /**
1521    * Test whether another node is bound to an external data source.
1522    */
1523   bool isTied (const char * relative_path) const;
1524
1525   /**
1526    * Test whether another node is bound to an external data source.
1527    */
1528   bool isTied (const std::string& relative_path) const
1529   { return isTied(relative_path.c_str()); }
1530
1531   /**
1532    * Bind another node to an external bool source.
1533    */
1534   bool tie (const char * relative_path, const SGRawValue<bool> &rawValue,
1535             bool useDefault = true);
1536
1537   /**
1538    * Bind another node to an external bool source.
1539    */
1540   bool tie (const std::string& relative_path, const SGRawValue<bool> &rawValue,
1541             bool useDefault = true)
1542   { return tie(relative_path.c_str(), rawValue, useDefault); }
1543
1544
1545   /**
1546    * Bind another node to an external int source.
1547    */
1548   bool tie (const char * relative_path, const SGRawValue<int> &rawValue,
1549             bool useDefault = true);
1550
1551   /**
1552    * Bind another node to an external int source.
1553    */
1554   bool tie (const std::string& relative_path, const SGRawValue<int> &rawValue,
1555             bool useDefault = true)
1556   { return tie(relative_path.c_str(), rawValue, useDefault); }
1557
1558
1559   /**
1560    * Bind another node to an external long int source.
1561    */
1562   bool tie (const char * relative_path, const SGRawValue<long> &rawValue,
1563             bool useDefault = true);
1564
1565   /**
1566    * Bind another node to an external long int source.
1567    */
1568   bool tie (const std::string& relative_path, const SGRawValue<long> &rawValue,
1569             bool useDefault = true)
1570   { return tie(relative_path.c_str(), rawValue, useDefault); }
1571
1572
1573   /**
1574    * Bind another node to an external float source.
1575    */
1576   bool tie (const char * relative_path, const SGRawValue<float> &rawValue,
1577             bool useDefault = true);
1578
1579   /**
1580    * Bind another node to an external float source.
1581    */
1582   bool tie (const std::string& relative_path, const SGRawValue<float> &rawValue,
1583             bool useDefault = true)
1584   { return tie(relative_path.c_str(), rawValue, useDefault); }
1585
1586
1587   /**
1588    * Bind another node to an external double source.
1589    */
1590   bool tie (const char * relative_path, const SGRawValue<double> &rawValue,
1591             bool useDefault = true);
1592
1593   /**
1594    * Bind another node to an external double source.
1595    */
1596   bool tie (const std::string& relative_path, const SGRawValue<double> &rawValue,
1597             bool useDefault = true)
1598   { return tie(relative_path.c_str(), rawValue, useDefault); }
1599
1600
1601   /**
1602    * Bind another node to an external string source.
1603    */
1604   bool tie (const char * relative_path, const SGRawValue<const char *> &rawValue,
1605             bool useDefault = true);
1606
1607   /**
1608    * Bind another node to an external string source.
1609    */
1610   bool tie (const std::string& relative_path, const SGRawValue<const char*> &rawValue,
1611             bool useDefault = true)
1612   { return tie(relative_path.c_str(), rawValue, useDefault); }
1613
1614
1615   /**
1616    * Unbind another node from any external data source.
1617    */
1618   bool untie (const char * relative_path);
1619
1620   /**
1621    * Unbind another node from any external data source.
1622    */
1623   bool untie (const std::string& relative_path)
1624   { return untie(relative_path.c_str()); }
1625
1626
1627   /**
1628    * Add a change listener to the property. If "initial" is set call the
1629    * listener initially.
1630    */
1631   void addChangeListener (SGPropertyChangeListener * listener,
1632                           bool initial = false);
1633
1634
1635   /**
1636    * Remove a change listener from the property.
1637    */
1638   void removeChangeListener (SGPropertyChangeListener * listener);
1639
1640
1641   /**
1642    * Get the number of listeners.
1643    */
1644   int nListeners () const { return _listeners ? (int)_listeners->size() : 0; }
1645
1646
1647   /**
1648    * Fire a value change event to all listeners.
1649    */
1650   void fireValueChanged ();
1651
1652
1653   /**
1654    * Fire a child-added event to all listeners.
1655    */
1656   void fireChildAdded (SGPropertyNode * child);
1657
1658   /**
1659    * Trigger a child-added and value-changed event for every child (Unlimited
1660    * depth).
1661    *
1662    * @param fire_self   Whether to trigger the events also for the node itself.
1663    *
1664    * It can be used to simulating the creation of a property tree, eg. for
1665    * (re)initializing a subsystem which is controlled through the property tree.
1666    */
1667   void fireCreatedRecursive(bool fire_self = false);
1668
1669   /**
1670    * Fire a child-removed event to all listeners.
1671    */
1672   void fireChildRemoved (SGPropertyNode * child);
1673
1674   /**
1675    * Fire a child-removed event for every child of this node (Unlimited depth)
1676    *
1677    * Upon removal of a child node only for this single node a child-removed
1678    * event is triggered. If eg. resource cleanup relies on receiving a
1679    * child-removed event for every child this method can be used.
1680    */
1681   void fireChildrenRemovedRecursive();
1682
1683
1684   /**
1685    * Clear any existing value and set the type to NONE.
1686    */
1687   void clearValue ();
1688
1689   /**
1690    * Compare two property trees. The property trees are equal if: 1)
1691    * They have no children, and have the same type and the values are
1692    * equal, or 2) have the same number of children, and the
1693    * corresponding children in each tree are equal. "corresponding"
1694    * means have the same name and index.
1695    *
1696    * Attributes, removed children, and aliases aren't considered.
1697    */
1698   static bool compare (const SGPropertyNode& lhs, const SGPropertyNode& rhs);
1699
1700 protected:
1701
1702   void fireValueChanged (SGPropertyNode * node);
1703   void fireChildAdded (SGPropertyNode * parent, SGPropertyNode * child);
1704   void fireChildRemoved (SGPropertyNode * parent, SGPropertyNode * child);
1705
1706   /**
1707    * Protected constructor for making new nodes on demand.
1708    */
1709   SGPropertyNode (const std::string& name, int index, SGPropertyNode * parent);
1710   template<typename Itr>
1711   SGPropertyNode (Itr begin, Itr end, int index, SGPropertyNode * parent);
1712
1713   static simgear::PropertyInterpolationMgr* _interpolation_mgr;
1714
1715 private:
1716
1717   // Get the raw value
1718   bool get_bool () const;
1719   int get_int () const;
1720   long get_long () const;
1721   float get_float () const;
1722   double get_double () const;
1723   const char * get_string () const;
1724
1725   // Set the raw value
1726   bool set_bool (bool value);
1727   bool set_int (int value);
1728   bool set_long (long value);
1729   bool set_float (float value);
1730   bool set_double (double value);
1731   bool set_string (const char * value);
1732
1733
1734   /**
1735    * Get the value as a string.
1736    */
1737   const char * make_string () const;
1738
1739   /**
1740    * Trace a read access.
1741    */
1742   void trace_read () const;
1743
1744
1745   /**
1746    * Trace a write access.
1747    */
1748   void trace_write () const;
1749
1750   int _index;
1751   std::string _name;
1752   /// To avoid cyclic reference counting loops this shall not be a reference
1753   /// counted pointer
1754   SGPropertyNode * _parent;
1755   simgear::PropertyList _children;
1756   simgear::PropertyList _removedChildren;
1757   mutable std::string _buffer;
1758   simgear::props::Type _type;
1759   bool _tied;
1760   int _attr;
1761
1762   // The right kind of pointer...
1763   union {
1764     SGPropertyNode * alias;
1765     SGRaw* val;
1766   } _value;
1767
1768   union {
1769     bool bool_val;
1770     int int_val;
1771     long long_val;
1772     float float_val;
1773     double double_val;
1774     char * string_val;
1775   } _local_val;
1776
1777   std::vector<SGPropertyChangeListener *> * _listeners;
1778
1779   // Pass name as a pair of iterators
1780   template<typename Itr>
1781   SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false);
1782   // very internal method
1783   template<typename Itr>
1784   SGPropertyNode* getExistingChild (Itr begin, Itr end, int index, bool create);
1785   // very internal path parsing function
1786   template<typename SplitItr>
1787   friend SGPropertyNode* find_node_aux(SGPropertyNode * current, SplitItr& itr,
1788                                        bool create, int last_index);
1789   // For boost
1790   friend size_t hash_value(const SGPropertyNode& node);
1791 };
1792
1793 // Convenience functions for use in templates
1794 template<typename T>
1795 typename boost::disable_if<boost::is_enum<T>, T>::type
1796 getValue(const SGPropertyNode*);
1797
1798 template<>
1799 inline bool getValue<bool>(const SGPropertyNode* node) { return node->getBoolValue(); }
1800
1801 template<>
1802 inline int getValue<int>(const SGPropertyNode* node) { return node->getIntValue(); }
1803
1804 template<>
1805 inline long getValue<long>(const SGPropertyNode* node) { return node->getLongValue(); }
1806
1807 template<>
1808 inline float getValue<float>(const SGPropertyNode* node)
1809 {
1810     return node->getFloatValue();
1811 }
1812
1813 template<>
1814 inline double getValue<double>(const SGPropertyNode* node)
1815 {
1816     return node->getDoubleValue();
1817 }
1818
1819 template<>
1820 inline const char * getValue<const char*>(const SGPropertyNode* node)
1821 {
1822     return node->getStringValue ();
1823 }
1824
1825 template<>
1826 inline std::string getValue<std::string>(const SGPropertyNode* node)
1827 {
1828     return node->getStringValue();
1829 }
1830
1831 namespace simgear
1832 {
1833   /**
1834    * Default trait for extracting enum values from SGPropertyNode. Create your
1835    * own specialization for specific enum types to enable validation of values.
1836    */
1837   template<class T>
1838   struct enum_traits
1839   {
1840     /**
1841      * Typename of the enum
1842      */
1843     static const char* name() { return typeid(T).name(); }
1844
1845     /**
1846      * @return Default value (will be used if validation fails)
1847      */
1848     static T defVal() { return T(); }
1849
1850     /**
1851      * @return Whether the given integer value has an enum value defined
1852      */
1853     static bool validate(int) { return true; }
1854   };
1855 } // namespace simgear
1856
1857 /** Extract enum from SGPropertyNode */
1858 template<typename T>
1859 inline typename boost::enable_if<boost::is_enum<T>, T>::type
1860 getValue(const SGPropertyNode* node)
1861 {
1862   typedef simgear::enum_traits<T> Traits;
1863   int val = node->getIntValue();
1864   if( !Traits::validate(val) )
1865   {
1866     SG_LOG
1867     (
1868       SG_GENERAL,
1869       SG_WARN,
1870       "Invalid value for enum (" << Traits::name() << ", val = " << val << ")"
1871     );
1872     return Traits::defVal();
1873   }
1874   return static_cast<T>(node->getIntValue());
1875 }
1876
1877 inline bool setValue(SGPropertyNode* node, bool value)
1878 {
1879     return node->setBoolValue(value);
1880 }
1881
1882 inline bool setValue(SGPropertyNode* node, int value)
1883 {
1884     return node->setIntValue(value);
1885 }
1886
1887 inline bool setValue(SGPropertyNode* node, long value)
1888 {
1889     return node->setLongValue(value);
1890 }
1891
1892 inline bool setValue(SGPropertyNode* node, float value)
1893 {
1894     return node->setFloatValue(value);
1895 }
1896
1897 inline bool setValue(SGPropertyNode* node, double value)
1898 {
1899     return node->setDoubleValue(value);
1900 }
1901
1902 inline bool setValue(SGPropertyNode* node, const char* value)
1903 {
1904     return node->setStringValue(value);
1905 }
1906
1907 inline bool setValue (SGPropertyNode* node, const std::string& value)
1908 {
1909     return node->setStringValue(value.c_str());
1910 }
1911
1912 template<typename T>
1913 bool SGPropertyNode::tie(const SGRawValue<T> &rawValue, bool useDefault)
1914 {
1915     using namespace simgear::props;
1916     if (_type == ALIAS || _tied)
1917         return false;
1918
1919     useDefault = useDefault && hasValue();
1920     T old_val = SGRawValue<T>::DefaultValue();
1921     if (useDefault)
1922         old_val = getValue<T>(this);
1923     clearValue();
1924     if (PropertyTraits<T>::Internal)
1925         _type = PropertyTraits<T>::type_tag;
1926     else
1927         _type = EXTENDED;
1928     _tied = true;
1929     _value.val = rawValue.clone();
1930     if (useDefault) {
1931         int save_attributes = getAttributes();
1932         setAttribute( WRITE, true );
1933         setValue(old_val);
1934         setAttributes( save_attributes );
1935     }
1936     return true;
1937 }
1938
1939 template<>
1940 bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
1941                           bool useDefault);
1942
1943 template<typename T>
1944 T SGPropertyNode::getValue(typename boost::disable_if_c<simgear::props
1945                            ::PropertyTraits<T>::Internal>::type* dummy) const
1946 {
1947     using namespace simgear::props;
1948     if (_attr == (READ|WRITE) && _type == EXTENDED
1949         && _value.val->getType() == PropertyTraits<T>::type_tag) {
1950         return static_cast<SGRawValue<T>*>(_value.val)->getValue();
1951     }
1952     if (getAttribute(TRACE_READ))
1953         trace_read();
1954     if (!getAttribute(READ))
1955       return SGRawValue<T>::DefaultValue();
1956     switch (_type) {
1957     case EXTENDED:
1958         if (_value.val->getType() == PropertyTraits<T>::type_tag)
1959             return static_cast<SGRawValue<T>*>(_value.val)->getValue();
1960         break;
1961     case STRING:
1962     case UNSPECIFIED:
1963         return simgear::parseString<T>(make_string());
1964         break;
1965     default: // avoid compiler warning
1966         break;
1967     }
1968     return SGRawValue<T>::DefaultValue();
1969 }
1970
1971 template<typename T>
1972 inline T SGPropertyNode::getValue(typename boost::enable_if_c<simgear::props
1973                                   ::PropertyTraits<T>::Internal>::type* dummy) const
1974 {
1975   return ::getValue<T>(this);
1976 }
1977
1978 template<typename T, typename T_get /* = T */> // TODO use C++11 or traits
1979 std::vector<T> SGPropertyNode::getChildValues(const std::string& name) const
1980 {
1981   const simgear::PropertyList& props = getChildren(name);
1982   std::vector<T> values( props.size() );
1983
1984   for( size_t i = 0; i < props.size(); ++i )
1985     values[i] = props[i]->getValue<T_get>();
1986
1987   return values;
1988 }
1989
1990 template<typename T>
1991 inline
1992 std::vector<T> SGPropertyNode::getChildValues(const std::string& name) const
1993 {
1994   return getChildValues<T, T>(name);
1995 }
1996
1997 template<typename T>
1998 bool SGPropertyNode::setValue(const T& val,
1999                               typename boost::disable_if_c<simgear::props
2000                               ::PropertyTraits<T>::Internal>::type* dummy)
2001 {
2002     using namespace simgear::props;
2003     if (_attr == (READ|WRITE) && _type == EXTENDED
2004         && _value.val->getType() == PropertyTraits<T>::type_tag) {
2005         static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
2006         return true;
2007     }
2008     if (getAttribute(WRITE)
2009         && ((_type == EXTENDED
2010             && _value.val->getType() == PropertyTraits<T>::type_tag)
2011             || _type == NONE || _type == UNSPECIFIED)) {
2012         if (_type == NONE || _type == UNSPECIFIED) {
2013             clearValue();
2014             _type = EXTENDED;
2015             _value.val = new SGRawValueContainer<T>(val);
2016         } else {
2017             static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
2018         }
2019         if (getAttribute(TRACE_WRITE))
2020             trace_write();
2021         return true;
2022     }
2023     return false;
2024 }
2025
2026 template<typename T>
2027 inline bool SGPropertyNode::setValue(const T& val,
2028                                      typename boost::enable_if_c<simgear::props
2029                                      ::PropertyTraits<T>::Internal>::type* dummy)
2030 {
2031   return ::setValue(this, val);
2032 }
2033
2034 /**
2035  * Utility function for creation of a child property node.
2036  */
2037 inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name,
2038                                  int index = 0)
2039 {
2040     return parent->getChild(name, index, true);
2041 }
2042
2043 /**
2044  * Utility function for creation of a child property node using a
2045  * relative path.
2046  */
2047 namespace simgear
2048 {
2049 template<typename StringType>
2050 inline SGPropertyNode* makeNode(SGPropertyNode* parent, const StringType& name)
2051 {
2052     return parent->getNode(name, true);
2053 }
2054 }
2055
2056 // For boost::hash
2057 size_t hash_value(const SGPropertyNode& node);
2058
2059 // Helper comparison and hash functions for common cases
2060
2061 namespace simgear
2062 {
2063 namespace props
2064 {
2065 struct Compare
2066 {
2067     bool operator()(const SGPropertyNode* lhs, const SGPropertyNode* rhs) const
2068     {
2069         return SGPropertyNode::compare(*lhs, *rhs);
2070     }
2071     bool operator()(SGPropertyNode_ptr lhs, const SGPropertyNode* rhs) const
2072     {
2073         return SGPropertyNode::compare(*lhs, *rhs);
2074     }
2075     bool operator()(const SGPropertyNode* lhs, SGPropertyNode_ptr rhs) const
2076     {
2077         return SGPropertyNode::compare(*lhs, *rhs);
2078     }
2079     bool operator()(SGPropertyNode_ptr lhs, SGPropertyNode_ptr rhs) const
2080     {
2081         return SGPropertyNode::compare(*lhs, *rhs);
2082     }
2083 };
2084
2085 struct Hash
2086 {
2087     size_t operator()(const SGPropertyNode* node) const
2088     {
2089         return hash_value(*node);
2090     }
2091     size_t operator()(SGPropertyNode_ptr node) const
2092     {
2093         return hash_value(*node);
2094     }
2095 };
2096 }
2097 }
2098
2099 /** Convenience class for change listener callbacks without
2100  * creating a derived class implementing a "valueChanged" method.
2101  * Also removes listener on destruction automatically.
2102  */
2103 template<class T>
2104 class SGPropertyChangeCallback
2105     : public SGPropertyChangeListener
2106 {
2107 public:
2108     SGPropertyChangeCallback(T* obj, void (T::*method)(SGPropertyNode*),
2109                              SGPropertyNode_ptr property,bool initial=false)
2110         : _obj(obj), _callback(method), _property(property)
2111     {
2112         _property->addChangeListener(this,initial);
2113     }
2114
2115         SGPropertyChangeCallback(const SGPropertyChangeCallback<T>& other) :
2116                 _obj(other._obj), _callback(other._callback), _property(other._property)
2117         {
2118                  _property->addChangeListener(this,false);
2119         }
2120
2121     virtual ~SGPropertyChangeCallback()
2122     {
2123         _property->removeChangeListener(this);
2124     }
2125     void valueChanged (SGPropertyNode * node)
2126     {
2127         (_obj->*_callback)(node);
2128     }
2129 private:
2130     T* _obj;
2131     void (T::*_callback)(SGPropertyNode*);
2132     SGPropertyNode_ptr _property;
2133 };
2134
2135 #endif // __PROPS_HXX
2136
2137 // end of props.hxx