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