tor-browser

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

CircularBuffer.h (5029B)


      1 //
      2 // Copyright 2021 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 // CircularBuffer.h:
      7 //   An array class with an index that loops through the elements.
      8 //
      9 
     10 #ifndef COMMON_CIRCULARBUFFER_H_
     11 #define COMMON_CIRCULARBUFFER_H_
     12 
     13 #include "common/debug.h"
     14 
     15 #include <algorithm>
     16 #include <array>
     17 
     18 namespace angle
     19 {
     20 template <class T, size_t N, class Storage = std::array<T, N>>
     21 class CircularBuffer final
     22 {
     23  public:
     24    using value_type      = typename Storage::value_type;
     25    using size_type       = typename Storage::size_type;
     26    using reference       = typename Storage::reference;
     27    using const_reference = typename Storage::const_reference;
     28    using pointer         = typename Storage::pointer;
     29    using const_pointer   = typename Storage::const_pointer;
     30    using iterator        = typename Storage::iterator;
     31    using const_iterator  = typename Storage::const_iterator;
     32 
     33    CircularBuffer();
     34    CircularBuffer(const value_type &value);
     35 
     36    CircularBuffer(const CircularBuffer<T, N, Storage> &other);
     37    CircularBuffer(CircularBuffer<T, N, Storage> &&other);
     38 
     39    CircularBuffer<T, N, Storage> &operator=(const CircularBuffer<T, N, Storage> &other);
     40    CircularBuffer<T, N, Storage> &operator=(CircularBuffer<T, N, Storage> &&other);
     41 
     42    ~CircularBuffer();
     43 
     44    // begin() and end() are used to iterate over all elements regardless of the current position of
     45    // the front of the buffer.  Useful for initialization and clean up, as otherwise only the front
     46    // element is expected to be accessed.
     47    iterator begin();
     48    const_iterator begin() const;
     49 
     50    iterator end();
     51    const_iterator end() const;
     52 
     53    size_type size() const;
     54 
     55    reference front();
     56    const_reference front() const;
     57 
     58    void swap(CircularBuffer<T, N, Storage> &other);
     59 
     60    // Move the front forward to the next index, looping back to the beginning if the end of the
     61    // array is reached.
     62    void next();
     63 
     64  private:
     65    Storage mData;
     66    size_type mFrontIndex;
     67 };
     68 
     69 template <class T, size_t N, class Storage>
     70 CircularBuffer<T, N, Storage>::CircularBuffer() : mFrontIndex(0)
     71 {}
     72 
     73 template <class T, size_t N, class Storage>
     74 CircularBuffer<T, N, Storage>::CircularBuffer(const value_type &value) : CircularBuffer()
     75 {
     76    std::fill(begin(), end(), value);
     77 }
     78 
     79 template <class T, size_t N, class Storage>
     80 CircularBuffer<T, N, Storage>::CircularBuffer(const CircularBuffer<T, N, Storage> &other)
     81 {
     82    *this = other;
     83 }
     84 
     85 template <class T, size_t N, class Storage>
     86 CircularBuffer<T, N, Storage>::CircularBuffer(CircularBuffer<T, N, Storage> &&other)
     87    : CircularBuffer()
     88 {
     89    swap(other);
     90 }
     91 
     92 template <class T, size_t N, class Storage>
     93 CircularBuffer<T, N, Storage> &CircularBuffer<T, N, Storage>::operator=(
     94    const CircularBuffer<T, N, Storage> &other)
     95 {
     96    std::copy(other.begin(), other.end(), begin());
     97    mFrontIndex = other.mFrontIndex;
     98    return *this;
     99 }
    100 
    101 template <class T, size_t N, class Storage>
    102 CircularBuffer<T, N, Storage> &CircularBuffer<T, N, Storage>::operator=(
    103    CircularBuffer<T, N, Storage> &&other)
    104 {
    105    swap(other);
    106    return *this;
    107 }
    108 
    109 template <class T, size_t N, class Storage>
    110 CircularBuffer<T, N, Storage>::~CircularBuffer() = default;
    111 
    112 template <class T, size_t N, class Storage>
    113 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::iterator CircularBuffer<T, N, Storage>::begin()
    114 {
    115    return mData.begin();
    116 }
    117 
    118 template <class T, size_t N, class Storage>
    119 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_iterator
    120 CircularBuffer<T, N, Storage>::begin() const
    121 {
    122    return mData.begin();
    123 }
    124 
    125 template <class T, size_t N, class Storage>
    126 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::iterator CircularBuffer<T, N, Storage>::end()
    127 {
    128    return mData.end();
    129 }
    130 
    131 template <class T, size_t N, class Storage>
    132 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_iterator
    133 CircularBuffer<T, N, Storage>::end() const
    134 {
    135    return mData.end();
    136 }
    137 
    138 template <class T, size_t N, class Storage>
    139 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::size_type CircularBuffer<T, N, Storage>::size()
    140    const
    141 {
    142    return N;
    143 }
    144 
    145 template <class T, size_t N, class Storage>
    146 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::reference
    147 CircularBuffer<T, N, Storage>::front()
    148 {
    149    ASSERT(mFrontIndex < size());
    150    return mData[mFrontIndex];
    151 }
    152 
    153 template <class T, size_t N, class Storage>
    154 ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_reference
    155 CircularBuffer<T, N, Storage>::front() const
    156 {
    157    ASSERT(mFrontIndex < size());
    158    return mData[mFrontIndex];
    159 }
    160 
    161 template <class T, size_t N, class Storage>
    162 void CircularBuffer<T, N, Storage>::swap(CircularBuffer<T, N, Storage> &other)
    163 {
    164    std::swap(mData, other.mData);
    165    std::swap(mFrontIndex, other.mFrontIndex);
    166 }
    167 
    168 template <class T, size_t N, class Storage>
    169 void CircularBuffer<T, N, Storage>::next()
    170 {
    171    mFrontIndex = (mFrontIndex + 1) % size();
    172 }
    173 }  // namespace angle
    174 
    175 #endif  // COMMON_CIRCULARBUFFER_H_