]> git.mxchange.org Git - simgear.git/blob - simgear/misc/props.cxx
- added missing return statement for getAliasTarget
[simgear.git] / simgear / misc / props.cxx
1 // props.cxx - implementation of a property list.
2 // Started Fall 2000 by David Megginson, david@megginson.com
3 // This code is released into the Public Domain.
4 //
5 // See props.html for documentation [replace with URL when available].
6 //
7 // $Id$
8
9 #include <simgear/compiler.h>
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include STL_IOSTREAM
14 #include <algorithm>
15 #include "props.hxx"
16
17 SG_USING_STD(sort);
18
19
20 \f
21 ////////////////////////////////////////////////////////////////////////
22 // Local classes.
23 ////////////////////////////////////////////////////////////////////////
24
25 /**
26  * Comparator class for sorting by index.
27  */
28 class CompareIndices
29 {
30 public:
31   int operator() (const SGPropertyNode * n1, const SGPropertyNode *n2) const {
32     return (n1->getIndex() < n2->getIndex());
33   }
34 };
35
36
37 \f
38 ////////////////////////////////////////////////////////////////////////
39 // Convenience macros for value access.
40 ////////////////////////////////////////////////////////////////////////
41
42 #define GET_BOOL (_value.bool_val->getValue())
43 #define GET_INT (_value.int_val->getValue())
44 #define GET_LONG (_value.long_val->getValue())
45 #define GET_FLOAT (_value.float_val->getValue())
46 #define GET_DOUBLE (_value.double_val->getValue())
47 #define GET_STRING (_value.string_val->getValue())
48
49 #define SET_BOOL(val) (_value.bool_val->setValue(val))
50 #define SET_INT(val) (_value.int_val->setValue(val))
51 #define SET_LONG(val) (_value.long_val->setValue(val))
52 #define SET_FLOAT(val) (_value.float_val->setValue(val))
53 #define SET_DOUBLE(val) (_value.double_val->setValue(val))
54 #define SET_STRING(val) (_value.string_val->setValue(val))
55
56
57 \f
58 ////////////////////////////////////////////////////////////////////////
59 // Default values for every type.
60 ////////////////////////////////////////////////////////////////////////
61
62 const bool SGRawValue<bool>::DefaultValue = false;
63 const int SGRawValue<int>::DefaultValue = 0;
64 const long SGRawValue<long>::DefaultValue = 0L;
65 const float SGRawValue<float>::DefaultValue = 0.0;
66 const double SGRawValue<double>::DefaultValue = 0.0L;
67 const string SGRawValue<string>::DefaultValue = "";
68
69
70 \f
71 ////////////////////////////////////////////////////////////////////////
72 // Local path normalization code.
73 ////////////////////////////////////////////////////////////////////////
74
75 /**
76  * A component in a path.
77  */
78 struct PathComponent
79 {
80   string name;
81   int index;
82 };
83
84 /**
85  * Parse the name for a path component.
86  *
87  * Name: [_a-zA-Z][-._a-zA-Z0-9]*
88  */
89 static inline string
90 parse_name (const string &path, int &i)
91 {
92   string name = "";
93   int max = path.size();
94
95   if (path[i] == '.') {
96     i++;
97     if (i < max && path[i] == '.') {
98       i++;
99       name = "..";
100     } else {
101       name = ".";
102     }
103     if (i < max && path[i] != '/')
104       throw string(string("Illegal character after ") + name);
105   }
106
107   else if (isalpha(path[i]) || path[i] == '_') {
108     name += path[i];
109     i++;
110
111                                 // The rules inside a name are a little
112                                 // less restrictive.
113     while (i < max) {
114       if (isalpha(path[i]) || isdigit(path[i]) || path[i] == '_' ||
115           path[i] == '-' || path[i] == '.') {
116         name += path[i];
117       } else if (path[i] == '[' || path[i] == '/') {
118         break;
119       } else {
120         throw string("name may contain only ._- and alphanumeric characters");
121       }
122       i++;
123     }
124   }
125
126   else {
127     if (name.size() == 0)
128       throw string("name must begin with alpha or '_'");
129   }
130
131   return name;
132 }
133
134
135 /**
136  * Parse the optional integer index for a path component.
137  *
138  * Index: "[" [0-9]+ "]"
139  */
140 static inline int
141 parse_index (const string &path, int &i)
142 {
143   int index = 0;
144
145   if (path[i] != '[')
146     return 0;
147   else
148     i++;
149
150   for (int max = path.size(); i < max; i++) {
151     if (isdigit(path[i])) {
152       index = (index * 10) + (path[i] - '0');
153     } else if (path[i] == ']') {
154       i++;
155       return index;
156     } else {
157       break;
158     }
159   }
160
161   throw string("unterminated index (looking for ']')");
162 }
163
164
165 /**
166  * Parse a single path component.
167  *
168  * Component: Name Index?
169  */
170 static inline PathComponent
171 parse_component (const string &path, int &i)
172 {
173   PathComponent component;
174   component.name = parse_name(path, i);
175   if (component.name[0] != '.')
176     component.index = parse_index(path, i);
177   else
178     component.index = -1;
179   return component;
180 }
181
182
183 /**
184  * Parse a path into its components.
185  */
186 static void
187 parse_path (const string &path, vector<PathComponent> &components)
188 {
189   int pos = 0;
190   int max = path.size();
191
192                                 // Check for initial '/'
193   if (path[pos] == '/') {
194     PathComponent root;
195     root.name = "";
196     root.index = -1;
197     components.push_back(root);
198     pos++;
199     while (pos < max && path[pos] == '/')
200       pos++;
201   }
202
203   while (pos < max) {
204     components.push_back(parse_component(path, pos));
205     while (pos < max && path[pos] == '/')
206       pos++;
207   }
208 }
209
210
211 \f
212 ////////////////////////////////////////////////////////////////////////
213 // Other static utility functions.
214 ////////////////////////////////////////////////////////////////////////
215
216
217 /**
218  * Locate a child node by name and index.
219  */
220 static int
221 find_child (const string &name, int index, vector<SGPropertyNode *> nodes)
222 {
223   int nNodes = nodes.size();
224   for (int i = 0; i < nNodes; i++) {
225     SGPropertyNode * node = nodes[i];
226     if (node->getName() == name && node->getIndex() == index)
227       return i;
228   }
229   return -1;
230 }
231
232
233 /**
234  * Locate another node, given a relative path.
235  */
236 static SGPropertyNode *
237 find_node (SGPropertyNode * current,
238            const vector<PathComponent> &components,
239            int position,
240            bool create)
241 {
242                                 // Run off the end of the list
243   if (current == 0) {
244     return 0;
245   }
246
247                                 // Success! This is the one we want.
248   else if (position >= (int)components.size()) {
249     return current;
250   }
251
252                                 // Empty component means root.
253   else if (components[position].name == "") {
254     return find_node(current->getRootNode(), components, position + 1, create);
255   }
256
257                                 // . means current directory
258   else if (components[position].name == ".") {
259     return find_node(current, components, position + 1, create);
260   }
261
262                                 // .. means parent directory
263   else if (components[position].name == "..") {
264     SGPropertyNode * parent = current->getParent();
265     if (parent == 0)
266       throw string("Attempt to move past root with '..'");
267     else
268       return find_node(parent, components, position + 1, create);
269   }
270
271                                 // Otherwise, a child name
272   else {
273     SGPropertyNode * child =
274       current->getChild(components[position].name,
275                         components[position].index,
276                         create);
277     return find_node(child, components, position + 1, create);
278   }
279 }
280
281
282 \f
283 ////////////////////////////////////////////////////////////////////////
284 // Implementation of SGValue.
285 ////////////////////////////////////////////////////////////////////////
286
287
288 /**
289  * Default constructor.
290  *
291  * The type will be UNKNOWN and the raw value will be "".
292  */
293 SGValue::SGValue ()
294   : _type(UNKNOWN), _tied(false)
295 {
296   _value.string_val = new SGRawValueInternal<string>;
297 }
298
299
300 /**
301  * Copy constructor.
302  */
303 SGValue::SGValue (const SGValue &source)
304 {
305   _type = source._type;
306   _tied = source._tied;
307   switch (source._type) {
308   case ALIAS:
309                                 // FIXME!!!
310     _value.alias = (SGValue *)(source.getAlias());
311     break;
312   case BOOL:
313     _value.bool_val = source._value.bool_val->clone();
314     break;
315   case INT:
316     _value.int_val = source._value.int_val->clone();
317     break;
318   case LONG:
319     _value.long_val = source._value.long_val->clone();
320     break;
321   case FLOAT:
322     _value.float_val = source._value.float_val->clone();
323     break;
324   case DOUBLE:
325     _value.double_val = source._value.double_val->clone();
326     break;
327   case STRING:
328   case UNKNOWN:
329     _value.string_val = source._value.string_val->clone();
330     break;
331   }
332 }
333
334
335 /**
336  * Destructor.
337  */
338 SGValue::~SGValue ()
339 {
340   if (_type != ALIAS)
341     clear_value();
342 }
343
344
345 /**
346  * Delete and clear the current value.
347  */
348 void
349 SGValue::clear_value ()
350 {
351   switch (_type) {
352   case ALIAS:
353     _value.alias->clear_value();
354   case BOOL:
355     delete _value.bool_val;
356     _value.bool_val = 0;
357     break;
358   case INT:
359     delete _value.int_val;
360     _value.int_val = 0;
361     break;
362   case LONG:
363     delete _value.long_val;
364     _value.long_val = 0L;
365     break;
366   case FLOAT:
367     delete _value.float_val;
368     _value.float_val = 0;
369     break;
370   case DOUBLE:
371     delete _value.double_val;
372     _value.double_val = 0;
373     break;
374   case STRING:
375   case UNKNOWN:
376     delete _value.string_val;
377     _value.string_val = 0;
378     break;
379   }
380 }
381
382
383 /**
384  * Get the current type.
385  *
386  * Does not return a type of ALIAS.
387  */
388 SGValue::Type
389 SGValue::getType () const
390 {
391   if (_type == ALIAS)
392     return _value.alias->getType();
393   else
394     return (Type)_type;
395 }
396
397
398 /**
399  * Get the current aliased value.
400  */
401 SGValue *
402 SGValue::getAlias ()
403 {
404   return (_type == ALIAS ? _value.alias : 0);
405 }
406
407
408 /**
409  * Get the current aliased value.
410  */
411 const SGValue *
412 SGValue::getAlias () const
413 {
414   return (_type == ALIAS ? _value.alias : 0);
415 }
416
417
418 /**
419  * Alias to another value.
420  */
421 bool
422 SGValue::alias (SGValue * alias)
423 {
424   if (alias == 0 || _type == ALIAS || _tied)
425     return false;
426   clear_value();
427   _value.alias = alias;
428   _type = ALIAS;
429   return true;
430 }
431
432
433 /**
434  * Unalias from another value.
435  */
436 bool
437 SGValue::unalias ()
438 {
439                                 // FIXME: keep copy of previous value,
440                                 // as with untie()
441   if (_type != ALIAS)
442     return false;
443   _value.string_val = new SGRawValueInternal<string>;
444   _type = UNKNOWN;
445   return true;
446 }
447
448
449 /**
450  * Get a boolean value.
451  */
452 bool
453 SGValue::getBoolValue () const
454 {
455   switch (_type) {
456   case ALIAS:
457     return _value.alias->getBoolValue();
458   case BOOL:
459     return GET_BOOL;
460   case INT:
461     return GET_INT == 0 ? false : true;
462   case LONG:
463     return GET_LONG == 0L ? false : true;
464   case FLOAT:
465     return GET_FLOAT == 0.0 ? false : true;
466   case DOUBLE:
467     return GET_DOUBLE == 0.0L ? false : true;
468   case STRING:
469   case UNKNOWN:
470     return (GET_STRING == "true" || getDoubleValue() != 0.0L);
471   }
472
473   return false;
474 }
475
476
477 /**
478  * Get an integer value.
479  */
480 int
481 SGValue::getIntValue () const
482 {
483   switch (_type) {
484   case ALIAS:
485     return _value.alias->getIntValue();
486   case BOOL:
487     return int(GET_BOOL);
488   case INT:
489     return GET_INT;
490   case LONG:
491     return int(GET_LONG);
492   case FLOAT:
493     return int(GET_FLOAT);
494   case DOUBLE:
495     return int(GET_DOUBLE);
496   case STRING:
497   case UNKNOWN:
498     return atoi(GET_STRING.c_str());
499   }
500
501   return 0;
502 }
503
504
505 /**
506  * Get a long integer value.
507  */
508 long
509 SGValue::getLongValue () const
510 {
511   switch (_type) {
512   case ALIAS:
513     return _value.alias->getLongValue();
514   case BOOL:
515     return long(GET_BOOL);
516   case INT:
517     return long(GET_INT);
518   case LONG:
519     return GET_LONG;
520   case FLOAT:
521     return long(GET_FLOAT);
522   case DOUBLE:
523     return long(GET_DOUBLE);
524   case STRING:
525   case UNKNOWN:
526     return strtol(GET_STRING.c_str(), 0, 0);
527   }
528 }
529
530
531 /**
532  * Get a float value.
533  */
534 float
535 SGValue::getFloatValue () const
536 {
537   switch (_type) {
538   case ALIAS:
539     return _value.alias->getFloatValue();
540   case BOOL:
541     return float(GET_BOOL);
542   case INT:
543     return float(GET_INT);
544   case LONG:
545     return float(GET_LONG);
546   case FLOAT:
547     return GET_FLOAT;
548   case DOUBLE:
549     return float(GET_DOUBLE);
550   case STRING:
551   case UNKNOWN:
552     return atof(GET_STRING.c_str());
553   }
554
555   return 0.0;
556 }
557
558
559 /**
560  * Get a double value.
561  */
562 double
563 SGValue::getDoubleValue () const
564 {
565   switch (_type) {
566   case ALIAS:
567     return _value.alias->getDoubleValue();
568   case BOOL:
569     return double(GET_BOOL);
570   case INT:
571     return double(GET_INT);
572   case LONG:
573     return double(GET_LONG);
574   case FLOAT:
575     return double(GET_FLOAT);
576   case DOUBLE:
577     return GET_DOUBLE;
578   case STRING:
579   case UNKNOWN:
580     return strtod(GET_STRING.c_str(), 0);
581   }
582
583   return 0.0;
584 }
585
586
587 /**
588  * Get a string value.
589  */
590 string
591 SGValue::getStringValue () const
592 {
593   char buf[128];
594
595   switch (_type) {
596   case ALIAS:
597     return _value.alias->getStringValue();
598   case BOOL:
599     if (GET_BOOL)
600       return "true";
601     else
602       return "false";
603   case INT:
604     sprintf(buf, "%d", GET_INT);
605     return buf;
606   case LONG:
607     sprintf(buf, "%ld", GET_LONG);
608     return buf;
609   case FLOAT:
610     sprintf(buf, "%f", GET_FLOAT);
611     return buf;
612   case DOUBLE:
613     sprintf(buf, "%f", GET_DOUBLE);
614     return buf;
615   case STRING:
616   case UNKNOWN:
617     return GET_STRING;
618   }
619
620   return "";
621 }
622
623
624 /**
625  * Set a bool value.
626  */
627 bool
628 SGValue::setBoolValue (bool value)
629 {
630   if (_type == UNKNOWN) {
631     clear_value();
632     _value.bool_val = new SGRawValueInternal<bool>;
633     _type = BOOL;
634   }
635
636   switch (_type) {
637   case ALIAS:
638     return _value.alias->setBoolValue(value);
639   case BOOL:
640     return SET_BOOL(value);
641   case INT:
642     return SET_INT(int(value));
643   case LONG:
644     return SET_LONG(long(value));
645   case FLOAT:
646     return SET_FLOAT(float(value));
647   case DOUBLE:
648     return SET_DOUBLE(double(value));
649   case STRING:
650     return SET_STRING(value ? "true" : "false");
651   }
652
653   return false;
654 }
655
656
657 /**
658  * Set an int value.
659  */
660 bool
661 SGValue::setIntValue (int value)
662 {
663   if (_type == UNKNOWN) {
664     clear_value();
665     _value.int_val = new SGRawValueInternal<int>;
666     _type = INT;
667   }
668
669   switch (_type) {
670   case ALIAS:
671     return _value.alias->setIntValue(value);
672   case BOOL:
673     return SET_BOOL(value == 0 ? false : true);
674   case INT:
675     return SET_INT(value);
676   case LONG:
677     return SET_LONG(long(value));
678   case FLOAT:
679     return SET_FLOAT(float(value));
680   case DOUBLE:
681     return SET_DOUBLE(double(value));
682   case STRING: {
683     char buf[128];
684     sprintf(buf, "%d", value);
685     return SET_STRING(buf);
686   }
687   }
688
689   return false;
690 }
691
692
693 /**
694  * Set a long value.
695  */
696 bool
697 SGValue::setLongValue (long value)
698 {
699   if (_type == UNKNOWN) {
700     clear_value();
701     _value.long_val = new SGRawValueInternal<long>;
702     _type = LONG;
703   }
704
705   switch (_type) {
706   case ALIAS:
707     return _value.alias->setLongValue(value);
708   case BOOL:
709     return SET_BOOL(value == 0L ? false : true);
710   case INT:
711     return SET_INT(int(value));
712   case LONG:
713     return SET_LONG(value);
714   case FLOAT:
715     return SET_FLOAT(float(value));
716   case DOUBLE:
717     return SET_DOUBLE(double(value));
718   case STRING: {
719     char buf[128];
720     sprintf(buf, "%d", value);
721     return SET_STRING(buf);
722   }
723   }
724
725   return false;
726 }
727
728
729 /**
730  * Set a float value.
731  */
732 bool
733 SGValue::setFloatValue (float value)
734 {
735   if (_type == UNKNOWN) {
736     clear_value();
737     _value.float_val = new SGRawValueInternal<float>;
738     _type = FLOAT;
739   }
740
741   switch (_type) {
742   case ALIAS:
743     return _value.alias->setFloatValue(value);
744   case BOOL:
745     return SET_BOOL(value == 0.0 ? false : true);
746   case INT:
747     return SET_INT(int(value));
748   case LONG:
749     return SET_LONG(long(value));
750   case FLOAT:
751     return SET_FLOAT(value);
752   case DOUBLE:
753     return SET_DOUBLE(double(value));
754   case STRING: {
755     char buf[128];
756     sprintf(buf, "%f", value);
757     return SET_STRING(buf);
758   }
759   }
760
761   return false;
762 }
763
764
765 /**
766  * Set a double value.
767  */
768 bool
769 SGValue::setDoubleValue (double value)
770 {
771   if (_type == UNKNOWN) {
772     clear_value();
773     _value.double_val = new SGRawValueInternal<double>;
774     _type = DOUBLE;
775   }
776
777   switch (_type) {
778   case ALIAS:
779     return _value.alias->setDoubleValue(value);
780   case BOOL:
781     return SET_BOOL(value == 0.0L ? false : true);
782   case INT:
783     return SET_INT(int(value));
784   case LONG:
785     return SET_LONG(long(value));
786   case FLOAT:
787     return SET_FLOAT(float(value));
788   case DOUBLE:
789     return SET_DOUBLE(value);
790   case STRING: {
791     char buf[128];
792     sprintf(buf, "%lf", value);
793     return SET_STRING(buf);
794   }
795   }
796
797   return false;
798 }
799
800
801 /**
802  * Set a string value.
803  */
804 bool
805 SGValue::setStringValue (string value)
806 {
807   if (_type == UNKNOWN) {
808     clear_value();
809     _value.string_val = new SGRawValueInternal<string>;
810     _type = STRING;
811   }
812
813   switch (_type) {
814   case ALIAS:
815     return _value.alias->setStringValue(value);
816   case BOOL:
817     return SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false);
818   case INT:
819     return SET_INT(atoi(value.c_str()));
820   case LONG:
821     return SET_LONG(strtol(value.c_str(), 0, 0));
822   case FLOAT:
823     return SET_FLOAT(atof(value.c_str()));
824   case DOUBLE:
825     return SET_DOUBLE(strtod(value.c_str(), 0));
826   case STRING:
827     return SET_STRING(value);
828   }
829
830   return false;
831 }
832
833
834 /**
835  * Set a value of unknown type (stored as a string).
836  */
837 bool
838 SGValue::setUnknownValue (string value)
839 {
840   switch (_type) {
841   case ALIAS:
842     return _value.alias->setUnknownValue(value);
843   case BOOL:
844     return SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false);
845   case INT:
846     return SET_INT(atoi(value.c_str()));
847   case LONG:
848     return SET_LONG(strtol(value.c_str(), 0, 0));
849   case FLOAT:
850     return SET_FLOAT(atof(value.c_str()));
851   case DOUBLE:
852     return SET_DOUBLE(strtod(value.c_str(), 0));
853   case STRING:
854   case UNKNOWN:
855     return SET_STRING(value);
856   }
857
858   return false;
859 }
860
861
862 /**
863  * Tie a bool value.
864  */
865 bool
866 SGValue::tie (const SGRawValue<bool> &value, bool use_default)
867 {
868   if (_type == ALIAS)
869     return _value.alias->tie(value, use_default);
870   else if (_tied)
871     return false;
872
873   bool old_val = false;
874   if (use_default)
875     old_val = getBoolValue();
876
877   clear_value();
878   _type = BOOL;
879   _tied = true;
880   _value.bool_val = value.clone();
881
882   if (use_default)
883     setBoolValue(old_val);
884
885   return true;
886 }
887
888
889 /**
890  * Tie an int value.
891  */
892 bool
893 SGValue::tie (const SGRawValue<int> &value, bool use_default)
894 {
895   if (_type == ALIAS)
896     return _value.alias->tie(value, use_default);
897   else if (_tied)
898     return false;
899
900   int old_val = 0;
901   if (use_default)
902     old_val = getIntValue();
903
904   clear_value();
905   _type = INT;
906   _tied = true;
907   _value.int_val = value.clone();
908
909   if (use_default)
910     setIntValue(old_val);
911
912   return true;
913 }
914
915
916 /**
917  * Tie a long value.
918  */
919 bool
920 SGValue::tie (const SGRawValue<long> &value, bool use_default)
921 {
922   if (_type == ALIAS)
923     return _value.alias->tie(value, use_default);
924   else if (_tied)
925     return false;
926
927   long old_val;
928   if (use_default)
929     old_val = getLongValue();
930
931   clear_value();
932   _type = LONG;
933   _tied = true;
934   _value.long_val = value.clone();
935
936   if (use_default)
937     setLongValue(old_val);
938
939   return true;
940 }
941
942
943 /**
944  * Tie a float value.
945  */
946 bool
947 SGValue::tie (const SGRawValue<float> &value, bool use_default)
948 {
949   if (_type == ALIAS)
950     return _value.alias->tie(value, use_default);
951   else if (_tied)
952     return false;
953
954   float old_val = 0.0;
955   if (use_default)
956     old_val = getFloatValue();
957
958   clear_value();
959   _type = FLOAT;
960   _tied = true;
961   _value.float_val = value.clone();
962
963   if (use_default)
964     setFloatValue(old_val);
965
966   return true;
967 }
968
969
970 /**
971  * Tie a double value.
972  */
973 bool
974 SGValue::tie (const SGRawValue<double> &value, bool use_default)
975 {
976   if (_type == ALIAS)
977     return _value.alias->tie(value, use_default);
978   else if (_tied)
979     return false;
980
981   double old_val = 0.0;
982   if (use_default)
983     old_val = getDoubleValue();
984
985   clear_value();
986   _type = DOUBLE;
987   _tied = true;
988   _value.double_val = value.clone();
989
990   if (use_default)
991     setDoubleValue(old_val);
992
993   return true;
994 }
995
996
997 /**
998  * Tie a string value.
999  */
1000 bool
1001 SGValue::tie (const SGRawValue<string> &value, bool use_default)
1002 {
1003   if (_type == ALIAS)
1004     return _value.alias->tie(value, use_default);
1005   else if (_tied)
1006     return false;
1007
1008   string old_val;
1009   if (use_default)
1010     old_val = getStringValue();
1011
1012   clear_value();
1013   _type = STRING;
1014   _tied = true;
1015   _value.string_val = value.clone();
1016
1017   if (use_default)
1018     setStringValue(old_val);
1019
1020   return true;
1021 }
1022
1023
1024 /**
1025  * Untie a value.
1026  */
1027 bool
1028 SGValue::untie ()
1029 {
1030   if (!_tied)
1031     return false;
1032
1033   switch (_type) {
1034   case ALIAS: {
1035     return _value.alias->untie();
1036   }
1037   case BOOL: {
1038     bool val = getBoolValue();
1039     clear_value();
1040     _value.bool_val = new SGRawValueInternal<bool>;
1041     SET_BOOL(val);
1042     break;
1043   }
1044   case INT: {
1045     int val = getIntValue();
1046     clear_value();
1047     _value.int_val = new SGRawValueInternal<int>;
1048     SET_INT(val);
1049     break;
1050   }
1051   case LONG: {
1052     long val = getLongValue();
1053     clear_value();
1054     _value.long_val = new SGRawValueInternal<long>;
1055     SET_LONG(val);
1056     break;
1057   }
1058   case FLOAT: {
1059     float val = getFloatValue();
1060     clear_value();
1061     _value.float_val = new SGRawValueInternal<float>;
1062     SET_FLOAT(val);
1063     break;
1064   }
1065   case DOUBLE: {
1066     double val = getDoubleValue();
1067     clear_value();
1068     _value.double_val = new SGRawValueInternal<double>;
1069     SET_DOUBLE(val);
1070     break;
1071   }
1072   case STRING: {
1073     string val = getStringValue();
1074     clear_value();
1075     _value.string_val = new SGRawValueInternal<string>;
1076     SET_STRING(val);
1077     break;
1078   }
1079   }
1080
1081   _tied = false;
1082   return true;
1083 }
1084
1085
1086 \f
1087 ////////////////////////////////////////////////////////////////////////
1088 // Implementation of SGPropertyNode.
1089 ////////////////////////////////////////////////////////////////////////
1090
1091
1092 /**
1093  * Utility function: given a value, find the property node.
1094  */
1095 static SGPropertyNode *
1096 find_node_by_value (SGPropertyNode * start_node, const SGValue * value)
1097 {
1098   if (start_node->getValue() == value) {
1099     return start_node;
1100   } else for (int i = 0; i < start_node->nChildren(); i++) {
1101     SGPropertyNode * child =
1102       find_node_by_value(start_node->getChild(i), value);
1103     if (child != 0)
1104       return child;
1105   }
1106   return 0;
1107 }
1108
1109
1110 /**
1111  * Default constructor: always creates a root node.
1112  */
1113 SGPropertyNode::SGPropertyNode ()
1114   : _value(0), _name(""), _index(0), _parent(0), _target(0)
1115 {
1116 }
1117
1118
1119 /**
1120  * Convenience constructor.
1121  */
1122 SGPropertyNode::SGPropertyNode (const string &name,
1123                                 int index, SGPropertyNode * parent)
1124   : _value(0), _name(name), _index(index), _parent(parent), _target(0)
1125 {
1126 }
1127
1128
1129 /**
1130  * Destructor.
1131  */
1132 SGPropertyNode::~SGPropertyNode ()
1133 {
1134   delete _value;
1135   for (int i = 0; i < (int)_children.size(); i++)
1136     delete _children[i];
1137 }
1138
1139
1140 /**
1141  * Get a value, optionally creating it if not present.
1142  */
1143 SGValue *
1144 SGPropertyNode::getValue (bool create)
1145 {
1146   if (_value == 0 && create)
1147     _value = new SGValue();
1148   return _value;
1149 }
1150
1151
1152 /**
1153  * Alias to another node.
1154  */
1155 bool
1156 SGPropertyNode::alias (SGPropertyNode * target)
1157 {
1158   if (_value == 0)
1159     _value = new SGValue();
1160   _target = target;
1161   return _value->alias(target->getValue(true));
1162 }
1163
1164
1165 /**
1166  * Alias to another node by path.
1167  */
1168 bool
1169 SGPropertyNode::alias (const string &path)
1170 {
1171   return alias(getNode(path, true));
1172 }
1173
1174
1175 /**
1176  * Remove an alias.
1177  */
1178 bool
1179 SGPropertyNode::unalias ()
1180 {
1181   _target = 0;
1182   return (_value != 0 ? _value->unalias() : false);
1183 }
1184
1185
1186 /**
1187  * Test whether this node is aliased.
1188  */
1189 bool
1190 SGPropertyNode::isAlias () const
1191 {
1192   return (_value != 0 ? _value->isAlias() : false);
1193 }
1194
1195
1196 /**
1197  * Get the target of an alias.
1198  *
1199  * This is tricky, because it is actually the value that is aliased,
1200  * and someone could realias or unalias the value directly without
1201  * going through the property node.  The node caches its best guess,
1202  * but it may have to search the whole property tree.
1203  *
1204  * @return The target node for the alias, or 0 if the node is not aliased.
1205  */
1206 SGPropertyNode *
1207 SGPropertyNode::getAliasTarget ()
1208 {
1209   if (_value == 0 || !_value->isAlias()) {
1210     return 0;
1211   } else if (_target != 0 && _target->getValue() == _value->getAlias()) {
1212     return _target;
1213   } else {
1214     _target = find_node_by_value(getRootNode(), _value->getAlias());
1215     return _target;
1216   }
1217 }
1218
1219
1220 const SGPropertyNode *
1221 SGPropertyNode::getAliasTarget () const
1222 {
1223   if (_value == 0 || !_value->isAlias()) {
1224     return 0;
1225   } else if (_target != 0 && _target->getValue() == _value->getAlias()) {
1226     return _target;
1227   } else {
1228                                 // FIXME: const cast
1229     _target =
1230       find_node_by_value((SGPropertyNode *)getRootNode(), _value->getAlias());
1231     return _target;
1232   }
1233 }
1234
1235
1236 /**
1237  * Get a non-const child by index.
1238  */
1239 SGPropertyNode *
1240 SGPropertyNode::getChild (int position)
1241 {
1242   if (position >= 0 && position < nChildren())
1243     return _children[position];
1244   else
1245     return 0;
1246 }
1247
1248
1249 /**
1250  * Get a const child by index.
1251  */
1252 const SGPropertyNode *
1253 SGPropertyNode::getChild (int position) const
1254 {
1255   if (position >= 0 && position < nChildren())
1256     return _children[position];
1257   else
1258     return 0;
1259 }
1260
1261
1262 /**
1263  * Get a non-const child by name and index, creating if necessary.
1264  */
1265 SGPropertyNode *
1266 SGPropertyNode::getChild (const string &name, int index, bool create)
1267 {
1268   int pos = find_child(name, index, _children);
1269   if (pos >= 0) {
1270     return _children[pos];
1271   } else if (create) {
1272     _children.push_back(new SGPropertyNode(name, index, this));
1273     return _children[_children.size()-1];
1274   } else {
1275     return 0;
1276   }
1277 }
1278
1279
1280 /**
1281  * Get a const child by name and index.
1282  */
1283 const SGPropertyNode *
1284 SGPropertyNode::getChild (const string &name, int index) const
1285 {
1286   int pos = find_child(name, index, _children);
1287   if (pos >= 0)
1288     return _children[pos];
1289   else
1290     return 0;
1291 }
1292
1293
1294 /**
1295  * Get all children with the same name (but different indices).
1296  */
1297 vector<SGPropertyNode *>
1298 SGPropertyNode::getChildren (const string &name)
1299 {
1300   vector<SGPropertyNode *> children;
1301   int max = _children.size();
1302
1303   for (int i = 0; i < max; i++)
1304     if (_children[i]->getName() == name)
1305       children.push_back(_children[i]);
1306
1307   sort(children.begin(), children.end(), CompareIndices());
1308   return children;
1309 }
1310
1311
1312 /**
1313  * Get all children const with the same name (but different indices).
1314  */
1315 vector<const SGPropertyNode *>
1316 SGPropertyNode::getChildren (const string &name) const
1317 {
1318   vector<const SGPropertyNode *> children;
1319   int max = _children.size();
1320
1321   for (int i = 0; i < max; i++)
1322     if (_children[i]->getName() == name)
1323       children.push_back(_children[i]);
1324
1325   sort(children.begin(), children.end(), CompareIndices());
1326   return children;
1327 }
1328
1329
1330 string
1331 SGPropertyNode::getPath (bool simplify) const
1332 {
1333   if (_parent == 0)
1334     return "";
1335
1336   string path = _parent->getPath(simplify);
1337   path += '/';
1338   path += _name;
1339   if (_index != 0 || !simplify) {
1340     char buffer[128];
1341     sprintf(buffer, "[%d]", _index);
1342     path += buffer;
1343   }
1344   return path;
1345 }
1346
1347 SGPropertyNode::Type
1348 SGPropertyNode::getType () const
1349 {
1350   if (_value != 0)
1351     return (Type)(_value->getType());
1352   else
1353     return UNKNOWN;
1354 }
1355
1356
1357 bool 
1358 SGPropertyNode::getBoolValue () const
1359 {
1360   return (_value == 0 ? SGRawValue<bool>::DefaultValue
1361           : _value->getBoolValue());
1362 }
1363
1364 int 
1365 SGPropertyNode::getIntValue () const
1366 {
1367   return (_value == 0 ? SGRawValue<int>::DefaultValue
1368           : _value->getIntValue());
1369 }
1370
1371 long 
1372 SGPropertyNode::getLongValue () const
1373 {
1374   return (_value == 0 ? SGRawValue<long>::DefaultValue
1375           : _value->getLongValue());
1376 }
1377
1378 float 
1379 SGPropertyNode::getFloatValue () const
1380 {
1381   return (_value == 0 ? SGRawValue<float>::DefaultValue
1382           : _value->getFloatValue());
1383 }
1384
1385 double 
1386 SGPropertyNode::getDoubleValue () const
1387 {
1388   return (_value == 0 ? SGRawValue<double>::DefaultValue
1389           : _value->getDoubleValue());
1390 }
1391
1392 string
1393 SGPropertyNode::getStringValue () const
1394 {
1395   return (_value == 0 ? SGRawValue<string>::DefaultValue
1396           : _value->getStringValue());
1397 }
1398
1399 bool
1400 SGPropertyNode::setBoolValue (bool val)
1401 {
1402   if (_value == 0)
1403     _value = new SGValue();
1404   return _value->setBoolValue(val);
1405 }
1406
1407 bool
1408 SGPropertyNode::setIntValue (int val)
1409 {
1410   if (_value == 0)
1411     _value = new SGValue();
1412   return _value->setIntValue(val);
1413 }
1414
1415 bool
1416 SGPropertyNode::setLongValue (long val)
1417 {
1418   if (_value == 0)
1419     _value = new SGValue();
1420   return _value->setLongValue(val);
1421 }
1422
1423 bool
1424 SGPropertyNode::setFloatValue (float val)
1425 {
1426   if (_value == 0)
1427     _value = new SGValue();
1428   return _value->setFloatValue(val);
1429 }
1430
1431 bool
1432 SGPropertyNode::setDoubleValue (double val)
1433 {
1434   if (_value == 0)
1435     _value = new SGValue();
1436   return _value->setDoubleValue(val);
1437 }
1438
1439 bool
1440 SGPropertyNode::setStringValue (string val)
1441 {
1442   if (_value == 0)
1443     _value = new SGValue();
1444   return _value->setStringValue(val);
1445 }
1446
1447 bool
1448 SGPropertyNode::setUnknownValue (string val)
1449 {
1450   if (_value == 0)
1451     _value = new SGValue();
1452   return _value->setUnknownValue(val);
1453 }
1454
1455 bool
1456 SGPropertyNode::isTied () const
1457 {
1458   return (_value == 0 ? false : _value->isTied());
1459 }
1460
1461 bool
1462 SGPropertyNode::tie (const SGRawValue<bool> &rawValue, bool useDefault)
1463 {
1464   if (_value == 0)
1465     _value = new SGValue();
1466   return _value->tie(rawValue, useDefault);
1467 }
1468
1469 bool
1470 SGPropertyNode::tie (const SGRawValue<int> &rawValue, bool useDefault)
1471 {
1472   if (_value == 0)
1473     _value = new SGValue();
1474   return _value->tie(rawValue, useDefault);
1475 }
1476
1477 bool
1478 SGPropertyNode::tie (const SGRawValue<long> &rawValue, bool useDefault)
1479 {
1480   if (_value == 0)
1481     _value = new SGValue();
1482   return _value->tie(rawValue, useDefault);
1483 }
1484
1485 bool
1486 SGPropertyNode::tie (const SGRawValue<float> &rawValue, bool useDefault)
1487 {
1488   if (_value == 0)
1489     _value = new SGValue();
1490   return _value->tie(rawValue, useDefault);
1491 }
1492
1493 bool
1494 SGPropertyNode::tie (const SGRawValue<double> &rawValue, bool useDefault)
1495 {
1496   if (_value == 0)
1497     _value = new SGValue();
1498   return _value->tie(rawValue, useDefault);
1499 }
1500
1501 bool
1502 SGPropertyNode::tie (const SGRawValue<string> &rawValue, bool useDefault)
1503 {
1504   if (_value == 0)
1505     _value = new SGValue();
1506   return _value->tie(rawValue, useDefault);
1507 }
1508
1509 bool
1510 SGPropertyNode::untie ()
1511 {
1512   return (_value == 0 ? false : _value->untie());
1513 }
1514
1515 SGPropertyNode *
1516 SGPropertyNode::getRootNode ()
1517 {
1518   if (_parent == 0)
1519     return this;
1520   else
1521     return _parent->getRootNode();
1522 }
1523
1524 const SGPropertyNode *
1525 SGPropertyNode::getRootNode () const
1526 {
1527   if (_parent == 0)
1528     return this;
1529   else
1530     return _parent->getRootNode();
1531 }
1532
1533 SGPropertyNode *
1534 SGPropertyNode::getNode (const string &relative_path, bool create)
1535 {
1536   vector<PathComponent> components;
1537   parse_path(relative_path, components);
1538   return find_node(this, components, 0, create);
1539 }
1540
1541 const SGPropertyNode *
1542 SGPropertyNode::getNode (const string &relative_path) const
1543 {
1544   vector<PathComponent> components;
1545   parse_path(relative_path, components);
1546                                 // FIXME: cast away const
1547   return find_node((SGPropertyNode *)this, components, 0, false);
1548 }
1549
1550
1551 \f
1552 ////////////////////////////////////////////////////////////////////////
1553 // Convenience methods using relative paths.
1554 ////////////////////////////////////////////////////////////////////////
1555
1556
1557 /**
1558  * Test whether another node has a value attached.
1559  */
1560 bool
1561 SGPropertyNode::hasValue (const string &relative_path) const
1562 {
1563   const SGPropertyNode * node = getNode(relative_path);
1564   return (node == 0 ? false : node->hasValue());
1565 }
1566
1567
1568 /**
1569  * Get the value for another node.
1570  */
1571 SGValue *
1572 SGPropertyNode::getValue (const string &relative_path, bool create)
1573 {
1574   SGPropertyNode * node = getNode(relative_path, create);
1575   if (node != 0 && !node->hasValue())
1576     node->setUnknownValue("");
1577   return (node == 0 ? 0 : node->getValue(create));
1578 }
1579
1580
1581 /**
1582  * Get the value for another node.
1583  */
1584 const SGValue *
1585 SGPropertyNode::getValue (const string &relative_path) const
1586 {
1587   const SGPropertyNode * node = getNode(relative_path);
1588   return (node == 0 ? 0 : node->getValue());
1589 }
1590
1591
1592 /**
1593  * Get the value type for another node.
1594  */
1595 SGPropertyNode::Type
1596 SGPropertyNode::getType (const string &relative_path) const
1597 {
1598   const SGPropertyNode * node = getNode(relative_path);
1599   return (node == 0 ? UNKNOWN : (Type)(node->getType()));
1600 }
1601
1602
1603 /**
1604  * Get a bool value for another node.
1605  */
1606 bool
1607 SGPropertyNode::getBoolValue (const string &relative_path,
1608                               bool defaultValue) const
1609 {
1610   const SGPropertyNode * node = getNode(relative_path);
1611   return (node == 0 ? defaultValue : node->getBoolValue());
1612 }
1613
1614
1615 /**
1616  * Get an int value for another node.
1617  */
1618 int
1619 SGPropertyNode::getIntValue (const string &relative_path,
1620                              int defaultValue) const
1621 {
1622   const SGPropertyNode * node = getNode(relative_path);
1623   return (node == 0 ? defaultValue : node->getIntValue());
1624 }
1625
1626
1627 /**
1628  * Get a long value for another node.
1629  */
1630 long
1631 SGPropertyNode::getLongValue (const string &relative_path,
1632                               long defaultValue) const
1633 {
1634   const SGPropertyNode * node = getNode(relative_path);
1635   return (node == 0 ? defaultValue : node->getLongValue());
1636 }
1637
1638
1639 /**
1640  * Get a float value for another node.
1641  */
1642 float
1643 SGPropertyNode::getFloatValue (const string &relative_path,
1644                                float defaultValue) const
1645 {
1646   const SGPropertyNode * node = getNode(relative_path);
1647   return (node == 0 ? defaultValue : node->getFloatValue());
1648 }
1649
1650
1651 /**
1652  * Get a double value for another node.
1653  */
1654 double
1655 SGPropertyNode::getDoubleValue (const string &relative_path,
1656                                 double defaultValue) const
1657 {
1658   const SGPropertyNode * node = getNode(relative_path);
1659   return (node == 0 ? defaultValue : node->getDoubleValue());
1660 }
1661
1662
1663 /**
1664  * Get a string value for another node.
1665  */
1666 string
1667 SGPropertyNode::getStringValue (const string &relative_path,
1668                                 string defaultValue) const
1669 {
1670   const SGPropertyNode * node = getNode(relative_path);
1671   return (node == 0 ? defaultValue : node->getStringValue());
1672 }
1673
1674
1675 /**
1676  * Set a bool value for another node.
1677  */
1678 bool
1679 SGPropertyNode::setBoolValue (const string &relative_path, bool value)
1680 {
1681   return getNode(relative_path, true)->setBoolValue(value);
1682 }
1683
1684
1685 /**
1686  * Set an int value for another node.
1687  */
1688 bool
1689 SGPropertyNode::setIntValue (const string &relative_path, int value)
1690 {
1691   return getNode(relative_path, true)->setIntValue(value);
1692 }
1693
1694
1695 /**
1696  * Set a long value for another node.
1697  */
1698 bool
1699 SGPropertyNode::setLongValue (const string &relative_path, long value)
1700 {
1701   return getNode(relative_path, true)->setLongValue(value);
1702 }
1703
1704
1705 /**
1706  * Set a float value for another node.
1707  */
1708 bool
1709 SGPropertyNode::setFloatValue (const string &relative_path, float value)
1710 {
1711   return getNode(relative_path, true)->setFloatValue(value);
1712 }
1713
1714
1715 /**
1716  * Set a double value for another node.
1717  */
1718 bool
1719 SGPropertyNode::setDoubleValue (const string &relative_path, double value)
1720 {
1721   return getNode(relative_path, true)->setDoubleValue(value);
1722 }
1723
1724
1725 /**
1726  * Set a string value for another node.
1727  */
1728 bool
1729 SGPropertyNode::setStringValue (const string &relative_path, string value)
1730 {
1731   return getNode(relative_path, true)->setStringValue(value);
1732 }
1733
1734
1735 /**
1736  * Set an unknown value for another node.
1737  */
1738 bool
1739 SGPropertyNode::setUnknownValue (const string &relative_path, string value)
1740 {
1741   return getNode(relative_path, true)->setUnknownValue(value);
1742 }
1743
1744
1745 /**
1746  * Test whether another node is tied.
1747  */
1748 bool
1749 SGPropertyNode::isTied (const string &relative_path) const
1750 {
1751   const SGPropertyNode * node = getNode(relative_path);
1752   return (node == 0 ? false : node->isTied());
1753 }
1754
1755
1756 /**
1757  * Tie a node reached by a relative path, creating it if necessary.
1758  */
1759 bool
1760 SGPropertyNode::tie (const string &relative_path,
1761                      const SGRawValue<bool> &rawValue,
1762                      bool useDefault)
1763 {
1764   return getNode(relative_path, true)->tie(rawValue, useDefault);
1765 }
1766
1767
1768 /**
1769  * Tie a node reached by a relative path, creating it if necessary.
1770  */
1771 bool
1772 SGPropertyNode::tie (const string &relative_path,
1773                      const SGRawValue<int> &rawValue,
1774                      bool useDefault)
1775 {
1776   return getNode(relative_path, true)->tie(rawValue, useDefault);
1777 }
1778
1779
1780 /**
1781  * Tie a node reached by a relative path, creating it if necessary.
1782  */
1783 bool
1784 SGPropertyNode::tie (const string &relative_path,
1785                      const SGRawValue<long> &rawValue,
1786                      bool useDefault)
1787 {
1788   return getNode(relative_path, true)->tie(rawValue, useDefault);
1789 }
1790
1791
1792 /**
1793  * Tie a node reached by a relative path, creating it if necessary.
1794  */
1795 bool
1796 SGPropertyNode::tie (const string &relative_path,
1797                      const SGRawValue<float> &rawValue,
1798                      bool useDefault)
1799 {
1800   return getNode(relative_path, true)->tie(rawValue, useDefault);
1801 }
1802
1803
1804 /**
1805  * Tie a node reached by a relative path, creating it if necessary.
1806  */
1807 bool
1808 SGPropertyNode::tie (const string &relative_path,
1809                      const SGRawValue<double> &rawValue,
1810                      bool useDefault)
1811 {
1812   return getNode(relative_path, true)->tie(rawValue, useDefault);
1813 }
1814
1815
1816 /**
1817  * Tie a node reached by a relative path, creating it if necessary.
1818  */
1819 bool
1820 SGPropertyNode::tie (const string &relative_path,
1821                      const SGRawValue<string> &rawValue,
1822                      bool useDefault)
1823 {
1824   return getNode(relative_path, true)->tie(rawValue, useDefault);
1825 }
1826
1827
1828 /**
1829  * Attempt to untie another node reached by a relative path.
1830  */
1831 bool
1832 SGPropertyNode::untie (const string &relative_path)
1833 {
1834   SGPropertyNode * node = getNode(relative_path);
1835   return (node == 0 ? false : node->untie());
1836 }
1837
1838 // end of props.cxx