Implemented a very simple hash-table cache for property lookup using
relative paths.
This commit is contained in:
@@ -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;
|
||||
if (_path_cache == 0)
|
||||
_path_cache = new hash_table;
|
||||
|
||||
// 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;
|
||||
// }
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
Reference in New Issue
Block a user