tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FastVector.h (22966B)


      1 //
      2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 // FastVector.h:
      7 //   A vector class with a initial fixed size and variable growth.
      8 //   Based on FixedVector.
      9 //
     10 
     11 #ifndef COMMON_FASTVECTOR_H_
     12 #define COMMON_FASTVECTOR_H_
     13 
     14 #include "bitset_utils.h"
     15 #include "common/debug.h"
     16 
     17 #include <algorithm>
     18 #include <array>
     19 #include <initializer_list>
     20 #include <iterator>
     21 
     22 namespace angle
     23 {
     24 
     25 template <class Iter>
     26 class WrapIter
     27 {
     28  public:
     29    typedef Iter iterator_type;
     30    typedef typename std::iterator_traits<iterator_type>::value_type value_type;
     31    typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
     32    typedef typename std::iterator_traits<iterator_type>::pointer pointer;
     33    typedef typename std::iterator_traits<iterator_type>::reference reference;
     34    typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category;
     35 
     36    WrapIter() : mIter() {}
     37    WrapIter(const Iter &iter) : mIter(iter) {}
     38    ~WrapIter() = default;
     39 
     40    WrapIter &operator=(const WrapIter &x)
     41    {
     42        mIter = x.mIter;
     43        return *this;
     44    }
     45 
     46    bool operator==(const WrapIter &x) const { return mIter == x.mIter; }
     47    bool operator!=(const WrapIter &x) const { return mIter != x.mIter; }
     48    bool operator<(const WrapIter &x) const { return mIter < x.mIter; }
     49    bool operator<=(const WrapIter &x) const { return mIter <= x.mIter; }
     50    bool operator>(const WrapIter &x) const { return mIter > x.mIter; }
     51    bool operator>=(const WrapIter &x) const { return mIter >= x.mIter; }
     52 
     53    WrapIter &operator++()
     54    {
     55        mIter++;
     56        return *this;
     57    }
     58 
     59    WrapIter operator++(int)
     60    {
     61        WrapIter tmp(mIter);
     62        mIter++;
     63        return tmp;
     64    }
     65 
     66    WrapIter operator+(difference_type n)
     67    {
     68        WrapIter tmp(mIter);
     69        tmp.mIter += n;
     70        return tmp;
     71    }
     72 
     73    WrapIter operator-(difference_type n)
     74    {
     75        WrapIter tmp(mIter);
     76        tmp.mIter -= n;
     77        return tmp;
     78    }
     79 
     80    difference_type operator-(const WrapIter &x) const { return mIter - x.mIter; }
     81 
     82    iterator_type operator->() const { return mIter; }
     83 
     84    reference operator*() const { return *mIter; }
     85 
     86  private:
     87    iterator_type mIter;
     88 };
     89 
     90 template <class T, size_t N, class Storage = std::array<T, N>>
     91 class FastVector final
     92 {
     93  public:
     94    using value_type      = typename Storage::value_type;
     95    using size_type       = typename Storage::size_type;
     96    using reference       = typename Storage::reference;
     97    using const_reference = typename Storage::const_reference;
     98    using pointer         = typename Storage::pointer;
     99    using const_pointer   = typename Storage::const_pointer;
    100    using iterator        = WrapIter<T *>;
    101    using const_iterator  = WrapIter<const T *>;
    102 
    103    FastVector();
    104    FastVector(size_type count, const value_type &value);
    105    FastVector(size_type count);
    106 
    107    FastVector(const FastVector<T, N, Storage> &other);
    108    FastVector(FastVector<T, N, Storage> &&other);
    109    FastVector(std::initializer_list<value_type> init);
    110 
    111    template <class InputIt, std::enable_if_t<!std::is_integral<InputIt>::value, bool> = true>
    112    FastVector(InputIt first, InputIt last);
    113 
    114    FastVector<T, N, Storage> &operator=(const FastVector<T, N, Storage> &other);
    115    FastVector<T, N, Storage> &operator=(FastVector<T, N, Storage> &&other);
    116    FastVector<T, N, Storage> &operator=(std::initializer_list<value_type> init);
    117 
    118    ~FastVector();
    119 
    120    reference at(size_type pos);
    121    const_reference at(size_type pos) const;
    122 
    123    reference operator[](size_type pos);
    124    const_reference operator[](size_type pos) const;
    125 
    126    pointer data();
    127    const_pointer data() const;
    128 
    129    iterator begin();
    130    const_iterator begin() const;
    131 
    132    iterator end();
    133    const_iterator end() const;
    134 
    135    bool empty() const;
    136    size_type size() const;
    137 
    138    void clear();
    139 
    140    void push_back(const value_type &value);
    141    void push_back(value_type &&value);
    142 
    143    template <typename... Args>
    144    void emplace_back(Args &&...args);
    145 
    146    void pop_back();
    147 
    148    reference front();
    149    const_reference front() const;
    150 
    151    reference back();
    152    const_reference back() const;
    153 
    154    void swap(FastVector<T, N, Storage> &other);
    155 
    156    void resize(size_type count);
    157    void resize(size_type count, const value_type &value);
    158 
    159    void reserve(size_type count);
    160 
    161    // Specialty function that removes a known element and might shuffle the list.
    162    void remove_and_permute(const value_type &element);
    163    void remove_and_permute(iterator pos);
    164 
    165  private:
    166    void assign_from_initializer_list(std::initializer_list<value_type> init);
    167    void ensure_capacity(size_t capacity);
    168    bool uses_fixed_storage() const;
    169 
    170    Storage mFixedStorage;
    171    pointer mData           = mFixedStorage.data();
    172    size_type mSize         = 0;
    173    size_type mReservedSize = N;
    174 };
    175 
    176 template <class T, size_t N, class StorageN, size_t M, class StorageM>
    177 bool operator==(const FastVector<T, N, StorageN> &a, const FastVector<T, M, StorageM> &b)
    178 {
    179    return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
    180 }
    181 
    182 template <class T, size_t N, class StorageN, size_t M, class StorageM>
    183 bool operator!=(const FastVector<T, N, StorageN> &a, const FastVector<T, M, StorageM> &b)
    184 {
    185    return !(a == b);
    186 }
    187 
    188 template <class T, size_t N, class Storage>
    189 ANGLE_INLINE bool FastVector<T, N, Storage>::uses_fixed_storage() const
    190 {
    191    return mData == mFixedStorage.data();
    192 }
    193 
    194 template <class T, size_t N, class Storage>
    195 FastVector<T, N, Storage>::FastVector()
    196 {}
    197 
    198 template <class T, size_t N, class Storage>
    199 FastVector<T, N, Storage>::FastVector(size_type count, const value_type &value)
    200 {
    201    ensure_capacity(count);
    202    mSize = count;
    203    std::fill(begin(), end(), value);
    204 }
    205 
    206 template <class T, size_t N, class Storage>
    207 FastVector<T, N, Storage>::FastVector(size_type count)
    208 {
    209    ensure_capacity(count);
    210    mSize = count;
    211 }
    212 
    213 template <class T, size_t N, class Storage>
    214 FastVector<T, N, Storage>::FastVector(const FastVector<T, N, Storage> &other)
    215    : FastVector(other.begin(), other.end())
    216 {}
    217 
    218 template <class T, size_t N, class Storage>
    219 FastVector<T, N, Storage>::FastVector(FastVector<T, N, Storage> &&other) : FastVector()
    220 {
    221    swap(other);
    222 }
    223 
    224 template <class T, size_t N, class Storage>
    225 FastVector<T, N, Storage>::FastVector(std::initializer_list<value_type> init)
    226 {
    227    assign_from_initializer_list(init);
    228 }
    229 
    230 template <class T, size_t N, class Storage>
    231 template <class InputIt, std::enable_if_t<!std::is_integral<InputIt>::value, bool>>
    232 FastVector<T, N, Storage>::FastVector(InputIt first, InputIt last)
    233 {
    234    size_t newSize = last - first;
    235    ensure_capacity(newSize);
    236    mSize = newSize;
    237    std::copy(first, last, begin());
    238 }
    239 
    240 template <class T, size_t N, class Storage>
    241 FastVector<T, N, Storage> &FastVector<T, N, Storage>::operator=(
    242    const FastVector<T, N, Storage> &other)
    243 {
    244    ensure_capacity(other.mSize);
    245    mSize = other.mSize;
    246    std::copy(other.begin(), other.end(), begin());
    247    return *this;
    248 }
    249 
    250 template <class T, size_t N, class Storage>
    251 FastVector<T, N, Storage> &FastVector<T, N, Storage>::operator=(FastVector<T, N, Storage> &&other)
    252 {
    253    swap(other);
    254    return *this;
    255 }
    256 
    257 template <class T, size_t N, class Storage>
    258 FastVector<T, N, Storage> &FastVector<T, N, Storage>::operator=(
    259    std::initializer_list<value_type> init)
    260 {
    261    assign_from_initializer_list(init);
    262    return *this;
    263 }
    264 
    265 template <class T, size_t N, class Storage>
    266 FastVector<T, N, Storage>::~FastVector()
    267 {
    268    clear();
    269    if (!uses_fixed_storage())
    270    {
    271        delete[] mData;
    272    }
    273 }
    274 
    275 template <class T, size_t N, class Storage>
    276 typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::at(size_type pos)
    277 {
    278    ASSERT(pos < mSize);
    279    return mData[pos];
    280 }
    281 
    282 template <class T, size_t N, class Storage>
    283 typename FastVector<T, N, Storage>::const_reference FastVector<T, N, Storage>::at(
    284    size_type pos) const
    285 {
    286    ASSERT(pos < mSize);
    287    return mData[pos];
    288 }
    289 
    290 template <class T, size_t N, class Storage>
    291 ANGLE_INLINE typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::operator[](
    292    size_type pos)
    293 {
    294    ASSERT(pos < mSize);
    295    return mData[pos];
    296 }
    297 
    298 template <class T, size_t N, class Storage>
    299 ANGLE_INLINE typename FastVector<T, N, Storage>::const_reference
    300 FastVector<T, N, Storage>::operator[](size_type pos) const
    301 {
    302    ASSERT(pos < mSize);
    303    return mData[pos];
    304 }
    305 
    306 template <class T, size_t N, class Storage>
    307 ANGLE_INLINE typename FastVector<T, N, Storage>::const_pointer
    308 angle::FastVector<T, N, Storage>::data() const
    309 {
    310    return mData;
    311 }
    312 
    313 template <class T, size_t N, class Storage>
    314 ANGLE_INLINE typename FastVector<T, N, Storage>::pointer angle::FastVector<T, N, Storage>::data()
    315 {
    316    return mData;
    317 }
    318 
    319 template <class T, size_t N, class Storage>
    320 ANGLE_INLINE typename FastVector<T, N, Storage>::iterator FastVector<T, N, Storage>::begin()
    321 {
    322    return mData;
    323 }
    324 
    325 template <class T, size_t N, class Storage>
    326 ANGLE_INLINE typename FastVector<T, N, Storage>::const_iterator FastVector<T, N, Storage>::begin()
    327    const
    328 {
    329    return mData;
    330 }
    331 
    332 template <class T, size_t N, class Storage>
    333 ANGLE_INLINE typename FastVector<T, N, Storage>::iterator FastVector<T, N, Storage>::end()
    334 {
    335    return mData + mSize;
    336 }
    337 
    338 template <class T, size_t N, class Storage>
    339 ANGLE_INLINE typename FastVector<T, N, Storage>::const_iterator FastVector<T, N, Storage>::end()
    340    const
    341 {
    342    return mData + mSize;
    343 }
    344 
    345 template <class T, size_t N, class Storage>
    346 ANGLE_INLINE bool FastVector<T, N, Storage>::empty() const
    347 {
    348    return mSize == 0;
    349 }
    350 
    351 template <class T, size_t N, class Storage>
    352 ANGLE_INLINE typename FastVector<T, N, Storage>::size_type FastVector<T, N, Storage>::size() const
    353 {
    354    return mSize;
    355 }
    356 
    357 template <class T, size_t N, class Storage>
    358 void FastVector<T, N, Storage>::clear()
    359 {
    360    resize(0);
    361 }
    362 
    363 template <class T, size_t N, class Storage>
    364 ANGLE_INLINE void FastVector<T, N, Storage>::push_back(const value_type &value)
    365 {
    366    if (mSize == mReservedSize)
    367        ensure_capacity(mSize + 1);
    368    mData[mSize++] = value;
    369 }
    370 
    371 template <class T, size_t N, class Storage>
    372 ANGLE_INLINE void FastVector<T, N, Storage>::push_back(value_type &&value)
    373 {
    374    emplace_back(std::move(value));
    375 }
    376 
    377 template <class T, size_t N, class Storage>
    378 template <typename... Args>
    379 ANGLE_INLINE void FastVector<T, N, Storage>::emplace_back(Args &&...args)
    380 {
    381    if (mSize == mReservedSize)
    382        ensure_capacity(mSize + 1);
    383    mData[mSize++] = std::move(T(std::forward<Args>(args)...));
    384 }
    385 
    386 template <class T, size_t N, class Storage>
    387 ANGLE_INLINE void FastVector<T, N, Storage>::pop_back()
    388 {
    389    ASSERT(mSize > 0);
    390    mSize--;
    391 }
    392 
    393 template <class T, size_t N, class Storage>
    394 ANGLE_INLINE typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::front()
    395 {
    396    ASSERT(mSize > 0);
    397    return mData[0];
    398 }
    399 
    400 template <class T, size_t N, class Storage>
    401 ANGLE_INLINE typename FastVector<T, N, Storage>::const_reference FastVector<T, N, Storage>::front()
    402    const
    403 {
    404    ASSERT(mSize > 0);
    405    return mData[0];
    406 }
    407 
    408 template <class T, size_t N, class Storage>
    409 ANGLE_INLINE typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::back()
    410 {
    411    ASSERT(mSize > 0);
    412    return mData[mSize - 1];
    413 }
    414 
    415 template <class T, size_t N, class Storage>
    416 ANGLE_INLINE typename FastVector<T, N, Storage>::const_reference FastVector<T, N, Storage>::back()
    417    const
    418 {
    419    ASSERT(mSize > 0);
    420    return mData[mSize - 1];
    421 }
    422 
    423 template <class T, size_t N, class Storage>
    424 void FastVector<T, N, Storage>::swap(FastVector<T, N, Storage> &other)
    425 {
    426    std::swap(mSize, other.mSize);
    427 
    428    pointer tempData = other.mData;
    429    if (uses_fixed_storage())
    430        other.mData = other.mFixedStorage.data();
    431    else
    432        other.mData = mData;
    433    if (tempData == other.mFixedStorage.data())
    434        mData = mFixedStorage.data();
    435    else
    436        mData = tempData;
    437    std::swap(mReservedSize, other.mReservedSize);
    438 
    439    if (uses_fixed_storage() || other.uses_fixed_storage())
    440        std::swap(mFixedStorage, other.mFixedStorage);
    441 }
    442 
    443 template <class T, size_t N, class Storage>
    444 void FastVector<T, N, Storage>::resize(size_type count)
    445 {
    446    if (count > mSize)
    447    {
    448        ensure_capacity(count);
    449    }
    450    mSize = count;
    451 }
    452 
    453 template <class T, size_t N, class Storage>
    454 void FastVector<T, N, Storage>::resize(size_type count, const value_type &value)
    455 {
    456    if (count > mSize)
    457    {
    458        ensure_capacity(count);
    459        std::fill(mData + mSize, mData + count, value);
    460    }
    461    mSize = count;
    462 }
    463 
    464 template <class T, size_t N, class Storage>
    465 void FastVector<T, N, Storage>::reserve(size_type count)
    466 {
    467    ensure_capacity(count);
    468 }
    469 
    470 template <class T, size_t N, class Storage>
    471 void FastVector<T, N, Storage>::assign_from_initializer_list(std::initializer_list<value_type> init)
    472 {
    473    ensure_capacity(init.size());
    474    mSize        = init.size();
    475    size_t index = 0;
    476    for (auto &value : init)
    477    {
    478        mData[index++] = value;
    479    }
    480 }
    481 
    482 template <class T, size_t N, class Storage>
    483 ANGLE_INLINE void FastVector<T, N, Storage>::remove_and_permute(const value_type &element)
    484 {
    485    size_t len = mSize - 1;
    486    for (size_t index = 0; index < len; ++index)
    487    {
    488        if (mData[index] == element)
    489        {
    490            mData[index] = std::move(mData[len]);
    491            break;
    492        }
    493    }
    494    pop_back();
    495 }
    496 
    497 template <class T, size_t N, class Storage>
    498 ANGLE_INLINE void FastVector<T, N, Storage>::remove_and_permute(iterator pos)
    499 {
    500    ASSERT(pos >= begin());
    501    ASSERT(pos < end());
    502    size_t len = mSize - 1;
    503    *pos       = std::move(mData[len]);
    504    pop_back();
    505 }
    506 
    507 template <class T, size_t N, class Storage>
    508 void FastVector<T, N, Storage>::ensure_capacity(size_t capacity)
    509 {
    510    // We have a minimum capacity of N.
    511    if (mReservedSize < capacity)
    512    {
    513        ASSERT(capacity > N);
    514        size_type newSize = std::max(mReservedSize, N);
    515        while (newSize < capacity)
    516        {
    517            newSize *= 2;
    518        }
    519 
    520        pointer newData = new value_type[newSize];
    521 
    522        if (mSize > 0)
    523        {
    524            std::move(begin(), end(), newData);
    525        }
    526 
    527        if (!uses_fixed_storage())
    528        {
    529            delete[] mData;
    530        }
    531 
    532        mData         = newData;
    533        mReservedSize = newSize;
    534    }
    535 }
    536 
    537 template <class Value, size_t N>
    538 class FastMap final
    539 {
    540  public:
    541    FastMap() {}
    542    ~FastMap() {}
    543 
    544    Value &operator[](uint32_t key)
    545    {
    546        if (mData.size() <= key)
    547        {
    548            mData.resize(key + 1, {});
    549        }
    550        return mData[key];
    551    }
    552 
    553    const Value &operator[](uint32_t key) const
    554    {
    555        ASSERT(key < mData.size());
    556        return mData[key];
    557    }
    558 
    559    void clear() { mData.clear(); }
    560 
    561    bool empty() const { return mData.empty(); }
    562    size_t size() const { return mData.size(); }
    563 
    564    const Value *data() const { return mData.data(); }
    565 
    566    bool operator==(const FastMap<Value, N> &other) const
    567    {
    568        return (size() == other.size()) &&
    569               (memcmp(data(), other.data(), size() * sizeof(Value)) == 0);
    570    }
    571 
    572  private:
    573    FastVector<Value, N> mData;
    574 };
    575 
    576 template <class Key, class Value, size_t N>
    577 class FlatUnorderedMap final
    578 {
    579  public:
    580    using Pair           = std::pair<Key, Value>;
    581    using Storage        = FastVector<Pair, N>;
    582    using iterator       = typename Storage::iterator;
    583    using const_iterator = typename Storage::const_iterator;
    584 
    585    FlatUnorderedMap()  = default;
    586    ~FlatUnorderedMap() = default;
    587 
    588    iterator begin() { return mData.begin(); }
    589    const_iterator begin() const { return mData.begin(); }
    590    iterator end() { return mData.end(); }
    591    const_iterator end() const { return mData.end(); }
    592 
    593    iterator find(const Key &key)
    594    {
    595        for (auto it = mData.begin(); it != mData.end(); ++it)
    596        {
    597            if (it->first == key)
    598            {
    599                return it;
    600            }
    601        }
    602        return mData.end();
    603    }
    604 
    605    const_iterator find(const Key &key) const
    606    {
    607        for (auto it = mData.begin(); it != mData.end(); ++it)
    608        {
    609            if (it->first == key)
    610            {
    611                return it;
    612            }
    613        }
    614        return mData.end();
    615    }
    616 
    617    Value &operator[](const Key &key)
    618    {
    619        iterator it = find(key);
    620        if (it != end())
    621        {
    622            return it->second;
    623        }
    624 
    625        mData.push_back(Pair(key, {}));
    626        return mData.back().second;
    627    }
    628 
    629    void insert(Pair pair)
    630    {
    631        ASSERT(!contains(pair.first));
    632        mData.push_back(std::move(pair));
    633    }
    634 
    635    void insert(const Key &key, Value value) { insert(Pair(key, value)); }
    636 
    637    void erase(iterator pos) { mData.remove_and_permute(pos); }
    638 
    639    bool contains(const Key &key) const { return find(key) != end(); }
    640 
    641    void clear() { mData.clear(); }
    642 
    643    bool get(const Key &key, Value *value) const
    644    {
    645        auto it = find(key);
    646        if (it != end())
    647        {
    648            *value = it->second;
    649            return true;
    650        }
    651        return false;
    652    }
    653 
    654    bool empty() const { return mData.empty(); }
    655    size_t size() const { return mData.size(); }
    656 
    657  private:
    658    FastVector<Pair, N> mData;
    659 };
    660 
    661 template <class T, size_t N>
    662 class FlatUnorderedSet final
    663 {
    664  public:
    665    using Storage        = FastVector<T, N>;
    666    using iterator       = typename Storage::iterator;
    667    using const_iterator = typename Storage::const_iterator;
    668 
    669    FlatUnorderedSet()  = default;
    670    ~FlatUnorderedSet() = default;
    671 
    672    iterator begin() { return mData.begin(); }
    673    const_iterator begin() const { return mData.begin(); }
    674    iterator end() { return mData.end(); }
    675    const_iterator end() const { return mData.end(); }
    676 
    677    iterator find(const T &value)
    678    {
    679        for (auto it = mData.begin(); it != mData.end(); ++it)
    680        {
    681            if (*it == value)
    682            {
    683                return it;
    684            }
    685        }
    686        return mData.end();
    687    }
    688 
    689    const_iterator find(const T &value) const
    690    {
    691        for (auto it = mData.begin(); it != mData.end(); ++it)
    692        {
    693            if (*it == value)
    694            {
    695                return it;
    696            }
    697        }
    698        return mData.end();
    699    }
    700 
    701    bool empty() const { return mData.empty(); }
    702 
    703    void insert(const T &value)
    704    {
    705        ASSERT(!contains(value));
    706        mData.push_back(value);
    707    }
    708 
    709    void erase(const T &value)
    710    {
    711        ASSERT(contains(value));
    712        mData.remove_and_permute(value);
    713    }
    714 
    715    void remove(const T &value) { erase(value); }
    716 
    717    bool contains(const T &value) const { return find(value) != end(); }
    718 
    719    void clear() { mData.clear(); }
    720 
    721    bool operator==(const FlatUnorderedSet<T, N> &other) const { return mData == other.mData; }
    722 
    723  private:
    724    Storage mData;
    725 };
    726 
    727 class FastIntegerSet final
    728 {
    729  public:
    730    static constexpr size_t kWindowSize             = 64;
    731    static constexpr size_t kOneLessThanKWindowSize = kWindowSize - 1;
    732    static constexpr size_t kShiftForDivision =
    733        static_cast<size_t>(rx::Log2(static_cast<unsigned int>(kWindowSize)));
    734    using KeyBitSet = angle::BitSet64<kWindowSize>;
    735 
    736    ANGLE_INLINE FastIntegerSet();
    737    ANGLE_INLINE ~FastIntegerSet();
    738 
    739    ANGLE_INLINE void ensureCapacity(size_t size)
    740    {
    741        if (capacity() <= size)
    742        {
    743            reserve(size * 2);
    744        }
    745    }
    746 
    747    ANGLE_INLINE void insert(uint64_t key)
    748    {
    749        size_t sizedKey = static_cast<size_t>(key);
    750 
    751        ASSERT(!contains(sizedKey));
    752        ensureCapacity(sizedKey);
    753        ASSERT(capacity() > sizedKey);
    754 
    755        size_t index  = sizedKey >> kShiftForDivision;
    756        size_t offset = sizedKey & kOneLessThanKWindowSize;
    757 
    758        mKeyData[index].set(offset, true);
    759    }
    760 
    761    ANGLE_INLINE bool contains(uint64_t key) const
    762    {
    763        size_t sizedKey = static_cast<size_t>(key);
    764 
    765        size_t index  = sizedKey >> kShiftForDivision;
    766        size_t offset = sizedKey & kOneLessThanKWindowSize;
    767 
    768        return (sizedKey < capacity()) && (mKeyData[index].test(offset));
    769    }
    770 
    771    ANGLE_INLINE void clear()
    772    {
    773        for (KeyBitSet &it : mKeyData)
    774        {
    775            it.reset();
    776        }
    777    }
    778 
    779    ANGLE_INLINE bool empty() const
    780    {
    781        for (const KeyBitSet &it : mKeyData)
    782        {
    783            if (it.any())
    784            {
    785                return false;
    786            }
    787        }
    788        return true;
    789    }
    790 
    791    ANGLE_INLINE size_t size() const
    792    {
    793        size_t valid_entries = 0;
    794        for (const KeyBitSet &it : mKeyData)
    795        {
    796            valid_entries += it.count();
    797        }
    798        return valid_entries;
    799    }
    800 
    801  private:
    802    ANGLE_INLINE size_t capacity() const { return kWindowSize * mKeyData.size(); }
    803 
    804    ANGLE_INLINE void reserve(size_t newSize)
    805    {
    806        size_t alignedSize = rx::roundUpPow2(newSize, kWindowSize);
    807        size_t count       = alignedSize >> kShiftForDivision;
    808 
    809        mKeyData.resize(count, KeyBitSet::Zero());
    810    }
    811 
    812    std::vector<KeyBitSet> mKeyData;
    813 };
    814 
    815 // This is needed to accommodate the chromium style guide error -
    816 //      [chromium-style] Complex constructor has an inlined body.
    817 ANGLE_INLINE FastIntegerSet::FastIntegerSet() {}
    818 ANGLE_INLINE FastIntegerSet::~FastIntegerSet() {}
    819 
    820 template <typename Value>
    821 class FastIntegerMap final
    822 {
    823  public:
    824    FastIntegerMap() {}
    825    ~FastIntegerMap() {}
    826 
    827    ANGLE_INLINE void ensureCapacity(size_t size)
    828    {
    829        // Ensure key set has capacity
    830        mKeySet.ensureCapacity(size);
    831 
    832        // Ensure value vector has capacity
    833        ensureCapacityImpl(size);
    834    }
    835 
    836    ANGLE_INLINE void insert(uint64_t key, Value value)
    837    {
    838        // Insert key
    839        ASSERT(!mKeySet.contains(key));
    840        mKeySet.insert(key);
    841 
    842        // Insert value
    843        size_t sizedKey = static_cast<size_t>(key);
    844        ensureCapacityImpl(sizedKey);
    845        ASSERT(capacity() > sizedKey);
    846        mValueData[sizedKey] = value;
    847    }
    848 
    849    ANGLE_INLINE bool contains(uint64_t key) const { return mKeySet.contains(key); }
    850 
    851    ANGLE_INLINE bool get(uint64_t key, Value *out) const
    852    {
    853        if (!mKeySet.contains(key))
    854        {
    855            return false;
    856        }
    857 
    858        size_t sizedKey = static_cast<size_t>(key);
    859        *out            = mValueData[sizedKey];
    860        return true;
    861    }
    862 
    863    ANGLE_INLINE void clear() { mKeySet.clear(); }
    864 
    865    ANGLE_INLINE bool empty() const { return mKeySet.empty(); }
    866 
    867    ANGLE_INLINE size_t size() const { return mKeySet.size(); }
    868 
    869  private:
    870    ANGLE_INLINE size_t capacity() const { return mValueData.size(); }
    871 
    872    ANGLE_INLINE void ensureCapacityImpl(size_t size)
    873    {
    874        if (capacity() <= size)
    875        {
    876            reserve(size * 2);
    877        }
    878    }
    879 
    880    ANGLE_INLINE void reserve(size_t newSize)
    881    {
    882        size_t alignedSize = rx::roundUpPow2(newSize, FastIntegerSet::kWindowSize);
    883        mValueData.resize(alignedSize);
    884    }
    885 
    886    FastIntegerSet mKeySet;
    887    std::vector<Value> mValueData;
    888 };
    889 }  // namespace angle
    890 
    891 #endif  // COMMON_FASTVECTOR_H_