Files
simgear/simgear/props/propertyObject.hxx

269 lines
6.0 KiB
C++

// Copyright (C) 2010 James Turner - zakalawe@mac.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef SG_PROPERTY_OBJECT
#define SG_PROPERTY_OBJECT
#include <simgear/props/props.hxx>
namespace simgear
{
class PropertyObjectBase
{
public:
static void setDefaultRoot(SGPropertyNode* aRoot);
PropertyObjectBase();
PropertyObjectBase(const PropertyObjectBase& aOther);
PropertyObjectBase(const char* aChild);
PropertyObjectBase(SGPropertyNode* aNode, const char* aChild = NULL);
SGPropertyNode* node(bool aCreate) const;
/**
* Resolve the property node, or throw an exception if it could not
* be resolved.
*/
SGPropertyNode* getOrThrow() const;
protected:
mutable const char* _path;
/**
* Important - if _path is NULL, this is the actual prop.
* If path is non-NULL, this is the parent which path should be resolved
* against (or NULL, if _path is absolute). Use node() instead of accessing
* this directly, and the above is handled automatically.
*/
mutable SGPropertyNode* _prop;
};
template <typename T>
class PropertyObject : PropertyObjectBase
{
public:
PropertyObject()
{}
/**
* Create from path relative to the default root, and option default value
*/
explicit PropertyObject(const char* aChild) :
PropertyObjectBase(aChild)
{ }
/**
* Create from a node, with optional relative path
*/
explicit PropertyObject(SGPropertyNode* aNode, const char* aChild = NULL) :
PropertyObjectBase(aNode, aChild)
{
}
// copy-constructor
PropertyObject(const PropertyObject<T>& aOther) :
PropertyObjectBase(aOther)
{
}
// create() form creates the property immediately
static PropertyObject<T> create(const char* aPath, T aValue)
{
PropertyObject<T> p(aPath);
p = aValue;
return p;
}
static PropertyObject<T> create(SGPropertyNode_ptr aNode)
{
PropertyObject<T> p(aNode);
return p;
}
static PropertyObject<T> create(SGPropertyNode* aNode, T aValue)
{
PropertyObject<T> p(aNode);
p = aValue;
return p;
}
static PropertyObject<T> create(SGPropertyNode* aNode, const char* aChild, T aValue)
{
PropertyObject<T> p(aNode, aChild);
p = aValue;
return p;
}
// conversion operators
operator T () const
{
return getOrThrow()->template getValue<T>();
}
T operator=(const T& aValue)
{
SGPropertyNode* n = PropertyObjectBase::node(true);
if( !n )
return aValue;
n->setValue<T>(aValue);
return aValue;
}
#define SG_DEF_ASSIGN_OP(op)\
T operator op##=(const T rhs)\
{\
SGPropertyNode* n = getOrThrow();\
T new_val = n->getValue<T>() op rhs;\
n->setValue<T>(new_val);\
return new_val;\
}
SG_DEF_ASSIGN_OP(+)
SG_DEF_ASSIGN_OP(-)
SG_DEF_ASSIGN_OP(*)
SG_DEF_ASSIGN_OP(/)
SG_DEF_ASSIGN_OP(%)
SG_DEF_ASSIGN_OP(>>)
SG_DEF_ASSIGN_OP(<<)
SG_DEF_ASSIGN_OP(&)
SG_DEF_ASSIGN_OP(^)
SG_DEF_ASSIGN_OP(|)
#undef SG_DEF_ASSIGN_OP
SGPropertyNode* node(bool aCreate = false) const
{
return PropertyObjectBase::node(aCreate);
}
}; // of template PropertyObject
// specialization for const char* / std::string
template <>
class PropertyObject<std::string> : PropertyObjectBase
{
public:
PropertyObject() = default;
explicit PropertyObject(const char* aChild) :
PropertyObjectBase(aChild)
{ }
explicit PropertyObject(SGPropertyNode* aNode, const char* aChild = NULL) :
PropertyObjectBase(aNode, aChild)
{
}
// copy-constructor
PropertyObject(const PropertyObject<std::string>& aOther) :
PropertyObjectBase(aOther)
{
}
// create form
static PropertyObject<std::string> create(const char* aPath, const std::string& aValue)
{
PropertyObject<std::string> p(aPath);
p = aValue;
return p;
}
static PropertyObject<std::string> create(SGPropertyNode_ptr aNode)
{
PropertyObject<std::string> p(aNode);
return p;
}
static PropertyObject<std::string> create(SGPropertyNode* aNode, const std::string& aValue)
{
PropertyObject<std::string> p(aNode);
p = aValue;
return p;
}
static PropertyObject<std::string> create(SGPropertyNode* aNode, const char* aChild, const std::string& aValue)
{
PropertyObject<std::string> p(aNode, aChild);
p = aValue;
return p;
}
operator std::string () const
{
return getOrThrow()->getStringValue();
}
const char* operator=(const char* aValue)
{
SGPropertyNode* n = PropertyObjectBase::node(true);
if (!n) {
return aValue;
}
n->setStringValue(aValue);
return aValue;
}
std::string operator=(const std::string& aValue)
{
SGPropertyNode* n = PropertyObjectBase::node(true);
if (!n) {
return aValue;
}
n->setStringValue(aValue);
return aValue;
}
bool operator==(const char* value) const
{
std::string s(*this);
return (s == value);
}
bool operator==(const std::string& value) const
{
std::string s(*this);
return (s == value);
}
SGPropertyNode* node(bool aCreate = false) const
{
return PropertyObjectBase::node(aCreate);
}
private:
};
} // of namespace simgear
typedef simgear::PropertyObject<double> SGPropObjDouble;
typedef simgear::PropertyObject<bool> SGPropObjBool;
typedef simgear::PropertyObject<std::string> SGPropObjString;
typedef simgear::PropertyObject<long> SGPropObjInt;
#endif