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].
9 #include <simgear/compiler.h>
21 ////////////////////////////////////////////////////////////////////////
23 ////////////////////////////////////////////////////////////////////////
26 * Comparator class for sorting by index.
31 int operator() (const SGPropertyNode * n1, const SGPropertyNode *n2) const {
32 return (n1->getIndex() < n2->getIndex());
38 ////////////////////////////////////////////////////////////////////////
39 // Convenience macros for value access.
40 ////////////////////////////////////////////////////////////////////////
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())
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))
58 ////////////////////////////////////////////////////////////////////////
59 // Default values for every type.
60 ////////////////////////////////////////////////////////////////////////
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 = "";
71 ////////////////////////////////////////////////////////////////////////
72 // Local path normalization code.
73 ////////////////////////////////////////////////////////////////////////
76 * A component in a path.
85 * Parse the name for a path component.
87 * Name: [_a-zA-Z][-._a-zA-Z0-9]*
90 parse_name (const string &path, int &i)
93 int max = path.size();
97 if (i < max && path[i] == '.') {
103 if (i < max && path[i] != '/')
104 throw string(string("Illegal character after ") + name);
107 else if (isalpha(path[i]) || path[i] == '_') {
111 // The rules inside a name are a little
114 if (isalpha(path[i]) || isdigit(path[i]) || path[i] == '_' ||
115 path[i] == '-' || path[i] == '.') {
117 } else if (path[i] == '[' || path[i] == '/') {
120 throw string("name may contain only ._- and alphanumeric characters");
127 if (name.size() == 0)
128 throw string("name must begin with alpha or '_'");
136 * Parse the optional integer index for a path component.
138 * Index: "[" [0-9]+ "]"
141 parse_index (const string &path, int &i)
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] == ']') {
161 throw string("unterminated index (looking for ']')");
166 * Parse a single path component.
168 * Component: Name Index?
170 static inline PathComponent
171 parse_component (const string &path, int &i)
173 PathComponent component;
174 component.name = parse_name(path, i);
175 if (component.name[0] != '.')
176 component.index = parse_index(path, i);
178 component.index = -1;
184 * Parse a path into its components.
187 parse_path (const string &path, vector<PathComponent> &components)
190 int max = path.size();
192 // Check for initial '/'
193 if (path[pos] == '/') {
197 components.push_back(root);
199 while (pos < max && path[pos] == '/')
204 components.push_back(parse_component(path, pos));
205 while (pos < max && path[pos] == '/')
212 ////////////////////////////////////////////////////////////////////////
213 // Other static utility functions.
214 ////////////////////////////////////////////////////////////////////////
218 * Locate a child node by name and index.
221 find_child (const string &name, int index, vector<SGPropertyNode *> nodes)
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)
234 * Locate another node, given a relative path.
236 static SGPropertyNode *
237 find_node (SGPropertyNode * current,
238 const vector<PathComponent> &components,
242 // Run off the end of the list
247 // Success! This is the one we want.
248 else if (position >= (int)components.size()) {
252 // Empty component means root.
253 else if (components[position].name == "") {
254 return find_node(current->getRootNode(), components, position + 1, create);
257 // . means current directory
258 else if (components[position].name == ".") {
259 return find_node(current, components, position + 1, create);
262 // .. means parent directory
263 else if (components[position].name == "..") {
264 SGPropertyNode * parent = current->getParent();
266 throw string("Attempt to move past root with '..'");
268 return find_node(parent, components, position + 1, create);
271 // Otherwise, a child name
273 SGPropertyNode * child =
274 current->getChild(components[position].name,
275 components[position].index,
277 return find_node(child, components, position + 1, create);
283 ////////////////////////////////////////////////////////////////////////
284 // Implementation of SGValue.
285 ////////////////////////////////////////////////////////////////////////
289 * Default constructor.
291 * The type will be UNKNOWN and the raw value will be "".
294 : _type(UNKNOWN), _tied(false)
296 _value.string_val = new SGRawValueInternal<string>;
303 SGValue::SGValue (const SGValue &source)
305 _type = source._type;
306 _tied = source._tied;
307 switch (source._type) {
310 _value.alias = (SGValue *)(source.getAlias());
313 _value.bool_val = source._value.bool_val->clone();
316 _value.int_val = source._value.int_val->clone();
319 _value.long_val = source._value.long_val->clone();
322 _value.float_val = source._value.float_val->clone();
325 _value.double_val = source._value.double_val->clone();
329 _value.string_val = source._value.string_val->clone();
346 * Delete and clear the current value.
349 SGValue::clear_value ()
353 _value.alias->clear_value();
355 delete _value.bool_val;
359 delete _value.int_val;
363 delete _value.long_val;
364 _value.long_val = 0L;
367 delete _value.float_val;
368 _value.float_val = 0;
371 delete _value.double_val;
372 _value.double_val = 0;
376 delete _value.string_val;
377 _value.string_val = 0;
384 * Get the current type.
386 * Does not return a type of ALIAS.
389 SGValue::getType () const
392 return _value.alias->getType();
399 * Get the current aliased value.
404 return (_type == ALIAS ? _value.alias : 0);
409 * Get the current aliased value.
412 SGValue::getAlias () const
414 return (_type == ALIAS ? _value.alias : 0);
419 * Alias to another value.
422 SGValue::alias (SGValue * alias)
424 if (alias == 0 || _type == ALIAS || _tied)
427 _value.alias = alias;
434 * Unalias from another value.
439 // FIXME: keep copy of previous value,
443 _value.string_val = new SGRawValueInternal<string>;
450 * Get a boolean value.
453 SGValue::getBoolValue () const
457 return _value.alias->getBoolValue();
461 return GET_INT == 0 ? false : true;
463 return GET_LONG == 0L ? false : true;
465 return GET_FLOAT == 0.0 ? false : true;
467 return GET_DOUBLE == 0.0L ? false : true;
470 return (GET_STRING == "true" || getDoubleValue() != 0.0L);
478 * Get an integer value.
481 SGValue::getIntValue () const
485 return _value.alias->getIntValue();
487 return int(GET_BOOL);
491 return int(GET_LONG);
493 return int(GET_FLOAT);
495 return int(GET_DOUBLE);
498 return atoi(GET_STRING.c_str());
506 * Get a long integer value.
509 SGValue::getLongValue () const
513 return _value.alias->getLongValue();
515 return long(GET_BOOL);
517 return long(GET_INT);
521 return long(GET_FLOAT);
523 return long(GET_DOUBLE);
526 return strtol(GET_STRING.c_str(), 0, 0);
535 SGValue::getFloatValue () const
539 return _value.alias->getFloatValue();
541 return float(GET_BOOL);
543 return float(GET_INT);
545 return float(GET_LONG);
549 return float(GET_DOUBLE);
552 return atof(GET_STRING.c_str());
560 * Get a double value.
563 SGValue::getDoubleValue () const
567 return _value.alias->getDoubleValue();
569 return double(GET_BOOL);
571 return double(GET_INT);
573 return double(GET_LONG);
575 return double(GET_FLOAT);
580 return strtod(GET_STRING.c_str(), 0);
588 * Get a string value.
591 SGValue::getStringValue () const
597 return _value.alias->getStringValue();
604 sprintf(buf, "%d", GET_INT);
607 sprintf(buf, "%ld", GET_LONG);
610 sprintf(buf, "%f", GET_FLOAT);
613 sprintf(buf, "%f", GET_DOUBLE);
628 SGValue::setBoolValue (bool value)
630 if (_type == UNKNOWN) {
632 _value.bool_val = new SGRawValueInternal<bool>;
638 return _value.alias->setBoolValue(value);
640 return SET_BOOL(value);
642 return SET_INT(int(value));
644 return SET_LONG(long(value));
646 return SET_FLOAT(float(value));
648 return SET_DOUBLE(double(value));
650 return SET_STRING(value ? "true" : "false");
661 SGValue::setIntValue (int value)
663 if (_type == UNKNOWN) {
665 _value.int_val = new SGRawValueInternal<int>;
671 return _value.alias->setIntValue(value);
673 return SET_BOOL(value == 0 ? false : true);
675 return SET_INT(value);
677 return SET_LONG(long(value));
679 return SET_FLOAT(float(value));
681 return SET_DOUBLE(double(value));
684 sprintf(buf, "%d", value);
685 return SET_STRING(buf);
697 SGValue::setLongValue (long value)
699 if (_type == UNKNOWN) {
701 _value.long_val = new SGRawValueInternal<long>;
707 return _value.alias->setLongValue(value);
709 return SET_BOOL(value == 0L ? false : true);
711 return SET_INT(int(value));
713 return SET_LONG(value);
715 return SET_FLOAT(float(value));
717 return SET_DOUBLE(double(value));
720 sprintf(buf, "%d", value);
721 return SET_STRING(buf);
733 SGValue::setFloatValue (float value)
735 if (_type == UNKNOWN) {
737 _value.float_val = new SGRawValueInternal<float>;
743 return _value.alias->setFloatValue(value);
745 return SET_BOOL(value == 0.0 ? false : true);
747 return SET_INT(int(value));
749 return SET_LONG(long(value));
751 return SET_FLOAT(value);
753 return SET_DOUBLE(double(value));
756 sprintf(buf, "%f", value);
757 return SET_STRING(buf);
766 * Set a double value.
769 SGValue::setDoubleValue (double value)
771 if (_type == UNKNOWN) {
773 _value.double_val = new SGRawValueInternal<double>;
779 return _value.alias->setDoubleValue(value);
781 return SET_BOOL(value == 0.0L ? false : true);
783 return SET_INT(int(value));
785 return SET_LONG(long(value));
787 return SET_FLOAT(float(value));
789 return SET_DOUBLE(value);
792 sprintf(buf, "%lf", value);
793 return SET_STRING(buf);
802 * Set a string value.
805 SGValue::setStringValue (string value)
807 if (_type == UNKNOWN) {
809 _value.string_val = new SGRawValueInternal<string>;
815 return _value.alias->setStringValue(value);
817 return SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false);
819 return SET_INT(atoi(value.c_str()));
821 return SET_LONG(strtol(value.c_str(), 0, 0));
823 return SET_FLOAT(atof(value.c_str()));
825 return SET_DOUBLE(strtod(value.c_str(), 0));
827 return SET_STRING(value);
835 * Set a value of unknown type (stored as a string).
838 SGValue::setUnknownValue (string value)
842 return _value.alias->setUnknownValue(value);
844 return SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false);
846 return SET_INT(atoi(value.c_str()));
848 return SET_LONG(strtol(value.c_str(), 0, 0));
850 return SET_FLOAT(atof(value.c_str()));
852 return SET_DOUBLE(strtod(value.c_str(), 0));
855 return SET_STRING(value);
866 SGValue::tie (const SGRawValue<bool> &value, bool use_default)
869 return _value.alias->tie(value, use_default);
873 bool old_val = false;
875 old_val = getBoolValue();
880 _value.bool_val = value.clone();
883 setBoolValue(old_val);
893 SGValue::tie (const SGRawValue<int> &value, bool use_default)
896 return _value.alias->tie(value, use_default);
902 old_val = getIntValue();
907 _value.int_val = value.clone();
910 setIntValue(old_val);
920 SGValue::tie (const SGRawValue<long> &value, bool use_default)
923 return _value.alias->tie(value, use_default);
929 old_val = getLongValue();
934 _value.long_val = value.clone();
937 setLongValue(old_val);
947 SGValue::tie (const SGRawValue<float> &value, bool use_default)
950 return _value.alias->tie(value, use_default);
956 old_val = getFloatValue();
961 _value.float_val = value.clone();
964 setFloatValue(old_val);
971 * Tie a double value.
974 SGValue::tie (const SGRawValue<double> &value, bool use_default)
977 return _value.alias->tie(value, use_default);
981 double old_val = 0.0;
983 old_val = getDoubleValue();
988 _value.double_val = value.clone();
991 setDoubleValue(old_val);
998 * Tie a string value.
1001 SGValue::tie (const SGRawValue<string> &value, bool use_default)
1004 return _value.alias->tie(value, use_default);
1010 old_val = getStringValue();
1015 _value.string_val = value.clone();
1018 setStringValue(old_val);
1035 return _value.alias->untie();
1038 bool val = getBoolValue();
1040 _value.bool_val = new SGRawValueInternal<bool>;
1045 int val = getIntValue();
1047 _value.int_val = new SGRawValueInternal<int>;
1052 long val = getLongValue();
1054 _value.long_val = new SGRawValueInternal<long>;
1059 float val = getFloatValue();
1061 _value.float_val = new SGRawValueInternal<float>;
1066 double val = getDoubleValue();
1068 _value.double_val = new SGRawValueInternal<double>;
1073 string val = getStringValue();
1075 _value.string_val = new SGRawValueInternal<string>;
1087 ////////////////////////////////////////////////////////////////////////
1088 // Implementation of SGPropertyNode.
1089 ////////////////////////////////////////////////////////////////////////
1093 * Utility function: given a value, find the property node.
1095 static SGPropertyNode *
1096 find_node_by_value (SGPropertyNode * start_node, const SGValue * value)
1098 if (start_node->getValue() == value) {
1100 } else for (int i = 0; i < start_node->nChildren(); i++) {
1101 SGPropertyNode * child =
1102 find_node_by_value(start_node->getChild(i), value);
1111 * Default constructor: always creates a root node.
1113 SGPropertyNode::SGPropertyNode ()
1114 : _value(0), _name(""), _index(0), _parent(0), _target(0)
1120 * Convenience constructor.
1122 SGPropertyNode::SGPropertyNode (const string &name,
1123 int index, SGPropertyNode * parent)
1124 : _value(0), _name(name), _index(index), _parent(parent), _target(0)
1132 SGPropertyNode::~SGPropertyNode ()
1135 for (int i = 0; i < (int)_children.size(); i++)
1136 delete _children[i];
1141 * Get a value, optionally creating it if not present.
1144 SGPropertyNode::getValue (bool create)
1146 if (_value == 0 && create)
1147 _value = new SGValue();
1153 * Alias to another node.
1156 SGPropertyNode::alias (SGPropertyNode * target)
1159 _value = new SGValue();
1161 return _value->alias(target->getValue(true));
1166 * Alias to another node by path.
1169 SGPropertyNode::alias (const string &path)
1171 return alias(getNode(path, true));
1179 SGPropertyNode::unalias ()
1182 return (_value != 0 ? _value->unalias() : false);
1187 * Test whether this node is aliased.
1190 SGPropertyNode::isAlias () const
1192 return (_value != 0 ? _value->isAlias() : false);
1197 * Get the target of an alias.
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.
1204 * @return The target node for the alias, or 0 if the node is not aliased.
1207 SGPropertyNode::getAliasTarget ()
1209 if (_value == 0 || !_value->isAlias()) {
1211 } else if (_target != 0 && _target->getValue() == _value->getAlias()) {
1214 _target = find_node_by_value(getRootNode(), _value->getAlias());
1220 const SGPropertyNode *
1221 SGPropertyNode::getAliasTarget () const
1223 if (_value == 0 || !_value->isAlias()) {
1225 } else if (_target != 0 && _target->getValue() == _value->getAlias()) {
1228 // FIXME: const cast
1230 find_node_by_value((SGPropertyNode *)getRootNode(), _value->getAlias());
1237 * Get a non-const child by index.
1240 SGPropertyNode::getChild (int position)
1242 if (position >= 0 && position < nChildren())
1243 return _children[position];
1250 * Get a const child by index.
1252 const SGPropertyNode *
1253 SGPropertyNode::getChild (int position) const
1255 if (position >= 0 && position < nChildren())
1256 return _children[position];
1263 * Get a non-const child by name and index, creating if necessary.
1266 SGPropertyNode::getChild (const string &name, int index, bool create)
1268 int pos = find_child(name, index, _children);
1270 return _children[pos];
1271 } else if (create) {
1272 _children.push_back(new SGPropertyNode(name, index, this));
1273 return _children[_children.size()-1];
1281 * Get a const child by name and index.
1283 const SGPropertyNode *
1284 SGPropertyNode::getChild (const string &name, int index) const
1286 int pos = find_child(name, index, _children);
1288 return _children[pos];
1295 * Get all children with the same name (but different indices).
1297 vector<SGPropertyNode *>
1298 SGPropertyNode::getChildren (const string &name)
1300 vector<SGPropertyNode *> children;
1301 int max = _children.size();
1303 for (int i = 0; i < max; i++)
1304 if (_children[i]->getName() == name)
1305 children.push_back(_children[i]);
1307 sort(children.begin(), children.end(), CompareIndices());
1313 * Get all children const with the same name (but different indices).
1315 vector<const SGPropertyNode *>
1316 SGPropertyNode::getChildren (const string &name) const
1318 vector<const SGPropertyNode *> children;
1319 int max = _children.size();
1321 for (int i = 0; i < max; i++)
1322 if (_children[i]->getName() == name)
1323 children.push_back(_children[i]);
1325 sort(children.begin(), children.end(), CompareIndices());
1331 SGPropertyNode::getPath (bool simplify) const
1336 string path = _parent->getPath(simplify);
1339 if (_index != 0 || !simplify) {
1341 sprintf(buffer, "[%d]", _index);
1347 SGPropertyNode::Type
1348 SGPropertyNode::getType () const
1351 return (Type)(_value->getType());
1358 SGPropertyNode::getBoolValue () const
1360 return (_value == 0 ? SGRawValue<bool>::DefaultValue
1361 : _value->getBoolValue());
1365 SGPropertyNode::getIntValue () const
1367 return (_value == 0 ? SGRawValue<int>::DefaultValue
1368 : _value->getIntValue());
1372 SGPropertyNode::getLongValue () const
1374 return (_value == 0 ? SGRawValue<long>::DefaultValue
1375 : _value->getLongValue());
1379 SGPropertyNode::getFloatValue () const
1381 return (_value == 0 ? SGRawValue<float>::DefaultValue
1382 : _value->getFloatValue());
1386 SGPropertyNode::getDoubleValue () const
1388 return (_value == 0 ? SGRawValue<double>::DefaultValue
1389 : _value->getDoubleValue());
1393 SGPropertyNode::getStringValue () const
1395 return (_value == 0 ? SGRawValue<string>::DefaultValue
1396 : _value->getStringValue());
1400 SGPropertyNode::setBoolValue (bool val)
1403 _value = new SGValue();
1404 return _value->setBoolValue(val);
1408 SGPropertyNode::setIntValue (int val)
1411 _value = new SGValue();
1412 return _value->setIntValue(val);
1416 SGPropertyNode::setLongValue (long val)
1419 _value = new SGValue();
1420 return _value->setLongValue(val);
1424 SGPropertyNode::setFloatValue (float val)
1427 _value = new SGValue();
1428 return _value->setFloatValue(val);
1432 SGPropertyNode::setDoubleValue (double val)
1435 _value = new SGValue();
1436 return _value->setDoubleValue(val);
1440 SGPropertyNode::setStringValue (string val)
1443 _value = new SGValue();
1444 return _value->setStringValue(val);
1448 SGPropertyNode::setUnknownValue (string val)
1451 _value = new SGValue();
1452 return _value->setUnknownValue(val);
1456 SGPropertyNode::isTied () const
1458 return (_value == 0 ? false : _value->isTied());
1462 SGPropertyNode::tie (const SGRawValue<bool> &rawValue, bool useDefault)
1465 _value = new SGValue();
1466 return _value->tie(rawValue, useDefault);
1470 SGPropertyNode::tie (const SGRawValue<int> &rawValue, bool useDefault)
1473 _value = new SGValue();
1474 return _value->tie(rawValue, useDefault);
1478 SGPropertyNode::tie (const SGRawValue<long> &rawValue, bool useDefault)
1481 _value = new SGValue();
1482 return _value->tie(rawValue, useDefault);
1486 SGPropertyNode::tie (const SGRawValue<float> &rawValue, bool useDefault)
1489 _value = new SGValue();
1490 return _value->tie(rawValue, useDefault);
1494 SGPropertyNode::tie (const SGRawValue<double> &rawValue, bool useDefault)
1497 _value = new SGValue();
1498 return _value->tie(rawValue, useDefault);
1502 SGPropertyNode::tie (const SGRawValue<string> &rawValue, bool useDefault)
1505 _value = new SGValue();
1506 return _value->tie(rawValue, useDefault);
1510 SGPropertyNode::untie ()
1512 return (_value == 0 ? false : _value->untie());
1516 SGPropertyNode::getRootNode ()
1521 return _parent->getRootNode();
1524 const SGPropertyNode *
1525 SGPropertyNode::getRootNode () const
1530 return _parent->getRootNode();
1534 SGPropertyNode::getNode (const string &relative_path, bool create)
1536 vector<PathComponent> components;
1537 parse_path(relative_path, components);
1538 return find_node(this, components, 0, create);
1541 const SGPropertyNode *
1542 SGPropertyNode::getNode (const string &relative_path) const
1544 vector<PathComponent> components;
1545 parse_path(relative_path, components);
1546 // FIXME: cast away const
1547 return find_node((SGPropertyNode *)this, components, 0, false);
1552 ////////////////////////////////////////////////////////////////////////
1553 // Convenience methods using relative paths.
1554 ////////////////////////////////////////////////////////////////////////
1558 * Test whether another node has a value attached.
1561 SGPropertyNode::hasValue (const string &relative_path) const
1563 const SGPropertyNode * node = getNode(relative_path);
1564 return (node == 0 ? false : node->hasValue());
1569 * Get the value for another node.
1572 SGPropertyNode::getValue (const string &relative_path, bool create)
1574 SGPropertyNode * node = getNode(relative_path, create);
1575 if (node != 0 && !node->hasValue())
1576 node->setUnknownValue("");
1577 return (node == 0 ? 0 : node->getValue(create));
1582 * Get the value for another node.
1585 SGPropertyNode::getValue (const string &relative_path) const
1587 const SGPropertyNode * node = getNode(relative_path);
1588 return (node == 0 ? 0 : node->getValue());
1593 * Get the value type for another node.
1595 SGPropertyNode::Type
1596 SGPropertyNode::getType (const string &relative_path) const
1598 const SGPropertyNode * node = getNode(relative_path);
1599 return (node == 0 ? UNKNOWN : (Type)(node->getType()));
1604 * Get a bool value for another node.
1607 SGPropertyNode::getBoolValue (const string &relative_path,
1608 bool defaultValue) const
1610 const SGPropertyNode * node = getNode(relative_path);
1611 return (node == 0 ? defaultValue : node->getBoolValue());
1616 * Get an int value for another node.
1619 SGPropertyNode::getIntValue (const string &relative_path,
1620 int defaultValue) const
1622 const SGPropertyNode * node = getNode(relative_path);
1623 return (node == 0 ? defaultValue : node->getIntValue());
1628 * Get a long value for another node.
1631 SGPropertyNode::getLongValue (const string &relative_path,
1632 long defaultValue) const
1634 const SGPropertyNode * node = getNode(relative_path);
1635 return (node == 0 ? defaultValue : node->getLongValue());
1640 * Get a float value for another node.
1643 SGPropertyNode::getFloatValue (const string &relative_path,
1644 float defaultValue) const
1646 const SGPropertyNode * node = getNode(relative_path);
1647 return (node == 0 ? defaultValue : node->getFloatValue());
1652 * Get a double value for another node.
1655 SGPropertyNode::getDoubleValue (const string &relative_path,
1656 double defaultValue) const
1658 const SGPropertyNode * node = getNode(relative_path);
1659 return (node == 0 ? defaultValue : node->getDoubleValue());
1664 * Get a string value for another node.
1667 SGPropertyNode::getStringValue (const string &relative_path,
1668 string defaultValue) const
1670 const SGPropertyNode * node = getNode(relative_path);
1671 return (node == 0 ? defaultValue : node->getStringValue());
1676 * Set a bool value for another node.
1679 SGPropertyNode::setBoolValue (const string &relative_path, bool value)
1681 return getNode(relative_path, true)->setBoolValue(value);
1686 * Set an int value for another node.
1689 SGPropertyNode::setIntValue (const string &relative_path, int value)
1691 return getNode(relative_path, true)->setIntValue(value);
1696 * Set a long value for another node.
1699 SGPropertyNode::setLongValue (const string &relative_path, long value)
1701 return getNode(relative_path, true)->setLongValue(value);
1706 * Set a float value for another node.
1709 SGPropertyNode::setFloatValue (const string &relative_path, float value)
1711 return getNode(relative_path, true)->setFloatValue(value);
1716 * Set a double value for another node.
1719 SGPropertyNode::setDoubleValue (const string &relative_path, double value)
1721 return getNode(relative_path, true)->setDoubleValue(value);
1726 * Set a string value for another node.
1729 SGPropertyNode::setStringValue (const string &relative_path, string value)
1731 return getNode(relative_path, true)->setStringValue(value);
1736 * Set an unknown value for another node.
1739 SGPropertyNode::setUnknownValue (const string &relative_path, string value)
1741 return getNode(relative_path, true)->setUnknownValue(value);
1746 * Test whether another node is tied.
1749 SGPropertyNode::isTied (const string &relative_path) const
1751 const SGPropertyNode * node = getNode(relative_path);
1752 return (node == 0 ? false : node->isTied());
1757 * Tie a node reached by a relative path, creating it if necessary.
1760 SGPropertyNode::tie (const string &relative_path,
1761 const SGRawValue<bool> &rawValue,
1764 return getNode(relative_path, true)->tie(rawValue, useDefault);
1769 * Tie a node reached by a relative path, creating it if necessary.
1772 SGPropertyNode::tie (const string &relative_path,
1773 const SGRawValue<int> &rawValue,
1776 return getNode(relative_path, true)->tie(rawValue, useDefault);
1781 * Tie a node reached by a relative path, creating it if necessary.
1784 SGPropertyNode::tie (const string &relative_path,
1785 const SGRawValue<long> &rawValue,
1788 return getNode(relative_path, true)->tie(rawValue, useDefault);
1793 * Tie a node reached by a relative path, creating it if necessary.
1796 SGPropertyNode::tie (const string &relative_path,
1797 const SGRawValue<float> &rawValue,
1800 return getNode(relative_path, true)->tie(rawValue, useDefault);
1805 * Tie a node reached by a relative path, creating it if necessary.
1808 SGPropertyNode::tie (const string &relative_path,
1809 const SGRawValue<double> &rawValue,
1812 return getNode(relative_path, true)->tie(rawValue, useDefault);
1817 * Tie a node reached by a relative path, creating it if necessary.
1820 SGPropertyNode::tie (const string &relative_path,
1821 const SGRawValue<string> &rawValue,
1824 return getNode(relative_path, true)->tie(rawValue, useDefault);
1829 * Attempt to untie another node reached by a relative path.
1832 SGPropertyNode::untie (const string &relative_path)
1834 SGPropertyNode * node = getNode(relative_path);
1835 return (node == 0 ? false : node->untie());