Move compact_hash_table before xml_allocator.
This helps streamline class dependencies and will make subsequent changes smaller.
This commit is contained in:
parent
89575f352a
commit
fbaab4dcad
266
src/pugixml.cpp
266
src/pugixml.cpp
@ -257,6 +257,140 @@ PUGI__NS_BEGIN
|
|||||||
PUGI__NS_END
|
PUGI__NS_END
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PUGIXML_COMPACT
|
||||||
|
size_t pugi_compact_stats[128];
|
||||||
|
|
||||||
|
PUGI__NS_BEGIN
|
||||||
|
class compact_hash_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
compact_hash_table(): _items(0), _capacity(0), _count(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
if (_items)
|
||||||
|
{
|
||||||
|
xml_memory::deallocate(_items);
|
||||||
|
_items = 0;
|
||||||
|
_capacity = 0;
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void** find(const void* key)
|
||||||
|
{
|
||||||
|
assert(key);
|
||||||
|
|
||||||
|
if (_capacity == 0) return 0;
|
||||||
|
|
||||||
|
size_t hashmod = _capacity - 1;
|
||||||
|
size_t bucket = hash(key) & hashmod;
|
||||||
|
|
||||||
|
for (size_t probe = 0; probe <= hashmod; ++probe)
|
||||||
|
{
|
||||||
|
item_t& probe_item = _items[bucket];
|
||||||
|
|
||||||
|
if (probe_item.key == key)
|
||||||
|
return &probe_item.value;
|
||||||
|
|
||||||
|
if (probe_item.key == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// hash collision, quadratic probing
|
||||||
|
bucket = (bucket + probe + 1) & hashmod;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!"Hash table is full");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void** insert(const void* key, size_t tag)
|
||||||
|
{
|
||||||
|
assert(key);
|
||||||
|
|
||||||
|
if (_count >= _capacity * 3 / 4)
|
||||||
|
rehash();
|
||||||
|
|
||||||
|
size_t hashmod = _capacity - 1;
|
||||||
|
size_t bucket = hash(key) & hashmod;
|
||||||
|
|
||||||
|
for (size_t probe = 0; probe <= hashmod; ++probe)
|
||||||
|
{
|
||||||
|
item_t& probe_item = _items[bucket];
|
||||||
|
|
||||||
|
if (probe_item.key == 0)
|
||||||
|
{
|
||||||
|
if (tag)
|
||||||
|
pugi_compact_stats[tag]++;
|
||||||
|
|
||||||
|
probe_item.key = key;
|
||||||
|
_count++;
|
||||||
|
return &probe_item.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (probe_item.key == key)
|
||||||
|
return &probe_item.value;
|
||||||
|
|
||||||
|
// hash collision, quadratic probing
|
||||||
|
bucket = (bucket + probe + 1) & hashmod;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!"Hash table is full");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct item_t
|
||||||
|
{
|
||||||
|
const void* key;
|
||||||
|
void* value;
|
||||||
|
};
|
||||||
|
|
||||||
|
item_t* _items;
|
||||||
|
size_t _capacity;
|
||||||
|
|
||||||
|
size_t _count;
|
||||||
|
|
||||||
|
void rehash()
|
||||||
|
{
|
||||||
|
compact_hash_table rt;
|
||||||
|
rt._capacity = (_capacity == 0) ? 256 : _capacity * 2;
|
||||||
|
rt._items = static_cast<item_t*>(xml_memory::allocate(sizeof(item_t) * rt._capacity));
|
||||||
|
|
||||||
|
assert(rt._items);
|
||||||
|
|
||||||
|
memset(rt._items, 0, sizeof(item_t) * rt._capacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < _capacity; ++i)
|
||||||
|
if (_items[i].key)
|
||||||
|
*rt.insert(_items[i].key, 0) = _items[i].value;
|
||||||
|
|
||||||
|
if (_items)
|
||||||
|
xml_memory::deallocate(_items);
|
||||||
|
|
||||||
|
_capacity = rt._capacity;
|
||||||
|
_items = rt._items;
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://burtleburtle.net/bob/hash/integer.html
|
||||||
|
static unsigned int hash(const void* key)
|
||||||
|
{
|
||||||
|
unsigned int a = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key));
|
||||||
|
|
||||||
|
a = (a ^ 61) ^ (a >> 16);
|
||||||
|
a = a + (a << 3);
|
||||||
|
a = a ^ (a >> 4);
|
||||||
|
a = a * 0x27d4eb2d;
|
||||||
|
a = a ^ (a >> 15);
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
PUGI__NS_END
|
||||||
|
#endif
|
||||||
|
|
||||||
PUGI__NS_BEGIN
|
PUGI__NS_BEGIN
|
||||||
static const size_t xml_memory_page_size =
|
static const size_t xml_memory_page_size =
|
||||||
#ifdef PUGIXML_MEMORY_PAGE_SIZE
|
#ifdef PUGIXML_MEMORY_PAGE_SIZE
|
||||||
@ -463,7 +597,7 @@ PUGI__NS_BEGIN
|
|||||||
size_t _busy_size;
|
size_t _busy_size;
|
||||||
|
|
||||||
#ifdef PUGIXML_COMPACT
|
#ifdef PUGIXML_COMPACT
|
||||||
class compact_hash_table* _hash;
|
compact_hash_table* _hash;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -508,137 +642,7 @@ PUGI__NS_BEGIN
|
|||||||
PUGI__NS_END
|
PUGI__NS_END
|
||||||
|
|
||||||
#ifdef PUGIXML_COMPACT
|
#ifdef PUGIXML_COMPACT
|
||||||
size_t pugi_compact_stats[128];
|
|
||||||
|
|
||||||
PUGI__NS_BEGIN
|
PUGI__NS_BEGIN
|
||||||
class compact_hash_table
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
compact_hash_table(): _items(0), _capacity(0), _count(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
if (_items)
|
|
||||||
{
|
|
||||||
xml_memory::deallocate(_items);
|
|
||||||
_items = 0;
|
|
||||||
_capacity = 0;
|
|
||||||
_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void** find(const void* key)
|
|
||||||
{
|
|
||||||
assert(key);
|
|
||||||
|
|
||||||
if (_capacity == 0) return 0;
|
|
||||||
|
|
||||||
size_t hashmod = _capacity - 1;
|
|
||||||
size_t bucket = hash(key) & hashmod;
|
|
||||||
|
|
||||||
for (size_t probe = 0; probe <= hashmod; ++probe)
|
|
||||||
{
|
|
||||||
item_t& probe_item = _items[bucket];
|
|
||||||
|
|
||||||
if (probe_item.key == key)
|
|
||||||
return &probe_item.value;
|
|
||||||
|
|
||||||
if (probe_item.key == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// hash collision, quadratic probing
|
|
||||||
bucket = (bucket + probe + 1) & hashmod;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!"Hash table is full");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void** insert(const void* key, size_t tag)
|
|
||||||
{
|
|
||||||
assert(key);
|
|
||||||
|
|
||||||
if (_count >= _capacity * 3 / 4)
|
|
||||||
rehash();
|
|
||||||
|
|
||||||
size_t hashmod = _capacity - 1;
|
|
||||||
size_t bucket = hash(key) & hashmod;
|
|
||||||
|
|
||||||
for (size_t probe = 0; probe <= hashmod; ++probe)
|
|
||||||
{
|
|
||||||
item_t& probe_item = _items[bucket];
|
|
||||||
|
|
||||||
if (probe_item.key == 0)
|
|
||||||
{
|
|
||||||
if (tag)
|
|
||||||
pugi_compact_stats[tag]++;
|
|
||||||
|
|
||||||
probe_item.key = key;
|
|
||||||
_count++;
|
|
||||||
return &probe_item.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (probe_item.key == key)
|
|
||||||
return &probe_item.value;
|
|
||||||
|
|
||||||
// hash collision, quadratic probing
|
|
||||||
bucket = (bucket + probe + 1) & hashmod;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!"Hash table is full");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct item_t
|
|
||||||
{
|
|
||||||
const void* key;
|
|
||||||
void* value;
|
|
||||||
};
|
|
||||||
|
|
||||||
item_t* _items;
|
|
||||||
size_t _capacity;
|
|
||||||
|
|
||||||
size_t _count;
|
|
||||||
|
|
||||||
void rehash()
|
|
||||||
{
|
|
||||||
compact_hash_table rt;
|
|
||||||
rt._capacity = (_capacity == 0) ? 256 : _capacity * 2;
|
|
||||||
rt._items = static_cast<item_t*>(xml_memory::allocate(sizeof(item_t) * rt._capacity));
|
|
||||||
|
|
||||||
assert(rt._items);
|
|
||||||
|
|
||||||
memset(rt._items, 0, sizeof(item_t) * rt._capacity);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < _capacity; ++i)
|
|
||||||
if (_items[i].key)
|
|
||||||
*rt.insert(_items[i].key, 0) = _items[i].value;
|
|
||||||
|
|
||||||
if (_items)
|
|
||||||
xml_memory::deallocate(_items);
|
|
||||||
|
|
||||||
_capacity = rt._capacity;
|
|
||||||
_items = rt._items;
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://burtleburtle.net/bob/hash/integer.html
|
|
||||||
static unsigned int hash(const void* key)
|
|
||||||
{
|
|
||||||
unsigned int a = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key));
|
|
||||||
|
|
||||||
a = (a ^ 61) ^ (a >> 16);
|
|
||||||
a = a + (a << 3);
|
|
||||||
a = a ^ (a >> 4);
|
|
||||||
a = a * 0x27d4eb2d;
|
|
||||||
a = a ^ (a >> 15);
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned int compact_alignment_log2 = 2;
|
static const unsigned int compact_alignment_log2 = 2;
|
||||||
static const unsigned int compact_alignment = 1 << compact_alignment_log2;
|
static const unsigned int compact_alignment = 1 << compact_alignment_log2;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user