From 5bd2d47571f2b9b2bc91b6a461c24d15c77b62ce Mon Sep 17 00:00:00 2001 From: timoore Date: Wed, 15 Jul 2009 23:07:45 +0000 Subject: [PATCH] Cleanup of properties Change most uses of the SGPropertyNode _value union to use static_cast. Move SGPropertyNode::Type out of the class into simgear::props namespace. Add a PropertyTraits class so that templates can calculate the property type tag based on a C++ type. In destructor, delete _value.val if it is not 0 (and the property is not aliased). --- simgear/props/condition.cxx | 17 ++- simgear/props/props.cxx | 282 ++++++++++-------------------------- simgear/props/props.hxx | 190 +++++++++++++++--------- simgear/props/props_io.cxx | 38 ++--- 4 files changed, 227 insertions(+), 300 deletions(-) diff --git a/simgear/props/condition.cxx b/simgear/props/condition.cxx index 7a382cd3..db06d8db 100644 --- a/simgear/props/condition.cxx +++ b/simgear/props/condition.cxx @@ -144,8 +144,9 @@ SGOrCondition::addCondition (SGCondition * condition) static int doComparison (const SGPropertyNode * left, const SGPropertyNode *right) { + using namespace simgear::props; switch (left->getType()) { - case SGPropertyNode::BOOL: { + case BOOL: { bool v1 = left->getBoolValue(); bool v2 = right->getBoolValue(); if (v1 < v2) @@ -156,7 +157,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right) return SGComparisonCondition::EQUALS; break; } - case SGPropertyNode::INT: { + case INT: { int v1 = left->getIntValue(); int v2 = right->getIntValue(); if (v1 < v2) @@ -167,7 +168,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right) return SGComparisonCondition::EQUALS; break; } - case SGPropertyNode::LONG: { + case LONG: { long v1 = left->getLongValue(); long v2 = right->getLongValue(); if (v1 < v2) @@ -178,7 +179,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right) return SGComparisonCondition::EQUALS; break; } - case SGPropertyNode::FLOAT: { + case FLOAT: { float v1 = left->getFloatValue(); float v2 = right->getFloatValue(); if (v1 < v2) @@ -189,7 +190,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right) return SGComparisonCondition::EQUALS; break; } - case SGPropertyNode::DOUBLE: { + case DOUBLE: { double v1 = left->getDoubleValue(); double v2 = right->getDoubleValue(); if (v1 < v2) @@ -200,9 +201,9 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right) return SGComparisonCondition::EQUALS; break; } - case SGPropertyNode::STRING: - case SGPropertyNode::NONE: - case SGPropertyNode::UNSPECIFIED: { + case STRING: + case NONE: + case UNSPECIFIED: { string v1 = left->getStringValue(); string v2 = right->getStringValue(); if (v1 < v2) diff --git a/simgear/props/props.cxx b/simgear/props/props.cxx index cd239ca3..0c783eb4 100644 --- a/simgear/props/props.cxx +++ b/simgear/props/props.cxx @@ -39,6 +39,8 @@ using std::string; using std::vector; using std::stringstream; +using namespace simgear; +using namespace simgear::props; //////////////////////////////////////////////////////////////////////// @@ -64,8 +66,6 @@ public: #define TEST_READ(dflt) if (!getAttribute(READ)) return dflt #define TEST_WRITE if (!getAttribute(WRITE)) return false - - //////////////////////////////////////////////////////////////////////// // Default values for every type. @@ -77,8 +77,6 @@ template<> const long SGRawValue::DefaultValue = 0L; template<> const float SGRawValue::DefaultValue = 0.0; template<> const double SGRawValue::DefaultValue = 0.0L; template<> const char * const SGRawValue::DefaultValue = ""; - - //////////////////////////////////////////////////////////////////////// // Local path normalization code. @@ -342,7 +340,7 @@ inline bool SGPropertyNode::get_bool () const { if (_tied) - return _value.bool_val->getValue(); + return static_cast*>(_value.val)->getValue(); else return _local_val.bool_val; } @@ -351,7 +349,7 @@ inline int SGPropertyNode::get_int () const { if (_tied) - return _value.int_val->getValue(); + return (static_cast*>(_value.val))->getValue(); else return _local_val.int_val; } @@ -360,7 +358,7 @@ inline long SGPropertyNode::get_long () const { if (_tied) - return _value.long_val->getValue(); + return static_cast*>(_value.val)->getValue(); else return _local_val.long_val; } @@ -369,7 +367,7 @@ inline float SGPropertyNode::get_float () const { if (_tied) - return _value.float_val->getValue(); + return static_cast*>(_value.val)->getValue(); else return _local_val.float_val; } @@ -378,7 +376,7 @@ inline double SGPropertyNode::get_double () const { if (_tied) - return _value.double_val->getValue(); + return static_cast*>(_value.val)->getValue(); else return _local_val.double_val; } @@ -387,7 +385,7 @@ inline const char * SGPropertyNode::get_string () const { if (_tied) - return _value.string_val->getValue(); + return static_cast*>(_value.val)->getValue(); else return _local_val.string_val; } @@ -396,7 +394,7 @@ inline bool SGPropertyNode::set_bool (bool val) { if (_tied) { - if (_value.bool_val->setValue(val)) { + if (static_cast*>(_value.val)->setValue(val)) { fireValueChanged(); return true; } else { @@ -413,7 +411,7 @@ inline bool SGPropertyNode::set_int (int val) { if (_tied) { - if (_value.int_val->setValue(val)) { + if (static_cast*>(_value.val)->setValue(val)) { fireValueChanged(); return true; } else { @@ -430,7 +428,7 @@ inline bool SGPropertyNode::set_long (long val) { if (_tied) { - if (_value.long_val->setValue(val)) { + if (static_cast*>(_value.val)->setValue(val)) { fireValueChanged(); return true; } else { @@ -447,7 +445,7 @@ inline bool SGPropertyNode::set_float (float val) { if (_tied) { - if (_value.float_val->setValue(val)) { + if (static_cast*>(_value.val)->setValue(val)) { fireValueChanged(); return true; } else { @@ -464,7 +462,7 @@ inline bool SGPropertyNode::set_double (double val) { if (_tied) { - if (_value.double_val->setValue(val)) { + if (static_cast*>(_value.val)->setValue(val)) { fireValueChanged(); return true; } else { @@ -481,7 +479,7 @@ inline bool SGPropertyNode::set_string (const char * val) { if (_tied) { - if (_value.string_val->setValue(val)) { + if (static_cast*>(_value.val)->setValue(val)) { fireValueChanged(); return true; } else { @@ -498,61 +496,39 @@ SGPropertyNode::set_string (const char * val) void SGPropertyNode::clearValue () { - switch (_type) { - case NONE: - break; - case ALIAS: - put(_value.alias); - _value.alias = 0; - break; - case BOOL: - if (_tied) { - delete _value.bool_val; - _value.bool_val = 0; - } - _local_val.bool_val = SGRawValue::DefaultValue; - break; - case INT: - if (_tied) { - delete _value.int_val; - _value.int_val = 0; - } - _local_val.int_val = SGRawValue::DefaultValue; - break; - case LONG: - if (_tied) { - delete _value.long_val; - _value.long_val = 0L; - } - _local_val.long_val = SGRawValue::DefaultValue; - break; - case FLOAT: - if (_tied) { - delete _value.float_val; - _value.float_val = 0; - } - _local_val.float_val = SGRawValue::DefaultValue; - break; - case DOUBLE: - if (_tied) { - delete _value.double_val; - _value.double_val = 0; + if (_type == ALIAS) { + put(_value.alias); + _value.alias = 0; + } else if (_type != NONE) { + switch (_type) { + case BOOL: + _local_val.bool_val = SGRawValue::DefaultValue; + break; + case INT: + _local_val.int_val = SGRawValue::DefaultValue; + break; + case LONG: + _local_val.long_val = SGRawValue::DefaultValue; + break; + case FLOAT: + _local_val.float_val = SGRawValue::DefaultValue; + break; + case DOUBLE: + _local_val.double_val = SGRawValue::DefaultValue; + break; + case STRING: + case UNSPECIFIED: + if (!_tied) { + delete [] _local_val.string_val; + } + _local_val.string_val = 0; + break; + } + delete _value.val; + _value.val = 0; } - _local_val.double_val = SGRawValue::DefaultValue; - break; - case STRING: - case UNSPECIFIED: - if (_tied) { - delete _value.string_val; - _value.string_val = 0; - } else { - delete [] _local_val.string_val; - } - _local_val.string_val = 0; - break; - } - _tied = false; - _type = NONE; + _tied = false; + _type = NONE; } @@ -665,6 +641,7 @@ SGPropertyNode::SGPropertyNode () _listeners(0) { _local_val.string_val = 0; + _value.val = 0; } @@ -682,6 +659,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) _listeners(0) // CHECK!! { _local_val.string_val = 0; + _value.val = 0; switch (_type) { case NONE: break; @@ -693,7 +671,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) case BOOL: if (_tied) { _tied = true; - _value.bool_val = node._value.bool_val->clone(); + _value.val = static_cast*>(node._value.val)->clone(); } else { _tied = false; set_bool(node.get_bool()); @@ -702,7 +680,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) case INT: if (_tied) { _tied = true; - _value.int_val = node._value.int_val->clone(); + _value.val = static_cast*>(node._value.val)->clone(); } else { _tied = false; set_int(node.get_int()); @@ -711,7 +689,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) case LONG: if (_tied) { _tied = true; - _value.long_val = node._value.long_val->clone(); + _value.val = static_cast*>(node._value.val)->clone(); } else { _tied = false; set_long(node.get_long()); @@ -720,7 +698,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) case FLOAT: if (_tied) { _tied = true; - _value.float_val = node._value.float_val->clone(); + _value.val = static_cast*>(node._value.val)->clone(); } else { _tied = false; set_float(node.get_float()); @@ -729,7 +707,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) case DOUBLE: if (_tied) { _tied = true; - _value.double_val = node._value.double_val->clone(); + _value.val = static_cast*>(node._value.val)->clone(); } else { _tied = false; set_double(node.get_double()); @@ -739,7 +717,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) case UNSPECIFIED: if (_tied) { _tied = true; - _value.string_val = node._value.string_val->clone(); + _value.val = static_cast*>(node._value.val)->clone(); } else { _tied = false; set_string(node.get_string()); @@ -764,11 +742,11 @@ SGPropertyNode::SGPropertyNode (const char * name, _listeners(0) { int i = 0; + _local_val.string_val = 0; + _value.val = 0; _name = parse_name(name, i); if (i != int(strlen(name)) || name[0] == '.') throw string("plain name expected instead of '") + name + '\''; - - _local_val.string_val = 0; } @@ -1070,7 +1048,7 @@ SGPropertyNode::getPath (bool simplify) const return _path.c_str(); } -SGPropertyNode::Type +Type SGPropertyNode::getType () const { if (_type == ALIAS) @@ -1604,139 +1582,27 @@ SGPropertyNode::setUnspecifiedValue (const char * value) return result; } -bool -SGPropertyNode::tie (const SGRawValue &rawValue, bool useDefault) +template<> +bool SGPropertyNode::tie (const SGRawValue &rawValue, + bool useDefault) { - if (_type == ALIAS || _tied) - return false; - - useDefault = useDefault && hasValue(); - bool old_val = false; - if (useDefault) - old_val = getBoolValue(); - - clearValue(); - _type = BOOL; - _tied = true; - _value.bool_val = rawValue.clone(); - - if (useDefault) - setBoolValue(old_val); - - return true; -} - -bool -SGPropertyNode::tie (const SGRawValue &rawValue, bool useDefault) -{ - if (_type == ALIAS || _tied) - return false; + if (_type == ALIAS || _tied) + return false; - useDefault = useDefault && hasValue(); - int old_val = 0; - if (useDefault) - old_val = getIntValue(); - - clearValue(); - _type = INT; - _tied = true; - _value.int_val = rawValue.clone(); - - if (useDefault) - setIntValue(old_val); - - return true; -} - -bool -SGPropertyNode::tie (const SGRawValue &rawValue, bool useDefault) -{ - if (_type == ALIAS || _tied) - return false; - - useDefault = useDefault && hasValue(); - long old_val = 0; - if (useDefault) - old_val = getLongValue(); - - clearValue(); - _type = LONG; - _tied = true; - _value.long_val = rawValue.clone(); - - if (useDefault) - setLongValue(old_val); - - return true; -} - -bool -SGPropertyNode::tie (const SGRawValue &rawValue, bool useDefault) -{ - if (_type == ALIAS || _tied) - return false; - - useDefault = useDefault && hasValue(); - float old_val = 0.0; - if (useDefault) - old_val = getFloatValue(); - - clearValue(); - _type = FLOAT; - _tied = true; - _value.float_val = rawValue.clone(); - - if (useDefault) - setFloatValue(old_val); - - return true; -} - -bool -SGPropertyNode::tie (const SGRawValue &rawValue, bool useDefault) -{ - if (_type == ALIAS || _tied) - return false; - - useDefault = useDefault && hasValue(); - double old_val = 0.0; - if (useDefault) - old_val = getDoubleValue(); - - clearValue(); - _type = DOUBLE; - _tied = true; - _value.double_val = rawValue.clone(); - - if (useDefault) - setDoubleValue(old_val); - - return true; - -} - -bool -SGPropertyNode::tie (const SGRawValue &rawValue, bool useDefault) -{ - if (_type == ALIAS || _tied) - return false; - - useDefault = useDefault && hasValue(); - string old_val; - if (useDefault) - old_val = getStringValue(); - - clearValue(); - _type = STRING; - _tied = true; - _value.string_val = rawValue.clone(); + useDefault = useDefault && hasValue(); + std::string old_val; + if (useDefault) + old_val = getStringValue(); + clearValue(); + _type = STRING; + _tied = true; + _value.val = rawValue.clone(); - if (useDefault) - setStringValue(old_val.c_str()); + if (useDefault) + setStringValue(old_val.c_str()); - return true; + return true; } - bool SGPropertyNode::untie () { @@ -1874,7 +1740,7 @@ SGPropertyNode::hasValue (const char * relative_path) const /** * Get the value type for another node. */ -SGPropertyNode::Type +Type SGPropertyNode::getType (const char * relative_path) const { const SGPropertyNode * node = getNode(relative_path); diff --git a/simgear/props/props.hxx b/simgear/props/props.hxx index cc1ed537..adcfdc47 100644 --- a/simgear/props/props.hxx +++ b/simgear/props/props.hxx @@ -30,6 +30,14 @@ #include #include +// XXX This whole file should be in the simgear namespace, but I don't +// have the guts yet... + +namespace simgear +{ +/** + * Property value types. + */ #ifdef NONE #pragma warn A sloppy coder has defined NONE as a macro! @@ -76,6 +84,66 @@ #undef STRING #endif +namespace props +{ +enum Type { + NONE = 0, + ALIAS, + BOOL, + INT, + LONG, + FLOAT, + DOUBLE, + STRING, + UNSPECIFIED +}; + + +template +struct PropertyTraits +{ + static const Type type_tag = NONE; +}; + +template<> +struct PropertyTraits +{ + static const Type type_tag = BOOL; +}; + +template<> +struct PropertyTraits +{ + static const Type type_tag = INT; +}; + +template<> +struct PropertyTraits +{ + static const Type type_tag = LONG; +}; + +template<> +struct PropertyTraits +{ + static const Type type_tag = FLOAT; +}; + +template<> +struct PropertyTraits +{ + static const Type type_tag = DOUBLE; +}; + +template<> +struct PropertyTraits +{ + static const Type type_tag = STRING; +}; +} +} + + //////////////////////////////////////////////////////////////////////// @@ -90,6 +158,13 @@ // a small performance hit for that. //////////////////////////////////////////////////////////////////////// +/** Base for virtual destructor + */ +class SGRawBase +{ +public: + virtual ~SGRawBase() {} +}; /** * Abstract base class for a raw value. @@ -129,7 +204,7 @@ * @see SGRawValueMethodsIndexed */ template -class SGRawValue +class SGRawValue : public SGRawBase { public: @@ -194,6 +269,16 @@ public: virtual SGRawValue * clone () const = 0; }; +//////////////////////////////////////////////////////////////////////// +// Default values for every type. +//////////////////////////////////////////////////////////////////////// + +template<> const bool SGRawValue::DefaultValue; +template<> const int SGRawValue::DefaultValue; +template<> const long SGRawValue::DefaultValue; +template<> const float SGRawValue::DefaultValue; +template<> const double SGRawValue::DefaultValue; +template<> const char * const SGRawValue::DefaultValue; /** * A raw value bound to a pointer. @@ -484,22 +569,6 @@ public: MAX_STRING_LEN = 1024 }; - /** - * Property value types. - */ - enum Type { - NONE = 0, - ALIAS, - BOOL, - INT, - LONG, - FLOAT, - DOUBLE, - STRING, - UNSPECIFIED - }; - - /** * Access mode attributes. * @@ -550,7 +619,7 @@ public: /** * Test whether this node contains a primitive leaf value. */ - bool hasValue () const { return (_type != NONE); } + bool hasValue () const { return (_type != simgear::props::NONE); } /** @@ -729,7 +798,7 @@ public: /** * Test whether the node's leaf value is aliased to another's. */ - bool isAlias () const { return (_type == ALIAS); } + bool isAlias () const { return (_type == simgear::props::ALIAS); } /** @@ -874,7 +943,7 @@ public: /** * Get the type of leaf value, if any, for this node. */ - Type getType () const; + simgear::props::Type getType () const; /** @@ -972,42 +1041,11 @@ public: */ bool isTied () const { return _tied; } - - /** - * Bind this node to an external bool source. - */ - bool tie (const SGRawValue &rawValue, bool useDefault = true); - - - /** - * Bind this node to an external int source. - */ - bool tie (const SGRawValue &rawValue, bool useDefault = true); - - - /** - * Bind this node to an external long int source. - */ - bool tie (const SGRawValue &rawValue, bool useDefault = true); - - - /** - * Bind this node to an external float source. - */ - bool tie (const SGRawValue &rawValue, bool useDefault = true); - - - /** - * Bind this node to an external double source. - */ - bool tie (const SGRawValue &rawValue, bool useDefault = true); - - - /** - * Bind this node to an external string source. - */ - bool tie (const SGRawValue &rawValue, bool useDefault = true); - + /** + * Bind this node to an external source. + */ + template + bool tie(const SGRawValue &rawValue, bool useDefault = true); /** * Unbind this node from any external data source. @@ -1024,12 +1062,12 @@ public: /** * Get another node's type. */ - Type getType (const char * relative_path) const; + simgear::props::Type getType (const char * relative_path) const; /** * Get another node's type. */ - Type getType (const std::string& relative_path) const + simgear::props::Type getType (const std::string& relative_path) const { return getType(relative_path.c_str()); } /** @@ -1423,19 +1461,14 @@ private: mutable std::string _path; mutable std::string _buffer; hash_table * _path_cache; - Type _type; + simgear::props::Type _type; bool _tied; int _attr; // The right kind of pointer... union { SGPropertyNode * alias; - SGRawValue * bool_val; - SGRawValue * int_val; - SGRawValue * long_val; - SGRawValue * float_val; - SGRawValue * double_val; - SGRawValue * string_val; + SGRawBase* val; } _value; union { @@ -1512,7 +1545,7 @@ private: }; -// Convenice functions for use in templates +// Convenience functions for use in templates template T getValue(const SGPropertyNode*); @@ -1578,6 +1611,31 @@ inline bool setValue (SGPropertyNode* node, const std::string& value) return node->setStringValue(value.c_str()); } +template +bool SGPropertyNode::tie(const SGRawValue &rawValue, bool useDefault) +{ + if (_type == simgear::props::ALIAS || _tied) + return false; + + useDefault = useDefault && hasValue(); + T old_val = SGRawValue::DefaultValue; + if (useDefault) + old_val = getValue(this); + clearValue(); + _type = simgear::props::PropertyTraits::type_tag; + _tied = true; + _value.val = rawValue.clone(); + + if (useDefault) + setValue(this, old_val); + + return true; +} + +template<> +bool SGPropertyNode::tie (const SGRawValue &rawValue, + bool useDefault); + #endif // __PROPS_HXX // end of props.hxx diff --git a/simgear/props/props_io.cxx b/simgear/props/props_io.cxx index 3938745f..881abe8c 100644 --- a/simgear/props/props_io.cxx +++ b/simgear/props/props_io.cxx @@ -400,25 +400,26 @@ void readProperties (const char *buf, const int size, * Return the type name. */ static const char * -getTypeName (SGPropertyNode::Type type) +getTypeName (simgear::props::Type type) { + using namespace simgear::props; switch (type) { - case SGPropertyNode::UNSPECIFIED: + case UNSPECIFIED: return "unspecified"; - case SGPropertyNode::BOOL: + case BOOL: return "bool"; - case SGPropertyNode::INT: + case INT: return "int"; - case SGPropertyNode::LONG: + case LONG: return "long"; - case SGPropertyNode::FLOAT: + case FLOAT: return "float"; - case SGPropertyNode::DOUBLE: + case DOUBLE: return "double"; - case SGPropertyNode::STRING: + case STRING: return "string"; - case SGPropertyNode::ALIAS: - case SGPropertyNode::NONE: + case ALIAS: + case NONE: return "unspecified"; } @@ -525,7 +526,7 @@ writeNode (ostream &output, const SGPropertyNode * node, output << " alias=\"" << node->getAliasTarget()->getPath() << "\"/>" << endl; } else { - if (node->getType() != SGPropertyNode::UNSPECIFIED) + if (node->getType() != simgear::props::UNSPECIFIED) output << " type=\"" << getTypeName(node->getType()) << '"'; output << '>'; writeData(output, node->getStringValue()); @@ -600,37 +601,38 @@ writeProperties (const string &file, const SGPropertyNode * start_node, bool copyProperties (const SGPropertyNode *in, SGPropertyNode *out) { + using namespace simgear::props; bool retval = true; // First, copy the actual value, // if any. if (in->hasValue()) { switch (in->getType()) { - case SGPropertyNode::BOOL: + case BOOL: if (!out->setBoolValue(in->getBoolValue())) retval = false; break; - case SGPropertyNode::INT: + case INT: if (!out->setIntValue(in->getIntValue())) retval = false; break; - case SGPropertyNode::LONG: + case LONG: if (!out->setLongValue(in->getLongValue())) retval = false; break; - case SGPropertyNode::FLOAT: + case FLOAT: if (!out->setFloatValue(in->getFloatValue())) retval = false; break; - case SGPropertyNode::DOUBLE: + case DOUBLE: if (!out->setDoubleValue(in->getDoubleValue())) retval = false; break; - case SGPropertyNode::STRING: + case STRING: if (!out->setStringValue(in->getStringValue())) retval = false; break; - case SGPropertyNode::UNSPECIFIED: + case UNSPECIFIED: if (!out->setUnspecifiedValue(in->getStringValue())) retval = false; break; -- 2.39.2