From: david Date: Sat, 6 Apr 2002 21:47:22 +0000 (+0000) Subject: Implemented a very simple hash-table cache for property lookup using X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=96474823b53a33d11410750b5b48a101afc6f020;p=simgear.git Implemented a very simple hash-table cache for property lookup using relative paths. --- diff --git a/simgear/misc/props.cxx b/simgear/misc/props.cxx index 9aeb2385..af2044a4 100644 --- a/simgear/misc/props.cxx +++ b/simgear/misc/props.cxx @@ -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 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 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 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()); } + + +//////////////////////////////////////////////////////////////////////// +// 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 diff --git a/simgear/misc/props.hxx b/simgear/misc/props.hxx index beeffa65..1be0c093 100644 --- a/simgear/misc/props.hxx +++ b/simgear/misc/props.hxx @@ -17,7 +17,6 @@ #endif #include -#include #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 _children; - typedef map cache_map; - cache_map * _path_cache; + hash_table * _path_cache; Type _type; bool _tied; int _attr; @@ -1113,6 +1111,54 @@ private: } _local_val; + + /** + * 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