Extend properties to support new property types.
An SGRawBase class has been added as a base class to the SGRawValue hierarchy so that SGPropertyValue functions don't necessarily need to know the type of the value stored in the node. A new SGRawValueContainer class stores properties that shouldn't be stored in the node itself. PropertyTraits indicates if a type is stored in the property node or externally. Add getValue and SetValue template member functions to SGPropertyNode. Read and write new extended properties. Rearrange props.hxx a bit so that the template magic actually works. Split out extended raw value virtual functions into a seperate base class. SGRawExtended is chosen as a base class of SGRawValue for extended property types.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -385,7 +386,7 @@ inline const char *
|
||||
SGPropertyNode::get_string () const
|
||||
{
|
||||
if (_tied)
|
||||
return static_cast<SGRawValue<const char*>*>(_value.val)->getValue();
|
||||
return static_cast<SGRawValue<const char*>*>(_value.val)->getValue();
|
||||
else
|
||||
return _local_val.string_val;
|
||||
}
|
||||
@@ -479,7 +480,7 @@ inline bool
|
||||
SGPropertyNode::set_string (const char * val)
|
||||
{
|
||||
if (_tied) {
|
||||
if (static_cast<SGRawValue<const char*>*>(_value.val)->setValue(val)) {
|
||||
if (static_cast<SGRawValue<const char*>*>(_value.val)->setValue(val)) {
|
||||
fireValueChanged();
|
||||
return true;
|
||||
} else {
|
||||
@@ -538,53 +539,43 @@ SGPropertyNode::clearValue ()
|
||||
const char *
|
||||
SGPropertyNode::make_string () const
|
||||
{
|
||||
if (!getAttribute(READ))
|
||||
return "";
|
||||
|
||||
switch (_type) {
|
||||
case ALIAS:
|
||||
return _value.alias->getStringValue();
|
||||
case BOOL:
|
||||
if (get_bool())
|
||||
return "true";
|
||||
else
|
||||
return "false";
|
||||
case INT:
|
||||
{
|
||||
stringstream sstr;
|
||||
sstr << get_int();
|
||||
_buffer = sstr.str();
|
||||
return _buffer.c_str();
|
||||
if (!getAttribute(READ))
|
||||
return "";
|
||||
switch (_type) {
|
||||
case ALIAS:
|
||||
return _value.alias->getStringValue();
|
||||
case BOOL:
|
||||
return get_bool() ? "true" : "false";
|
||||
case STRING:
|
||||
case UNSPECIFIED:
|
||||
return get_string();
|
||||
case NONE:
|
||||
return "";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case LONG:
|
||||
{
|
||||
stringstream sstr;
|
||||
sstr << get_long();
|
||||
_buffer = sstr.str();
|
||||
return _buffer.c_str();
|
||||
stringstream sstr;
|
||||
switch (_type) {
|
||||
case INT:
|
||||
sstr << get_int();
|
||||
break;
|
||||
case LONG:
|
||||
sstr << get_long();
|
||||
break;
|
||||
case FLOAT:
|
||||
sstr << get_float();
|
||||
break;
|
||||
case DOUBLE:
|
||||
sstr << std::setprecision(10) << get_double();
|
||||
break;
|
||||
case EXTENDED:
|
||||
static_cast<SGRawExtended*>(_value.val)->printOn(sstr);
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
case FLOAT:
|
||||
{
|
||||
stringstream sstr;
|
||||
sstr << get_float();
|
||||
_buffer = sstr.str();
|
||||
return _buffer.c_str();
|
||||
}
|
||||
case DOUBLE:
|
||||
{
|
||||
stringstream sstr;
|
||||
sstr.precision( 10 );
|
||||
sstr << get_double();
|
||||
_buffer = sstr.str();
|
||||
return _buffer.c_str();
|
||||
}
|
||||
case STRING:
|
||||
case UNSPECIFIED:
|
||||
return get_string();
|
||||
case NONE:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
_buffer = sstr.str();
|
||||
return _buffer.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -660,68 +651,39 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
|
||||
{
|
||||
_local_val.string_val = 0;
|
||||
_value.val = 0;
|
||||
switch (_type) {
|
||||
case NONE:
|
||||
break;
|
||||
case ALIAS:
|
||||
if (_type == NONE)
|
||||
return;
|
||||
if (_type == ALIAS) {
|
||||
_value.alias = node._value.alias;
|
||||
get(_value.alias);
|
||||
_tied = false;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
if (_tied || _type == EXTENDED) {
|
||||
_value.val = node._value.val->clone();
|
||||
return;
|
||||
}
|
||||
switch (_type) {
|
||||
case BOOL:
|
||||
if (_tied) {
|
||||
_tied = true;
|
||||
_value.val = static_cast<SGRawValue<bool>*>(node._value.val)->clone();
|
||||
} else {
|
||||
_tied = false;
|
||||
set_bool(node.get_bool());
|
||||
}
|
||||
set_bool(node.get_bool());
|
||||
break;
|
||||
case INT:
|
||||
if (_tied) {
|
||||
_tied = true;
|
||||
_value.val = static_cast<SGRawValue<int>*>(node._value.val)->clone();
|
||||
} else {
|
||||
_tied = false;
|
||||
set_int(node.get_int());
|
||||
}
|
||||
set_int(node.get_int());
|
||||
break;
|
||||
case LONG:
|
||||
if (_tied) {
|
||||
_tied = true;
|
||||
_value.val = static_cast<SGRawValue<long>*>(node._value.val)->clone();
|
||||
} else {
|
||||
_tied = false;
|
||||
set_long(node.get_long());
|
||||
}
|
||||
set_long(node.get_long());
|
||||
break;
|
||||
case FLOAT:
|
||||
if (_tied) {
|
||||
_tied = true;
|
||||
_value.val = static_cast<SGRawValue<float>*>(node._value.val)->clone();
|
||||
} else {
|
||||
_tied = false;
|
||||
set_float(node.get_float());
|
||||
}
|
||||
set_float(node.get_float());
|
||||
break;
|
||||
case DOUBLE:
|
||||
if (_tied) {
|
||||
_tied = true;
|
||||
_value.val = static_cast<SGRawValue<double>*>(node._value.val)->clone();
|
||||
} else {
|
||||
_tied = false;
|
||||
set_double(node.get_double());
|
||||
}
|
||||
set_double(node.get_double());
|
||||
break;
|
||||
case STRING:
|
||||
case UNSPECIFIED:
|
||||
if (_tied) {
|
||||
_tied = true;
|
||||
_value.val = static_cast<SGRawValue<const char*>*>(node._value.val)->clone();
|
||||
} else {
|
||||
_tied = false;
|
||||
set_string(node.get_string());
|
||||
}
|
||||
set_string(node.get_string());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1053,6 +1015,8 @@ SGPropertyNode::getType () const
|
||||
{
|
||||
if (_type == ALIAS)
|
||||
return _value.alias->getType();
|
||||
else if (_type == EXTENDED)
|
||||
return _value.val->getType();
|
||||
else
|
||||
return _type;
|
||||
}
|
||||
@@ -1528,6 +1492,12 @@ SGPropertyNode::setStringValue (const char * value)
|
||||
case UNSPECIFIED:
|
||||
result = set_string(value);
|
||||
break;
|
||||
case EXTENDED:
|
||||
{
|
||||
stringstream sstr(value);
|
||||
static_cast<SGRawExtended*>(_value.val)->readFrom(sstr);
|
||||
}
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
break;
|
||||
@@ -1547,8 +1517,10 @@ SGPropertyNode::setUnspecifiedValue (const char * value)
|
||||
clearValue();
|
||||
_type = UNSPECIFIED;
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
Type type = _type;
|
||||
if (type == EXTENDED)
|
||||
type = _value.val->getType();
|
||||
switch (type) {
|
||||
case ALIAS:
|
||||
result = _value.alias->setUnspecifiedValue(value);
|
||||
break;
|
||||
@@ -1582,6 +1554,41 @@ SGPropertyNode::setUnspecifiedValue (const char * value)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& SGPropertyNode::printOn(std::ostream& stream) const
|
||||
{
|
||||
if (!getAttribute(READ))
|
||||
return stream;
|
||||
switch (_type) {
|
||||
case ALIAS:
|
||||
return _value.alias->printOn(stream);
|
||||
case BOOL:
|
||||
stream << (get_bool() ? "true" : "false");
|
||||
break;
|
||||
case INT:
|
||||
stream << get_int();
|
||||
break;
|
||||
case LONG:
|
||||
stream << get_long();
|
||||
break;
|
||||
case FLOAT:
|
||||
stream << get_float();
|
||||
break;
|
||||
case DOUBLE:
|
||||
stream << get_double();
|
||||
break;
|
||||
case STRING:
|
||||
case UNSPECIFIED:
|
||||
stream << get_string();
|
||||
break;
|
||||
case EXTENDED:
|
||||
static_cast<SGRawExtended*>(_value.val)->printOn(stream);
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
|
||||
bool useDefault)
|
||||
@@ -1653,6 +1660,15 @@ SGPropertyNode::untie ()
|
||||
_local_val.string_val = copy_string(val.c_str());
|
||||
break;
|
||||
}
|
||||
case EXTENDED: {
|
||||
SGRawExtended* val = static_cast<SGRawExtended*>(_value.val);
|
||||
_value.val = 0; // Prevent clearValue() from deleting
|
||||
clearValue();
|
||||
_type = EXTENDED;
|
||||
_value.val = val->makeContainer();
|
||||
delete val;
|
||||
break;
|
||||
}
|
||||
case NONE:
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#if PROPS_STANDALONE
|
||||
#else
|
||||
@@ -35,6 +39,30 @@
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
template<typename T>
|
||||
std::istream& readFrom(std::istream& stream, T& result)
|
||||
{
|
||||
stream >> result;
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string as an object of a given type.
|
||||
* XXX no error behavior yet.
|
||||
*
|
||||
* @tparam T the return type
|
||||
* @param str the string
|
||||
* @return the object.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T parseString(const std::string& str)
|
||||
{
|
||||
std::istringstream stream(str);
|
||||
T result;
|
||||
readFrom(stream, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property value types.
|
||||
*/
|
||||
@@ -86,60 +114,45 @@ namespace simgear
|
||||
|
||||
namespace props
|
||||
{
|
||||
/**
|
||||
* The possible types of an SGPropertyNode. Types that appear after
|
||||
* EXTENDED are not stored in the SGPropertyNode itself.
|
||||
*/
|
||||
enum Type {
|
||||
NONE = 0,
|
||||
ALIAS,
|
||||
NONE = 0, /**< The node hasn't been assigned a value yet. */
|
||||
ALIAS, /**< The node "points" to another node. */
|
||||
BOOL,
|
||||
INT,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
STRING,
|
||||
UNSPECIFIED
|
||||
UNSPECIFIED,
|
||||
EXTENDED /**< The node's value is not stored in the property;
|
||||
* the actual value and type is retrieved from an
|
||||
* SGRawValue node. This type is never returned by @see
|
||||
* SGPropertyNode::getType.
|
||||
*/
|
||||
};
|
||||
|
||||
template<typename T> struct PropertyTraits;
|
||||
|
||||
template<typename T>
|
||||
struct PropertyTraits
|
||||
{
|
||||
static const Type type_tag = NONE;
|
||||
};
|
||||
#define DEFINTERNALPROP(TYPE, PROP) \
|
||||
template<> \
|
||||
struct PropertyTraits<TYPE> \
|
||||
{ \
|
||||
static const Type type_tag = PROP; \
|
||||
enum { Internal = 1 }; \
|
||||
}
|
||||
|
||||
template<>
|
||||
struct PropertyTraits<bool>
|
||||
{
|
||||
static const Type type_tag = BOOL;
|
||||
};
|
||||
DEFINTERNALPROP(bool, BOOL);
|
||||
DEFINTERNALPROP(int, INT);
|
||||
DEFINTERNALPROP(long, LONG);
|
||||
DEFINTERNALPROP(float, FLOAT);
|
||||
DEFINTERNALPROP(double, DOUBLE);
|
||||
DEFINTERNALPROP(const char *, STRING);
|
||||
#undef DEFINTERNALPROP
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,12 +171,73 @@ struct PropertyTraits<const char *>
|
||||
// a small performance hit for that.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Base for virtual destructor
|
||||
/**
|
||||
* Base class for SGRawValue classes that holds no type
|
||||
* information. This allows some generic manipulation of the
|
||||
* SGRawValue object.
|
||||
*/
|
||||
class SGRawBase
|
||||
class SGRaw
|
||||
{
|
||||
public:
|
||||
virtual ~SGRawBase() {}
|
||||
/**
|
||||
* Get the type enumeration for the raw value.
|
||||
*
|
||||
* @return the type.
|
||||
*/
|
||||
virtual simgear::props::Type getType() const = 0;
|
||||
virtual ~SGRaw() {}
|
||||
|
||||
/**
|
||||
* Create a new deep copy of this raw value.
|
||||
*
|
||||
* The copy will contain its own version of the underlying value
|
||||
* as well, and will be the same type.
|
||||
*
|
||||
* @return A deep copy of the current object.
|
||||
*/
|
||||
virtual SGRaw* clone() const = 0;
|
||||
|
||||
};
|
||||
|
||||
class SGRawExtended : public SGRaw
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Make an SGRawValueContainer from the SGRawValue.
|
||||
*
|
||||
* This is a virtual function of SGRawExtended so that
|
||||
* SGPropertyNode::untie doesn't need to know the type of an
|
||||
* extended property.
|
||||
*/
|
||||
virtual SGRawExtended* makeContainer() const = 0;
|
||||
/**
|
||||
* Write value out to a stream
|
||||
*/
|
||||
virtual std::ostream& printOn(std::ostream& stream) const = 0;
|
||||
/**
|
||||
* Read value from a stream and store it.
|
||||
*/
|
||||
virtual std::istream& readFrom(std::istream& stream) = 0;
|
||||
};
|
||||
|
||||
// Choose between different base classes based on whether the value is
|
||||
// stored internal to the property node. This frees us from defining
|
||||
// the virtual functions in the SGRawExtended interface where they
|
||||
// don't make sense, e.g. readFrom for the const char* type.
|
||||
template<typename T, int internal = simgear::props::PropertyTraits<T>::Internal>
|
||||
class SGRawBase;
|
||||
|
||||
template<typename T>
|
||||
class SGRawBase<T, 1> : public SGRaw
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SGRawBase<T, 0> : public SGRawExtended
|
||||
{
|
||||
virtual SGRawExtended* makeContainer() const;
|
||||
virtual std::ostream& printOn(std::ostream& stream) const;
|
||||
virtual std::istream& readFrom(std::istream& stream);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -183,10 +257,7 @@ public:
|
||||
* set, and clone the underlying value. The SGRawValue may change
|
||||
* frequently during a session as a value is retyped or bound and
|
||||
* unbound to various data source, but the abstract SGPropertyNode
|
||||
* layer insulates the application from those changes. The raw value
|
||||
* contains no facilities for data binding or for type conversion: it
|
||||
* is simply the abstraction of a primitive data type (or a compound
|
||||
* data type, in the case of a string).</p>
|
||||
* layer insulates the application from those changes.
|
||||
*
|
||||
* <p>The SGPropertyNode class always keeps a *copy* of a raw value,
|
||||
* not the original one passed to it; if you override a derived class
|
||||
@@ -202,9 +273,10 @@ public:
|
||||
* @see SGRawValueFunctionsIndexed
|
||||
* @see SGRawValueMethods
|
||||
* @see SGRawValueMethodsIndexed
|
||||
* @see SGRawValueContainer
|
||||
*/
|
||||
template <class T>
|
||||
class SGRawValue : public SGRawBase
|
||||
class SGRawValue : public SGRawBase<T>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -259,16 +331,16 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
* Create a new deep copy of this raw value.
|
||||
*
|
||||
* The copy will contain its own version of the underlying value
|
||||
* as well.
|
||||
*
|
||||
* @return A deep copy of the current object.
|
||||
* Return the type tag for this raw value type.
|
||||
*/
|
||||
virtual SGRawValue * clone () const = 0;
|
||||
virtual simgear::props::Type getType() const
|
||||
{
|
||||
return simgear::props::PropertyTraits<T>::type_tag;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Default values for every type.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -332,8 +404,8 @@ public:
|
||||
*
|
||||
* The copy will use the same external pointer as the original.
|
||||
*/
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValuePointer<T>(_ptr);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValuePointer(_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -407,8 +479,8 @@ public:
|
||||
/**
|
||||
* Create a copy of this raw value, bound to the same functions.
|
||||
*/
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueFunctions<T>(_getter,_setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueFunctions(_getter,_setter);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -444,8 +516,8 @@ public:
|
||||
if (_setter) { (*_setter)(_index, value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueFunctionsIndexed<T>(_index, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueFunctionsIndexed(_index, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
int _index;
|
||||
@@ -477,8 +549,8 @@ public:
|
||||
if (_setter) { (_obj.*_setter)(value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueMethods<C,T>(_obj, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueMethods(_obj, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
C &_obj;
|
||||
@@ -511,8 +583,8 @@ public:
|
||||
if (_setter) { (_obj.*_setter)(_index, value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueMethodsIndexed<C,T>(_obj, _index, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueMethodsIndexed(_obj, _index, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
C &_obj;
|
||||
@@ -521,6 +593,71 @@ private:
|
||||
setter_t _setter;
|
||||
};
|
||||
|
||||
/**
|
||||
* A raw value that contains its value. This provides a way for
|
||||
* property nodes to contain values that shouldn't be stored in the
|
||||
* property node itself.
|
||||
*/
|
||||
template <class T>
|
||||
class SGRawValueContainer : public SGRawValue<T>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Explicit constructor.
|
||||
*/
|
||||
SGRawValueContainer(const T& obj) : _obj(obj) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SGRawValueContainer() {}
|
||||
|
||||
/**
|
||||
* Get the underlying value.
|
||||
*/
|
||||
virtual T getValue() const { return _obj; }
|
||||
|
||||
/**
|
||||
* Set the underlying value.
|
||||
*
|
||||
* This method will dereference the pointer and change the
|
||||
* variable's value.
|
||||
*/
|
||||
virtual bool setValue (T value) { _obj = value; return true; }
|
||||
|
||||
/**
|
||||
* Create a copy of this raw value.
|
||||
*/
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueContainer(_obj);
|
||||
}
|
||||
|
||||
private:
|
||||
T _obj;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
SGRawExtended* SGRawBase<T, 0>::makeContainer() const
|
||||
{
|
||||
return new SGRawValueContainer<T>(static_cast<const SGRawValue<T>*>(this)
|
||||
->getValue());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& SGRawBase<T, 0>::printOn(std::ostream& stream) const
|
||||
{
|
||||
return stream << static_cast<SGRawValue<T>*>(this)->getValue();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::istream& SGRawBase<T, 0>::readFrom(std::istream& stream)
|
||||
{
|
||||
T value;
|
||||
simgear::readFrom(stream, value);
|
||||
static_cast<SGRawValue<T>*>(this)->setValue(value);
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* The smart pointer that manage reference counting
|
||||
@@ -981,7 +1118,17 @@ public:
|
||||
*/
|
||||
const char * getStringValue () const;
|
||||
|
||||
|
||||
/**
|
||||
* Get a value from a node. If the actual type of the node doesn't
|
||||
* match the desired type, a conversion isn't guaranteed.
|
||||
*/
|
||||
template<typename T>
|
||||
T getValue(typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0) const;
|
||||
// Getter for extended property
|
||||
template<typename T>
|
||||
T getValue(typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0) const;
|
||||
|
||||
/**
|
||||
* Set a bool value for this node.
|
||||
@@ -1030,7 +1177,21 @@ public:
|
||||
*/
|
||||
bool setUnspecifiedValue (const char * value);
|
||||
|
||||
template<typename T>
|
||||
bool setValue(const T& val,
|
||||
typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0);
|
||||
|
||||
template<typename T>
|
||||
bool setValue(const T& val,
|
||||
typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0);
|
||||
|
||||
/**
|
||||
* Print the value of the property to a stream.
|
||||
*/
|
||||
std::ostream& printOn(std::ostream& stream) const;
|
||||
|
||||
//
|
||||
// Data binding.
|
||||
//
|
||||
@@ -1428,7 +1589,6 @@ private:
|
||||
*/
|
||||
const char * make_string () const;
|
||||
|
||||
|
||||
/**
|
||||
* Trace a read access.
|
||||
*/
|
||||
@@ -1468,7 +1628,7 @@ private:
|
||||
// The right kind of pointer...
|
||||
union {
|
||||
SGPropertyNode * alias;
|
||||
SGRawBase* val;
|
||||
SGRaw* val;
|
||||
} _value;
|
||||
|
||||
union {
|
||||
@@ -1614,7 +1774,8 @@ inline bool setValue (SGPropertyNode* node, const std::string& value)
|
||||
template<typename T>
|
||||
bool SGPropertyNode::tie(const SGRawValue<T> &rawValue, bool useDefault)
|
||||
{
|
||||
if (_type == simgear::props::ALIAS || _tied)
|
||||
using namespace simgear::props;
|
||||
if (_type == ALIAS || _tied)
|
||||
return false;
|
||||
|
||||
useDefault = useDefault && hasValue();
|
||||
@@ -1622,13 +1783,14 @@ bool SGPropertyNode::tie(const SGRawValue<T> &rawValue, bool useDefault)
|
||||
if (useDefault)
|
||||
old_val = getValue<T>(this);
|
||||
clearValue();
|
||||
_type = simgear::props::PropertyTraits<T>::type_tag;
|
||||
if (PropertyTraits<T>::Internal)
|
||||
_type = PropertyTraits<T>::type_tag;
|
||||
else
|
||||
_type = EXTENDED;
|
||||
_tied = true;
|
||||
_value.val = rawValue.clone();
|
||||
|
||||
if (useDefault)
|
||||
setValue(this, old_val);
|
||||
|
||||
setValue(old_val);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1636,6 +1798,75 @@ 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
#endif // __PROPS_HXX
|
||||
|
||||
// end of props.hxx
|
||||
|
||||
Reference in New Issue
Block a user