]> git.mxchange.org Git - simgear.git/blobdiff - simgear/props/props.cxx
Don't reset the random texture base when rebuilding a cloud layer
[simgear.git] / simgear / props / props.cxx
index 2f26f2a697648a12f9b154614f49b4f493b08eac..aa37f1db2083605edab681d550a728bbace844d3 100644 (file)
@@ -116,7 +116,7 @@ parse_name (const string &path, int &i)
       name = ".";
     }
     if (i < max && path[i] != '/')
-      throw string("Illegal character after " + name);
+      throw string("illegal character after " + name);
   }
 
   else if (isalpha(path[i]) || path[i] == '_') {
@@ -250,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++) {
@@ -295,7 +295,7 @@ find_node (SGPropertyNode * current,
   else if (components[position].name == "..") {
     SGPropertyNode * parent = current->getParent();
     if (parent == 0)
-      throw string("Attempt to move past root with '..'");
+      throw string("attempt to move past root with '..'");
     else
       return find_node(parent, components, position + 1, create);
   }
@@ -574,6 +574,7 @@ SGPropertyNode::make_string () const
   case DOUBLE:
     {
       stringstream sstr;
+      sstr.precision( 10 );
       sstr << get_double();
       _buffer = sstr.str();
       return _buffer.c_str();
@@ -594,11 +595,11 @@ void
 SGPropertyNode::trace_write () const
 {
 #if PROPS_STANDALONE
-  cerr << "TRACE: Write node " << getPath () << ", value\""
+  cerr << "TRACE: Write node " << getPath () << ", value \""
        << make_string() << '"' << endl;
 #else
-  SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Write node " << getPath()
-        << ", value\"" << make_string() << '"');
+  SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Write node " << getPath()
+        << ", value \"" << make_string() << '"');
 #endif
 }
 
@@ -612,7 +613,7 @@ SGPropertyNode::trace_read () const
   cerr << "TRACE: Write node " << getPath () << ", value \""
        << make_string() << '"' << endl;
 #else
-  SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Read node " << getPath()
+  SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Read node " << getPath()
         << ", value \"" << make_string() << '"');
 #endif
 }
@@ -738,7 +739,11 @@ SGPropertyNode::SGPropertyNode (const char * name,
     _attr(READ|WRITE),
     _listeners(0)
 {
-  _name = name;
+  int i = 0;
+  _name = parse_name(name, i);
+  if (i != int(strlen(name)) || name[0] == '.')
+    throw string("plain name expected instead of '") + name + '\'';
+
   _local_val.string_val = 0;
 }
 
@@ -748,9 +753,20 @@ SGPropertyNode::SGPropertyNode (const char * name,
  */
 SGPropertyNode::~SGPropertyNode ()
 {
+  // 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;
+
+  if (_listeners) {
+    vector<SGPropertyChangeListener*>::iterator it;
+    for (it = _listeners->begin(); it != _listeners->end(); ++it)
+      (*it)->unregister_property(this);
+    delete _listeners;
+  }
 }
 
 
@@ -898,6 +914,22 @@ SGPropertyNode::getChildren (const char * name) const
 }
 
 
+/**
+ * Remove this node and all children from nodes that link to them
+ * in their path cache.
+ */
+void
+SGPropertyNode::remove_from_path_caches ()
+{
+  for (unsigned int i = 0; i < _children.size(); ++i)
+    _children[i]->remove_from_path_caches();
+
+  for (unsigned int i = 0; i < _linkedNodes.size(); i++)
+    _linkedNodes[i]->erase(this);
+  _linkedNodes.clear();
+}
+
+
 /**
  * Remove child by position.
  */
@@ -905,7 +937,7 @@ SGPropertyNode_ptr
 SGPropertyNode::removeChild (int pos, bool keep)
 {
   SGPropertyNode_ptr node;
-  if (pos < 0 || pos >= _children.size())
+  if (pos < 0 || pos >= (int)_children.size())
     return node;
 
   vector<SGPropertyNode_ptr>::iterator it = _children.begin();
@@ -915,8 +947,8 @@ SGPropertyNode::removeChild (int pos, bool keep)
   if (keep) {
     _removedChildren.push_back(node);
   }
-  if (_path_cache)
-     _path_cache->erase(node->getName()); // EMH - TODO: Take "index" into account!
+
+  node->remove_from_path_caches();
   node->setAttribute(REMOVED, true);
   node->clearValue();
   fireChildRemoved(node);
@@ -927,7 +959,7 @@ SGPropertyNode::removeChild (int pos, bool keep)
 /**
  * Remove a child node
  */
-SGPropertyNode_ptr 
+SGPropertyNode_ptr
 SGPropertyNode::removeChild (const char * name, int index, bool keep)
 {
   SGPropertyNode_ptr ret;
@@ -955,6 +987,24 @@ SGPropertyNode::removeChildren (const char * name, bool keep)
 }
 
 
+/**
+  * Remove a linked node.
+  */
+bool
+SGPropertyNode::remove_linked_node (hash_table * node)
+{
+  for (unsigned int i = 0; i < _linkedNodes.size(); i++) {
+    if (_linkedNodes[i] == node) {
+      vector<hash_table *>::iterator it = _linkedNodes.begin();
+      it += i;
+      _linkedNodes.erase(it);
+      return true;
+    }
+  }
+  return false;
+}
+
+
 const char *
 SGPropertyNode::getDisplayName (bool simplify) const
 {
@@ -2181,23 +2231,31 @@ SGPropertyNode::hash_table::bucket::get_entry (const char * key, bool create)
   }
 }
 
-void
-SGPropertyNode::hash_table::bucket::erase (const char * key)
+bool
+SGPropertyNode::hash_table::bucket::erase (SGPropertyNode * node)
 {
-  int i;
-  for (i = 0; i < _length; i++) {
-    if (!strcmp(_entries[i]->get_key(), key))
-       break;
-  }
-
-  if (i < _length) {
-    for (++i; i < _length; i++) {
-      _entries[i-1] = _entries[i];
+  for (int i = 0; i < _length; i++) {
+    if (_entries[i]->get_value() == node) {
+      delete _entries[i];
+      for (++i; i < _length; i++) {
+        _entries[i-1] = _entries[i];
+      }
+      _length--;
+      return true;
     }
-     _length--;
   }
+  return false;
 }
 
+void
+SGPropertyNode::hash_table::bucket::clear (SGPropertyNode::hash_table * owner)
+{
+  for (int i = 0; i < _length; i++) {
+    SGPropertyNode * node = _entries[i]->get_value();
+    if (node)
+      node->remove_linked_node(owner);
+  }
+}
 
 SGPropertyNode::hash_table::hash_table ()
   : _data_length(0),
@@ -2207,8 +2265,12 @@ SGPropertyNode::hash_table::hash_table ()
 
 SGPropertyNode::hash_table::~hash_table ()
 {
-  for (unsigned int i = 0; i < _data_length; i++)
-    delete _data[i];
+  for (unsigned int i = 0; i < _data_length; i++) {
+    if (_data[i]) {
+      _data[i]->clear(this);
+      delete _data[i];
+    }
+  }
   delete [] _data;
 }
 
@@ -2242,17 +2304,17 @@ SGPropertyNode::hash_table::put (const char * key, SGPropertyNode * value)
   }
   entry * e = _data[index]->get_entry(key, true);
   e->set_value(value);
+  value->add_linked_node(this);
 }
 
-void
-SGPropertyNode::hash_table::erase (const char * key)
+bool
+SGPropertyNode::hash_table::erase (SGPropertyNode * node)
 {
-   if (_data_length == 0)
-    return;
-  unsigned int index = hashcode(key) % _data_length;
-  if (_data[index] == 0)
-    return;
-  _data[index]->erase(key);
+  for (unsigned int i = 0; i < _data_length; i++)
+    if (_data[i] && _data[i]->erase(node))
+      return true;
+
+  return false;
 }
 
 unsigned int
@@ -2274,12 +2336,8 @@ SGPropertyNode::hash_table::hashcode (const char * key)
 
 SGPropertyChangeListener::~SGPropertyChangeListener ()
 {
-                               // This will come back and remove
-                               // the current item each time.  Is
-                               // that OK?
-  vector<SGPropertyNode *>::iterator it;
-  for (it = _properties.begin(); it != _properties.end(); it++)
-    (*it)->removeChangeListener(this);
+  for (int i = _properties.size() - 1; i >= 0; i--)
+    _properties[i]->removeChangeListener(this);
 }
 
 void