#include <string>
#include <iostream>
#include <sstream>
+#include <typeinfo>
#include <boost/utility.hpp>
+#include <boost/type_traits/is_enum.hpp>
#if PROPS_STANDALONE
#else
* whether the property should normally be saved and restored.</p>
*/
enum Attribute {
+ NO_ATTR = 0,
READ = 1,
WRITE = 2,
ARCHIVE = 4,
simgear::PropertyList getChildren (const std::string& name) const
{ return getChildren(name.c_str()); }
+ // TODO do we need the removeXXX methods to return the deleted nodes?
/**
* Remove child by position.
*/
- SGPropertyNode_ptr removeChild (int pos, bool keep = true);
+ SGPropertyNode_ptr removeChild(int pos);
/**
* Remove a child node
*/
- SGPropertyNode_ptr removeChild (const char * name, int index = 0,
- bool keep = true);
+ SGPropertyNode_ptr removeChild(const char * name, int index = 0);
/**
* Remove a child node
*/
- SGPropertyNode_ptr removeChild (const std::string& name, int index = 0,
- bool keep = true)
- { return removeChild(name.c_str(), index, keep); }
+ SGPropertyNode_ptr removeChild(const std::string& name, int index = 0)
+ { return removeChild(name.c_str(), index); }
/**
* Remove all children with the specified name.
*/
- simgear::PropertyList removeChildren (const char * name, bool keep = true);
+ simgear::PropertyList removeChildren(const char * name);
/**
* Remove all children with the specified name.
*/
- simgear::PropertyList removeChildren (const std::string& name,
- bool keep = true)
- { return removeChildren(name.c_str(), keep); }
+ simgear::PropertyList removeChildren(const std::string& name)
+ { return removeChildren(name.c_str()); }
+
+ /**
+ * Remove all children (does not change the value of the node)
+ */
+ void removeAllChildren();
//
// Alias support.
/// counted pointer
SGPropertyNode * _parent;
simgear::PropertyList _children;
- simgear::PropertyList _removedChildren;
mutable std::string _buffer;
simgear::props::Type _type;
bool _tied;
SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false);
// very internal method
template<typename Itr>
- SGPropertyNode* getExistingChild (Itr begin, Itr end, int index, bool create);
+ SGPropertyNode* getExistingChild (Itr begin, Itr end, int index);
// very internal path parsing function
template<typename SplitItr>
friend SGPropertyNode* find_node_aux(SGPropertyNode * current, SplitItr& itr,
// Convenience functions for use in templates
template<typename T>
-T getValue(const SGPropertyNode*);
+typename boost::disable_if<boost::is_enum<T>, T>::type
+getValue(const SGPropertyNode*);
template<>
inline bool getValue<bool>(const SGPropertyNode* node) { return node->getBoolValue(); }
return node->getStringValue();
}
+namespace simgear
+{
+ /**
+ * Default trait for extracting enum values from SGPropertyNode. Create your
+ * own specialization for specific enum types to enable validation of values.
+ */
+ template<class T>
+ struct enum_traits
+ {
+ /**
+ * Typename of the enum
+ */
+ static const char* name() { return typeid(T).name(); }
+
+ /**
+ * @return Default value (will be used if validation fails)
+ */
+ static T defVal() { return T(); }
+
+ /**
+ * @return Whether the given integer value has an enum value defined
+ */
+ static bool validate(int) { return true; }
+ };
+} // namespace simgear
+
+/** Extract enum from SGPropertyNode */
+template<typename T>
+inline typename boost::enable_if<boost::is_enum<T>, T>::type
+getValue(const SGPropertyNode* node)
+{
+ typedef simgear::enum_traits<T> Traits;
+ int val = node->getIntValue();
+ if( !Traits::validate(val) )
+ {
+ SG_LOG
+ (
+ SG_GENERAL,
+ SG_WARN,
+ "Invalid value for enum (" << Traits::name() << ", val = " << val << ")"
+ );
+ return Traits::defVal();
+ }
+ return static_cast<T>(node->getIntValue());
+}
+
inline bool setValue(SGPropertyNode* node, bool value)
{
return node->setBoolValue(value);