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.
5 // See props.html for documentation [replace with URL when available].
24 #include <simgear/compiler.h>
25 #include <simgear/debug/logstream.hxx>
33 ////////////////////////////////////////////////////////////////////////
35 ////////////////////////////////////////////////////////////////////////
38 * Comparator class for sorting by index.
43 int operator() (const SGPropertyNode * n1, const SGPropertyNode *n2) const {
44 return (n1->getIndex() < n2->getIndex());
50 ////////////////////////////////////////////////////////////////////////
51 // Convenience macros for value access.
52 ////////////////////////////////////////////////////////////////////////
54 #define TEST_READ(dflt) if (!getAttribute(READ)) return dflt
55 #define TEST_WRITE if (!getAttribute(WRITE)) return false
59 ////////////////////////////////////////////////////////////////////////
60 // Default values for every type.
61 ////////////////////////////////////////////////////////////////////////
63 const bool SGRawValue<bool>::DefaultValue = false;
64 const int SGRawValue<int>::DefaultValue = 0;
65 const long SGRawValue<long>::DefaultValue = 0L;
66 const float SGRawValue<float>::DefaultValue = 0.0;
67 const double SGRawValue<double>::DefaultValue = 0.0L;
68 const char * const SGRawValue<const char *>::DefaultValue = "";
72 ////////////////////////////////////////////////////////////////////////
73 // Local path normalization code.
74 ////////////////////////////////////////////////////////////////////////
77 * A component in a path.
86 * Parse the name for a path component.
88 * Name: [_a-zA-Z][-._a-zA-Z0-9]*
90 static inline const string
91 parse_name (const string &path, int &i)
94 int max = path.size();
98 if (i < max && path[i] == '.') {
104 if (i < max && path[i] != '/')
105 throw string(string("Illegal character after ") + name);
108 else if (isalpha(path[i]) || path[i] == '_') {
112 // The rules inside a name are a little
115 if (isalpha(path[i]) || isdigit(path[i]) || path[i] == '_' ||
116 path[i] == '-' || path[i] == '.') {
118 } else if (path[i] == '[' || path[i] == '/') {
121 throw string("name may contain only ._- and alphanumeric characters");
128 if (name.size() == 0)
129 throw string("name must begin with alpha or '_'");
137 * Parse the optional integer index for a path component.
139 * Index: "[" [0-9]+ "]"
142 parse_index (const string &path, int &i)
151 for (int max = path.size(); i < max; i++) {
152 if (isdigit(path[i])) {
153 index = (index * 10) + (path[i] - '0');
154 } else if (path[i] == ']') {
162 throw string("unterminated index (looking for ']')");
167 * Parse a single path component.
169 * Component: Name Index?
171 static inline PathComponent
172 parse_component (const string &path, int &i)
174 PathComponent component;
175 component.name = parse_name(path, i);
176 if (component.name[0] != '.')
177 component.index = parse_index(path, i);
179 component.index = -1;
185 * Parse a path into its components.
188 parse_path (const string &path, vector<PathComponent> &components)
191 int max = path.size();
193 // Check for initial '/'
194 if (path[pos] == '/') {
198 components.push_back(root);
200 while (pos < max && path[pos] == '/')
205 components.push_back(parse_component(path, pos));
206 while (pos < max && path[pos] == '/')
213 ////////////////////////////////////////////////////////////////////////
214 // Other static utility functions.
215 ////////////////////////////////////////////////////////////////////////
219 copy_string (const char * s)
221 // FIXME: potential buffer overflow.
222 // For some reason, strnlen and
223 // strncpy cause all kinds of crashes.
224 char * copy = new char[strlen(s) + 1];
230 compare_strings (const char * s1, const char * s2)
232 return !strncmp(s1, s2, SGPropertyNode::MAX_STRING_LEN);
236 * Locate a child node by name and index.
239 find_child (const char * name, int index, vector<SGPropertyNode *> nodes)
241 int nNodes = nodes.size();
242 for (int i = 0; i < nNodes; i++) {
243 SGPropertyNode * node = nodes[i];
244 if (compare_strings(node->getName(), name) && node->getIndex() == index)
252 * Locate another node, given a relative path.
254 static SGPropertyNode *
255 find_node (SGPropertyNode * current,
256 const vector<PathComponent> &components,
260 // Run off the end of the list
265 // Success! This is the one we want.
266 else if (position >= (int)components.size()) {
270 // Empty component means root.
271 else if (components[position].name == "") {
272 return find_node(current->getRootNode(), components, position + 1, create);
275 // . means current directory
276 else if (components[position].name == ".") {
277 return find_node(current, components, position + 1, create);
280 // .. means parent directory
281 else if (components[position].name == "..") {
282 SGPropertyNode * parent = current->getParent();
284 throw string("Attempt to move past root with '..'");
286 return find_node(parent, components, position + 1, create);
289 // Otherwise, a child name
291 SGPropertyNode * child =
292 current->getChild(components[position].name.c_str(),
293 components[position].index,
295 return find_node(child, components, position + 1, create);
301 ////////////////////////////////////////////////////////////////////////
302 // Private methods from SGPropertyNode (may be inlined for speed).
303 ////////////////////////////////////////////////////////////////////////
306 SGPropertyNode::get_bool () const
309 return _value.bool_val->getValue();
311 return _local_val.bool_val;
315 SGPropertyNode::get_int () const
318 return _value.int_val->getValue();
320 return _local_val.int_val;
324 SGPropertyNode::get_long () const
327 return _value.long_val->getValue();
329 return _local_val.long_val;
333 SGPropertyNode::get_float () const
336 return _value.float_val->getValue();
338 return _local_val.float_val;
342 SGPropertyNode::get_double () const
345 return _value.double_val->getValue();
347 return _local_val.double_val;
351 SGPropertyNode::get_string () const
354 return _value.string_val->getValue();
356 return _local_val.string_val;
360 SGPropertyNode::set_bool (bool val)
363 return _value.bool_val->setValue(val);
365 _local_val.bool_val = val;
371 SGPropertyNode::set_int (int val)
374 return _value.int_val->setValue(val);
376 _local_val.int_val = val;
382 SGPropertyNode::set_long (long val)
385 return _value.long_val->setValue(val);
387 _local_val.long_val = val;
393 SGPropertyNode::set_float (float val)
396 return _value.float_val->setValue(val);
398 _local_val.float_val = val;
404 SGPropertyNode::set_double (double val)
407 return _value.double_val->setValue(val);
409 _local_val.double_val = val;
415 SGPropertyNode::set_string (const char * val)
418 return _value.string_val->setValue(val);
420 delete [] (char *)_local_val.string_val;
421 _local_val.string_val = copy_string(val);
427 SGPropertyNode::clear_value ()
437 delete _value.bool_val;
440 _local_val.bool_val = SGRawValue<bool>::DefaultValue;
444 delete _value.int_val;
447 _local_val.int_val = SGRawValue<int>::DefaultValue;
451 delete _value.long_val;
452 _value.long_val = 0L;
454 _local_val.long_val = SGRawValue<long>::DefaultValue;
458 delete _value.float_val;
459 _value.float_val = 0;
461 _local_val.float_val = SGRawValue<float>::DefaultValue;
465 delete _value.double_val;
466 _value.double_val = 0;
468 _local_val.double_val = SGRawValue<double>::DefaultValue;
473 delete _value.string_val;
474 _value.string_val = 0;
476 delete [] (char *)_local_val.string_val;
478 _local_val.string_val = 0;
487 * Get the value as a string.
490 SGPropertyNode::make_string () const
492 if (!getAttribute(READ))
497 return _value.alias->getStringValue();
504 sprintf(_buffer, "%d", get_int());
507 sprintf(_buffer, "%ld", get_long());
510 sprintf(_buffer, "%f", get_float());
513 sprintf(_buffer, "%f", get_double());
525 * Trace a write access for a property.
528 SGPropertyNode::trace_write () const
531 cerr << "TRACE: Write node " << getPath () << ", value\""
532 << make_string() << '"' << endl;
534 SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Write node " << getPath()
535 << ", value\"" << make_string() << '"');
540 * Trace a read access for a property.
543 SGPropertyNode::trace_read () const
546 cerr << "TRACE: Write node " << getPath () << ", value \""
547 << make_string() << '"' << endl;
549 SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Read node " << getPath()
550 << ", value \"" << make_string() << '"');
556 ////////////////////////////////////////////////////////////////////////
557 // Public methods from SGPropertyNode.
558 ////////////////////////////////////////////////////////////////////////
561 * Default constructor: always creates a root node.
563 SGPropertyNode::SGPropertyNode ()
564 : _name(copy_string("")),
572 _local_val.string_val = 0;
579 SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
580 : _index(node._index),
581 _parent(0), // don't copy the parent
587 _name = copy_string(node._name);
588 _local_val.string_val = 0;
593 _value.alias = node._value.alias;
599 _value.bool_val = node._value.bool_val->clone();
602 set_bool(node.get_bool());
608 _value.int_val = node._value.int_val->clone();
611 set_int(node.get_int());
617 _value.long_val = node._value.long_val->clone();
620 set_long(node.get_long());
626 _value.float_val = node._value.float_val->clone();
629 set_float(node.get_float());
635 _value.double_val = node._value.double_val->clone();
638 set_double(node.get_double());
645 _value.string_val = node._value.string_val->clone();
648 set_string(node.get_string());
656 * Convenience constructor.
658 SGPropertyNode::SGPropertyNode (const char * name,
660 SGPropertyNode * parent)
668 _name = copy_string(name);
669 _local_val.string_val = 0;
676 SGPropertyNode::~SGPropertyNode ()
678 delete [] (char *)_name;
679 for (int i = 0; i < (int)_children.size(); i++) {
682 // delete _path_cache;
688 * Alias to another node.
691 SGPropertyNode::alias (SGPropertyNode * target)
693 if (target == 0 || _type == ALIAS || _tied)
696 _value.alias = target;
703 * Alias to another node by path.
706 SGPropertyNode::alias (const char * path)
708 return alias(getNode(path, true));
716 SGPropertyNode::unalias ()
727 * Get the target of an alias.
730 SGPropertyNode::getAliasTarget ()
732 return (_type == ALIAS ? _value.alias : 0);
736 const SGPropertyNode *
737 SGPropertyNode::getAliasTarget () const
739 return (_type == ALIAS ? _value.alias : 0);
744 * Get a non-const child by index.
747 SGPropertyNode::getChild (int position)
749 if (position >= 0 && position < nChildren())
750 return _children[position];
757 * Get a const child by index.
759 const SGPropertyNode *
760 SGPropertyNode::getChild (int position) const
762 if (position >= 0 && position < nChildren())
763 return _children[position];
770 * Get a non-const child by name and index, creating if necessary.
773 SGPropertyNode::getChild (const char * name, int index, bool create)
775 int pos = find_child(name, index, _children);
777 return _children[pos];
779 _children.push_back(new SGPropertyNode(name, index, this));
780 return _children[_children.size()-1];
788 * Get a const child by name and index.
790 const SGPropertyNode *
791 SGPropertyNode::getChild (const char * name, int index) const
793 int pos = find_child(name, index, _children);
795 return _children[pos];
802 * Get all children with the same name (but different indices).
804 vector<SGPropertyNode *>
805 SGPropertyNode::getChildren (const char * name)
807 vector<SGPropertyNode *> children;
808 int max = _children.size();
810 for (int i = 0; i < max; i++)
811 if (compare_strings(_children[i]->getName(), name))
812 children.push_back(_children[i]);
814 sort(children.begin(), children.end(), CompareIndices());
820 * Get all children const with the same name (but different indices).
822 vector<const SGPropertyNode *>
823 SGPropertyNode::getChildren (const char * name) const
825 vector<const SGPropertyNode *> children;
826 int max = _children.size();
828 for (int i = 0; i < max; i++)
829 if (compare_strings(_children[i]->getName(), name))
830 children.push_back(_children[i]);
832 sort(children.begin(), children.end(), CompareIndices());
838 SGPropertyNode::getPath (bool simplify) const
843 string path = _parent->getPath(simplify);
846 if (_index != 0 || !simplify) {
848 sprintf(buffer, "[%d]", _index);
855 SGPropertyNode::getType () const
858 return _value.alias->getType();
865 SGPropertyNode::getBoolValue () const
867 // Shortcut for common case
868 if (_attr == (READ|WRITE) && _type == BOOL)
871 if (getAttribute(TRACE_READ))
873 if (!getAttribute(READ))
874 return SGRawValue<bool>::DefaultValue;
877 return _value.alias->getBoolValue();
881 return get_int() == 0 ? false : true;
883 return get_long() == 0L ? false : true;
885 return get_float() == 0.0 ? false : true;
887 return get_double() == 0.0L ? false : true;
890 return (compare_strings(get_string(), "true") || getDoubleValue() != 0.0L);
893 return SGRawValue<bool>::DefaultValue;
898 SGPropertyNode::getIntValue () const
900 // Shortcut for common case
901 if (_attr == (READ|WRITE) && _type == INT)
904 if (getAttribute(TRACE_READ))
906 if (!getAttribute(READ))
907 return SGRawValue<int>::DefaultValue;
910 return _value.alias->getIntValue();
912 return int(get_bool());
916 return int(get_long());
918 return int(get_float());
920 return int(get_double());
923 return atoi(get_string());
926 return SGRawValue<int>::DefaultValue;
931 SGPropertyNode::getLongValue () const
933 // Shortcut for common case
934 if (_attr == (READ|WRITE) && _type == LONG)
937 if (getAttribute(TRACE_READ))
939 if (!getAttribute(READ))
940 return SGRawValue<long>::DefaultValue;
943 return _value.alias->getLongValue();
945 return long(get_bool());
947 return long(get_int());
951 return long(get_float());
953 return long(get_double());
956 return strtol(get_string(), 0, 0);
959 return SGRawValue<long>::DefaultValue;
964 SGPropertyNode::getFloatValue () const
966 // Shortcut for common case
967 if (_attr == (READ|WRITE) && _type == FLOAT)
970 if (getAttribute(TRACE_READ))
972 if (!getAttribute(READ))
973 return SGRawValue<float>::DefaultValue;
976 return _value.alias->getFloatValue();
978 return float(get_bool());
980 return float(get_int());
982 return float(get_long());
986 return float(get_double());
989 return atof(get_string());
992 return SGRawValue<float>::DefaultValue;
997 SGPropertyNode::getDoubleValue () const
999 // Shortcut for common case
1000 if (_attr == (READ|WRITE) && _type == DOUBLE)
1001 return get_double();
1003 if (getAttribute(TRACE_READ))
1005 if (!getAttribute(READ))
1006 return SGRawValue<double>::DefaultValue;
1010 return _value.alias->getDoubleValue();
1012 return double(get_bool());
1014 return double(get_int());
1016 return double(get_long());
1018 return double(get_float());
1020 return get_double();
1023 return strtod(get_string(), 0);
1026 return SGRawValue<double>::DefaultValue;
1031 SGPropertyNode::getStringValue () const
1033 // Shortcut for common case
1034 if (_attr == (READ|WRITE) && _type == STRING)
1035 return get_string();
1037 if (getAttribute(TRACE_READ))
1039 if (!getAttribute(READ))
1040 return SGRawValue<const char *>::DefaultValue;
1041 return make_string();
1045 SGPropertyNode::setBoolValue (bool value)
1047 // Shortcut for common case
1048 if (_attr == (READ|WRITE) && _type == BOOL)
1049 return set_bool(value);
1051 bool result = false;
1053 if (_type == NONE || _type == UNSPECIFIED) {
1061 result = _value.alias->setBoolValue(value);
1064 result = set_bool(value);
1067 result = set_int(int(value));
1070 result = set_long(long(value));
1073 result = set_float(float(value));
1076 result = set_double(double(value));
1080 result = set_string(value ? "true" : "false");
1087 if (getAttribute(TRACE_WRITE))
1093 SGPropertyNode::setIntValue (int value)
1095 // Shortcut for common case
1096 if (_attr == (READ|WRITE) && _type == INT)
1097 return set_int(value);
1099 bool result = false;
1101 if (_type == NONE || _type == UNSPECIFIED) {
1104 _local_val.int_val = 0;
1109 result = _value.alias->setIntValue(value);
1112 result = set_bool(value == 0 ? false : true);
1115 result = set_int(value);
1118 result = set_long(long(value));
1121 result = set_float(float(value));
1124 result = set_double(double(value));
1129 sprintf(buf, "%d", value);
1130 result = set_string(buf);
1138 if (getAttribute(TRACE_WRITE))
1144 SGPropertyNode::setLongValue (long value)
1146 // Shortcut for common case
1147 if (_attr == (READ|WRITE) && _type == LONG)
1148 return set_long(value);
1150 bool result = false;
1152 if (_type == NONE || _type == UNSPECIFIED) {
1155 _local_val.long_val = 0L;
1160 result = _value.alias->setLongValue(value);
1163 result = set_bool(value == 0L ? false : true);
1166 result = set_int(int(value));
1169 result = set_long(value);
1172 result = set_float(float(value));
1175 result = set_double(double(value));
1180 sprintf(buf, "%ld", value);
1181 result = set_string(buf);
1189 if (getAttribute(TRACE_WRITE))
1195 SGPropertyNode::setFloatValue (float value)
1197 // Shortcut for common case
1198 if (_attr == (READ|WRITE) && _type == FLOAT)
1199 return set_float(value);
1201 bool result = false;
1203 if (_type == NONE || _type == UNSPECIFIED) {
1206 _local_val.float_val = 0;
1211 result = _value.alias->setFloatValue(value);
1214 result = set_bool(value == 0.0 ? false : true);
1217 result = set_int(int(value));
1220 result = set_long(long(value));
1223 result = set_float(value);
1226 result = set_double(double(value));
1231 sprintf(buf, "%f", value);
1232 result = set_string(buf);
1240 if (getAttribute(TRACE_WRITE))
1246 SGPropertyNode::setDoubleValue (double value)
1248 // Shortcut for common case
1249 if (_attr == (READ|WRITE) && _type == DOUBLE)
1250 return set_double(value);
1252 bool result = false;
1254 if (_type == NONE || _type == UNSPECIFIED) {
1256 _local_val.double_val = value;
1262 result = _value.alias->setDoubleValue(value);
1265 result = set_bool(value == 0.0L ? false : true);
1268 result = set_int(int(value));
1271 result = set_long(long(value));
1274 result = set_float(float(value));
1277 result = set_double(value);
1282 sprintf(buf, "%f", value);
1283 result = set_string(buf);
1291 if (getAttribute(TRACE_WRITE))
1297 SGPropertyNode::setStringValue (const char * value)
1299 // Shortcut for common case
1300 if (_attr == (READ|WRITE) && _type == STRING)
1301 return set_string(value);
1303 bool result = false;
1305 if (_type == NONE || _type == UNSPECIFIED) {
1312 result = _value.alias->setStringValue(value);
1315 result = set_bool((compare_strings(value, "true")
1316 || atoi(value)) ? true : false);
1319 result = set_int(atoi(value));
1322 result = set_long(strtol(value, 0, 0));
1325 result = set_float(atof(value));
1328 result = set_double(strtod(value, 0));
1332 result = set_string(value);
1339 if (getAttribute(TRACE_WRITE))
1345 SGPropertyNode::setUnspecifiedValue (const char * value)
1347 bool result = false;
1349 if (_type == NONE) {
1351 _type = UNSPECIFIED;
1356 result = _value.alias->setUnspecifiedValue(value);
1359 result = set_bool((compare_strings(value, "true")
1360 || atoi(value)) ? true : false);
1363 result = set_int(atoi(value));
1366 result = set_long(strtol(value, 0, 0));
1369 result = set_float(atof(value));
1372 result = set_double(strtod(value, 0));
1376 result = set_string(value);
1383 if (getAttribute(TRACE_WRITE))
1389 SGPropertyNode::tie (const SGRawValue<bool> &rawValue, bool useDefault)
1391 if (_type == ALIAS || _tied)
1394 useDefault = useDefault && hasValue();
1395 bool old_val = false;
1397 old_val = getBoolValue();
1402 _value.bool_val = rawValue.clone();
1405 setBoolValue(old_val);
1411 SGPropertyNode::tie (const SGRawValue<int> &rawValue, bool useDefault)
1413 if (_type == ALIAS || _tied)
1416 useDefault = useDefault && hasValue();
1419 old_val = getIntValue();
1424 _value.int_val = rawValue.clone();
1427 setIntValue(old_val);
1433 SGPropertyNode::tie (const SGRawValue<long> &rawValue, bool useDefault)
1435 if (_type == ALIAS || _tied)
1438 useDefault = useDefault && hasValue();
1441 old_val = getLongValue();
1446 _value.long_val = rawValue.clone();
1449 setLongValue(old_val);
1455 SGPropertyNode::tie (const SGRawValue<float> &rawValue, bool useDefault)
1457 if (_type == ALIAS || _tied)
1460 useDefault = useDefault && hasValue();
1461 float old_val = 0.0;
1463 old_val = getFloatValue();
1468 _value.float_val = rawValue.clone();
1471 setFloatValue(old_val);
1477 SGPropertyNode::tie (const SGRawValue<double> &rawValue, bool useDefault)
1479 if (_type == ALIAS || _tied)
1482 useDefault = useDefault && hasValue();
1483 double old_val = 0.0;
1485 old_val = getDoubleValue();
1490 _value.double_val = rawValue.clone();
1493 setDoubleValue(old_val);
1500 SGPropertyNode::tie (const SGRawValue<const char *> &rawValue, bool useDefault)
1502 if (_type == ALIAS || _tied)
1505 useDefault = useDefault && hasValue();
1508 old_val = getStringValue();
1513 _value.string_val = rawValue.clone();
1516 setStringValue(old_val.c_str());
1522 SGPropertyNode::untie ()
1529 bool val = getBoolValue();
1532 _local_val.bool_val = val;
1536 int val = getIntValue();
1539 _local_val.int_val = val;
1543 long val = getLongValue();
1546 _local_val.long_val = val;
1550 float val = getFloatValue();
1553 _local_val.float_val = val;
1557 double val = getDoubleValue();
1560 _local_val.double_val = val;
1565 string val = getStringValue();
1568 _local_val.string_val = copy_string(val.c_str());
1581 SGPropertyNode::getRootNode ()
1586 return _parent->getRootNode();
1589 const SGPropertyNode *
1590 SGPropertyNode::getRootNode () const
1595 return _parent->getRootNode();
1599 SGPropertyNode::getNode (const char * relative_path, bool create)
1601 // if (_path_cache == 0)
1602 // _path_cache = new cache_map;
1604 // SGPropertyNode * result = (*_path_cache)[relative_path];
1605 // if (result == 0) {
1606 // vector<PathComponent> components;
1607 // parse_path(relative_path, components);
1608 // result = find_node(this, components, 0, create);
1610 // (*_path_cache)[relative_path] = result;
1614 vector<PathComponent> components;
1615 parse_path(relative_path, components);
1616 return find_node(this, components, 0, create);
1620 SGPropertyNode::getNode (const char * relative_path, int index, bool create)
1622 vector<PathComponent> components;
1623 parse_path(relative_path, components);
1624 if (components.size() > 0)
1625 components[components.size()-1].index = index;
1626 return find_node(this, components, 0, create);
1629 const SGPropertyNode *
1630 SGPropertyNode::getNode (const char * relative_path) const
1632 return ((SGPropertyNode *)this)->getNode(relative_path, false);
1635 const SGPropertyNode *
1636 SGPropertyNode::getNode (const char * relative_path, int index) const
1638 return ((SGPropertyNode *)this)->getNode(relative_path, index, false);
1642 ////////////////////////////////////////////////////////////////////////
1643 // Convenience methods using relative paths.
1644 ////////////////////////////////////////////////////////////////////////
1648 * Test whether another node has a value attached.
1651 SGPropertyNode::hasValue (const char * relative_path) const
1653 const SGPropertyNode * node = getNode(relative_path);
1654 return (node == 0 ? false : node->hasValue());
1659 * Get the value type for another node.
1661 SGPropertyNode::Type
1662 SGPropertyNode::getType (const char * relative_path) const
1664 const SGPropertyNode * node = getNode(relative_path);
1665 return (node == 0 ? UNSPECIFIED : (Type)(node->getType()));
1670 * Get a bool value for another node.
1673 SGPropertyNode::getBoolValue (const char * relative_path,
1674 bool defaultValue) const
1676 const SGPropertyNode * node = getNode(relative_path);
1677 return (node == 0 ? defaultValue : node->getBoolValue());
1682 * Get an int value for another node.
1685 SGPropertyNode::getIntValue (const char * relative_path,
1686 int defaultValue) const
1688 const SGPropertyNode * node = getNode(relative_path);
1689 return (node == 0 ? defaultValue : node->getIntValue());
1694 * Get a long value for another node.
1697 SGPropertyNode::getLongValue (const char * relative_path,
1698 long defaultValue) const
1700 const SGPropertyNode * node = getNode(relative_path);
1701 return (node == 0 ? defaultValue : node->getLongValue());
1706 * Get a float value for another node.
1709 SGPropertyNode::getFloatValue (const char * relative_path,
1710 float defaultValue) const
1712 const SGPropertyNode * node = getNode(relative_path);
1713 return (node == 0 ? defaultValue : node->getFloatValue());
1718 * Get a double value for another node.
1721 SGPropertyNode::getDoubleValue (const char * relative_path,
1722 double defaultValue) const
1724 const SGPropertyNode * node = getNode(relative_path);
1725 return (node == 0 ? defaultValue : node->getDoubleValue());
1730 * Get a string value for another node.
1733 SGPropertyNode::getStringValue (const char * relative_path,
1734 const char * defaultValue) const
1736 const SGPropertyNode * node = getNode(relative_path);
1737 return (node == 0 ? defaultValue : node->getStringValue());
1742 * Set a bool value for another node.
1745 SGPropertyNode::setBoolValue (const char * relative_path, bool value)
1747 return getNode(relative_path, true)->setBoolValue(value);
1752 * Set an int value for another node.
1755 SGPropertyNode::setIntValue (const char * relative_path, int value)
1757 return getNode(relative_path, true)->setIntValue(value);
1762 * Set a long value for another node.
1765 SGPropertyNode::setLongValue (const char * relative_path, long value)
1767 return getNode(relative_path, true)->setLongValue(value);
1772 * Set a float value for another node.
1775 SGPropertyNode::setFloatValue (const char * relative_path, float value)
1777 return getNode(relative_path, true)->setFloatValue(value);
1782 * Set a double value for another node.
1785 SGPropertyNode::setDoubleValue (const char * relative_path, double value)
1787 return getNode(relative_path, true)->setDoubleValue(value);
1792 * Set a string value for another node.
1795 SGPropertyNode::setStringValue (const char * relative_path, const char * value)
1797 return getNode(relative_path, true)->setStringValue(value);
1802 * Set an unknown value for another node.
1805 SGPropertyNode::setUnspecifiedValue (const char * relative_path,
1808 return getNode(relative_path, true)->setUnspecifiedValue(value);
1813 * Test whether another node is tied.
1816 SGPropertyNode::isTied (const char * relative_path) const
1818 const SGPropertyNode * node = getNode(relative_path);
1819 return (node == 0 ? false : node->isTied());
1824 * Tie a node reached by a relative path, creating it if necessary.
1827 SGPropertyNode::tie (const char * relative_path,
1828 const SGRawValue<bool> &rawValue,
1831 return getNode(relative_path, true)->tie(rawValue, useDefault);
1836 * Tie a node reached by a relative path, creating it if necessary.
1839 SGPropertyNode::tie (const char * relative_path,
1840 const SGRawValue<int> &rawValue,
1843 return getNode(relative_path, true)->tie(rawValue, useDefault);
1848 * Tie a node reached by a relative path, creating it if necessary.
1851 SGPropertyNode::tie (const char * relative_path,
1852 const SGRawValue<long> &rawValue,
1855 return getNode(relative_path, true)->tie(rawValue, useDefault);
1860 * Tie a node reached by a relative path, creating it if necessary.
1863 SGPropertyNode::tie (const char * relative_path,
1864 const SGRawValue<float> &rawValue,
1867 return getNode(relative_path, true)->tie(rawValue, useDefault);
1872 * Tie a node reached by a relative path, creating it if necessary.
1875 SGPropertyNode::tie (const char * relative_path,
1876 const SGRawValue<double> &rawValue,
1879 return getNode(relative_path, true)->tie(rawValue, useDefault);
1884 * Tie a node reached by a relative path, creating it if necessary.
1887 SGPropertyNode::tie (const char * relative_path,
1888 const SGRawValue<const char *> &rawValue,
1891 return getNode(relative_path, true)->tie(rawValue, useDefault);
1896 * Attempt to untie another node reached by a relative path.
1899 SGPropertyNode::untie (const char * relative_path)
1901 SGPropertyNode * node = getNode(relative_path);
1902 return (node == 0 ? false : node->untie());