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