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