]> git.mxchange.org Git - simgear.git/blob - simgear/misc/props.cxx
Attempt to resolve ambiguity between #include <config.h> for simgear vs.
[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   }
1216 }
1217
1218
1219 const SGPropertyNode *
1220 SGPropertyNode::getAliasTarget () const
1221 {
1222   if (_value == 0 || !_value->isAlias()) {
1223     return 0;
1224   } else if (_target != 0 && _target->getValue() == _value->getAlias()) {
1225     return _target;
1226   } else {
1227                                 // FIXME: const cast
1228     _target =
1229       find_node_by_value((SGPropertyNode *)getRootNode(), _value->getAlias());
1230   }
1231 }
1232
1233
1234 /**
1235  * Get a non-const child by index.
1236  */
1237 SGPropertyNode *
1238 SGPropertyNode::getChild (int position)
1239 {
1240   if (position >= 0 && position < nChildren())
1241     return _children[position];
1242   else
1243     return 0;
1244 }
1245
1246
1247 /**
1248  * Get a const child by index.
1249  */
1250 const SGPropertyNode *
1251 SGPropertyNode::getChild (int position) const
1252 {
1253   if (position >= 0 && position < nChildren())
1254     return _children[position];
1255   else
1256     return 0;
1257 }
1258
1259
1260 /**
1261  * Get a non-const child by name and index, creating if necessary.
1262  */
1263 SGPropertyNode *
1264 SGPropertyNode::getChild (const string &name, int index, bool create)
1265 {
1266   int pos = find_child(name, index, _children);
1267   if (pos >= 0) {
1268     return _children[pos];
1269   } else if (create) {
1270     _children.push_back(new SGPropertyNode(name, index, this));
1271     return _children[_children.size()-1];
1272   } else {
1273     return 0;
1274   }
1275 }
1276
1277
1278 /**
1279  * Get a const child by name and index.
1280  */
1281 const SGPropertyNode *
1282 SGPropertyNode::getChild (const string &name, int index) const
1283 {
1284   int pos = find_child(name, index, _children);
1285   if (pos >= 0)
1286     return _children[pos];
1287   else
1288     return 0;
1289 }
1290
1291
1292 /**
1293  * Get all children with the same name (but different indices).
1294  */
1295 vector<SGPropertyNode *>
1296 SGPropertyNode::getChildren (const string &name)
1297 {
1298   vector<SGPropertyNode *> children;
1299   int max = _children.size();
1300
1301   for (int i = 0; i < max; i++)
1302     if (_children[i]->getName() == name)
1303       children.push_back(_children[i]);
1304
1305   sort(children.begin(), children.end(), CompareIndices());
1306   return children;
1307 }
1308
1309
1310 /**
1311  * Get all children const with the same name (but different indices).
1312  */
1313 vector<const SGPropertyNode *>
1314 SGPropertyNode::getChildren (const string &name) const
1315 {
1316   vector<const SGPropertyNode *> children;
1317   int max = _children.size();
1318
1319   for (int i = 0; i < max; i++)
1320     if (_children[i]->getName() == name)
1321       children.push_back(_children[i]);
1322
1323   sort(children.begin(), children.end(), CompareIndices());
1324   return children;
1325 }
1326
1327
1328 string
1329 SGPropertyNode::getPath (bool simplify) const
1330 {
1331   if (_parent == 0)
1332     return "";
1333
1334   string path = _parent->getPath(simplify);
1335   path += '/';
1336   path += _name;
1337   if (_index != 0 || !simplify) {
1338     char buffer[128];
1339     sprintf(buffer, "[%d]", _index);
1340     path += buffer;
1341   }
1342   return path;
1343 }
1344
1345 SGValue::Type
1346 SGPropertyNode::getType () const
1347 {
1348   if (_value != 0)
1349     return _value->getType();
1350   else
1351     return SGValue::UNKNOWN;
1352 }
1353
1354
1355 bool 
1356 SGPropertyNode::getBoolValue () const
1357 {
1358   return (_value == 0 ? SGRawValue<bool>::DefaultValue
1359           : _value->getBoolValue());
1360 }
1361
1362 int 
1363 SGPropertyNode::getIntValue () const
1364 {
1365   return (_value == 0 ? SGRawValue<int>::DefaultValue
1366           : _value->getIntValue());
1367 }
1368
1369 long 
1370 SGPropertyNode::getLongValue () const
1371 {
1372   return (_value == 0 ? SGRawValue<long>::DefaultValue
1373           : _value->getLongValue());
1374 }
1375
1376 float 
1377 SGPropertyNode::getFloatValue () const
1378 {
1379   return (_value == 0 ? SGRawValue<float>::DefaultValue
1380           : _value->getFloatValue());
1381 }
1382
1383 double 
1384 SGPropertyNode::getDoubleValue () const
1385 {
1386   return (_value == 0 ? SGRawValue<double>::DefaultValue
1387           : _value->getDoubleValue());
1388 }
1389
1390 string
1391 SGPropertyNode::getStringValue () const
1392 {
1393   return (_value == 0 ? SGRawValue<string>::DefaultValue
1394           : _value->getStringValue());
1395 }
1396
1397 bool
1398 SGPropertyNode::setBoolValue (bool val)
1399 {
1400   if (_value == 0)
1401     _value = new SGValue();
1402   return _value->setBoolValue(val);
1403 }
1404
1405 bool
1406 SGPropertyNode::setIntValue (int val)
1407 {
1408   if (_value == 0)
1409     _value = new SGValue();
1410   return _value->setIntValue(val);
1411 }
1412
1413 bool
1414 SGPropertyNode::setLongValue (long val)
1415 {
1416   if (_value == 0)
1417     _value = new SGValue();
1418   return _value->setLongValue(val);
1419 }
1420
1421 bool
1422 SGPropertyNode::setFloatValue (float val)
1423 {
1424   if (_value == 0)
1425     _value = new SGValue();
1426   return _value->setFloatValue(val);
1427 }
1428
1429 bool
1430 SGPropertyNode::setDoubleValue (double val)
1431 {
1432   if (_value == 0)
1433     _value = new SGValue();
1434   return _value->setDoubleValue(val);
1435 }
1436
1437 bool
1438 SGPropertyNode::setStringValue (string val)
1439 {
1440   if (_value == 0)
1441     _value = new SGValue();
1442   return _value->setStringValue(val);
1443 }
1444
1445 bool
1446 SGPropertyNode::setUnknownValue (string val)
1447 {
1448   if (_value == 0)
1449     _value = new SGValue();
1450   return _value->setUnknownValue(val);
1451 }
1452
1453 bool
1454 SGPropertyNode::isTied () const
1455 {
1456   return (_value == 0 ? false : _value->isTied());
1457 }
1458
1459 bool
1460 SGPropertyNode::tie (const SGRawValue<bool> &rawValue, bool useDefault)
1461 {
1462   if (_value == 0)
1463     _value = new SGValue();
1464   return _value->tie(rawValue, useDefault);
1465 }
1466
1467 bool
1468 SGPropertyNode::tie (const SGRawValue<int> &rawValue, bool useDefault)
1469 {
1470   if (_value == 0)
1471     _value = new SGValue();
1472   return _value->tie(rawValue, useDefault);
1473 }
1474
1475 bool
1476 SGPropertyNode::tie (const SGRawValue<long> &rawValue, bool useDefault)
1477 {
1478   if (_value == 0)
1479     _value = new SGValue();
1480   return _value->tie(rawValue, useDefault);
1481 }
1482
1483 bool
1484 SGPropertyNode::tie (const SGRawValue<float> &rawValue, bool useDefault)
1485 {
1486   if (_value == 0)
1487     _value = new SGValue();
1488   return _value->tie(rawValue, useDefault);
1489 }
1490
1491 bool
1492 SGPropertyNode::tie (const SGRawValue<double> &rawValue, bool useDefault)
1493 {
1494   if (_value == 0)
1495     _value = new SGValue();
1496   return _value->tie(rawValue, useDefault);
1497 }
1498
1499 bool
1500 SGPropertyNode::tie (const SGRawValue<string> &rawValue, bool useDefault)
1501 {
1502   if (_value == 0)
1503     _value = new SGValue();
1504   return _value->tie(rawValue, useDefault);
1505 }
1506
1507 bool
1508 SGPropertyNode::untie ()
1509 {
1510   return (_value == 0 ? false : _value->untie());
1511 }
1512
1513 SGPropertyNode *
1514 SGPropertyNode::getRootNode ()
1515 {
1516   if (_parent == 0)
1517     return this;
1518   else
1519     return _parent->getRootNode();
1520 }
1521
1522 const SGPropertyNode *
1523 SGPropertyNode::getRootNode () const
1524 {
1525   if (_parent == 0)
1526     return this;
1527   else
1528     return _parent->getRootNode();
1529 }
1530
1531 SGPropertyNode *
1532 SGPropertyNode::getNode (const string &relative_path, bool create)
1533 {
1534   vector<PathComponent> components;
1535   parse_path(relative_path, components);
1536   return find_node(this, components, 0, create);
1537 }
1538
1539 const SGPropertyNode *
1540 SGPropertyNode::getNode (const string &relative_path) const
1541 {
1542   vector<PathComponent> components;
1543   parse_path(relative_path, components);
1544                                 // FIXME: cast away const
1545   return find_node((SGPropertyNode *)this, components, 0, false);
1546 }
1547
1548
1549 \f
1550 ////////////////////////////////////////////////////////////////////////
1551 // Convenience methods using relative paths.
1552 ////////////////////////////////////////////////////////////////////////
1553
1554
1555 /**
1556  * Test whether another node has a value attached.
1557  */
1558 bool
1559 SGPropertyNode::hasValue (const string &relative_path) const
1560 {
1561   const SGPropertyNode * node = getNode(relative_path);
1562   return (node == 0 ? false : node->hasValue());
1563 }
1564
1565
1566 /**
1567  * Get the value for another node.
1568  */
1569 SGValue *
1570 SGPropertyNode::getValue (const string &relative_path, bool create)
1571 {
1572   SGPropertyNode * node = getNode(relative_path, create);
1573   if (node != 0 && !node->hasValue())
1574     node->setUnknownValue("");
1575   return (node == 0 ? 0 : node->getValue(create));
1576 }
1577
1578
1579 /**
1580  * Get the value for another node.
1581  */
1582 const SGValue *
1583 SGPropertyNode::getValue (const string &relative_path) const
1584 {
1585   const SGPropertyNode * node = getNode(relative_path);
1586   return (node == 0 ? 0 : node->getValue());
1587 }
1588
1589
1590 /**
1591  * Get the value type for another node.
1592  */
1593 SGValue::Type
1594 SGPropertyNode::getType (const string &relative_path) const
1595 {
1596   const SGPropertyNode * node = getNode(relative_path);
1597   return (node == 0 ? SGValue::UNKNOWN : node->getType());
1598 }
1599
1600
1601 /**
1602  * Get a bool value for another node.
1603  */
1604 bool
1605 SGPropertyNode::getBoolValue (const string &relative_path,
1606                               bool defaultValue) const
1607 {
1608   const SGPropertyNode * node = getNode(relative_path);
1609   return (node == 0 ? defaultValue : node->getBoolValue());
1610 }
1611
1612
1613 /**
1614  * Get an int value for another node.
1615  */
1616 int
1617 SGPropertyNode::getIntValue (const string &relative_path,
1618                              int defaultValue) const
1619 {
1620   const SGPropertyNode * node = getNode(relative_path);
1621   return (node == 0 ? defaultValue : node->getIntValue());
1622 }
1623
1624
1625 /**
1626  * Get a long value for another node.
1627  */
1628 long
1629 SGPropertyNode::getLongValue (const string &relative_path,
1630                               long defaultValue) const
1631 {
1632   const SGPropertyNode * node = getNode(relative_path);
1633   return (node == 0 ? defaultValue : node->getLongValue());
1634 }
1635
1636
1637 /**
1638  * Get a float value for another node.
1639  */
1640 float
1641 SGPropertyNode::getFloatValue (const string &relative_path,
1642                                float defaultValue) const
1643 {
1644   const SGPropertyNode * node = getNode(relative_path);
1645   return (node == 0 ? defaultValue : node->getFloatValue());
1646 }
1647
1648
1649 /**
1650  * Get a double value for another node.
1651  */
1652 double
1653 SGPropertyNode::getDoubleValue (const string &relative_path,
1654                                 double defaultValue) const
1655 {
1656   const SGPropertyNode * node = getNode(relative_path);
1657   return (node == 0 ? defaultValue : node->getDoubleValue());
1658 }
1659
1660
1661 /**
1662  * Get a string value for another node.
1663  */
1664 string
1665 SGPropertyNode::getStringValue (const string &relative_path,
1666                                 string defaultValue) const
1667 {
1668   const SGPropertyNode * node = getNode(relative_path);
1669   return (node == 0 ? defaultValue : node->getStringValue());
1670 }
1671
1672
1673 /**
1674  * Set a bool value for another node.
1675  */
1676 bool
1677 SGPropertyNode::setBoolValue (const string &relative_path, bool value)
1678 {
1679   return getNode(relative_path, true)->setBoolValue(value);
1680 }
1681
1682
1683 /**
1684  * Set an int value for another node.
1685  */
1686 bool
1687 SGPropertyNode::setIntValue (const string &relative_path, int value)
1688 {
1689   return getNode(relative_path, true)->setIntValue(value);
1690 }
1691
1692
1693 /**
1694  * Set a long value for another node.
1695  */
1696 bool
1697 SGPropertyNode::setLongValue (const string &relative_path, long value)
1698 {
1699   return getNode(relative_path, true)->setLongValue(value);
1700 }
1701
1702
1703 /**
1704  * Set a float value for another node.
1705  */
1706 bool
1707 SGPropertyNode::setFloatValue (const string &relative_path, float value)
1708 {
1709   return getNode(relative_path, true)->setFloatValue(value);
1710 }
1711
1712
1713 /**
1714  * Set a double value for another node.
1715  */
1716 bool
1717 SGPropertyNode::setDoubleValue (const string &relative_path, double value)
1718 {
1719   return getNode(relative_path, true)->setDoubleValue(value);
1720 }
1721
1722
1723 /**
1724  * Set a string value for another node.
1725  */
1726 bool
1727 SGPropertyNode::setStringValue (const string &relative_path, string value)
1728 {
1729   return getNode(relative_path, true)->setStringValue(value);
1730 }
1731
1732
1733 /**
1734  * Set an unknown value for another node.
1735  */
1736 bool
1737 SGPropertyNode::setUnknownValue (const string &relative_path, string value)
1738 {
1739   return getNode(relative_path, true)->setUnknownValue(value);
1740 }
1741
1742
1743 /**
1744  * Test whether another node is tied.
1745  */
1746 bool
1747 SGPropertyNode::isTied (const string &relative_path) const
1748 {
1749   const SGPropertyNode * node = getNode(relative_path);
1750   return (node == 0 ? false : node->isTied());
1751 }
1752
1753
1754 /**
1755  * Tie a node reached by a relative path, creating it if necessary.
1756  */
1757 bool
1758 SGPropertyNode::tie (const string &relative_path,
1759                      const SGRawValue<bool> &rawValue,
1760                      bool useDefault)
1761 {
1762   return getNode(relative_path, true)->tie(rawValue, useDefault);
1763 }
1764
1765
1766 /**
1767  * Tie a node reached by a relative path, creating it if necessary.
1768  */
1769 bool
1770 SGPropertyNode::tie (const string &relative_path,
1771                      const SGRawValue<int> &rawValue,
1772                      bool useDefault)
1773 {
1774   return getNode(relative_path, true)->tie(rawValue, useDefault);
1775 }
1776
1777
1778 /**
1779  * Tie a node reached by a relative path, creating it if necessary.
1780  */
1781 bool
1782 SGPropertyNode::tie (const string &relative_path,
1783                      const SGRawValue<long> &rawValue,
1784                      bool useDefault)
1785 {
1786   return getNode(relative_path, true)->tie(rawValue, useDefault);
1787 }
1788
1789
1790 /**
1791  * Tie a node reached by a relative path, creating it if necessary.
1792  */
1793 bool
1794 SGPropertyNode::tie (const string &relative_path,
1795                      const SGRawValue<float> &rawValue,
1796                      bool useDefault)
1797 {
1798   return getNode(relative_path, true)->tie(rawValue, useDefault);
1799 }
1800
1801
1802 /**
1803  * Tie a node reached by a relative path, creating it if necessary.
1804  */
1805 bool
1806 SGPropertyNode::tie (const string &relative_path,
1807                      const SGRawValue<double> &rawValue,
1808                      bool useDefault)
1809 {
1810   return getNode(relative_path, true)->tie(rawValue, useDefault);
1811 }
1812
1813
1814 /**
1815  * Tie a node reached by a relative path, creating it if necessary.
1816  */
1817 bool
1818 SGPropertyNode::tie (const string &relative_path,
1819                      const SGRawValue<string> &rawValue,
1820                      bool useDefault)
1821 {
1822   return getNode(relative_path, true)->tie(rawValue, useDefault);
1823 }
1824
1825
1826 /**
1827  * Attempt to untie another node reached by a relative path.
1828  */
1829 bool
1830 SGPropertyNode::untie (const string &relative_path)
1831 {
1832   SGPropertyNode * node = getNode(relative_path);
1833   return (node == 0 ? false : node->untie());
1834 }
1835
1836 // end of props.cxx