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).
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)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::INT: {
+ case INT: {
int v1 = left->getIntValue();
int v2 = right->getIntValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::LONG: {
+ case LONG: {
long v1 = left->getLongValue();
long v2 = right->getLongValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::FLOAT: {
+ case FLOAT: {
float v1 = left->getFloatValue();
float v2 = right->getFloatValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::DOUBLE: {
+ case DOUBLE: {
double v1 = left->getDoubleValue();
double v2 = right->getDoubleValue();
if (v1 < v2)
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)
using std::vector;
using std::stringstream;
+using namespace simgear;
+using namespace simgear::props;
\f
////////////////////////////////////////////////////////////////////////
#define TEST_READ(dflt) if (!getAttribute(READ)) return dflt
#define TEST_WRITE if (!getAttribute(WRITE)) return false
-
-
\f
////////////////////////////////////////////////////////////////////////
// Default values for every type.
template<> const float SGRawValue<float>::DefaultValue = 0.0;
template<> const double SGRawValue<double>::DefaultValue = 0.0L;
template<> const char * const SGRawValue<const char *>::DefaultValue = "";
-
-
\f
////////////////////////////////////////////////////////////////////////
// Local path normalization code.
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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 {
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 {
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 {
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 {
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 {
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 {
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<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;
+ 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.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;
}
_listeners(0)
{
_local_val.string_val = 0;
+ _value.val = 0;
}
_listeners(0) // CHECK!!
{
_local_val.string_val = 0;
+ _value.val = 0;
switch (_type) {
case NONE:
break;
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());
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());
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());
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());
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());
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());
_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;
}
return _path.c_str();
}
-SGPropertyNode::Type
+Type
SGPropertyNode::getType () const
{
if (_type == ALIAS)
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;
-
- 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<int> &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<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();
+ 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 ()
{
/**
* Get the value type for another node.
*/
-SGPropertyNode::Type
+Type
SGPropertyNode::getType (const char * relative_path) const
{
const SGPropertyNode * node = getNode(relative_path);
#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!
#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;
+};
+}
+}
+
+
\f
////////////////////////////////////////////////////////////////////////
// a small performance hit for that.
////////////////////////////////////////////////////////////////////////
+/** Base for virtual destructor
+ */
+class SGRawBase
+{
+public:
+ virtual ~SGRawBase() {}
+};
/**
* Abstract base class for a raw value.
* @see SGRawValueMethodsIndexed
*/
template <class T>
-class SGRawValue
+class SGRawValue : public SGRawBase
{
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.
MAX_STRING_LEN = 1024
};
- /**
- * Property value types.
- */
- enum Type {
- NONE = 0,
- ALIAS,
- BOOL,
- INT,
- LONG,
- FLOAT,
- DOUBLE,
- STRING,
- UNSPECIFIED
- };
-
-
/**
* Access mode attributes.
*
/**
* Test whether this node contains a primitive leaf value.
*/
- bool hasValue () const { return (_type != NONE); }
+ bool hasValue () const { return (_type != simgear::props::NONE); }
/**
/**
* 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); }
/**
/**
* Get the type of leaf value, if any, for this node.
*/
- Type getType () const;
+ simgear::props::Type getType () const;
/**
*/
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.
/**
* 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()); }
/**
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 {
};
-// Convenice functions for use in templates
+// Convenience functions for use in templates
template<typename T>
T getValue(const SGPropertyNode*);
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
* 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";
}
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());
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;