]> git.mxchange.org Git - simgear.git/blobdiff - simgear/props/props.cxx
- new FSF addresses
[simgear.git] / simgear / props / props.cxx
index 2e14a643f90231accf59d3c4fd7737fe4a3e2424..322a09cdd24d9a3e52ab1d9aff0a781be23324c6 100644 (file)
@@ -9,6 +9,7 @@
 #include "props.hxx"
 
 #include <algorithm>
+#include <sstream>
 #include <stdio.h>
 #include <string.h>
 
@@ -20,6 +21,7 @@ using std::endl;
 using std::find;
 using std::sort;
 using std::vector;
+using std::stringstream;
 
 #else
 
@@ -29,6 +31,7 @@ using std::vector;
 SG_USING_STD(sort);
 SG_USING_STD(find);
 SG_USING_STD(vector);
+SG_USING_STD(stringstream);
 
 #if ( _MSC_VER == 1200 )
 // MSVC 6 is buggy, and needs something strange here
@@ -247,7 +250,7 @@ compare_strings (const char * s1, const char * s2)
  * Locate a child node by name and index.
  */
 static int
-find_child (const char * name, int index, vector<SGPropertyNode_ptr> nodes)
+find_child (const char * name, int index, const vector<SGPropertyNode_ptr>& nodes)
 {
   int nNodes = nodes.size();
   for (int i = 0; i < nNodes; i++) {
@@ -548,17 +551,34 @@ SGPropertyNode::make_string () const
     else
       return "false";
   case INT:
-    sprintf(_buffer, "%d", get_int());
-    return _buffer;
+    {
+      stringstream sstr;
+      sstr << get_int();
+      _buffer = sstr.str();
+      return _buffer.c_str();
+    }
   case LONG:
-    sprintf(_buffer, "%ld", get_long());
-    return _buffer;
+    {
+      stringstream sstr;
+      sstr << get_long();
+      _buffer = sstr.str();
+      return _buffer.c_str();
+    }
   case FLOAT:
-    sprintf(_buffer, "%f", get_float());
-    return _buffer;
+    {
+      stringstream sstr;
+      sstr << get_float();
+      _buffer = sstr.str();
+      return _buffer.c_str();
+    }
   case DOUBLE:
-    sprintf(_buffer, "%f", get_double());
-    return _buffer;
+    {
+      stringstream sstr;
+      sstr.precision( 10 );
+      sstr << get_double();
+      _buffer = sstr.str();
+      return _buffer.c_str();
+    }
   case STRING:
   case UNSPECIFIED:
     return get_string();
@@ -598,25 +618,6 @@ SGPropertyNode::trace_read () const
 #endif
 }
 
-/**
- * Increment reference counter
- */
-void
-SGPropertyNode::incrementRef()
-{
-  ++_count;
-}
-
-/**
- * Decrement reference counter
- */
-int
-SGPropertyNode::decrementRef()
-{
-  return --_count;
-}
-
-
 \f
 ////////////////////////////////////////////////////////////////////////
 // Public methods from SGPropertyNode.
@@ -632,16 +633,12 @@ const int SGPropertyNode::LAST_USED_ATTRIBUTE = TRACE_WRITE;
  * Default constructor: always creates a root node.
  */
 SGPropertyNode::SGPropertyNode ()
-  : _name(copy_string("")),
-    _display_name(0),
-    _index(0),
+  : _index(0),
     _parent(0),
-    _path(0),
     _path_cache(0),
     _type(NONE),
     _tied(false),
     _attr(READ|WRITE),
-    _count(0),
     _listeners(0)
 {
   _local_val.string_val = 0;
@@ -652,18 +649,15 @@ SGPropertyNode::SGPropertyNode ()
  * Copy constructor.
  */
 SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
-  : _display_name(0),
-    _index(node._index),
+  : _index(node._index),
+    _name(node._name),
     _parent(0),                        // don't copy the parent
-    _path(0),
     _path_cache(0),
     _type(node._type),
     _tied(node._tied),
     _attr(node._attr),
-    _count(0),
     _listeners(0)              // CHECK!!
 {
-  _name = copy_string(node._name);
   _local_val.string_val = 0;
   switch (_type) {
   case NONE:
@@ -737,18 +731,15 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
 SGPropertyNode::SGPropertyNode (const char * name,
                                int index,
                                SGPropertyNode * parent)
-  : _display_name(0),
-    _index(index),
+  : _index(index),
     _parent(parent),
-    _path(0),
     _path_cache(0),
     _type(NONE),
     _tied(false),
     _attr(READ|WRITE),
-    _count(0),
     _listeners(0)
 {
-  _name = copy_string(name);
+  _name = name;
   _local_val.string_val = 0;
 }
 
@@ -758,9 +749,11 @@ SGPropertyNode::SGPropertyNode (const char * name,
  */
 SGPropertyNode::~SGPropertyNode ()
 {
-  delete [] _name;
-  delete [] _display_name;
-  delete [] _path;
+  // zero out all parent pointers, else they might be dangling
+  for (unsigned i = 0; i < _children.size(); ++i)
+    _children[i]->_parent = 0;
+  for (unsigned i = 0; i < _removedChildren.size(); ++i)
+    _removedChildren[i]->_parent = 0;
   delete _path_cache;
   clearValue();
   delete _listeners;
@@ -778,7 +771,6 @@ SGPropertyNode::alias (SGPropertyNode * target)
   clearValue();
   _value.alias = target;
   _type = ALIAS;
-  _value.alias->incrementRef();
   return true;
 }
 
@@ -802,7 +794,6 @@ SGPropertyNode::unalias ()
   if (_type != ALIAS)
     return false;
   _type = NONE;
-  _value.alias->decrementRef();
   _value.alias = 0;
   return true;
 }
@@ -914,105 +905,86 @@ SGPropertyNode::getChildren (const char * name) const
 
 
 /**
- * Remove a child node, and all children that aren't referenced.
- * "keep" does only apply to the outmost item. Returns "true" if
- * not all nodes could be removed.
+ * Remove child by position.
  */
-bool
-SGPropertyNode::removeChild (const char * name, int index, bool keep)
+SGPropertyNode_ptr
+SGPropertyNode::removeChild (int pos, bool keep)
 {
-  bool dirty = false;
-  int pos = find_child(name, index, _children);
-  if (pos >= 0) {
-    vector<SGPropertyNode_ptr>::iterator it = _children.begin();
-    it += pos;
-    SGPropertyNode *node = _children[pos];
-    if (node->nChildren() && node->removeChildren())
-      dirty = true;
-
-    if (node->isTied() || node->_count != 1 || node->nChildren())
-      dirty = true;
-    else {
-      if (keep)
-        _removedChildren.push_back(node);
-
-      if (_path_cache)
-        _path_cache->erase(name); // EMH - TODO: Take "index" into account!
-
-      node->setAttribute(REMOVED, true);
-      node->clearValue();
-      fireChildRemoved(node);
-      _children.erase(it);
-    }
+  SGPropertyNode_ptr node;
+  if (pos < 0 || pos >= _children.size())
+    return node;
+
+  vector<SGPropertyNode_ptr>::iterator it = _children.begin();
+  it += pos;
+  node = _children[pos];
+  _children.erase(it);
+  if (keep) {
+    _removedChildren.push_back(node);
   }
-  return dirty;
+  if (_path_cache)
+     _path_cache->erase(node->getName()); // EMH - TODO: Take "index" into account!
+  node->setAttribute(REMOVED, true);
+  node->clearValue();
+  fireChildRemoved(node);
+  return node;
 }
 
+
 /**
- * Remove all children nodes, or all with a given name. Returns
- * "true" if not all nodes could be removed.
+ * Remove a child node
  */
-bool
-SGPropertyNode::removeChildren(const char *name)
-{
-  bool dirty = false;
-  vector<SGPropertyNode_ptr>::iterator it = _children.end();
-  vector<SGPropertyNode_ptr>::iterator begin = _children.begin();
-  while (it-- != begin) {
-    SGPropertyNode *node = *it;
-    if (name && !compare_strings(node->getName(), name))
-      continue;
-
-    if (node->nChildren() && node->removeChildren())
-      dirty = true;
-
-    if (node->isTied() || node->_count != 1 || node->nChildren())
-      dirty = true;
-    else {
-      if (_path_cache)
-        _path_cache->erase(node->getName());
-
-      node->setAttribute(REMOVED, true);
-      node->clearValue();
-      fireChildRemoved(node);
-      _children.erase(it);
-    }
-  }
-  return dirty;
+SGPropertyNode_ptr 
+SGPropertyNode::removeChild (const char * name, int index, bool keep)
+{
+  SGPropertyNode_ptr ret;
+  int pos = find_child(name, index, _children);
+  if (pos >= 0)
+    ret = removeChild(pos, keep);
+  return ret;
+}
+
+
+/**
+  * Remove all children with the specified name.
+  */
+vector<SGPropertyNode_ptr>
+SGPropertyNode::removeChildren (const char * name, bool keep)
+{
+  vector<SGPropertyNode_ptr> children;
+
+  for (int pos = _children.size() - 1; pos >= 0; pos--)
+    if (compare_strings(_children[pos]->getName(), name))
+      children.push_back(removeChild(pos, keep));
+
+  sort(children.begin(), children.end(), CompareIndices());
+  return children;
 }
 
 
 const char *
 SGPropertyNode::getDisplayName (bool simplify) const
 {
-  string display = _name;
+  _display_name = _name;
   if (_index != 0 || !simplify) {
-    char buffer[64];
-    sprintf(buffer, "[%d]", _index);
-    display += buffer;
+    stringstream sstr;
+    sstr << '[' << _index << ']';
+    _display_name += sstr.str();
   }
-  _display_name = copy_string(display.c_str());
-  return _display_name;
+  return _display_name.c_str();
 }
 
 
 const char *
 SGPropertyNode::getPath (bool simplify) const
 {
-                               // Calculate the complete path only once.
-  if (_path == 0) {
-    string path;
-    if (_parent == 0) {
-      path = "";
-    } else {
-      path = _parent->getPath(simplify);
-      path += '/';
-      path += getDisplayName(simplify);
-    }
-    _path = copy_string(path.c_str());
+  // Calculate the complete path only once.
+  if (_parent != 0 && _path.empty()) {
+    _path = _parent->getPath(simplify);
+    _path += '/';
+    _path += getDisplayName(simplify);
   }
 
-  return _path;
+  return _path.c_str();
 }
 
 SGPropertyNode::Type
@@ -2064,24 +2036,27 @@ SGPropertyNode::untie (const char * relative_path)
 }
 
 void
-SGPropertyNode::addChangeListener (SGPropertyChangeListener * listener)
+SGPropertyNode::addChangeListener (SGPropertyChangeListener * listener,
+                                   bool initial)
 {
   if (_listeners == 0)
-    _listeners = new vector<SGPropertyChangeListener *>;
+    _listeners = new vector<SGPropertyChangeListener*>;
   _listeners->push_back(listener);
   listener->register_property(this);
+  if (initial)
+    listener->valueChanged(this);
 }
 
 void
 SGPropertyNode::removeChangeListener (SGPropertyChangeListener * listener)
 {
-  vector<SGPropertyChangeListener *>::iterator it =
+  vector<SGPropertyChangeListener*>::iterator it =
     find(_listeners->begin(), _listeners->end(), listener);
   if (it != _listeners->end()) {
     _listeners->erase(it);
     listener->unregister_property(this);
     if (_listeners->empty()) {
-      vector<SGPropertyChangeListener *> * tmp = _listeners;
+      vector<SGPropertyChangeListener*>* tmp = _listeners;
       _listeners = 0;
       delete tmp;
     }
@@ -2153,8 +2128,7 @@ SGPropertyNode::fireChildRemoved (SGPropertyNode * parent,
 #define HASH_TABLE_SIZE 199
 
 SGPropertyNode::hash_table::entry::entry ()
-  : _key(0),
-    _value(0)
+  : _value(0)
 {
 }
 
@@ -2162,13 +2136,12 @@ SGPropertyNode::hash_table::entry::~entry ()
 {
                                // Don't delete the value; we don't own
                                // the pointer.
-  delete [] _key;
 }
 
 void
 SGPropertyNode::hash_table::entry::set_key (const char * key)
 {
-  _key = copy_string(key);
+  _key = key;
 }
 
 void
@@ -2187,6 +2160,7 @@ SGPropertyNode::hash_table::bucket::~bucket ()
 {
   for (int i = 0; i < _length; i++)
     delete _entries[i];
+  delete [] _entries;
 }
 
 SGPropertyNode::hash_table::entry *
@@ -2241,6 +2215,7 @@ SGPropertyNode::hash_table::~hash_table ()
 {
   for (unsigned int i = 0; i < _data_length; i++)
     delete _data[i];
+  delete [] _data;
 }
 
 SGPropertyNode *
@@ -2298,103 +2273,6 @@ SGPropertyNode::hash_table::hashcode (const char * key)
 }
 
 
-
-/**
- * Default constructor
- */
-SGPropertyNode_ptr::SGPropertyNode_ptr()
-{
-  _ptr = 0;
-}
-
-/**
- * Copy constructor
- */
-SGPropertyNode_ptr::SGPropertyNode_ptr( const SGPropertyNode_ptr &r )
-{
-  _ptr = r._ptr;
-  if (_ptr)
-     _ptr->incrementRef();
-}
-
-/**
- * Constructor from a pointer to a node
- */
-SGPropertyNode_ptr::SGPropertyNode_ptr( SGPropertyNode *p )
-{
-  _ptr = p;
-  if (_ptr)
-     _ptr->incrementRef();
-}
-
-/**
- * Destructor
- */
-SGPropertyNode_ptr::~SGPropertyNode_ptr()
-{
-  if (_ptr && _ptr->decrementRef() == 0)
-    delete _ptr;
-}
-
-/**
- * Assignement operator
- */
-SGPropertyNode_ptr &
-SGPropertyNode_ptr::operator=( const SGPropertyNode_ptr &r )
-{
-  if (_ptr && _ptr->decrementRef() == 0)
-    delete _ptr;
-  _ptr = r._ptr;
-  if (_ptr)
-     _ptr->incrementRef();
-
-  return *this;
-}
-
-/**
- * Pointer access operator
- */
-SGPropertyNode *
-SGPropertyNode_ptr::operator->()
-{
-  return _ptr;
-}
-
-/**
- * Pointer access operator (const)
- */
-const SGPropertyNode *
-SGPropertyNode_ptr::operator->() const
-{
-  return _ptr;
-}
-
-/**
- * Conversion to SGPropertyNode * operator
- */
-SGPropertyNode_ptr::operator SGPropertyNode *()
-{
-  return _ptr;
-}
-
-/**
- * Conversion to const SGPropertyNode * operator
- */
-SGPropertyNode_ptr::operator const SGPropertyNode *() const
-{
-  return _ptr;
-}
-
-/**
- * Validity test
- */
-bool 
-SGPropertyNode_ptr::valid() const
-{
-  return _ptr != 0;
-}
-
-
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGPropertyChangeListener.