| 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> | 
| +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> 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> | 
| +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 typename entry_type::value_type 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)); | 
| } | 
| }; | 
|  |