| Index: compiled/Map.h |
| =================================================================== |
| copy from compiled/StringMap.h |
| copy to compiled/Map.h |
| --- a/compiled/StringMap.h |
| +++ b/compiled/Map.h |
| @@ -12,42 +12,40 @@ |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| #pragma once |
| -#include <cstddef> |
| #include <cmath> |
| #include <initializer_list> |
| #include <memory> |
| -#include "String.h" |
| #include "debug.h" |
| -template<typename T> |
| -class StringMap; |
| +template<typename Entry, typename Value> |
| +class Map; |
| -namespace StringMap_internal |
| +namespace Map_internal |
| { |
| template<typename Entry> |
| struct HashContainerIterator |
| { |
| typedef Entry entry_type; |
| typedef HashContainerIterator<Entry> iterator; |
| const entry_type* mPos; |
| const entry_type* mEnd; |
| explicit HashContainerIterator(const entry_type* start, const entry_type* end) |
| : mPos(start), mEnd(end) |
| { |
| - if (mPos != mEnd && mPos->first.is_invalid()) |
| + if (mPos != mEnd && mPos->is_invalid()) |
| ++(*this); |
| } |
| const entry_type& operator*() const |
| { |
| return *mPos; |
| } |
| @@ -55,17 +53,17 @@ namespace StringMap_internal |
| { |
| return mPos; |
| } |
| iterator& operator++() |
| { |
| do { |
| ++mPos; |
| - } while(mPos != mEnd && mPos->first.is_invalid()); |
| + } while(mPos != mEnd && mPos->is_invalid()); |
| return *this; |
| } |
| bool operator==(const iterator& it) const |
| { |
| return mPos == it.mPos; |
| } |
| @@ -89,26 +87,27 @@ namespace StringMap_internal |
| const entry_type* operator->() const |
| { |
| return mEntry; |
| } |
| operator bool() const |
| { |
| - return !mEntry->first.is_invalid(); |
| + return !mEntry->is_invalid(); |
| } |
| }; |
| template<typename Entry> |
| class HashContainer |
| { |
| public: |
| typedef Entry entry_type; |
| - typedef size_t size_type; |
| + typedef typename Entry::key_type key_type; |
| + typedef typename entry_type::size_type size_type; |
| typedef HashContainerIterator<Entry> const_iterator; |
| typedef HashContainerReference<const Entry> const_reference; |
| private: |
| explicit HashContainer(const HashContainer& other); |
| void operator=(const HashContainer& other); |
| protected: |
| @@ -117,50 +116,28 @@ namespace StringMap_internal |
| std::unique_ptr<entry_type[]> mBuckets; |
| size_type mBucketCount; |
| size_type mEntryCount; |
| #if defined(DEBUG) |
| size_type mInsertCounter; |
| #endif |
| - explicit HashContainer(size_type expectedEntries = 0) |
| - : mEntryCount(0) |
| + entry_type* find_bucket(const key_type& key) const |
| { |
| - expectedEntries = ceil(expectedEntries / LOAD_FACTOR); |
| - mBucketCount = MIN_BUCKETS; |
| - while (mBucketCount < expectedEntries) |
| - mBucketCount <<= 1; |
| - |
| - mBuckets.reset(new entry_type[mBucketCount]); |
| - // Working around https://github.com/waywardmonkeys/emscripten-trace-collector/issues/2 here |
| - annotate_address(reinterpret_cast<size_type*>(mBuckets.get()) - 1, "Hash table buffer"); |
| - } |
| - |
| - static size_type hash(const String& str) |
| - { |
| - // FNV-1a hash function |
| - size_type result = 2166136261; |
| - for (String::size_type i = 0; i < str.length(); i++) |
| - result = (result ^ str[i]) * 16777619; |
| - return result; |
| - } |
| - |
| - entry_type* find_bucket(const String& key) const |
| - { |
| - size_type h = hash(key); |
| + size_type h = entry_type::hash(key); |
| // This does quadratic probing, effectively the following formula is used: |
| // pos = (hash + 1/2 i + 1/2 i ^ 2) mod bucketCount |
| for (size_type i = 0; ; ++i) |
| { |
| // mBucketCount is 2^n so (h & mBucketCount - 1) is equivalent to |
| // h % mBucketCount but significantly faster. |
| entry_type* entry = &mBuckets[h & (mBucketCount - 1)]; |
| - if (entry->first.is_invalid() || entry->first.equals(key)) |
| + if (entry->is_invalid() || entry->equals(key)) |
| return entry; |
| h += i; |
| } |
| } |
| void resize(size_type bucketCount) |
| { |
| std::unique_ptr<entry_type[]> oldBuckets(std::move(mBuckets)); |
| @@ -171,59 +148,72 @@ namespace StringMap_internal |
| mBuckets.reset(new entry_type[mBucketCount]); |
| // Working around https://github.com/waywardmonkeys/emscripten-trace-collector/issues/2 here |
| annotate_address(reinterpret_cast<size_type*>(mBuckets.get()) - 1, "Hash table buffer"); |
| // Copy old entries into the new buffer |
| for (size_type i = 0; i < oldCount; i++) |
| { |
| entry_type& entry = oldBuckets[i]; |
| - if (!entry.first.is_invalid() && !entry.first.is_deleted()) |
| + if (!entry.is_invalid() && !entry.is_deleted()) |
| { |
| *find_bucket(entry.first) = entry; |
| mEntryCount++; |
| } |
| } |
| } |
| entry_type* assign(entry_type* existing, const entry_type& entry) |
| { |
| - if (existing->first.is_invalid()) |
| + if (existing->is_invalid()) |
| { |
| if (mEntryCount + 1 >= mBucketCount * LOAD_FACTOR) |
| { |
| resize(mBucketCount << 1); |
| existing = find_bucket(entry.first); |
| } |
| mEntryCount++; |
| #if defined(DEBUG) |
| mInsertCounter++; |
| #endif |
| } |
| *existing = entry; |
| return existing; |
| } |
| public: |
| + explicit HashContainer(size_type expectedEntries = 0) |
| + : mEntryCount(0) |
| + { |
| + expectedEntries = ceil(expectedEntries / LOAD_FACTOR); |
| + mBucketCount = MIN_BUCKETS; |
| + while (mBucketCount < expectedEntries) |
| + mBucketCount <<= 1; |
| + |
| + mBuckets.reset(new entry_type[mBucketCount]); |
| + // Working around https://github.com/waywardmonkeys/emscripten-trace-collector/issues/2 here |
| + annotate_address(reinterpret_cast<size_type*>(mBuckets.get()) - 1, "Hash table buffer"); |
| + } |
| + |
| void insert(const entry_type& entry) |
| { |
| assign(find_bucket(entry.first), entry); |
| } |
| - bool erase(const String& key) |
| + bool erase(const key_type& key) |
| { |
| entry_type* entry = find_bucket(key); |
| - if (entry->first.is_invalid()) |
| + if (entry->is_invalid()) |
| return false; |
| - entry->first.erase(); |
| + entry->erase(); |
| return true; |
| } |
| - const_reference find(const String& key) const |
| + const_reference find(const key_type& key) const |
| { |
| return const_reference(find_bucket(key)); |
| } |
| const_iterator begin() const |
| { |
| return const_iterator(&mBuckets[0], &mBuckets[mBucketCount]); |
| } |
| @@ -234,124 +224,96 @@ namespace StringMap_internal |
| } |
| size_type size() const |
| { |
| return mEntryCount; |
| } |
| }; |
| - struct StringSetEntry |
| - { |
| - StringSetEntry() {} |
| - StringSetEntry(const String& key) |
| - : first(key) |
| - { |
| - } |
| - |
| - DependentString first; |
| - }; |
| - |
| - template<typename T> |
| - struct StringMapEntry |
| + template<typename Entry> |
| + struct MapReference : public HashContainerReference<Entry> |
| { |
| - StringMapEntry() {} |
| - StringMapEntry(const String& key) |
| - : first(key), second() |
| - { |
| - } |
| - StringMapEntry(const String& key, T value) |
| - : first(key), second(value) |
| - { |
| - } |
| - |
| - DependentString first; |
| - T second; |
| - }; |
| - |
| - template<typename T> |
| - struct StringMapEntryReference : public HashContainerReference<StringMapEntry<T>> |
| - { |
| - typedef HashContainerReference<StringMapEntry<T>> super; |
| + typedef HashContainerReference<Entry> super; |
| typedef typename super::entry_type entry_type; |
| - typedef StringMap<T> map_type; |
| + typedef typename entry_type::key_type key_type; |
| + typedef typename entry_type::value_type value_type; |
| + typedef Map<entry_type, value_type> map_type; |
| map_type* mMap; |
| #if defined(DEBUG) |
| typename map_type::size_type mInsertCounter; |
| typename map_type::size_type mHash; |
| #endif |
| - StringMapEntryReference(map_type* map, const String& key, entry_type* entry) |
| + MapReference(map_type* map, const key_type& key, entry_type* entry) |
| : super(entry), mMap(map) |
| { |
| #if defined(DEBUG) |
| mInsertCounter = mMap->mInsertCounter; |
| - mHash = mMap->hash(key); |
| + mHash = entry_type::hash(key); |
| #endif |
| } |
| - void assign(const String& key, const T& value) |
| + void assign(const key_type& key, const value_type& value) |
| { |
| #if defined(DEBUG) |
| assert2(mInsertCounter == mMap->mInsertCounter, |
| u"There should be no insert operations performed between map.find() and assign()"_str); |
| - assert2(mHash == mMap->hash(key), |
| + assert2(mHash == entry_type::hash(key), |
| u"The keys used in map.find() and assign() should be identical"_str); |
| #endif |
| mMap->assign(this->mEntry, entry_type(key, value)); |
| } |
| }; |
| } |
| -class StringSet |
| - : public StringMap_internal::HashContainer<StringMap_internal::StringSetEntry> |
| -{ |
| -}; |
| - |
| -template<typename T> |
| -class StringMap |
| - : public StringMap_internal::HashContainer<StringMap_internal::StringMapEntry<T>> |
| +template<typename Entry> |
| +class Set : public Map_internal::HashContainer<Entry> |
| { |
| public: |
| - typedef StringMap_internal::HashContainer<StringMap_internal::StringMapEntry<T>> super; |
| + typedef Map_internal::HashContainer<Entry> super; |
| + |
| + using super::super; |
| +}; |
| + |
| +template<typename Entry, typename Value> |
| +class Map : public Map_internal::HashContainer<Entry> |
| +{ |
| +public: |
| + typedef Map_internal::HashContainer<Entry> super; |
| typedef typename super::size_type size_type; |
| typedef typename super::entry_type entry_type; |
| + typedef typename super::key_type key_type; |
| + typedef Value value_type; |
| typedef typename super::const_reference const_reference; |
| - typedef StringMap_internal::StringMapEntryReference<T> reference; |
| - friend struct StringMap_internal::StringMapEntryReference<T>; |
| + typedef Map_internal::MapReference<entry_type> reference; |
| + friend struct Map_internal::MapReference<entry_type>; |
| - explicit StringMap(size_type expectedEntries = 0) |
| - : super(expectedEntries) |
| - { |
| - } |
| + using super::super; |
| - StringMap(std::initializer_list<entry_type> list) |
| + Map(std::initializer_list<entry_type> list) |
| : super(list.size()) |
| { |
| for (const auto& item : list) |
| super::insert(item); |
| } |
| - ~StringMap() |
| - { |
| - } |
| - |
| - T& operator[](const String& key) |
| + value_type& operator[](const key_type& key) |
| { |
| entry_type* entry = super::find_bucket(key); |
| - if (entry->first.is_invalid()) |
| + if (entry->is_invalid()) |
| entry = super::assign(entry, key); |
| return entry->second; |
| } |
| - const_reference find(const String& key) const |
| + const_reference find(const key_type& key) const |
| { |
| return super::find(key); |
| } |
| - reference find(const String& key) |
| + reference find(const key_type& key) |
| { |
| return reference(this, key, super::find_bucket(key)); |
| } |
| }; |