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).
This commit is contained in:
timoore
2009-07-15 23:07:45 +00:00
committed by Tim Moore
parent f8e475cd34
commit 5bd2d47571
4 changed files with 227 additions and 300 deletions

View File

@@ -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)

View File

@@ -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<long>::DefaultValue = 0L;
template<> const float SGRawValue<float>::DefaultValue = 0.0;
template<> const double SGRawValue<double>::DefaultValue = 0.0L;
template<> const char * const SGRawValue<const char *>::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<SGRawValue<bool>*>(_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<SGRawValue<int>*>(_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<SGRawValue<long>*>(_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<SGRawValue<float>*>(_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<SGRawValue<double>*>(_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<SGRawValue<const char*>*>(_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<SGRawValue<bool>*>(_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<SGRawValue<int>*>(_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<SGRawValue<long>*>(_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<SGRawValue<float>*>(_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<SGRawValue<double>*>(_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<SGRawValue<const char*>*>(_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;
if (_type == ALIAS) {
put(_value.alias);
_value.alias = 0;
} else if (_type != NONE) {
switch (_type) {
case BOOL:
_local_val.bool_val = SGRawValue<bool>::DefaultValue;
break;
case INT:
_local_val.int_val = SGRawValue<int>::DefaultValue;
break;
case LONG:
_local_val.long_val = SGRawValue<long>::DefaultValue;
break;
case FLOAT:
_local_val.float_val = SGRawValue<float>::DefaultValue;
break;
case DOUBLE:
_local_val.double_val = SGRawValue<double>::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.bool_val = SGRawValue<bool>::DefaultValue;
break;
case INT:
if (_tied) {
delete _value.int_val;
_value.int_val = 0;
}
_local_val.int_val = SGRawValue<int>::DefaultValue;
break;
case LONG:
if (_tied) {
delete _value.long_val;
_value.long_val = 0L;
}
_local_val.long_val = SGRawValue<long>::DefaultValue;
break;
case FLOAT:
if (_tied) {
delete _value.float_val;
_value.float_val = 0;
}
_local_val.float_val = SGRawValue<float>::DefaultValue;
break;
case DOUBLE:
if (_tied) {
delete _value.double_val;
_value.double_val = 0;
}
_local_val.double_val = SGRawValue<double>::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<SGRawValue<bool>*>(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<SGRawValue<int>*>(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<SGRawValue<long>*>(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<SGRawValue<float>*>(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<SGRawValue<double>*>(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<SGRawValue<const char*>*>(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<bool> &rawValue, bool useDefault)
template<>
bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
bool useDefault)
{
if (_type == ALIAS || _tied)
return false;
if (_type == ALIAS || _tied)
return false;
useDefault = useDefault && hasValue();
bool old_val = false;
if (useDefault)
old_val = getBoolValue();
useDefault = useDefault && hasValue();
std::string old_val;
if (useDefault)
old_val = getStringValue();
clearValue();
_type = STRING;
_tied = true;
_value.val = rawValue.clone();
clearValue();
_type = BOOL;
_tied = true;
_value.bool_val = rawValue.clone();
if (useDefault)
setStringValue(old_val.c_str());
if (useDefault)
setBoolValue(old_val);
return true;
return true;
}
bool
SGPropertyNode::tie (const SGRawValue<int> &rawValue, bool useDefault)
{
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<long> &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<float> &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<double> &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<const char *> &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();
if (useDefault)
setStringValue(old_val.c_str());
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);

View File

@@ -30,6 +30,14 @@
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
// 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<typename T>
struct PropertyTraits
{
static const Type type_tag = NONE;
};
template<>
struct PropertyTraits<bool>
{
static const Type type_tag = BOOL;
};
template<>
struct PropertyTraits<int>
{
static const Type type_tag = INT;
};
template<>
struct PropertyTraits<long>
{
static const Type type_tag = LONG;
};
template<>
struct PropertyTraits<float>
{
static const Type type_tag = FLOAT;
};
template<>
struct PropertyTraits<double>
{
static const Type type_tag = DOUBLE;
};
template<>
struct PropertyTraits<const char *>
{
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 T>
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<bool>::DefaultValue;
template<> const int SGRawValue<int>::DefaultValue;
template<> const long SGRawValue<long>::DefaultValue;
template<> const float SGRawValue<float>::DefaultValue;
template<> const double SGRawValue<double>::DefaultValue;
template<> const char * const SGRawValue<const char *>::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<bool> &rawValue, bool useDefault = true);
/**
* Bind this node to an external int source.
*/
bool tie (const SGRawValue<int> &rawValue, bool useDefault = true);
/**
* Bind this node to an external long int source.
*/
bool tie (const SGRawValue<long> &rawValue, bool useDefault = true);
/**
* Bind this node to an external float source.
*/
bool tie (const SGRawValue<float> &rawValue, bool useDefault = true);
/**
* Bind this node to an external double source.
*/
bool tie (const SGRawValue<double> &rawValue, bool useDefault = true);
/**
* Bind this node to an external string source.
*/
bool tie (const SGRawValue<const char *> &rawValue, bool useDefault = true);
/**
* Bind this node to an external source.
*/
template<typename T>
bool tie(const SGRawValue<T> &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> * bool_val;
SGRawValue<int> * int_val;
SGRawValue<long> * long_val;
SGRawValue<float> * float_val;
SGRawValue<double> * double_val;
SGRawValue<const char *> * string_val;
SGRawBase* val;
} _value;
union {
@@ -1512,7 +1545,7 @@ private:
};
// Convenice functions for use in templates
// Convenience functions for use in templates
template<typename T>
T getValue(const SGPropertyNode*);
@@ -1578,6 +1611,31 @@ 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)
{
if (_type == simgear::props::ALIAS || _tied)
return false;
useDefault = useDefault && hasValue();
T old_val = SGRawValue<T>::DefaultValue;
if (useDefault)
old_val = getValue<T>(this);
clearValue();
_type = simgear::props::PropertyTraits<T>::type_tag;
_tied = true;
_value.val = rawValue.clone();
if (useDefault)
setValue(this, old_val);
return true;
}
template<>
bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
bool useDefault);
#endif // __PROPS_HXX
// end of props.hxx

View File

@@ -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;