X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fprops%2Fprops.hxx;h=8cf38e6da7954becd375207277a69e56381e837f;hb=708ae35068499af33329f9db91f55441f4956acb;hp=960d2aeac631535f22c085c156f401a857837e38;hpb=ff17b44a411f7892600159aa769229716019c751;p=simgear.git diff --git a/simgear/props/props.hxx b/simgear/props/props.hxx index 960d2aea..8cf38e6d 100644 --- a/simgear/props/props.hxx +++ b/simgear/props/props.hxx @@ -30,7 +30,7 @@ #endif - +#include #include #include @@ -63,6 +63,13 @@ inline T parseString(const std::string& str) return result; } +// Extended properties +template<> +std::istream& readFrom(std::istream& stream, SGVec3d& result); +template<> +std::istream& readFrom(std::istream& stream, SGVec4d& result); + + /** * Property value types. */ @@ -128,11 +135,14 @@ enum Type { DOUBLE, STRING, UNSPECIFIED, - EXTENDED /**< The node's value is not stored in the property; + 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. */ + // Extended properties + VEC3D, + VEC4D }; template struct PropertyTraits; @@ -151,8 +161,22 @@ DEFINTERNALPROP(long, LONG); DEFINTERNALPROP(float, FLOAT); DEFINTERNALPROP(double, DOUBLE); DEFINTERNALPROP(const char *, STRING); +DEFINTERNALPROP(const char[], STRING); #undef DEFINTERNALPROP +template<> +struct PropertyTraits +{ + static const Type type_tag = VEC3D; + enum { Internal = 0 }; +}; + +template<> +struct PropertyTraits +{ + static const Type type_tag = VEC4D; + enum { Internal = 0 }; +}; } } @@ -289,7 +313,10 @@ public: * may need different kinds of default values (such as epoch for a * date type). The default value is used when creating new values. */ - static const T DefaultValue; // Default for this kind of raw value. + static T DefaultValue() + { + return T(); + } /** @@ -345,12 +372,15 @@ public: // Default values for every type. //////////////////////////////////////////////////////////////////////// -template<> const bool SGRawValue::DefaultValue; -template<> const int SGRawValue::DefaultValue; -template<> const long SGRawValue::DefaultValue; -template<> const float SGRawValue::DefaultValue; -template<> const double SGRawValue::DefaultValue; -template<> const char * const SGRawValue::DefaultValue; +template<> inline bool SGRawValue::DefaultValue() +{ + return false; +} + +template<> inline const char * SGRawValue::DefaultValue() +{ + return ""; +} /** * A raw value bound to a pointer. @@ -461,7 +491,7 @@ public: */ virtual T getValue () const { if (_getter) return (*_getter)(); - else return SGRawValue::DefaultValue; + else return SGRawValue::DefaultValue(); } /** @@ -510,7 +540,7 @@ public: virtual ~SGRawValueFunctionsIndexed () {} virtual T getValue () const { if (_getter) return (*_getter)(_index); - else return SGRawValue::DefaultValue; + else return SGRawValue::DefaultValue(); } virtual bool setValue (T value) { if (_setter) { (*_setter)(_index, value); return true; } @@ -543,7 +573,7 @@ public: virtual ~SGRawValueMethods () {} virtual T getValue () const { if (_getter) { return (_obj.*_getter)(); } - else { return SGRawValue::DefaultValue; } + else { return SGRawValue::DefaultValue(); } } virtual bool setValue (T value) { if (_setter) { (_obj.*_setter)(value); return true; } @@ -577,7 +607,7 @@ public: virtual ~SGRawValueMethodsIndexed () {} virtual T getValue () const { if (_getter) { return (_obj.*_getter)(_index); } - else { return SGRawValue::DefaultValue; } + else { return SGRawValue::DefaultValue(); } } virtual bool setValue (T value) { if (_setter) { (_obj.*_setter)(_index, value); return true; } @@ -658,6 +688,12 @@ std::istream& SGRawBase::readFrom(std::istream& stream) static_cast*>(this)->setValue(value); return stream; } + +template<> +std::ostream& SGRawBase::printOn(std::ostream& stream) const; +template<> +std::ostream& SGRawBase::printOn(std::ostream& stream) const; + /** * The smart pointer that manage reference counting @@ -666,6 +702,11 @@ class SGPropertyNode; typedef SGSharedPtr SGPropertyNode_ptr; typedef SGSharedPtr SGConstPropertyNode_ptr; +namespace simgear +{ +typedef std::vector PropertyList; +} + /** * The property change listener interface. @@ -719,7 +760,10 @@ public: REMOVED = 8, TRACE_READ = 16, TRACE_WRITE = 32, - USERARCHIVE = 64 + USERARCHIVE = 64, + PRESERVE = 128 + // beware: if you add another attribute here, + // also update value of "LAST_USED_ATTRIBUTE". }; @@ -764,11 +808,15 @@ public: */ const char * getName () const { return _name.c_str(); } + /** + * Get the node's simple name as a string. + */ + const std::string& getNameString () const { return _name; } /** * Get the node's pretty display name, with subscript when needed. */ - const char * getDisplayName (bool simplify = false) const; + std::string getDisplayName (bool simplify = false) const; /** @@ -797,7 +845,7 @@ public: /** * Get the number of child nodes. */ - int nChildren () const { return _children.size(); } + int nChildren () const { return (int)_children.size(); } /** @@ -836,17 +884,10 @@ public: /** * Get a child node by name and index. */ - SGPropertyNode * getChild (const char * name, int index = 0, - bool create = false); - - /** - * Get a child node by name and index. - */ + SGPropertyNode * getChild (const char* name, int index = 0, + bool create = false); SGPropertyNode * getChild (const std::string& name, int index = 0, - bool create = false) - { return getChild(name.c_str(), index, create); } - - + bool create = false); /** * Get a const child node by name and index. */ @@ -862,12 +903,12 @@ public: /** * Get a vector of all children with the specified name. */ - std::vector getChildren (const char * name) const; + simgear::PropertyList getChildren (const char * name) const; /** * Get a vector of all children with the specified name. */ - std::vector getChildren (const std::string& name) const + simgear::PropertyList getChildren (const std::string& name) const { return getChildren(name.c_str()); } /** @@ -892,15 +933,13 @@ public: /** * Remove all children with the specified name. */ - std::vector removeChildren (const char * name, - bool keep = true); - + simgear::PropertyList removeChildren (const char * name, bool keep = true); /** * Remove all children with the specified name. */ - std::vector removeChildren (const std::string& name, - bool keep = true) + simgear::PropertyList removeChildren (const std::string& name, + bool keep = true) { return removeChildren(name.c_str(), keep); } // @@ -958,7 +997,7 @@ public: /** * Get the path to this node from the root. */ - const char * getPath (bool simplify = false) const; + std::string getPath (bool simplify = false) const; /** @@ -1186,6 +1225,12 @@ public: bool setValue(const T& val, typename boost::disable_if_c::Internal> ::type* dummy = 0); + + template + bool setValue(const char (&val)[N]) + { + return setValue(&val[0]); + } /** * Print the value of the property to a stream. @@ -1389,12 +1434,17 @@ public: */ bool setStringValue (const char * relative_path, const char * value); + bool setStringValue(const char * relative_path, const std::string& value) + { return setStringValue(relative_path, value.c_str()); } /** * Set another node's value as a string. */ bool setStringValue (const std::string& relative_path, const char * value) { return setStringValue(relative_path.c_str(), value); } + bool setStringValue (const std::string& relative_path, + const std::string& value) + { return setStringValue(relative_path.c_str(), value.c_str()); } /** * Set another node's value with no specified type. @@ -1526,7 +1576,7 @@ public: /** * Get the number of listeners. */ - int nListeners () const { return _listeners ? _listeners->size() : 0; } + int nListeners () const { return _listeners ? (int)_listeners->size() : 0; } /** @@ -1552,6 +1602,16 @@ public: */ void clearValue (); + /** + * Compare two property trees. The property trees are equal if: 1) + * They have no children, and have the same type and the values are + * equal, or 2) have the same number of children, and the + * corresponding children in each tree are equal. "corresponding" + * means have the same name and index. + * + * Attributes, removed children, and aliases aren't considered. + */ + static bool compare (const SGPropertyNode& lhs, const SGPropertyNode& rhs); protected: @@ -1562,12 +1622,13 @@ protected: /** * Protected constructor for making new nodes on demand. */ - SGPropertyNode (const char * name, int index, SGPropertyNode * parent); - + SGPropertyNode (const std::string& name, int index, SGPropertyNode * parent); + template + SGPropertyNode (Itr begin, Itr end, int index, SGPropertyNode * parent); private: - // Get the raw value + // Get the raw value bool get_bool () const; int get_int () const; long get_long () const; @@ -1575,7 +1636,7 @@ private: double get_double () const; const char * get_string () const; - // Set the raw value + // Set the raw value bool set_bool (bool value); bool set_int (int value); bool set_long (long value); @@ -1600,32 +1661,19 @@ private: */ void trace_write () const; - - /** - * Remove this node from all nodes that link to it in their path cache. - */ - void remove_from_path_caches(); - - - class hash_table; - int _index; std::string _name; - mutable std::string _display_name; /// To avoid cyclic reference counting loops this shall not be a reference /// counted pointer SGPropertyNode * _parent; - std::vector _children; - std::vector _removedChildren; - std::vector _linkedNodes; - mutable std::string _path; + simgear::PropertyList _children; + simgear::PropertyList _removedChildren; mutable std::string _buffer; - hash_table * _path_cache; simgear::props::Type _type; bool _tied; int _attr; - // The right kind of pointer... + // The right kind of pointer... union { SGPropertyNode * alias; SGRaw* val; @@ -1642,67 +1690,19 @@ private: std::vector * _listeners; - - /** - * Register/unregister node that links to this node in its path cache. - */ - void add_linked_node (hash_table * node) { _linkedNodes.push_back(node); } - bool remove_linked_node (hash_table * node); - - - /** - * A very simple hash table. - */ - class hash_table { - public: - - /** - * An entry in a bucket in a hash table. - */ - class entry { - public: - entry (); - ~entry (); - const char * get_key () { return _key.c_str(); } - void set_key (const char * key); - SGPropertyNode * get_value () { return _value; } - void set_value (SGPropertyNode * value); - private: - std::string _key; - SGSharedPtr _value; - }; - - - /** - * A bucket in a hash table. - */ - class bucket { - public: - bucket (); - ~bucket (); - entry * get_entry (const char * key, bool create = false); - bool erase (SGPropertyNode * node); - void clear (hash_table * owner); - private: - int _length; - entry ** _entries; - }; - - friend class bucket; - - hash_table (); - ~hash_table (); - SGPropertyNode * get (const char * key); - void put (const char * key, SGPropertyNode * value); - bool erase (SGPropertyNode * node); - - private: - unsigned int hashcode (const char * key); - unsigned int _data_length; - bucket ** _data; - }; - + // Pass name as a pair of iterators + template + SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false); + // very internal method + template + SGPropertyNode* getExistingChild (Itr begin, Itr end, int index, bool create); + // very internal path parsing function + template + friend SGPropertyNode* find_node_aux(SGPropertyNode * current, SplitItr& itr, + bool create, int last_index); + // For boost + friend size_t hash_value(const SGPropertyNode& node); }; // Convenience functions for use in templates @@ -1779,7 +1779,7 @@ bool SGPropertyNode::tie(const SGRawValue &rawValue, bool useDefault) return false; useDefault = useDefault && hasValue(); - T old_val = SGRawValue::DefaultValue; + T old_val = SGRawValue::DefaultValue(); if (useDefault) old_val = getValue(this); clearValue(); @@ -1789,8 +1789,12 @@ bool SGPropertyNode::tie(const SGRawValue &rawValue, bool useDefault) _type = EXTENDED; _tied = true; _value.val = rawValue.clone(); - if (useDefault) + if (useDefault) { + int save_attributes = getAttributes(); + setAttribute( WRITE, true ); setValue(old_val); + setAttributes( save_attributes ); + } return true; } @@ -1810,7 +1814,7 @@ T SGPropertyNode::getValue(typename boost::disable_if_c::DefaultValue; + return SGRawValue::DefaultValue(); switch (_type) { case EXTENDED: if (_value.val->getType() == PropertyTraits::type_tag) @@ -1820,8 +1824,10 @@ T SGPropertyNode::getValue(typename boost::disable_if_c(make_string()); break; + default: // avoid compiler warning + break; } - return SGRawValue::DefaultValue; + return SGRawValue::DefaultValue(); } template @@ -1867,6 +1873,71 @@ inline bool SGPropertyNode::setValue(const T& val, { return ::setValue(this, val); } + +/** + * Utility function for creation of a child property node. + */ +inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name, + int index = 0) +{ + return parent->getChild(name, index, true); +} + +/** + * Utility function for creation of a child property node using a + * relative path. + */ +namespace simgear +{ +template +inline SGPropertyNode* makeNode(SGPropertyNode* parent, const StringType& name) +{ + return parent->getNode(name, true); +} +} + +// For boost::hash +size_t hash_value(const SGPropertyNode& node); + +// Helper comparison and hash functions for common cases + +namespace simgear +{ +namespace props +{ +struct Compare +{ + bool operator()(const SGPropertyNode* lhs, const SGPropertyNode* rhs) const + { + return SGPropertyNode::compare(*lhs, *rhs); + } + bool operator()(SGPropertyNode_ptr lhs, const SGPropertyNode* rhs) const + { + return SGPropertyNode::compare(*lhs, *rhs); + } + bool operator()(const SGPropertyNode* lhs, SGPropertyNode_ptr rhs) const + { + return SGPropertyNode::compare(*lhs, *rhs); + } + bool operator()(SGPropertyNode_ptr lhs, SGPropertyNode_ptr rhs) const + { + return SGPropertyNode::compare(*lhs, *rhs); + } +}; + +struct Hash +{ + size_t operator()(const SGPropertyNode* node) const + { + return hash_value(*node); + } + size_t operator()(SGPropertyNode_ptr node) const + { + return hash_value(*node); + } +}; +} +} #endif // __PROPS_HXX // end of props.hxx