Add namespaces for OpenDict files

This commit is contained in:
Tim Wojtulewicz 2020-07-06 10:00:00 -07:00
parent 8f0e8037ba
commit 10e4694f8e
2 changed files with 59 additions and 40 deletions

View file

@ -23,6 +23,8 @@
#define ASSERT_VALID(o)
#endif//DEBUG
namespace zeek {
class IterCookie {
public:
IterCookie(Dictionary* d) : d(d) {}
@ -35,11 +37,11 @@ public:
int next = -1; //index for next valid entry. -1 is default not started yet.
// Tracks the new entries inserted while iterating. Only used for robust cookies.
std::vector<DictEntry>* inserted = nullptr;
std::vector<detail::DictEntry>* inserted = nullptr;
// Tracks the entries already visited but were moved across the next iteration
// point due to an insertion. Only used for robust cookies.
std::vector<DictEntry>* visited = nullptr;
std::vector<detail::DictEntry>* visited = nullptr;
void MakeRobust()
{
@ -48,8 +50,8 @@ public:
ASSERT(d && d->cookies);
robust = true;
inserted = new std::vector<DictEntry>();
visited = new std::vector<DictEntry>();
inserted = new std::vector<detail::DictEntry>();
visited = new std::vector<detail::DictEntry>();
d->cookies->push_back(this);
}
@ -71,6 +73,8 @@ public:
}
};
// namespace detail
TEST_SUITE_BEGIN("Dict");
TEST_CASE("dict construction")
@ -402,14 +406,14 @@ size_t Dictionary::MemoryAllocation() const
size_t size = padded_sizeof(*this);
if ( table )
{
size += pad_size(Capacity() * sizeof(DictEntry));
size += pad_size(Capacity() * sizeof(detail::DictEntry));
for ( int i = Capacity()-1; i>=0; i-- )
if ( ! table[i].Empty() && table[i].key_size > 8 )
size += pad_size(table[i].key_size);
}
if ( order )
size += padded_sizeof(std::vector<DictEntry>) + pad_size(sizeof(DictEntry) * order->capacity());
size += padded_sizeof(std::vector<detail::DictEntry>) + pad_size(sizeof(detail::DictEntry) * order->capacity());
return size;
}
@ -528,7 +532,7 @@ void Dictionary::Dump(int level) const
//////////////////////////////////////////////////////////////////////////////////////////////////
//Initialization.
////////////////////////////////////////////////////////////////////////////////////////////////////
Dictionary::Dictionary(dict_order ordering, int initial_size)
Dictionary::Dictionary(DictOrder ordering, int initial_size)
{
if ( initial_size > 0 )
{
@ -539,7 +543,7 @@ Dictionary::Dictionary(dict_order ordering, int initial_size)
}
if ( ordering == ORDERED )
order = new std::vector<DictEntry>;
order = new std::vector<detail::DictEntry>;
}
Dictionary::~Dictionary()
@ -584,7 +588,7 @@ void Dictionary::Clear()
void Dictionary::Init()
{
ASSERT(! table);
table = (DictEntry*)malloc(sizeof(DictEntry)*Capacity(true));
table = (detail::DictEntry*)malloc(sizeof(detail::DictEntry)*Capacity(true));
for (int i = Capacity()-1; i >= 0; i--)
table[i].SetEmpty();
}
@ -746,7 +750,7 @@ void* Dictionary::Insert(void* key, int key_size, hash_t hash, void* val, bool c
else
{
// Allocate memory for key if necesary. Key is updated to reflect internal key if necessary.
DictEntry entry(key, key_size, hash, val, insert_distance, copy_key);
detail::DictEntry entry(key, key_size, hash, val, insert_distance, copy_key);
InsertRelocateAndAdjust(entry, insert_position);
if ( order )
order->push_back(entry);
@ -769,7 +773,7 @@ void* Dictionary::Insert(void* key, int key_size, hash_t hash, void* val, bool c
}
///e.distance is adjusted to be the one at insert_position.
void Dictionary::InsertRelocateAndAdjust(DictEntry& entry, int insert_position)
void Dictionary::InsertRelocateAndAdjust(detail::DictEntry& entry, int insert_position)
{
#ifdef DEBUG
entry.bucket = BucketByHash(entry.hash,log2_buckets);
@ -790,7 +794,7 @@ void Dictionary::InsertRelocateAndAdjust(DictEntry& entry, int insert_position)
}
/// insert entry into position, relocate other entries when necessary.
void Dictionary::InsertAndRelocate(DictEntry& entry, int insert_position, int* last_affected_position)
void Dictionary::InsertAndRelocate(detail::DictEntry& entry, int insert_position, int* last_affected_position)
{///take out the head of cluster and append to the end of the cluster.
while ( true )
{
@ -824,7 +828,7 @@ void Dictionary::InsertAndRelocate(DictEntry& entry, int insert_position, int* l
}
/// Adjust Cookies on Insert.
void Dictionary::AdjustOnInsert(IterCookie* c, const DictEntry& entry, int insert_position, int last_affected_position)
void Dictionary::AdjustOnInsert(IterCookie* c, const detail::DictEntry& entry, int insert_position, int last_affected_position)
{
ASSERT(c);
ASSERT_VALID(c);
@ -843,7 +847,7 @@ void Dictionary::SizeUp()
int prev_capacity = Capacity();
log2_buckets++;
int capacity = Capacity();
table = (DictEntry*)realloc(table, capacity*sizeof(DictEntry));
table = (detail::DictEntry*)realloc(table, capacity*sizeof(detail::DictEntry));
for ( int i = prev_capacity; i < capacity; i++ )
table[i].SetEmpty();
@ -872,7 +876,7 @@ void* Dictionary::Remove(const void* key, int key_size, hash_t hash, bool dont_d
if ( position < 0 )
return nullptr;
DictEntry entry = RemoveRelocateAndAdjust(position);
detail::DictEntry entry = RemoveRelocateAndAdjust(position);
num_entries--;
ASSERT(num_entries >= 0);
//e is about to be invalid. remove it from all references.
@ -885,10 +889,10 @@ void* Dictionary::Remove(const void* key, int key_size, hash_t hash, bool dont_d
return v;
}
DictEntry Dictionary::RemoveRelocateAndAdjust(int position)
detail::DictEntry Dictionary::RemoveRelocateAndAdjust(int position)
{
int last_affected_position = position;
DictEntry entry = RemoveAndRelocate(position, &last_affected_position);
detail::DictEntry entry = RemoveAndRelocate(position, &last_affected_position);
#ifdef DEBUG
//validation: index to i-1 should be continuous without empty spaces.
@ -903,12 +907,12 @@ DictEntry Dictionary::RemoveRelocateAndAdjust(int position)
return entry;
}
DictEntry Dictionary::RemoveAndRelocate(int position, int* last_affected_position)
detail::DictEntry Dictionary::RemoveAndRelocate(int position, int* last_affected_position)
{
//fill the empty position with the tail of the cluster of position+1.
ASSERT(position >= 0 && position < Capacity() && ! table[position].Empty());
DictEntry entry = table[position];
detail::DictEntry entry = table[position];
while ( true )
{
if ( position == Capacity() - 1 || table[position+1].Empty() || table[position+1].distance == 0 )
@ -928,7 +932,7 @@ DictEntry Dictionary::RemoveAndRelocate(int position, int* last_affected_positio
return entry;
}
void Dictionary::AdjustOnRemove(IterCookie* c, const DictEntry& entry, int position, int last_affected_position)
void Dictionary::AdjustOnRemove(IterCookie* c, const detail::DictEntry& entry, int position, int last_affected_position)
{
ASSERT_VALID(c);
c->inserted->erase(std::remove(c->inserted->begin(), c->inserted->end(), entry), c->inserted->end());
@ -981,7 +985,7 @@ bool Dictionary::Remap(int position, int* new_position)
//equal because 1: it's a new item, 2: it's an old item, but new bucket is the same as old. 50% of old items act this way due to fibhash.
if ( current == expected )
return false;
DictEntry entry = RemoveAndRelocate(position); // no iteration cookies to adjust, no need for last_affected_position.
detail::DictEntry entry = RemoveAndRelocate(position); // no iteration cookies to adjust, no need for last_affected_position.
#ifdef DEBUG
entry.bucket = expected;
#endif//DEBUG
@ -1004,7 +1008,7 @@ void* Dictionary::NthEntry(int n, const void*& key, int& key_size) const
{
if ( ! order || n < 0 || n >= Length() )
return nullptr;
DictEntry entry = (*order)[n];
detail::DictEntry entry = (*order)[n];
key = entry.GetKey();
key_size = entry.key_size;
return entry.value;
@ -1052,7 +1056,7 @@ void* Dictionary::NextEntryNonConst(HashKey*& h, IterCookie*& c, bool return_has
{
// Return the last one. Order doesn't matter,
// and removing from the tail is cheaper.
DictEntry e = c->inserted->back();
detail::DictEntry e = c->inserted->back();
if ( return_hash )
h = new HashKey(e.GetKey(), e.key_size, e.hash);
void* v = e.value;
@ -1126,3 +1130,5 @@ void Dictionary::StopIteration(IterCookie* cookie) const
Dictionary* dp = const_cast<Dictionary*>(this);
dp->StopIterationNonConst(cookie);
}
} // namespace zeek

View file

@ -7,8 +7,13 @@
#include "Hash.h"
class Dictionary;
class IterCookie;
ZEEK_FORWARD_DECLARE_NAMESPACED(IterCookie, zeek);
ZEEK_FORWARD_DECLARE_NAMESPACED(DictEntry, zeek::detail);
// Type for function to be called when deleting elements.
typedef void (*dict_delete_func)(void*);
namespace zeek {
// Default number of hash buckets in dictionary. The dictionary will increase the size
// of the hash table as needed.
@ -44,14 +49,13 @@ constexpr uint8_t DICT_THRESHOLD_BITS = 3;
// bucket at which to start looking for the next value to return.
constexpr uint16_t TOO_FAR_TO_REACH = 0xFFFF;
enum dict_order { ORDERED, UNORDERED };
// Type for function to be called when deleting elements.
typedef void (*dict_delete_func)(void*);
enum DictOrder { ORDERED, UNORDERED };
// A dict_delete_func that just calls delete.
extern void generic_delete_func(void*);
namespace detail {
/**
* An entry stored in the dictionary.
*/
@ -140,6 +144,8 @@ public:
}
};
} // namespace detail
/**
* A dictionary type that uses clustered hashing, a variation of Robinhood/Open Addressing
* hashing. The following posts help to understand the implementation:
@ -154,7 +160,7 @@ public:
*/
class Dictionary{
public:
explicit Dictionary(dict_order ordering = UNORDERED, int initial_size = DEFAULT_DICT_SIZE);
explicit Dictionary(DictOrder ordering = UNORDERED, int initial_size = DEFAULT_DICT_SIZE);
~Dictionary();
// Member functions for looking up a key, inserting/changing its
@ -254,7 +260,7 @@ public:
void DumpKeys() const;
private:
friend IterCookie;
friend zeek::IterCookie;
/// Buckets of the table, not including overflow size.
int Buckets(bool expected=false) const;
@ -310,22 +316,22 @@ private:
int* insert_position = nullptr, int* insert_distance = nullptr);
/// Insert entry, Adjust cookies when necessary.
void InsertRelocateAndAdjust(DictEntry& entry, int insert_position);
void InsertRelocateAndAdjust(detail::DictEntry& entry, int insert_position);
/// insert entry into position, relocate other entries when necessary.
void InsertAndRelocate(DictEntry& entry, int insert_position, int* last_affected_position = nullptr);
void InsertAndRelocate(detail::DictEntry& entry, int insert_position, int* last_affected_position = nullptr);
/// Adjust Cookies on Insert.
void AdjustOnInsert(IterCookie* c, const DictEntry& entry, int insert_position, int last_affected_position);
void AdjustOnInsert(IterCookie* c, const detail::DictEntry& entry, int insert_position, int last_affected_position);
///Remove, Relocate & Adjust cookies.
DictEntry RemoveRelocateAndAdjust(int position);
detail::DictEntry RemoveRelocateAndAdjust(int position);
///Remove & Relocate
DictEntry RemoveAndRelocate(int position, int* last_affected_position = nullptr);
detail::DictEntry RemoveAndRelocate(int position, int* last_affected_position = nullptr);
///Adjust safe cookies after Removal of entry at position.
void AdjustOnRemove(IterCookie* c, const DictEntry& entry, int position, int last_affected_position);
void AdjustOnRemove(IterCookie* c, const detail::DictEntry& entry, int position, int last_affected_position);
bool Remapping() const { return remap_end >= 0;} //remap in reverse order.
@ -360,11 +366,11 @@ private:
uint64_t cum_entries = 0;
dict_delete_func delete_func = nullptr;
DictEntry* table = nullptr;
detail::DictEntry* table = nullptr;
std::vector<IterCookie*>* cookies = nullptr;
// Order means the order of insertion. means no deletion until exit. will be inefficient.
std::vector<DictEntry>* order = nullptr;
std::vector<detail::DictEntry>* order = nullptr;
};
/*
@ -373,7 +379,7 @@ private:
template<typename T>
class PDict : public Dictionary {
public:
explicit PDict(dict_order ordering = UNORDERED, int initial_size = 0) :
explicit PDict(DictOrder ordering = UNORDERED, int initial_size = 0) :
Dictionary(ordering, initial_size) {}
T* Lookup(const char* key) const
{
@ -405,4 +411,11 @@ public:
{ return (T*) Dictionary::NextEntry(h, cookie, true); }
T* RemoveEntry(const HashKey* key)
{ return (T*) Remove(key->Key(), key->Size(), key->Hash()); }
T* RemoveEntry(const HashKey& key)
{ return (T*) Remove(key.Key(), key.Size(), key.Hash()); }
};
} // namespace zeek
using Dictionary [[deprecated("Remove in v4.1. Use zeek::Dictionary instead.")]] = zeek::Dictionary;
template<typename T> using PDict [[deprecated("Remove in v4.1. Use zeek::PDict instead.")]] = zeek::PDict<T>;