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