| Index: compiled/StringMap.h |
| =================================================================== |
| --- a/compiled/StringMap.h |
| +++ b/compiled/StringMap.h |
| @@ -13,345 +13,84 @@ |
| * |
| * 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 "Map.h" |
| #include "String.h" |
| -#include "debug.h" |
| - |
| -template<typename T> |
| -class StringMap; |
| namespace StringMap_internal |
| { |
| - template<typename Entry> |
| - struct HashContainerIterator |
| + struct StringSetEntry |
| { |
| - typedef Entry entry_type; |
| - typedef HashContainerIterator<Entry> iterator; |
| - |
| - const entry_type* mPos; |
| - const entry_type* mEnd; |
| + typedef DependentString key_type; |
| + typedef const String& key_type_cref; |
| + typedef size_t size_type; |
| - explicit HashContainerIterator(const entry_type* start, const entry_type* end) |
| - : mPos(start), mEnd(end) |
| - { |
| - if (mPos != mEnd && mPos->first.is_invalid()) |
| - ++(*this); |
| - } |
| + key_type first; |
| - const entry_type& operator*() const |
| + StringSetEntry(key_type_cref key = key_type()) |
| { |
| - return *mPos; |
| - } |
| - |
| - const entry_type* operator->() const |
| - { |
| - return mPos; |
| - } |
| - |
| - iterator& operator++() |
| - { |
| - do { |
| - ++mPos; |
| - } while(mPos != mEnd && mPos->first.is_invalid()); |
| - return *this; |
| - } |
| - |
| - bool operator==(const iterator& it) const |
| - { |
| - return mPos == it.mPos; |
| + if (!key.is_invalid()) |
| + first.reset(key); |
| } |
| - bool operator!=(const iterator& it) const |
| + bool equals(key_type_cref other) const |
| { |
| - return mPos != it.mPos; |
| - } |
| - }; |
| - |
| - template<typename Entry> |
| - struct HashContainerReference |
| - { |
| - typedef Entry entry_type; |
| - |
| - entry_type* mEntry; |
| - |
| - explicit HashContainerReference(entry_type* entry) |
| - : mEntry(entry) |
| - { |
| + return first.equals(other); |
| } |
| - const entry_type* operator->() const |
| + bool is_invalid() const |
| { |
| - return mEntry; |
| + return first.is_invalid(); |
| } |
| - operator bool() const |
| + bool is_deleted() const |
| { |
| - return !mEntry->first.is_invalid(); |
| - } |
| - }; |
| - |
| - template<typename Entry> |
| - class HashContainer |
| - { |
| - public: |
| - typedef Entry entry_type; |
| - typedef size_t 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: |
| - static constexpr size_type MIN_BUCKETS = 1; |
| - static constexpr double LOAD_FACTOR = 0.8; |
| - 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) |
| - { |
| - 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"); |
| + return first.is_deleted(); |
| } |
| - static size_type hash(const String& str) |
| + void erase() |
| + { |
| + first.erase(); |
| + } |
| + |
| + static size_type hash(key_type_cref key) |
| { |
| // FNV-1a hash function |
| size_type result = 2166136261; |
| - for (String::size_type i = 0; i < str.length(); i++) |
| - result = (result ^ str[i]) * 16777619; |
| + for (String::size_type i = 0; i < key.length(); i++) |
| + result = (result ^ key[i]) * 16777619; |
| return result; |
| } |
| - |
| - entry_type* find_bucket(const String& key) const |
| - { |
| - size_type h = 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)) |
| - return entry; |
| - h += i; |
| - } |
| - } |
| - |
| - void resize(size_type bucketCount) |
| - { |
| - std::unique_ptr<entry_type[]> oldBuckets(std::move(mBuckets)); |
| - size_type oldCount = mBucketCount; |
| - |
| - mEntryCount = 0; |
| - mBucketCount = bucketCount; |
| - 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()) |
| - { |
| - *find_bucket(entry.first) = entry; |
| - mEntryCount++; |
| - } |
| - } |
| - } |
| - |
| - entry_type* assign(entry_type* existing, const entry_type& entry) |
| - { |
| - if (existing->first.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: |
| - void insert(const entry_type& entry) |
| - { |
| - assign(find_bucket(entry.first), entry); |
| - } |
| - |
| - bool erase(const String& key) |
| - { |
| - entry_type* entry = find_bucket(key); |
| - if (entry->first.is_invalid()) |
| - return false; |
| - |
| - entry->first.erase(); |
| - return true; |
| - } |
| - |
| - const_reference find(const String& key) const |
| - { |
| - return const_reference(find_bucket(key)); |
| - } |
| - |
| - const_iterator begin() const |
| - { |
| - return const_iterator(&mBuckets[0], &mBuckets[mBucketCount]); |
| - } |
| - |
| - const_iterator end() const |
| - { |
| - return const_iterator(&mBuckets[mBucketCount], &mBuckets[mBucketCount]); |
| - } |
| - |
| - size_type size() const |
| - { |
| - return mEntryCount; |
| - } |
| }; |
| - struct StringSetEntry |
| + template<typename Value> |
| + struct StringMapEntry : StringSetEntry |
| { |
| - StringSetEntry() {} |
| - StringSetEntry(const String& key) |
| - : first(key) |
| - { |
| - } |
| - |
| - DependentString first; |
| - }; |
| + typedef StringSetEntry super; |
| + typedef Value value_type; |
| - template<typename T> |
| - struct StringMapEntry |
| - { |
| - StringMapEntry() {} |
| - StringMapEntry(const String& key) |
| - : first(key), second() |
| - { |
| - } |
| - StringMapEntry(const String& key, T value) |
| - : first(key), second(value) |
| + value_type second; |
| + |
| + StringMapEntry(key_type_cref key = DependentString(), |
| + value_type value = value_type()) |
| + : super(key), second(value) |
| { |
| } |
| - DependentString first; |
| - T second; |
| - }; |
| - |
| - template<typename T> |
| - struct StringMapEntryReference : public HashContainerReference<StringMapEntry<T>> |
| - { |
| - typedef HashContainerReference<StringMapEntry<T>> super; |
| - typedef typename super::entry_type entry_type; |
| - typedef StringMap<T> 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) |
| - : super(entry), mMap(map) |
| + void erase() |
| { |
| -#if defined(DEBUG) |
| - mInsertCounter = mMap->mInsertCounter; |
| - mHash = mMap->hash(key); |
| -#endif |
| - } |
| - |
| - void assign(const String& key, const T& 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), |
| - u"The keys used in map.find() and assign() should be identical"_str); |
| -#endif |
| - |
| - mMap->assign(this->mEntry, entry_type(key, value)); |
| + super::erase(); |
| + second = value_type(); |
| } |
| }; |
| } |
| -class StringSet |
| - : public StringMap_internal::HashContainer<StringMap_internal::StringSetEntry> |
| -{ |
| -}; |
| - |
| -template<typename T> |
| -class StringMap |
| - : public StringMap_internal::HashContainer<StringMap_internal::StringMapEntry<T>> |
| -{ |
| -public: |
| - typedef StringMap_internal::HashContainer<StringMap_internal::StringMapEntry<T>> super; |
| - typedef typename super::size_type size_type; |
| - typedef typename super::entry_type entry_type; |
| - typedef typename super::const_reference const_reference; |
| - typedef StringMap_internal::StringMapEntryReference<T> reference; |
| - friend struct StringMap_internal::StringMapEntryReference<T>; |
| - |
| - explicit StringMap(size_type expectedEntries = 0) |
| - : super(expectedEntries) |
| - { |
| - } |
| +using StringSet = Set<StringMap_internal::StringSetEntry>; |
| - StringMap(std::initializer_list<entry_type> list) |
| - : super(list.size()) |
| - { |
| - for (const auto& item : list) |
| - super::insert(item); |
| - } |
| - |
| - ~StringMap() |
| - { |
| - } |
| - |
| - T& operator[](const String& key) |
| - { |
| - entry_type* entry = super::find_bucket(key); |
| - if (entry->first.is_invalid()) |
| - entry = super::assign(entry, key); |
| - return entry->second; |
| - } |
| - |
| - const_reference find(const String& key) const |
| - { |
| - return super::find(key); |
| - } |
| - |
| - reference find(const String& key) |
| - { |
| - return reference(this, key, super::find_bucket(key)); |
| - } |
| -}; |
| +template<typename Value> |
| +using StringMap = Map<StringMap_internal::StringMapEntry<Value>>; |