+inline bool setValue(SGPropertyNode* node, const char* value)
+{
+ return node->setStringValue(value);
+}
+
+inline bool setValue (SGPropertyNode* node, const std::string& value)
+{
+ return node->setStringValue(value.c_str());
+}
+
+template<typename T>
+bool SGPropertyNode::tie(const SGRawValue<T> &rawValue, bool useDefault)
+{
+ using namespace simgear::props;
+ if (_type == ALIAS || _tied)
+ return false;
+
+ useDefault = useDefault && hasValue();
+ T old_val = SGRawValue<T>::DefaultValue();
+ if (useDefault)
+ old_val = getValue<T>(this);
+ clearValue();
+ if (PropertyTraits<T>::Internal)
+ _type = PropertyTraits<T>::type_tag;
+ else
+ _type = EXTENDED;
+ _tied = true;
+ _value.val = rawValue.clone();
+ if (useDefault)
+ setValue(old_val);
+ return true;
+}
+
+template<>
+bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
+ bool useDefault);
+
+template<typename T>
+T SGPropertyNode::getValue(typename boost::disable_if_c<simgear::props
+ ::PropertyTraits<T>::Internal>::type* dummy) const
+{
+ using namespace simgear::props;
+ if (_attr == (READ|WRITE) && _type == EXTENDED
+ && _value.val->getType() == PropertyTraits<T>::type_tag) {
+ return static_cast<SGRawValue<T>*>(_value.val)->getValue();
+ }
+ if (getAttribute(TRACE_READ))
+ trace_read();
+ if (!getAttribute(READ))
+ return SGRawValue<T>::DefaultValue();
+ switch (_type) {
+ case EXTENDED:
+ if (_value.val->getType() == PropertyTraits<T>::type_tag)
+ return static_cast<SGRawValue<T>*>(_value.val)->getValue();
+ break;
+ case STRING:
+ case UNSPECIFIED:
+ return simgear::parseString<T>(make_string());
+ break;
+ default: // avoid compiler warning
+ break;
+ }
+ return SGRawValue<T>::DefaultValue();
+}
+
+template<typename T>
+inline T SGPropertyNode::getValue(typename boost::enable_if_c<simgear::props
+ ::PropertyTraits<T>::Internal>::type* dummy) const
+{
+ return ::getValue<T>(this);
+}
+
+template<typename T>
+bool SGPropertyNode::setValue(const T& val,
+ typename boost::disable_if_c<simgear::props
+ ::PropertyTraits<T>::Internal>::type* dummy)
+{
+ using namespace simgear::props;
+ if (_attr == (READ|WRITE) && _type == EXTENDED
+ && _value.val->getType() == PropertyTraits<T>::type_tag) {
+ static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
+ return true;
+ }
+ if (getAttribute(WRITE)
+ && ((_type == EXTENDED
+ && _value.val->getType() == PropertyTraits<T>::type_tag)
+ || _type == NONE || _type == UNSPECIFIED)) {
+ if (_type == NONE || _type == UNSPECIFIED) {
+ clearValue();
+ _type = EXTENDED;
+ _value.val = new SGRawValueContainer<T>(val);
+ } else {
+ static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
+ }
+ if (getAttribute(TRACE_WRITE))
+ trace_write();
+ return true;
+ }
+ return false;
+}
+
+template<typename T>
+inline bool SGPropertyNode::setValue(const T& val,
+ typename boost::enable_if_c<simgear::props
+ ::PropertyTraits<T>::Internal>::type* dummy)
+{
+ return ::setValue(this, val);
+}
+
+/**
+ * Utility function for creation of a child property node.
+ */
+inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name,
+ int index = 0)
+{
+ return parent->getChild(name, index, true);
+}
+
+/**
+ * Utility function for creation of a child property node using a
+ * relative path.
+ */
+namespace simgear
+{
+template<typename StringType>
+inline SGPropertyNode* makeNode(SGPropertyNode* parent, const StringType& name)
+{
+ return parent->getNode(name, true);
+}
+}
+
+// For boost::hash
+size_t hash_value(const SGPropertyNode& node);
+
+// Helper comparison and hash functions for common cases
+
+namespace simgear
+{
+namespace props
+{
+struct Compare
+{
+ bool operator()(const SGPropertyNode* lhs, const SGPropertyNode* rhs) const
+ {
+ return SGPropertyNode::compare(*lhs, *rhs);
+ }
+ bool operator()(SGPropertyNode_ptr lhs, const SGPropertyNode* rhs) const
+ {
+ return SGPropertyNode::compare(*lhs, *rhs);
+ }
+ bool operator()(const SGPropertyNode* lhs, SGPropertyNode_ptr rhs) const
+ {
+ return SGPropertyNode::compare(*lhs, *rhs);
+ }
+ bool operator()(SGPropertyNode_ptr lhs, SGPropertyNode_ptr rhs) const
+ {
+ return SGPropertyNode::compare(*lhs, *rhs);
+ }