diff --git a/src/OpenDict.cc b/src/OpenDict.cc index 51b96ba859..a126e56c6a 100644 --- a/src/OpenDict.cc +++ b/src/OpenDict.cc @@ -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* inserted = nullptr; + std::vector* 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* visited = nullptr; + std::vector* visited = nullptr; void MakeRobust() { @@ -48,8 +50,8 @@ public: ASSERT(d && d->cookies); robust = true; - inserted = new std::vector(); - visited = new std::vector(); + inserted = new std::vector(); + visited = new std::vector(); 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) + pad_size(sizeof(DictEntry) * order->capacity()); + size += padded_sizeof(std::vector) + 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; + order = new std::vector; } 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(this); dp->StopIterationNonConst(cookie); } + +} // namespace zeek diff --git a/src/OpenDict.h b/src/OpenDict.h index b78152cf1a..7658abb5a5 100644 --- a/src/OpenDict.h +++ b/src/OpenDict.h @@ -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* cookies = nullptr; // Order means the order of insertion. means no deletion until exit. will be inefficient. - std::vector* order = nullptr; + std::vector* order = nullptr; }; /* @@ -373,7 +379,7 @@ private: template 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 using PDict [[deprecated("Remove in v4.1. Use zeek::PDict instead.")]] = zeek::PDict;