]> git.mxchange.org Git - simgear.git/commitdiff
Implemented a very simple hash-table cache for property lookup using
authordavid <david>
Sat, 6 Apr 2002 21:47:22 +0000 (21:47 +0000)
committerdavid <david>
Sat, 6 Apr 2002 21:47:22 +0000 (21:47 +0000)
relative paths.

simgear/misc/props.cxx
simgear/misc/props.hxx

index 9aeb2385450b8c1e0678dc824dacc35cfa6dec13..af2044a47983d3507395c3f06921985d61c6db5b 100644 (file)
@@ -679,7 +679,7 @@ SGPropertyNode::~SGPropertyNode ()
   for (int i = 0; i < (int)_children.size(); i++) {
     delete _children[i];
   }
-//   delete _path_cache;
+  delete _path_cache;
   clear_value();
 }
 
@@ -1598,22 +1598,19 @@ SGPropertyNode::getRootNode () const
 SGPropertyNode *
 SGPropertyNode::getNode (const char * relative_path, bool create)
 {
-//   if (_path_cache == 0)
-//     _path_cache = new cache_map;
-
-//   SGPropertyNode * result = (*_path_cache)[relative_path];
-//   if (result == 0) {
-//     vector<PathComponent> components;
-//     parse_path(relative_path, components);
-//     result = find_node(this, components, 0, create);
-//     if (result != 0)
-//       (*_path_cache)[relative_path] = result;
-//   }
+  if (_path_cache == 0)
+    _path_cache = new hash_table;
+
+  SGPropertyNode * result = _path_cache->get(relative_path);
+  if (result == 0) {
+    vector<PathComponent> components;
+    parse_path(relative_path, components);
+    result = find_node(this, components, 0, create);
+    if (result != 0)
+      _path_cache->put(relative_path, result);
+  }
   
-//   return result;
-  vector<PathComponent> components;
-  parse_path(relative_path, components);
-  return find_node(this, components, 0, create);
+  return result;
 }
 
 SGPropertyNode *
@@ -1902,4 +1899,129 @@ SGPropertyNode::untie (const char * relative_path)
   return (node == 0 ? false : node->untie());
 }
 
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Simplified hash table for caching paths.
+////////////////////////////////////////////////////////////////////////
+
+#define HASH_TABLE_SIZE 199
+
+SGPropertyNode::hash_table::entry::entry ()
+  : _key(0),
+    _value(0)
+{
+}
+
+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);
+}
+
+void
+SGPropertyNode::hash_table::entry::set_value (SGPropertyNode * value)
+{
+  _value = value;
+}
+
+SGPropertyNode::hash_table::bucket::bucket ()
+  : _length(0),
+    _entries(0)
+{
+}
+
+SGPropertyNode::hash_table::bucket::~bucket ()
+{
+  for (int i = 0; i < _length; i++)
+    delete _entries[i];
+}
+
+SGPropertyNode::hash_table::entry *
+SGPropertyNode::hash_table::bucket::get_entry (const char * key, bool create)
+{
+  int i;
+  for (i = 0; i < _length; i++) {
+    if (!strcmp(_entries[i]->get_key(), key))
+      return _entries[i];
+  }
+  if (create) {
+    entry ** new_entries = new entry*[_length+1];
+    for (i = 0; i < _length; i++) {
+      new_entries[i] = _entries[i];
+    }
+    delete _entries;
+    _entries = new_entries;
+    _entries[_length] = new entry;
+    _entries[_length]->set_key(key);
+    _length++;
+    return _entries[_length - 1];
+  } else {
+    return 0;
+  }
+}
+
+
+SGPropertyNode::hash_table::hash_table ()
+  : _data_length(0),
+    _data(0)
+{
+}
+
+SGPropertyNode::hash_table::~hash_table ()
+{
+  for (int i = 0; i < _data_length; i++)
+    delete _data[i];
+}
+
+SGPropertyNode *
+SGPropertyNode::hash_table::get (const char * key)
+{
+  if (_data_length == 0)
+    return 0;
+  unsigned int index = hashcode(key) % _data_length;
+  if (_data[index] == 0)
+    return 0;
+  entry * e = _data[index]->get_entry(key);
+  if (e == 0)
+    return 0;
+  else
+    return e->get_value();
+}
+
+void
+SGPropertyNode::hash_table::put (const char * key, SGPropertyNode * value)
+{
+  if (_data_length == 0) {
+    _data = new bucket*[HASH_TABLE_SIZE];
+    _data_length = HASH_TABLE_SIZE;
+    for (unsigned int i = 0; i < HASH_TABLE_SIZE; i++)
+      _data[i] = 0;
+  }
+  unsigned int index = hashcode(key) % _data_length;
+  if (_data[index] == 0) {
+    _data[index] = new bucket;
+  }
+  entry * e = _data[index]->get_entry(key, true);
+  e->set_value(value);
+}
+
+unsigned int
+SGPropertyNode::hash_table::hashcode (const char * key)
+{
+  unsigned int hash = 0;
+  while (*key != 0) {
+    hash = 31 * hash + *key;
+    key++;
+  }
+  return hash;
+}
+
 // end of props.cxx
index beeffa657c69c6e65ddff28bb010e0d50904eff9..1be0c093c307dffdfa25c75f6ced07309c058f15 100644 (file)
@@ -17,7 +17,6 @@
 #endif
 
 #include <vector>
-#include <map>
 
 #if PROPS_STANDALONE
 
@@ -26,7 +25,6 @@
 
 using std::string;
 using std::vector;
-using std::map;
 using std::istream;
 using std::ostream;
 
@@ -38,7 +36,6 @@ using std::ostream;
 #include STL_IOSTREAM
 SG_USING_STD(string);
 SG_USING_STD(vector);
-SG_USING_STD(map);
 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
 SG_USING_STD(istream);
 SG_USING_STD(ostream);
@@ -1082,12 +1079,13 @@ private:
 
   mutable char _buffer[MAX_STRING_LEN+1];
 
+  class hash_table;
+
   const char * _name;
   int _index;
   SGPropertyNode * _parent;
   vector<SGPropertyNode *> _children;
-  typedef map<const string,SGPropertyNode *> cache_map;
-  cache_map * _path_cache;
+  hash_table * _path_cache;
   Type _type;
   bool _tied;
   int _attr;
@@ -1113,6 +1111,54 @@ private:
   } _local_val;
 
 
+\f
+  /**
+   * A very simple hash table with no remove functionality.
+   */
+  class hash_table {
+  public:
+
+    /**
+     * An entry in a bucket in a hash table.
+     */
+    class entry {
+    public:
+      entry ();
+      virtual ~entry ();
+      virtual const char * get_key () { return _key; }
+      virtual void set_key (const char * key);
+      virtual SGPropertyNode * get_value () { return _value; }
+      virtual void set_value (SGPropertyNode * value);
+    private:
+      const char * _key;
+      SGPropertyNode * _value;
+    };
+
+
+    /**
+     * A bucket in a hash table.
+     */
+    class bucket {
+    public:
+      bucket ();
+      virtual ~bucket ();
+      virtual entry * get_entry (const char * key, bool create = false);
+    private:
+      int _length;
+      entry ** _entries;
+    };
+
+    hash_table ();
+    virtual ~hash_table ();
+    virtual SGPropertyNode * get (const char * key);
+    virtual void put (const char * key, SGPropertyNode * value);
+
+  private:
+    unsigned int hashcode (const char * key);
+    unsigned int _data_length;
+    bucket ** _data;
+  };
+
 };
 
 #endif // __PROPS_HXX