]> git.mxchange.org Git - simgear.git/blob - simgear/misc/props.hxx
Added some new functionality to the property manager:
[simgear.git] / simgear / misc / 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 #include <simgear/compiler.h>
16
17 #include <stdio.h>
18
19 #include STL_STRING
20 #include <vector>
21 #include <map>
22 #include STL_IOSTREAM
23
24 SG_USING_STD(string);
25 SG_USING_STD(vector);
26 SG_USING_STD(map);
27 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
28 SG_USING_STD(istream);
29 SG_USING_STD(ostream);
30 #endif
31
32 #ifdef NONE
33 #pragma warn A sloppy coder has defined NONE as a macro!
34 #undef NONE
35 #endif
36
37 #ifdef ALIAS
38 #pragma warn A sloppy coder has defined ALIAS as a macro!
39 #undef ALIAS
40 #endif
41
42 #ifdef UNSPECIFIED
43 #pragma warn A sloppy coder has defined UNSPECIFIED as a macro!
44 #undef UNSPECIFIED
45 #endif
46
47 #ifdef BOOL
48 #pragma warn A sloppy coder has defined BOOL as a macro!
49 #undef BOOL
50 #endif
51
52 #ifdef INT
53 #pragma warn A sloppy coder has defined INT as a macro!
54 #undef INT
55 #endif
56
57 #ifdef LONG
58 #pragma warn A sloppy coder has defined LONG as a macro!
59 #undef LONG
60 #endif
61
62 #ifdef FLOAT
63 #pragma warn A sloppy coder has defined FLOAT as a macro!
64 #undef FLOAT
65 #endif
66
67 #ifdef DOUBLE
68 #pragma warn A sloppy coder has defined DOUBLE as a macro!
69 #undef DOUBLE
70 #endif
71
72 #ifdef STRING
73 #pragma warn A sloppy coder has defined STRING as a macro!
74 #undef STRING
75 #endif
76
77
78 \f
79 ////////////////////////////////////////////////////////////////////////
80 // A raw value.
81 //
82 // This is the mechanism that information-providing routines can
83 // use to link their own values to the property manager.  Any
84 // SGValue can be tied to a raw value and then untied again.
85 ////////////////////////////////////////////////////////////////////////
86
87
88 /**
89  * Abstract base class for a raw value.
90  *
91  * The property manager is implemented in three layers.  The {@link
92  * SGPropertyNode} is the highest and most abstract layer,
93  * representing * an LValue/RValue pair: it * records the position
94  * of the property in the property tree and * contains facilities
95  * for navigation to other nodes.  Each node * may contain an {@link
96  * SGValue}, which is guaranteed persistent: the * {@link SGValue}
97  * will not change during a session, even if the * property is bound
98  * and unbound multiple times.  The SGValue is the * abstraction of
99  * an RValue: it allows for conversion among all of the different
100  * types, and can be bound to external pointers, functions, methods,
101  * or other data sources.  Every SGValue contains an SGRawValue of
102  * a specific type.  The SGRawValue (this class) may change frequently
103  * during a session as a value is retyped or bound and unbound to
104  * various data source, but the abstract SGValue layer insulates
105  * the application from those changes.  The raw value contains no
106  * facilities for data binding or for type conversion: it is simply
107  * the abstraction of a primitive data type (or a compound data
108  * type, in the case of a string).
109  *
110  * The SGValue class always keeps a *copy* of a raw value, not the
111  * original one passed to it; if you override a derived class but do
112  * not replace the {@link #clone} method, strange things will happen.
113  *
114  * All raw values must implement {@link #getValue}, {@link #setValue},
115  * and {@link #clone} for the appropriate type.
116  *
117  * @see SGValue
118  * @see SGPropertyNode */
119 template <class T>
120 class SGRawValue
121 {
122 public:
123
124   /**
125    * The default underlying value for this type.
126    *
127    * Every raw value has a default; the default is false for a
128    * boolean, 0 for the various numeric values, and "" for a string.
129    * If additional types of raw values are added in the future, they
130    * may need different kinds of default values (such as epoch for a
131    * date type).  The default value is used when creating new values.
132    */
133   static const T DefaultValue;  // Default for this kind of raw value.
134
135
136   /**
137    * Constructor.
138    *
139    * Use the default value for this type.
140    */
141   SGRawValue () {}
142
143
144   /**
145    * Destructor.
146    */
147   virtual ~SGRawValue () {}
148
149
150   /**
151    * Return the underlying value.
152    *
153    * @return The actual value for the property.
154    * @see #setValue
155    */
156   virtual T getValue () const = 0;
157
158
159   /**
160    * Assign a new underlying value.
161    *
162    * If the new value cannot be set (because this is a read-only
163    * raw value, or because the new value is not acceptable for
164    * some reason) this method returns false and leaves the original
165    * value unchanged.
166    *
167    * @param value The actual value for the property.
168    * @return true if the value was set successfully, false otherwise.
169    * @see #getValue
170    */
171   virtual bool setValue (T value) = 0;
172
173
174   /**
175    * Create a new deep copy of this raw value.
176    *
177    * The copy will contain its own version of the underlying value
178    * as well.
179    *
180    * @return A deep copy of the current object.
181    */
182   virtual SGRawValue * clone () const = 0;
183 };
184
185
186 /**
187  * An unbound raw value, stored internally.
188  *
189  * Instances of this class are created automatically, by default,
190  * by the SGValue class; ordinarily the application should not
191  * need to touch it.
192  */
193 template <class T>
194 class SGRawValueInternal : public SGRawValue<T>
195 {
196 public:
197
198   /**
199    * Default constructor.
200    *
201    * Initialize with the default value for this type.
202    */
203   SGRawValueInternal () {}
204
205   /**
206    * Explicit value constructor.
207    *
208    * Initialize with the underlying value provided.
209    *
210    * @param value The initial value for this property.
211    */
212   SGRawValueInternal (T value) : _value(value) {}
213
214   /**
215    * Destructor.
216    */
217   virtual ~SGRawValueInternal () {}
218
219   /**
220    * Get the underlying value.
221    */
222   virtual T getValue () const { return _value; }
223
224   /**
225    * Set the underlying value.
226    */
227   virtual bool setValue (T value) { _value = value; return true; }
228
229   /**
230    * Create a deep copy of this raw value.
231    */
232   virtual SGRawValue<T> * clone () const {
233     return new SGRawValueInternal<T>(_value);
234   }
235
236 private:
237   T _value;
238 };
239
240
241 /**
242  * A raw value bound to a pointer.
243  *
244  * This is the most efficient way to tie an external value, but also
245  * the most dangerous, because there is no way for the supplier to
246  * perform bounds checking and derived calculations except by polling
247  * the variable to see if it has changed.  There is no default
248  * constructor, because this class would be meaningless without a
249  * pointer.
250  */
251 template <class T>
252 class SGRawValuePointer : public SGRawValue<T>
253 {
254 public:
255
256   /**
257    * Explicit pointer constructor.
258    *
259    * Create a new raw value bound to the value of the variable
260    * referenced by the pointer.
261    *
262    * @param ptr The pointer to the variable to which this raw value
263    * will be bound.
264    */
265   SGRawValuePointer (T * ptr) : _ptr(ptr) {}
266
267   /**
268    * Destructor.
269    */
270   virtual ~SGRawValuePointer () {}
271
272   /**
273    * Get the underlying value.
274    *
275    * This method will dereference the pointer and return the
276    * variable's value.
277    */
278   virtual T getValue () const { return *_ptr; }
279
280   /**
281    * Set the underlying value.
282    *
283    * This method will dereference the pointer and change the
284    * variable's value.
285    */
286   virtual bool setValue (T value) { *_ptr = value; return true; }
287
288   /**
289    * Create a copy of this raw value.
290    *
291    * The copy will use the same external pointer as the original.
292    */
293   virtual SGRawValue<T> * clone () const {
294     return new SGRawValuePointer<T>(_ptr);
295   }
296
297 private:
298   T * _ptr;
299 };
300
301
302 /**
303  * A value managed through static functions.
304  *
305  * A read-only value will not have a setter; a write-only value will
306  * not have a getter.
307  */
308 template <class T>
309 class SGRawValueFunctions : public SGRawValue<T>
310 {
311 public:
312
313   /**
314    * The template type of a static getter function.
315    */
316   typedef T (*getter_t)();
317
318   /**
319    * The template type of a static setter function.
320    */
321   typedef void (*setter_t)(T);
322
323   /**
324    * Explicit constructor.
325    *
326    * Create a new raw value bound to the getter and setter supplied.
327    *
328    * @param getter A static function for getting a value, or 0
329    * to read-disable the value.
330    * @param setter A static function for setting a value, or 0
331    * to write-disable the value.
332    */
333   SGRawValueFunctions (getter_t getter = 0, setter_t setter = 0)
334     : _getter(getter), _setter(setter) {}
335
336   /**
337    * Destructor.
338    */
339   virtual ~SGRawValueFunctions () {}
340
341   /**
342    * Get the underlying value.
343    *
344    * This method will invoke the getter function to get a value.
345    * If no getter function was supplied, this method will always
346    * return the default value for the type.
347    */
348   virtual T getValue () const {
349     if (_getter) return (*_getter)();
350     else return SGRawValue<T>::DefaultValue;
351   }
352
353   /**
354    * Set the underlying value.
355    *
356    * This method will invoke the setter function to change the
357    * underlying value.  If no setter function was supplied, this
358    * method will return false.
359    */
360   virtual bool setValue (T value) {
361     if (_setter) { (*_setter)(value); return true; }
362     else return false;
363   }
364
365   /**
366    * Create a copy of this raw value, bound to the same functions.
367    */
368   virtual SGRawValue<T> * clone () const {
369     return new SGRawValueFunctions<T>(_getter,_setter);
370   }
371
372 private:
373   getter_t _getter;
374   setter_t _setter;
375 };
376
377
378 /**
379  * An indexed value bound to static functions.
380  *
381  * A read-only value will not have a setter; a write-only value will
382  * not have a getter.  An indexed value is useful for binding one
383  * of a list of possible values (such as multiple engines for a
384  * plane).  The index is hard-coded at creation time.
385  */
386 template <class T>
387 class SGRawValueFunctionsIndexed : public SGRawValue<T>
388 {
389 public:
390   typedef T (*getter_t)(int);
391   typedef void (*setter_t)(int,T);
392   SGRawValueFunctionsIndexed (int index, getter_t getter = 0, setter_t setter = 0)
393     : _index(index), _getter(getter), _setter(setter) {}
394   virtual ~SGRawValueFunctionsIndexed () {}
395   virtual T getValue () const {
396     if (_getter) return (*_getter)(_index);
397     else return SGRawValue<T>::DefaultValue;
398   }
399   virtual bool setValue (T value) {
400     if (_setter) { (*_setter)(_index, value); return true; }
401     else return false;
402   }
403   virtual SGRawValue<T> * clone () const {
404     return new SGRawValueFunctionsIndexed<T>(_index, _getter, _setter);
405   }
406 private:
407   int _index;
408   getter_t _getter;
409   setter_t _setter;
410 };
411
412
413 /**
414  * A value managed through an object and access methods.
415  *
416  * A read-only value will not have a setter; a write-only value will
417  * not have a getter.
418  */
419 template <class C, class T>
420 class SGRawValueMethods : public SGRawValue<T>
421 {
422 public:
423   typedef T (C::*getter_t)() const;
424   typedef void (C::*setter_t)(T);
425   SGRawValueMethods (C &obj, getter_t getter = 0, setter_t setter = 0)
426     : _obj(obj), _getter(getter), _setter(setter) {}
427   virtual ~SGRawValueMethods () {}
428   virtual T getValue () const {
429     if (_getter) { return (_obj.*_getter)(); }
430     else { return SGRawValue<T>::DefaultValue; }
431   }
432   virtual bool setValue (T value) {
433     if (_setter) { (_obj.*_setter)(value); return true; }
434     else return false;
435   }
436   virtual SGRawValue<T> * clone () const {
437     return new SGRawValueMethods<C,T>(_obj, _getter, _setter);
438   }
439 private:
440   C &_obj;
441   getter_t _getter;
442   setter_t _setter;
443 };
444
445
446 /**
447  * An indexed value managed through an object and access methods.
448  *
449  * A read-only value will not have a setter; a write-only value will
450  * not have a getter.
451  */
452 template <class C, class T>
453 class SGRawValueMethodsIndexed : public SGRawValue<T>
454 {
455 public:
456   typedef T (C::*getter_t)(int) const;
457   typedef void (C::*setter_t)(int, T);
458   SGRawValueMethodsIndexed (C &obj, int index,
459                      getter_t getter = 0, setter_t setter = 0)
460     : _obj(obj), _index(index), _getter(getter), _setter(setter) {}
461   virtual ~SGRawValueMethodsIndexed () {}
462   virtual T getValue () const {
463     if (_getter) { return (_obj.*_getter)(_index); }
464     else { return SGRawValue<T>::DefaultValue; }
465   }
466   virtual bool setValue (T value) {
467     if (_setter) { (_obj.*_setter)(_index, value); return true; }
468     else return false;
469   }
470   virtual SGRawValue<T> * clone () const {
471     return new SGRawValueMethodsIndexed<C,T>(_obj, _index, _getter, _setter);
472   }
473 private:
474   C &_obj;
475   int _index;
476   getter_t _getter;
477   setter_t _setter;
478 };
479
480
481 \f
482 /**
483  * A node in a property tree.
484  */
485 class SGPropertyNode
486 {
487
488 public:
489
490
491   /**
492    * Property value types.
493    */
494   enum Type {
495     NONE,
496     ALIAS,
497     BOOL,
498     INT,
499     LONG,
500     FLOAT,
501     DOUBLE,
502     STRING,
503     UNSPECIFIED
504   };
505
506
507   /**
508    * Access mode attributes.
509    *
510    * <p>The ARCHIVE attribute is strictly advisory, and controls
511    * whether the property should normally be saved and restored.</p>
512    */
513   enum Attribute {
514     READ = 1,
515     WRITE = 2,
516     ARCHIVE = 4,
517     TRACE_READ = 8,
518     TRACE_WRITE = 16
519   };
520
521
522   /**
523    * Default constructor.
524    */
525   SGPropertyNode ();
526
527
528   /**
529    * Copy constructor.
530    */
531   SGPropertyNode (const SGPropertyNode &node);
532
533
534   /**
535    * Destructor.
536    */
537   virtual ~SGPropertyNode ();
538
539
540
541   //
542   // Basic properties.
543   //
544
545   /**
546    * Test whether this node contains a primitive leaf value.
547    */
548   bool hasValue () const { return (_type != NONE); }
549
550
551   /**
552    * Get the node's simple (XML) name.
553    */
554   const string &getName () const { return _name; }
555
556
557   /**
558    * Get the node's integer index.
559    */
560   const int getIndex () const { return _index; }
561
562
563   /**
564    * Get a non-const pointer to the node's parent.
565    */
566   SGPropertyNode * getParent () { return _parent; }
567
568
569   /**
570    * Get a const pointer to the node's parent.
571    */
572   const SGPropertyNode * getParent () const { return _parent; }
573
574
575   //
576   // Children.
577   //
578
579
580   /**
581    * Get the number of child nodes.
582    */
583   const int nChildren () const { return _children.size(); }
584
585
586   /**
587    * Get a child node by position (*NOT* index).
588    */
589   SGPropertyNode * getChild (int position);
590
591
592   /**
593    * Get a const child node by position (*NOT* index).
594    */
595   const SGPropertyNode * getChild (int position) const;
596
597
598   /**
599    * Get a child node by name and index.
600    */
601   SGPropertyNode * getChild (const string &name, int index = 0,
602                              bool create = false);
603
604
605   /**
606    * Get a const child node by name and index.
607    */
608   const SGPropertyNode * getChild (const string &name, int index = 0) const;
609
610
611   /**
612    * Get a vector of all children with the specified name.
613    */
614   vector<SGPropertyNode *> getChildren (const string &name);
615
616
617   /**
618    * Get a vector all all children (const) with the specified name.
619    */
620   vector<const SGPropertyNode *> getChildren (const string &name) const;
621
622
623   //
624   // Alias support.
625   //
626
627
628   /**
629    * Alias this node's leaf value to another's.
630    */
631   bool alias (SGPropertyNode * target);
632
633
634   /**
635    * Alias this node's leaf value to another's by relative path.
636    */
637   bool alias (const string &path);
638
639
640   /**
641    * Remove any alias for this node.
642    */
643   bool unalias ();
644
645
646   /**
647    * Test whether the node's leaf value is aliased to another's.
648    */
649   bool isAlias () const { return (_type == ALIAS); }
650
651
652   /**
653    * Get a non-const pointer to the current alias target, if any.
654    */
655   SGPropertyNode * getAliasTarget ();
656
657
658   /**
659    * Get a const pointer to the current alias target, if any.
660    */
661   const SGPropertyNode * getAliasTarget () const;
662
663
664   //
665   // Path information.
666   //
667
668
669   /**
670    * Get the path to this node from the root.
671    */
672   string getPath (bool simplify = false) const;
673
674
675   /**
676    * Get a pointer to the root node.
677    */
678   SGPropertyNode * getRootNode ();
679
680
681   /**
682    * Get a const pointer to the root node.
683    */
684   const SGPropertyNode * getRootNode () const;
685
686
687   /**
688    * Get a pointer to another node by relative path.
689    */
690   SGPropertyNode * getNode (const string &relative_path, bool create = false);
691
692
693   /**
694    * Get a pointer to another node by relative path.
695    *
696    * This method leaves the index off the last member of the path,
697    * so that the user can specify it separately (and save some
698    * string building).  For example, getNode("/bar[1]/foo", 3) is
699    * exactly equivalent to getNode("bar[1]/foo[3]").  The index
700    * provided overrides any given in the path itself for the last
701    * component.
702    */
703   SGPropertyNode * getNode (const string &relative_path, int index,
704                             bool create = false);
705
706
707   /**
708    * Get a const pointer to another node by relative path.
709    */
710   const SGPropertyNode * getNode (const string &relative_path) const;
711
712
713   /**
714    * Get a const pointer to another node by relative path.
715    *
716    * This method leaves the index off the last member of the path,
717    * so that the user can specify it separate.
718    */
719   const SGPropertyNode * getNode (const string &relative_path,
720                                   int index) const;
721
722
723   //
724   // Access Mode.
725   //
726
727   /**
728    * Check a single mode attribute for the property node.
729    */
730   bool getAttribute (Attribute attr) const { return ((_attr & attr) != 0); }
731
732
733   /**
734    * Set a single mode attribute for the property node.
735    */
736   void setAttribute (Attribute attr, bool state) {
737     (state ? _attr |= attr : _attr &= ~attr);
738   }
739
740
741   /**
742    * Get all of the mode attributes for the property node.
743    */
744   int getAttributes () const { return _attr; }
745
746
747   /**
748    * Set all of the mode attributes for the property node.
749    */
750   void setAttributes (int attr) { _attr = attr; }
751   
752
753   //
754   // Leaf Value (primitive).
755   //
756
757
758   /**
759    * Get the type of leaf value, if any, for this node.
760    */
761   Type getType () const;
762
763
764   /**
765    * Get a bool value for this node.
766    */
767   bool getBoolValue () const;
768
769
770   /**
771    * Get an int value for this node.
772    */
773   int getIntValue () const;
774
775
776   /**
777    * Get a long int value for this node.
778    */
779   long getLongValue () const;
780
781
782   /**
783    * Get a float value for this node.
784    */
785   float getFloatValue () const;
786
787
788   /**
789    * Get a double value for this node.
790    */
791   double getDoubleValue () const;
792
793
794   /**
795    * Get a string value for this node.
796    */
797   string getStringValue () const;
798
799
800
801   /**
802    * Set a bool value for this node.
803    */
804   bool setBoolValue (bool value);
805
806
807   /**
808    * Set an int value for this node.
809    */
810   bool setIntValue (int value);
811
812
813   /**
814    * Set a long int value for this node.
815    */
816   bool setLongValue (long value);
817
818
819   /**
820    * Set a float value for this node.
821    */
822   bool setFloatValue (float value);
823
824
825   /**
826    * Set a double value for this node.
827    */
828   bool setDoubleValue (double value);
829
830
831   /**
832    * Set a string value for this node.
833    */
834   bool setStringValue (string value);
835
836
837   /**
838    * Set a value of unspecified type for this node.
839    */
840   bool setUnspecifiedValue (string value);
841
842
843   //
844   // Data binding.
845   //
846
847
848   /**
849    * Test whether this node is bound to an external data source.
850    */
851   bool isTied () const { return _tied; }
852
853
854   /**
855    * Bind this node to an external bool source.
856    */
857   bool tie (const SGRawValue<bool> &rawValue, bool useDefault = true);
858
859
860   /**
861    * Bind this node to an external int source.
862    */
863   bool tie (const SGRawValue<int> &rawValue, bool useDefault = true);
864
865
866   /**
867    * Bind this node to an external long int source.
868    */
869   bool tie (const SGRawValue<long> &rawValue, bool useDefault = true);
870
871
872   /**
873    * Bind this node to an external float source.
874    */
875   bool tie (const SGRawValue<float> &rawValue, bool useDefault = true);
876
877
878   /**
879    * Bind this node to an external double source.
880    */
881   bool tie (const SGRawValue<double> &rawValue, bool useDefault = true);
882
883
884   /**
885    * Bind this node to an external string source.
886    */
887   bool tie (const SGRawValue<string> &rawValue, bool useDefault = true);
888
889
890   /**
891    * Unbind this node from any external data source.
892    */
893   bool untie ();
894
895
896   //
897   // Convenience methods using paths.
898   // TODO: add attribute methods
899   //
900
901
902   /**
903    * Get another node's type.
904    */
905   Type getType (const string &relative_path) const;
906
907
908   /**
909    * Test whether another node has a leaf value.
910    */
911   bool hasValue (const string &relative_path) const;
912
913
914   /**
915    * Get another node's value as a bool.
916    */
917   bool getBoolValue (const string &relative_path,
918                      bool defaultValue = false) const;
919
920
921   /**
922    * Get another node's value as an int.
923    */
924   int getIntValue (const string &relative_path,
925                    int defaultValue = 0) const;
926
927
928   /**
929    * Get another node's value as a long int.
930    */
931   long getLongValue (const string &relative_path,
932                      long defaultValue = 0L) const;
933
934
935   /**
936    * Get another node's value as a float.
937    */
938   float getFloatValue (const string &relative_path,
939                        float defaultValue = 0.0) const;
940
941
942   /**
943    * Get another node's value as a double.
944    */
945   double getDoubleValue (const string &relative_path,
946                          double defaultValue = 0.0L) const;
947
948
949   /**
950    * Get another node's value as a string.
951    */
952   string getStringValue (const string &relative_path,
953                          string defaultValue = "") const;
954
955
956   /**
957    * Set another node's value as a bool.
958    */
959   bool setBoolValue (const string &relative_path, bool value);
960
961
962   /**
963    * Set another node's value as an int.
964    */
965   bool setIntValue (const string &relative_path, int value);
966
967
968   /**
969    * Set another node's value as a long int.
970    */
971   bool setLongValue (const string &relative_path, long value);
972
973
974   /**
975    * Set another node's value as a float.
976    */
977   bool setFloatValue (const string &relative_path, float value);
978
979
980   /**
981    * Set another node's value as a double.
982    */
983   bool setDoubleValue (const string &relative_path, double value);
984
985
986   /**
987    * Set another node's value as a string.
988    */
989   bool setStringValue (const string &relative_path, string value);
990
991
992   /**
993    * Set another node's value with no specified type.
994    */
995   bool setUnspecifiedValue (const string &relative_path, string value);
996
997
998   /**
999    * Test whether another node is bound to an external data source.
1000    */
1001   bool isTied (const string &relative_path) const;
1002
1003
1004   /**
1005    * Bind another node to an external bool source.
1006    */
1007   bool tie (const string &relative_path, const SGRawValue<bool> &rawValue,
1008             bool useDefault = true);
1009
1010
1011   /**
1012    * Bind another node to an external int source.
1013    */
1014   bool tie (const string &relative_path, const SGRawValue<int> &rawValue,
1015             bool useDefault = true);
1016
1017
1018   /**
1019    * Bind another node to an external long int source.
1020    */
1021   bool tie (const string &relative_path, const SGRawValue<long> &rawValue,
1022             bool useDefault = true);
1023
1024
1025   /**
1026    * Bind another node to an external float source.
1027    */
1028   bool tie (const string &relative_path, const SGRawValue<float> &rawValue,
1029             bool useDefault = true);
1030
1031
1032   /**
1033    * Bind another node to an external double source.
1034    */
1035   bool tie (const string &relative_path, const SGRawValue<double> &rawValue,
1036             bool useDefault = true);
1037
1038
1039   /**
1040    * Bind another node to an external string source.
1041    */
1042   bool tie (const string &relative_path, const SGRawValue<string> &rawValue,
1043             bool useDefault = true);
1044
1045
1046   /**
1047    * Unbind another node from any external data source.
1048    */
1049   bool untie (const string &relative_path);
1050
1051
1052 protected:
1053
1054
1055   /**
1056    * Protected constructor for making new nodes on demand.
1057    */
1058   SGPropertyNode (const string &name, int index, SGPropertyNode * parent);
1059
1060
1061 private:
1062
1063
1064   /**
1065    * Clear any existing value and set the type to NONE.
1066    */
1067   void clear_value ();
1068
1069
1070   /**
1071    * Get the value as a string.
1072    */
1073   string get_string () const;
1074
1075
1076   /**
1077    * Trace a read access.
1078    */
1079   void trace_read (Type accessType) const;
1080
1081
1082   /**
1083    * Trace a write access.
1084    */
1085   void trace_write (Type accessType) const;
1086
1087   string _name;
1088   int _index;
1089   SGPropertyNode * _parent;
1090   vector<SGPropertyNode *> _children;
1091   typedef map<const string,SGPropertyNode *> cache_map;
1092   cache_map * _path_cache;
1093   Type _type;
1094   bool _tied;
1095   int _attr;
1096
1097                                 // The right kind of pointer...
1098   union {
1099     SGPropertyNode * alias;
1100     SGRawValue<bool> * bool_val;
1101     SGRawValue<int> * int_val;
1102     SGRawValue<long> * long_val;
1103     SGRawValue<float> * float_val;
1104     SGRawValue<double> * double_val;
1105     SGRawValue<string> * string_val;
1106   } _value;
1107
1108
1109 };
1110
1111
1112 \f
1113 ////////////////////////////////////////////////////////////////////////
1114 // I/O functions.
1115 ////////////////////////////////////////////////////////////////////////
1116
1117
1118 /**
1119  * Read properties from an XML input stream.
1120  */
1121 void readProperties (istream &input, SGPropertyNode * start_node,
1122                      const string &base = "");
1123
1124
1125 /**
1126  * Read properties from an XML file.
1127  */
1128 void readProperties (const string &file, SGPropertyNode * start_node);
1129
1130
1131 /**
1132  * Write properties to an XML output stream.
1133  */
1134 void writeProperties (ostream &output, const SGPropertyNode * start_node);
1135
1136
1137 /**
1138  * Write properties to an XML file.
1139  */
1140 void writeProperties (const string &file, const SGPropertyNode * start_node);
1141
1142
1143 /**
1144  * Copy properties from one node to another.
1145  */
1146 bool copyProperties (const SGPropertyNode *in, SGPropertyNode *out);
1147
1148
1149 #endif // __PROPS_HXX
1150
1151 // end of props.hxx