#endif
#include <vector>
-
-#if PROPS_STANDALONE
-
#include <string>
-#include <iostream>
-
-using std::string;
-using std::vector;
-using std::istream;
-using std::ostream;
+#if PROPS_STANDALONE
#else
-
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
-#include STL_STRING
-#include STL_IOSTREAM
-SG_USING_STD(string);
-SG_USING_STD(vector);
-SG_USING_STD(istream);
-SG_USING_STD(ostream);
-
#endif
+
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+
+
#ifdef NONE
#pragma warn A sloppy coder has defined NONE as a macro!
#undef NONE
* The smart pointer that manage reference counting
*/
class SGPropertyNode;
-class SGPropertyNode_ptr
-{
-public:
-
- /**
- * Default constructor
- */
- SGPropertyNode_ptr();
-
- /**
- * Copy constructor
- */
- SGPropertyNode_ptr( const SGPropertyNode_ptr &r );
-
- /**
- * Constructor from a pointer to a node
- */
- SGPropertyNode_ptr( SGPropertyNode *p );
-
- /**
- * Destructor
- */
- ~SGPropertyNode_ptr();
-
- /**
- * Assignement operator
- */
- SGPropertyNode_ptr &operator=( const SGPropertyNode_ptr &r );
-
- /**
- * Pointer access operator
- */
- SGPropertyNode *operator->();
-
- /**
- * Pointer access operator (const)
- */
- const SGPropertyNode *operator->() const;
-
- /**
- * Conversion to SGPropertyNode * operator
- */
- operator SGPropertyNode *();
-
- /**
- * Conversion to const SGPropertyNode * operator
- */
- operator const SGPropertyNode *() const;
-
- /**
- * Return the pointer.
- */
- SGPropertyNode * ptr () { return _ptr; }
-
- /**
- * Validity test
- */
- bool valid() const;
-
-private:
-
- SGPropertyNode *_ptr;
-};
-
+typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
+typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
\f
/**
virtual void unregister_property (SGPropertyNode * node);
private:
- vector<SGPropertyNode *> _properties;
+ std::vector<SGPropertyNode *> _properties;
};
/**
* A node in a property tree.
*/
-class SGPropertyNode
+class SGPropertyNode : public SGReferenced
{
public:
ARCHIVE = 4,
REMOVED = 8,
TRACE_READ = 16,
- TRACE_WRITE = 32
+ TRACE_WRITE = 32,
+ USERARCHIVE = 64
};
/**
* Get the node's simple (XML) name.
*/
- const char * getName () const { return _name; }
+ const char * getName () const { return _name.c_str(); }
/**
return (getChild(name, index) != 0);
}
+ /**
+ * Test whether a named child exists.
+ */
+ bool hasChild (const std::string& name, int index = 0) const
+ {
+ return (getChild(name, index) != 0);
+ }
+
/**
* 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 std::string& name, int index = 0,
+ bool create = false)
+ { return getChild(name.c_str(), index, create); }
+
/**
* Get a const child node by name and index.
*/
const SGPropertyNode * getChild (const char * name, int index = 0) const;
+ /**
+ * Get a const child node by name and index.
+ */
+ const SGPropertyNode * getChild (const std::string& name, int index = 0) const
+ { return getChild(name.c_str(), index); }
+
/**
* Get a vector of all children with the specified name.
*/
- vector<SGPropertyNode_ptr> getChildren (const char * name) const;
+ std::vector<SGPropertyNode_ptr> getChildren (const char * name) const;
+
+ /**
+ * Get a vector of all children with the specified name.
+ */
+ std::vector<SGPropertyNode_ptr> getChildren (const std::string& name) const
+ { return getChildren(name.c_str()); }
+
+ /**
+ * Remove child by position.
+ */
+ SGPropertyNode_ptr removeChild (int pos, bool keep = true);
/**
SGPropertyNode_ptr removeChild (const char * name, int index = 0,
bool keep = true);
+ /**
+ * Remove a child node
+ */
+ SGPropertyNode_ptr removeChild (const std::string& name, int index = 0,
+ bool keep = true)
+ { return removeChild(name.c_str(), index, keep); }
+
+ /**
+ * Remove all children with the specified name.
+ */
+ std::vector<SGPropertyNode_ptr> removeChildren (const char * name,
+ bool keep = true);
+
+
+ /**
+ * Remove all children with the specified name.
+ */
+ std::vector<SGPropertyNode_ptr> removeChildren (const std::string& name,
+ bool keep = true)
+ { return removeChildren(name.c_str(), keep); }
//
// Alias support.
*/
bool alias (const char * path);
+ /**
+ * Alias this node's leaf value to another's by relative path.
+ */
+ bool alias (const std::string& path)
+ { return alias(path.c_str()); }
+
/**
* Remove any alias for this node.
*/
SGPropertyNode * getNode (const char * relative_path, bool create = false);
+ /**
+ * Get a pointer to another node by relative path.
+ */
+ SGPropertyNode * getNode (const std::string& relative_path, bool create = false)
+ { return getNode(relative_path.c_str(), create); }
/**
* Get a pointer to another node by relative path.
SGPropertyNode * getNode (const char * relative_path, int index,
bool create = false);
+ /**
+ * Get a pointer to another node by relative path.
+ *
+ * This method leaves the index off the last member of the path,
+ * so that the user can specify it separately (and save some
+ * string building). For example, getNode("/bar[1]/foo", 3) is
+ * exactly equivalent to getNode("bar[1]/foo[3]"). The index
+ * provided overrides any given in the path itself for the last
+ * component.
+ */
+ SGPropertyNode * getNode (const std::string& relative_path, int index,
+ bool create = false)
+ { return getNode(relative_path.c_str(), index, create); }
/**
* Get a const pointer to another node by relative path.
*/
const SGPropertyNode * getNode (const char * relative_path) const;
+ /**
+ * Get a const pointer to another node by relative path.
+ */
+ const SGPropertyNode * getNode (const std::string& relative_path) const
+ { return getNode(relative_path.c_str()); }
+
/**
* Get a const pointer to another node by relative path.
const SGPropertyNode * getNode (const char * relative_path,
int index) const;
+ /**
+ * Get a const pointer to another node by relative path.
+ *
+ * This method leaves the index off the last member of the path,
+ * so that the user can specify it separate.
+ */
+ const SGPropertyNode * getNode (const std::string& relative_path,
+ int index) const
+ { return getNode(relative_path.c_str(), index); }
//
// Access Mode.
*/
bool setStringValue (const char * value);
+ /**
+ * Set a string value for this node.
+ */
+ bool setStringValue (const std::string& value)
+ { return setStringValue(value.c_str()); }
+
/**
* Set a value of unspecified type for this node.
*/
Type getType (const char * relative_path) const;
+ /**
+ * Get another node's type.
+ */
+ Type getType (const std::string& relative_path) const
+ { return getType(relative_path.c_str()); }
/**
* Test whether another node has a leaf value.
*/
bool hasValue (const char * relative_path) const;
+ /**
+ * Test whether another node has a leaf value.
+ */
+ bool hasValue (const std::string& relative_path) const
+ { return hasValue(relative_path.c_str()); }
/**
* Get another node's value as a bool.
bool getBoolValue (const char * relative_path,
bool defaultValue = false) const;
+ /**
+ * Get another node's value as a bool.
+ */
+ bool getBoolValue (const std::string& relative_path,
+ bool defaultValue = false) const
+ { return getBoolValue(relative_path.c_str(), defaultValue); }
/**
* Get another node's value as an int.
int getIntValue (const char * relative_path,
int defaultValue = 0) const;
+ /**
+ * Get another node's value as an int.
+ */
+ int getIntValue (const std::string& relative_path,
+ int defaultValue = 0) const
+ { return getIntValue(relative_path.c_str(), defaultValue); }
+
/**
* Get another node's value as a long int.
long getLongValue (const char * relative_path,
long defaultValue = 0L) const;
+ /**
+ * Get another node's value as a long int.
+ */
+ long getLongValue (const std::string& relative_path,
+ long defaultValue = 0L) const
+ { return getLongValue(relative_path.c_str(), defaultValue); }
/**
* Get another node's value as a float.
*/
float getFloatValue (const char * relative_path,
- float defaultValue = 0.0) const;
+ float defaultValue = 0.0f) const;
+
+ /**
+ * Get another node's value as a float.
+ */
+ float getFloatValue (const std::string& relative_path,
+ float defaultValue = 0.0f) const
+ { return getFloatValue(relative_path.c_str(), defaultValue); }
/**
* Get another node's value as a double.
*/
double getDoubleValue (const char * relative_path,
- double defaultValue = 0.0L) const;
+ double defaultValue = 0.0) const;
+ /**
+ * Get another node's value as a double.
+ */
+ double getDoubleValue (const std::string& relative_path,
+ double defaultValue = 0.0) const
+ { return getDoubleValue(relative_path.c_str(), defaultValue); }
/**
* Get another node's value as a string.
const char * defaultValue = "") const;
+ /**
+ * Get another node's value as a string.
+ */
+ const char * getStringValue (const std::string& relative_path,
+ const char * defaultValue = "") const
+ { return getStringValue(relative_path.c_str(), defaultValue); }
+
+
/**
* Set another node's value as a bool.
*/
bool setBoolValue (const char * relative_path, bool value);
+ /**
+ * Set another node's value as a bool.
+ */
+ bool setBoolValue (const std::string& relative_path, bool value)
+ { return setBoolValue(relative_path.c_str(), value); }
+
/**
* Set another node's value as an int.
*/
bool setIntValue (const char * relative_path, int value);
+ /**
+ * Set another node's value as an int.
+ */
+ bool setIntValue (const std::string& relative_path, int value)
+ { return setIntValue(relative_path.c_str(), value); }
+
/**
* Set another node's value as a long int.
*/
bool setLongValue (const char * relative_path, long value);
+ /**
+ * Set another node's value as a long int.
+ */
+ bool setLongValue (const std::string& relative_path, long value)
+ { return setLongValue(relative_path.c_str(), value); }
+
/**
* Set another node's value as a float.
*/
bool setFloatValue (const char * relative_path, float value);
+ /**
+ * Set another node's value as a float.
+ */
+ bool setFloatValue (const std::string& relative_path, float value)
+ { return setFloatValue(relative_path.c_str(), value); }
+
/**
* Set another node's value as a double.
*/
bool setDoubleValue (const char * relative_path, double value);
+ /**
+ * Set another node's value as a double.
+ */
+ bool setDoubleValue (const std::string& relative_path, double value)
+ { return setDoubleValue(relative_path.c_str(), value); }
+
/**
* Set another node's value as a string.
*/
bool setStringValue (const char * relative_path, const char * value);
+ /**
+ * 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); }
+
/**
* Set another node's value with no specified type.
*/
bool isTied (const char * relative_path) const;
+ /**
+ * Test whether another node is bound to an external data source.
+ */
+ bool isTied (const std::string& relative_path) const
+ { return isTied(relative_path.c_str()); }
/**
* Bind another node to an external bool source.
bool tie (const char * relative_path, const SGRawValue<bool> &rawValue,
bool useDefault = true);
+ /**
+ * Bind another node to an external bool source.
+ */
+ bool tie (const std::string& relative_path, const SGRawValue<bool> &rawValue,
+ bool useDefault = true)
+ { return tie(relative_path.c_str(), rawValue, useDefault); }
+
/**
* Bind another node to an external int source.
bool tie (const char * relative_path, const SGRawValue<int> &rawValue,
bool useDefault = true);
+ /**
+ * Bind another node to an external int source.
+ */
+ bool tie (const std::string& relative_path, const SGRawValue<int> &rawValue,
+ bool useDefault = true)
+ { return tie(relative_path.c_str(), rawValue, useDefault); }
+
/**
* Bind another node to an external long int source.
bool tie (const char * relative_path, const SGRawValue<long> &rawValue,
bool useDefault = true);
+ /**
+ * Bind another node to an external long int source.
+ */
+ bool tie (const std::string& relative_path, const SGRawValue<long> &rawValue,
+ bool useDefault = true)
+ { return tie(relative_path.c_str(), rawValue, useDefault); }
+
/**
* Bind another node to an external float source.
bool tie (const char * relative_path, const SGRawValue<float> &rawValue,
bool useDefault = true);
+ /**
+ * Bind another node to an external float source.
+ */
+ bool tie (const std::string& relative_path, const SGRawValue<float> &rawValue,
+ bool useDefault = true)
+ { return tie(relative_path.c_str(), rawValue, useDefault); }
+
/**
* Bind another node to an external double source.
bool tie (const char * relative_path, const SGRawValue<double> &rawValue,
bool useDefault = true);
+ /**
+ * Bind another node to an external double source.
+ */
+ bool tie (const std::string& relative_path, const SGRawValue<double> &rawValue,
+ bool useDefault = true)
+ { return tie(relative_path.c_str(), rawValue, useDefault); }
+
/**
* Bind another node to an external string source.
bool tie (const char * relative_path, const SGRawValue<const char *> &rawValue,
bool useDefault = true);
+ /**
+ * Bind another node to an external string source.
+ */
+ bool tie (const std::string& relative_path, const SGRawValue<const char*> &rawValue,
+ bool useDefault = true)
+ { return tie(relative_path.c_str(), rawValue, useDefault); }
+
/**
* Unbind another node from any external data source.
*/
bool untie (const char * relative_path);
+ /**
+ * Unbind another node from any external data source.
+ */
+ bool untie (const std::string& relative_path)
+ { return untie(relative_path.c_str()); }
+
/**
- * Add a change listener to the property.
+ * Add a change listener to the property. If "initial" is set call the
+ * listener initially.
*/
- void addChangeListener (SGPropertyChangeListener * listener);
+ void addChangeListener (SGPropertyChangeListener * listener,
+ bool initial = false);
/**
void removeChangeListener (SGPropertyChangeListener * listener);
+ /**
+ * Get the number of listeners.
+ */
+ int nListeners () const { return _listeners ? _listeners->size() : 0; }
+
+
/**
* Fire a value change event to all listeners.
*/
/**
- * Increment reference counter
+ * Remove this node from all nodes that link to it in their path cache.
*/
- void incrementRef();
+ void remove_from_path_caches();
- /**
- * Decrement reference counter
- */
- int decrementRef();
-
- friend class SGPropertyNode_ptr;
-
-
- mutable char _buffer[MAX_STRING_LEN+1];
class hash_table;
- char * _name;
- mutable char * _display_name;
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;
- vector<SGPropertyNode_ptr> _children;
- vector<SGPropertyNode_ptr> _removedChildren;
- mutable char * _path;
+ std::vector<SGPropertyNode_ptr> _children;
+ std::vector<SGPropertyNode_ptr> _removedChildren;
+ std::vector<hash_table *> _linkedNodes;
+ mutable std::string _path;
+ mutable std::string _buffer;
hash_table * _path_cache;
Type _type;
bool _tied;
int _attr;
- int _count;
// The right kind of pointer...
union {
char * string_val;
} _local_val;
- vector <SGPropertyChangeListener *> * _listeners;
+ std::vector<SGPropertyChangeListener *> * _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);
\f
/**
- * A very simple hash table with no remove functionality.
+ * A very simple hash table.
*/
class hash_table {
public:
public:
entry ();
~entry ();
- const char * get_key () { return _key; }
+ 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:
- char * _key;
- SGPropertyNode * _value;
+ std::string _key;
+ SGSharedPtr<SGPropertyNode> _value;
};
bucket ();
~bucket ();
entry * get_entry (const char * key, bool create = false);
- void erase(const char * key);
+ bool erase (SGPropertyNode * node);
+ void clear (hash_table * owner);
private:
int _length;
entry ** _entries;
~hash_table ();
SGPropertyNode * get (const char * key);
void put (const char * key, SGPropertyNode * value);
- void erase(const char * key);
+ bool erase (SGPropertyNode * node);
private:
unsigned int hashcode (const char * key);