16d528ed9Sopenharmony_ci// Copyright 2017 The Chromium Authors. All rights reserved.
26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
36d528ed9Sopenharmony_ci// found in the LICENSE file.
46d528ed9Sopenharmony_ci
56d528ed9Sopenharmony_ci#ifndef BASE_CONTAINERS_CIRCULAR_DEQUE_H_
66d528ed9Sopenharmony_ci#define BASE_CONTAINERS_CIRCULAR_DEQUE_H_
76d528ed9Sopenharmony_ci
86d528ed9Sopenharmony_ci#include <algorithm>
96d528ed9Sopenharmony_ci#include <cstddef>
106d528ed9Sopenharmony_ci#include <iterator>
116d528ed9Sopenharmony_ci#include <type_traits>
126d528ed9Sopenharmony_ci#include <utility>
136d528ed9Sopenharmony_ci
146d528ed9Sopenharmony_ci#include "base/containers/vector_buffer.h"
156d528ed9Sopenharmony_ci#include "base/logging.h"
166d528ed9Sopenharmony_ci#include "base/template_util.h"
176d528ed9Sopenharmony_ci
186d528ed9Sopenharmony_ci// base::circular_deque is similar to std::deque. Unlike std::deque, the
196d528ed9Sopenharmony_ci// storage is provided in a flat circular buffer conceptually similar to a
206d528ed9Sopenharmony_ci// vector. The beginning and end will wrap around as necessary so that
216d528ed9Sopenharmony_ci// pushes and pops will be constant time as long as a capacity expansion is
226d528ed9Sopenharmony_ci// not required.
236d528ed9Sopenharmony_ci//
246d528ed9Sopenharmony_ci// The API should be identical to std::deque with the following differences:
256d528ed9Sopenharmony_ci//
266d528ed9Sopenharmony_ci//  - ITERATORS ARE NOT STABLE. Mutating the container will invalidate all
276d528ed9Sopenharmony_ci//    iterators.
286d528ed9Sopenharmony_ci//
296d528ed9Sopenharmony_ci//  - Insertions may resize the vector and so are not constant time (std::deque
306d528ed9Sopenharmony_ci//    guarantees constant time for insertions at the ends).
316d528ed9Sopenharmony_ci//
326d528ed9Sopenharmony_ci//  - Container-wide comparisons are not implemented. If you want to compare
336d528ed9Sopenharmony_ci//    two containers, use an algorithm so the expensive iteration is explicit.
346d528ed9Sopenharmony_ci//
356d528ed9Sopenharmony_ci// If you want a similar container with only a queue API, use base::queue in
366d528ed9Sopenharmony_ci// base/containers/queue.h.
376d528ed9Sopenharmony_ci//
386d528ed9Sopenharmony_ci// Constructors:
396d528ed9Sopenharmony_ci//   circular_deque();
406d528ed9Sopenharmony_ci//   circular_deque(size_t count);
416d528ed9Sopenharmony_ci//   circular_deque(size_t count, const T& value);
426d528ed9Sopenharmony_ci//   circular_deque(InputIterator first, InputIterator last);
436d528ed9Sopenharmony_ci//   circular_deque(const circular_deque&);
446d528ed9Sopenharmony_ci//   circular_deque(circular_deque&&);
456d528ed9Sopenharmony_ci//   circular_deque(std::initializer_list<value_type>);
466d528ed9Sopenharmony_ci//
476d528ed9Sopenharmony_ci// Assignment functions:
486d528ed9Sopenharmony_ci//   circular_deque& operator=(const circular_deque&);
496d528ed9Sopenharmony_ci//   circular_deque& operator=(circular_deque&&);
506d528ed9Sopenharmony_ci//   circular_deque& operator=(std::initializer_list<T>);
516d528ed9Sopenharmony_ci//   void assign(size_t count, const T& value);
526d528ed9Sopenharmony_ci//   void assign(InputIterator first, InputIterator last);
536d528ed9Sopenharmony_ci//   void assign(std::initializer_list<T> value);
546d528ed9Sopenharmony_ci//
556d528ed9Sopenharmony_ci// Random accessors:
566d528ed9Sopenharmony_ci//   T& at(size_t);
576d528ed9Sopenharmony_ci//   const T& at(size_t) const;
586d528ed9Sopenharmony_ci//   T& operator[](size_t);
596d528ed9Sopenharmony_ci//   const T& operator[](size_t) const;
606d528ed9Sopenharmony_ci//
616d528ed9Sopenharmony_ci// End accessors:
626d528ed9Sopenharmony_ci//   T& front();
636d528ed9Sopenharmony_ci//   const T& front() const;
646d528ed9Sopenharmony_ci//   T& back();
656d528ed9Sopenharmony_ci//   const T& back() const;
666d528ed9Sopenharmony_ci//
676d528ed9Sopenharmony_ci// Iterator functions:
686d528ed9Sopenharmony_ci//   iterator               begin();
696d528ed9Sopenharmony_ci//   const_iterator         begin() const;
706d528ed9Sopenharmony_ci//   const_iterator         cbegin() const;
716d528ed9Sopenharmony_ci//   iterator               end();
726d528ed9Sopenharmony_ci//   const_iterator         end() const;
736d528ed9Sopenharmony_ci//   const_iterator         cend() const;
746d528ed9Sopenharmony_ci//   reverse_iterator       rbegin();
756d528ed9Sopenharmony_ci//   const_reverse_iterator rbegin() const;
766d528ed9Sopenharmony_ci//   const_reverse_iterator crbegin() const;
776d528ed9Sopenharmony_ci//   reverse_iterator       rend();
786d528ed9Sopenharmony_ci//   const_reverse_iterator rend() const;
796d528ed9Sopenharmony_ci//   const_reverse_iterator crend() const;
806d528ed9Sopenharmony_ci//
816d528ed9Sopenharmony_ci// Memory management:
826d528ed9Sopenharmony_ci//   void reserve(size_t);  // SEE IMPLEMENTATION FOR SOME GOTCHAS.
836d528ed9Sopenharmony_ci//   size_t capacity() const;
846d528ed9Sopenharmony_ci//   void shrink_to_fit();
856d528ed9Sopenharmony_ci//
866d528ed9Sopenharmony_ci// Size management:
876d528ed9Sopenharmony_ci//   void clear();
886d528ed9Sopenharmony_ci//   bool empty() const;
896d528ed9Sopenharmony_ci//   size_t size() const;
906d528ed9Sopenharmony_ci//   void resize(size_t);
916d528ed9Sopenharmony_ci//   void resize(size_t count, const T& value);
926d528ed9Sopenharmony_ci//
936d528ed9Sopenharmony_ci// Positional insert and erase:
946d528ed9Sopenharmony_ci//   void insert(const_iterator pos, size_type count, const T& value);
956d528ed9Sopenharmony_ci//   void insert(const_iterator pos,
966d528ed9Sopenharmony_ci//               InputIterator first, InputIterator last);
976d528ed9Sopenharmony_ci//   iterator insert(const_iterator pos, const T& value);
986d528ed9Sopenharmony_ci//   iterator insert(const_iterator pos, T&& value);
996d528ed9Sopenharmony_ci//   iterator emplace(const_iterator pos, Args&&... args);
1006d528ed9Sopenharmony_ci//   iterator erase(const_iterator pos);
1016d528ed9Sopenharmony_ci//   iterator erase(const_iterator first, const_iterator last);
1026d528ed9Sopenharmony_ci//
1036d528ed9Sopenharmony_ci// End insert and erase:
1046d528ed9Sopenharmony_ci//   void push_front(const T&);
1056d528ed9Sopenharmony_ci//   void push_front(T&&);
1066d528ed9Sopenharmony_ci//   void push_back(const T&);
1076d528ed9Sopenharmony_ci//   void push_back(T&&);
1086d528ed9Sopenharmony_ci//   T& emplace_front(Args&&...);
1096d528ed9Sopenharmony_ci//   T& emplace_back(Args&&...);
1106d528ed9Sopenharmony_ci//   void pop_front();
1116d528ed9Sopenharmony_ci//   void pop_back();
1126d528ed9Sopenharmony_ci//
1136d528ed9Sopenharmony_ci// General:
1146d528ed9Sopenharmony_ci//   void swap(circular_deque&);
1156d528ed9Sopenharmony_ci
1166d528ed9Sopenharmony_cinamespace base {
1176d528ed9Sopenharmony_ci
1186d528ed9Sopenharmony_citemplate <class T>
1196d528ed9Sopenharmony_ciclass circular_deque;
1206d528ed9Sopenharmony_ci
1216d528ed9Sopenharmony_cinamespace internal {
1226d528ed9Sopenharmony_ci
1236d528ed9Sopenharmony_ci// Start allocating nonempty buffers with this many entries. This is the
1246d528ed9Sopenharmony_ci// external capacity so the internal buffer will be one larger (= 4) which is
1256d528ed9Sopenharmony_ci// more even for the allocator. See the descriptions of internal vs. external
1266d528ed9Sopenharmony_ci// capacity on the comment above the buffer_ variable below.
1276d528ed9Sopenharmony_ciconstexpr size_t kCircularBufferInitialCapacity = 3;
1286d528ed9Sopenharmony_ci
1296d528ed9Sopenharmony_citemplate <typename T>
1306d528ed9Sopenharmony_ciclass circular_deque_const_iterator {
1316d528ed9Sopenharmony_ci public:
1326d528ed9Sopenharmony_ci  using difference_type = std::ptrdiff_t;
1336d528ed9Sopenharmony_ci  using value_type = T;
1346d528ed9Sopenharmony_ci  using pointer = const T*;
1356d528ed9Sopenharmony_ci  using reference = const T&;
1366d528ed9Sopenharmony_ci  using iterator_category = std::random_access_iterator_tag;
1376d528ed9Sopenharmony_ci
1386d528ed9Sopenharmony_ci  circular_deque_const_iterator() : parent_deque_(nullptr), index_(0) {
1396d528ed9Sopenharmony_ci#if DCHECK_IS_ON()
1406d528ed9Sopenharmony_ci    created_generation_ = 0;
1416d528ed9Sopenharmony_ci#endif  // DCHECK_IS_ON()
1426d528ed9Sopenharmony_ci  }
1436d528ed9Sopenharmony_ci
1446d528ed9Sopenharmony_ci  // Dereferencing.
1456d528ed9Sopenharmony_ci  const T& operator*() const {
1466d528ed9Sopenharmony_ci    CheckUnstableUsage();
1476d528ed9Sopenharmony_ci    parent_deque_->CheckValidIndex(index_);
1486d528ed9Sopenharmony_ci    return parent_deque_->buffer_[index_];
1496d528ed9Sopenharmony_ci  }
1506d528ed9Sopenharmony_ci  const T* operator->() const {
1516d528ed9Sopenharmony_ci    CheckUnstableUsage();
1526d528ed9Sopenharmony_ci    parent_deque_->CheckValidIndex(index_);
1536d528ed9Sopenharmony_ci    return &parent_deque_->buffer_[index_];
1546d528ed9Sopenharmony_ci  }
1556d528ed9Sopenharmony_ci  const value_type& operator[](difference_type i) const { return *(*this + i); }
1566d528ed9Sopenharmony_ci
1576d528ed9Sopenharmony_ci  // Increment and decrement.
1586d528ed9Sopenharmony_ci  circular_deque_const_iterator& operator++() {
1596d528ed9Sopenharmony_ci    Increment();
1606d528ed9Sopenharmony_ci    return *this;
1616d528ed9Sopenharmony_ci  }
1626d528ed9Sopenharmony_ci  circular_deque_const_iterator operator++(int) {
1636d528ed9Sopenharmony_ci    circular_deque_const_iterator ret = *this;
1646d528ed9Sopenharmony_ci    Increment();
1656d528ed9Sopenharmony_ci    return ret;
1666d528ed9Sopenharmony_ci  }
1676d528ed9Sopenharmony_ci  circular_deque_const_iterator& operator--() {
1686d528ed9Sopenharmony_ci    Decrement();
1696d528ed9Sopenharmony_ci    return *this;
1706d528ed9Sopenharmony_ci  }
1716d528ed9Sopenharmony_ci  circular_deque_const_iterator operator--(int) {
1726d528ed9Sopenharmony_ci    circular_deque_const_iterator ret = *this;
1736d528ed9Sopenharmony_ci    Decrement();
1746d528ed9Sopenharmony_ci    return ret;
1756d528ed9Sopenharmony_ci  }
1766d528ed9Sopenharmony_ci
1776d528ed9Sopenharmony_ci  // Random access mutation.
1786d528ed9Sopenharmony_ci  friend circular_deque_const_iterator operator+(
1796d528ed9Sopenharmony_ci      const circular_deque_const_iterator& iter,
1806d528ed9Sopenharmony_ci      difference_type offset) {
1816d528ed9Sopenharmony_ci    circular_deque_const_iterator ret = iter;
1826d528ed9Sopenharmony_ci    ret.Add(offset);
1836d528ed9Sopenharmony_ci    return ret;
1846d528ed9Sopenharmony_ci  }
1856d528ed9Sopenharmony_ci  circular_deque_const_iterator& operator+=(difference_type offset) {
1866d528ed9Sopenharmony_ci    Add(offset);
1876d528ed9Sopenharmony_ci    return *this;
1886d528ed9Sopenharmony_ci  }
1896d528ed9Sopenharmony_ci  friend circular_deque_const_iterator operator-(
1906d528ed9Sopenharmony_ci      const circular_deque_const_iterator& iter,
1916d528ed9Sopenharmony_ci      difference_type offset) {
1926d528ed9Sopenharmony_ci    circular_deque_const_iterator ret = iter;
1936d528ed9Sopenharmony_ci    ret.Add(-offset);
1946d528ed9Sopenharmony_ci    return ret;
1956d528ed9Sopenharmony_ci  }
1966d528ed9Sopenharmony_ci  circular_deque_const_iterator& operator-=(difference_type offset) {
1976d528ed9Sopenharmony_ci    Add(-offset);
1986d528ed9Sopenharmony_ci    return *this;
1996d528ed9Sopenharmony_ci  }
2006d528ed9Sopenharmony_ci
2016d528ed9Sopenharmony_ci  friend std::ptrdiff_t operator-(const circular_deque_const_iterator& lhs,
2026d528ed9Sopenharmony_ci                                  const circular_deque_const_iterator& rhs) {
2036d528ed9Sopenharmony_ci    lhs.CheckComparable(rhs);
2046d528ed9Sopenharmony_ci    return lhs.OffsetFromBegin() - rhs.OffsetFromBegin();
2056d528ed9Sopenharmony_ci  }
2066d528ed9Sopenharmony_ci
2076d528ed9Sopenharmony_ci  // Comparisons.
2086d528ed9Sopenharmony_ci  friend bool operator==(const circular_deque_const_iterator& lhs,
2096d528ed9Sopenharmony_ci                         const circular_deque_const_iterator& rhs) {
2106d528ed9Sopenharmony_ci    lhs.CheckComparable(rhs);
2116d528ed9Sopenharmony_ci    return lhs.index_ == rhs.index_;
2126d528ed9Sopenharmony_ci  }
2136d528ed9Sopenharmony_ci  friend bool operator!=(const circular_deque_const_iterator& lhs,
2146d528ed9Sopenharmony_ci                         const circular_deque_const_iterator& rhs) {
2156d528ed9Sopenharmony_ci    return !(lhs == rhs);
2166d528ed9Sopenharmony_ci  }
2176d528ed9Sopenharmony_ci  friend bool operator<(const circular_deque_const_iterator& lhs,
2186d528ed9Sopenharmony_ci                        const circular_deque_const_iterator& rhs) {
2196d528ed9Sopenharmony_ci    lhs.CheckComparable(rhs);
2206d528ed9Sopenharmony_ci    return lhs.OffsetFromBegin() < rhs.OffsetFromBegin();
2216d528ed9Sopenharmony_ci  }
2226d528ed9Sopenharmony_ci  friend bool operator<=(const circular_deque_const_iterator& lhs,
2236d528ed9Sopenharmony_ci                         const circular_deque_const_iterator& rhs) {
2246d528ed9Sopenharmony_ci    return !(lhs > rhs);
2256d528ed9Sopenharmony_ci  }
2266d528ed9Sopenharmony_ci  friend bool operator>(const circular_deque_const_iterator& lhs,
2276d528ed9Sopenharmony_ci                        const circular_deque_const_iterator& rhs) {
2286d528ed9Sopenharmony_ci    lhs.CheckComparable(rhs);
2296d528ed9Sopenharmony_ci    return lhs.OffsetFromBegin() > rhs.OffsetFromBegin();
2306d528ed9Sopenharmony_ci  }
2316d528ed9Sopenharmony_ci  friend bool operator>=(const circular_deque_const_iterator& lhs,
2326d528ed9Sopenharmony_ci                         const circular_deque_const_iterator& rhs) {
2336d528ed9Sopenharmony_ci    return !(lhs < rhs);
2346d528ed9Sopenharmony_ci  }
2356d528ed9Sopenharmony_ci
2366d528ed9Sopenharmony_ci protected:
2376d528ed9Sopenharmony_ci  friend class circular_deque<T>;
2386d528ed9Sopenharmony_ci
2396d528ed9Sopenharmony_ci  circular_deque_const_iterator(const circular_deque<T>* parent, size_t index)
2406d528ed9Sopenharmony_ci      : parent_deque_(parent), index_(index) {
2416d528ed9Sopenharmony_ci#if DCHECK_IS_ON()
2426d528ed9Sopenharmony_ci    created_generation_ = parent->generation_;
2436d528ed9Sopenharmony_ci#endif  // DCHECK_IS_ON()
2446d528ed9Sopenharmony_ci  }
2456d528ed9Sopenharmony_ci
2466d528ed9Sopenharmony_ci  // Returns the offset from the beginning index of the buffer to the current
2476d528ed9Sopenharmony_ci  // item.
2486d528ed9Sopenharmony_ci  size_t OffsetFromBegin() const {
2496d528ed9Sopenharmony_ci    if (index_ >= parent_deque_->begin_)
2506d528ed9Sopenharmony_ci      return index_ - parent_deque_->begin_;  // On the same side as begin.
2516d528ed9Sopenharmony_ci    return parent_deque_->buffer_.capacity() - parent_deque_->begin_ + index_;
2526d528ed9Sopenharmony_ci  }
2536d528ed9Sopenharmony_ci
2546d528ed9Sopenharmony_ci  // Most uses will be ++ and -- so use a simplified implementation.
2556d528ed9Sopenharmony_ci  void Increment() {
2566d528ed9Sopenharmony_ci    CheckUnstableUsage();
2576d528ed9Sopenharmony_ci    parent_deque_->CheckValidIndex(index_);
2586d528ed9Sopenharmony_ci    index_++;
2596d528ed9Sopenharmony_ci    if (index_ == parent_deque_->buffer_.capacity())
2606d528ed9Sopenharmony_ci      index_ = 0;
2616d528ed9Sopenharmony_ci  }
2626d528ed9Sopenharmony_ci  void Decrement() {
2636d528ed9Sopenharmony_ci    CheckUnstableUsage();
2646d528ed9Sopenharmony_ci    parent_deque_->CheckValidIndexOrEnd(index_);
2656d528ed9Sopenharmony_ci    if (index_ == 0)
2666d528ed9Sopenharmony_ci      index_ = parent_deque_->buffer_.capacity() - 1;
2676d528ed9Sopenharmony_ci    else
2686d528ed9Sopenharmony_ci      index_--;
2696d528ed9Sopenharmony_ci  }
2706d528ed9Sopenharmony_ci  void Add(difference_type delta) {
2716d528ed9Sopenharmony_ci    CheckUnstableUsage();
2726d528ed9Sopenharmony_ci#if DCHECK_IS_ON()
2736d528ed9Sopenharmony_ci    if (delta <= 0)
2746d528ed9Sopenharmony_ci      parent_deque_->CheckValidIndexOrEnd(index_);
2756d528ed9Sopenharmony_ci    else
2766d528ed9Sopenharmony_ci      parent_deque_->CheckValidIndex(index_);
2776d528ed9Sopenharmony_ci#endif
2786d528ed9Sopenharmony_ci    // It should be valid to add 0 to any iterator, even if the container is
2796d528ed9Sopenharmony_ci    // empty and the iterator points to end(). The modulo below will divide
2806d528ed9Sopenharmony_ci    // by 0 if the buffer capacity is empty, so it's important to check for
2816d528ed9Sopenharmony_ci    // this case explicitly.
2826d528ed9Sopenharmony_ci    if (delta == 0)
2836d528ed9Sopenharmony_ci      return;
2846d528ed9Sopenharmony_ci
2856d528ed9Sopenharmony_ci    difference_type new_offset = OffsetFromBegin() + delta;
2866d528ed9Sopenharmony_ci    DCHECK(new_offset >= 0 &&
2876d528ed9Sopenharmony_ci           new_offset <= static_cast<difference_type>(parent_deque_->size()));
2886d528ed9Sopenharmony_ci    index_ = (new_offset + parent_deque_->begin_) %
2896d528ed9Sopenharmony_ci             parent_deque_->buffer_.capacity();
2906d528ed9Sopenharmony_ci  }
2916d528ed9Sopenharmony_ci
2926d528ed9Sopenharmony_ci#if DCHECK_IS_ON()
2936d528ed9Sopenharmony_ci  void CheckUnstableUsage() const {
2946d528ed9Sopenharmony_ci    DCHECK(parent_deque_);
2956d528ed9Sopenharmony_ci    // Since circular_deque doesn't guarantee stability, any attempt to
2966d528ed9Sopenharmony_ci    // dereference this iterator after a mutation (i.e. the generation doesn't
2976d528ed9Sopenharmony_ci    // match the original) in the container is illegal.
2986d528ed9Sopenharmony_ci    DCHECK_EQ(created_generation_, parent_deque_->generation_)
2996d528ed9Sopenharmony_ci        << "circular_deque iterator dereferenced after mutation.";
3006d528ed9Sopenharmony_ci  }
3016d528ed9Sopenharmony_ci  void CheckComparable(const circular_deque_const_iterator& other) const {
3026d528ed9Sopenharmony_ci    DCHECK_EQ(parent_deque_, other.parent_deque_);
3036d528ed9Sopenharmony_ci    // Since circular_deque doesn't guarantee stability, two iterators that
3046d528ed9Sopenharmony_ci    // are compared must have been generated without mutating the container.
3056d528ed9Sopenharmony_ci    // If this fires, the container was mutated between generating the two
3066d528ed9Sopenharmony_ci    // iterators being compared.
3076d528ed9Sopenharmony_ci    DCHECK_EQ(created_generation_, other.created_generation_);
3086d528ed9Sopenharmony_ci  }
3096d528ed9Sopenharmony_ci#else
3106d528ed9Sopenharmony_ci  inline void CheckUnstableUsage() const {}
3116d528ed9Sopenharmony_ci  inline void CheckComparable(const circular_deque_const_iterator&) const {}
3126d528ed9Sopenharmony_ci#endif  // DCHECK_IS_ON()
3136d528ed9Sopenharmony_ci
3146d528ed9Sopenharmony_ci  const circular_deque<T>* parent_deque_;
3156d528ed9Sopenharmony_ci  size_t index_;
3166d528ed9Sopenharmony_ci
3176d528ed9Sopenharmony_ci#if DCHECK_IS_ON()
3186d528ed9Sopenharmony_ci  // The generation of the parent deque when this iterator was created. The
3196d528ed9Sopenharmony_ci  // container will update the generation for every modification so we can
3206d528ed9Sopenharmony_ci  // test if the container was modified by comparing them.
3216d528ed9Sopenharmony_ci  uint64_t created_generation_;
3226d528ed9Sopenharmony_ci#endif  // DCHECK_IS_ON()
3236d528ed9Sopenharmony_ci};
3246d528ed9Sopenharmony_ci
3256d528ed9Sopenharmony_citemplate <typename T>
3266d528ed9Sopenharmony_ciclass circular_deque_iterator : public circular_deque_const_iterator<T> {
3276d528ed9Sopenharmony_ci  using base = circular_deque_const_iterator<T>;
3286d528ed9Sopenharmony_ci
3296d528ed9Sopenharmony_ci public:
3306d528ed9Sopenharmony_ci  friend class circular_deque<T>;
3316d528ed9Sopenharmony_ci
3326d528ed9Sopenharmony_ci  using difference_type = std::ptrdiff_t;
3336d528ed9Sopenharmony_ci  using value_type = T;
3346d528ed9Sopenharmony_ci  using pointer = T*;
3356d528ed9Sopenharmony_ci  using reference = T&;
3366d528ed9Sopenharmony_ci  using iterator_category = std::random_access_iterator_tag;
3376d528ed9Sopenharmony_ci
3386d528ed9Sopenharmony_ci  // Expose the base class' constructor.
3396d528ed9Sopenharmony_ci  circular_deque_iterator() : circular_deque_const_iterator<T>() {}
3406d528ed9Sopenharmony_ci
3416d528ed9Sopenharmony_ci  // Dereferencing.
3426d528ed9Sopenharmony_ci  T& operator*() const { return const_cast<T&>(base::operator*()); }
3436d528ed9Sopenharmony_ci  T* operator->() const { return const_cast<T*>(base::operator->()); }
3446d528ed9Sopenharmony_ci  T& operator[](difference_type i) {
3456d528ed9Sopenharmony_ci    return const_cast<T&>(base::operator[](i));
3466d528ed9Sopenharmony_ci  }
3476d528ed9Sopenharmony_ci
3486d528ed9Sopenharmony_ci  // Random access mutation.
3496d528ed9Sopenharmony_ci  friend circular_deque_iterator operator+(const circular_deque_iterator& iter,
3506d528ed9Sopenharmony_ci                                           difference_type offset) {
3516d528ed9Sopenharmony_ci    circular_deque_iterator ret = iter;
3526d528ed9Sopenharmony_ci    ret.Add(offset);
3536d528ed9Sopenharmony_ci    return ret;
3546d528ed9Sopenharmony_ci  }
3556d528ed9Sopenharmony_ci  circular_deque_iterator& operator+=(difference_type offset) {
3566d528ed9Sopenharmony_ci    base::Add(offset);
3576d528ed9Sopenharmony_ci    return *this;
3586d528ed9Sopenharmony_ci  }
3596d528ed9Sopenharmony_ci  friend circular_deque_iterator operator-(const circular_deque_iterator& iter,
3606d528ed9Sopenharmony_ci                                           difference_type offset) {
3616d528ed9Sopenharmony_ci    circular_deque_iterator ret = iter;
3626d528ed9Sopenharmony_ci    ret.Add(-offset);
3636d528ed9Sopenharmony_ci    return ret;
3646d528ed9Sopenharmony_ci  }
3656d528ed9Sopenharmony_ci  circular_deque_iterator& operator-=(difference_type offset) {
3666d528ed9Sopenharmony_ci    base::Add(-offset);
3676d528ed9Sopenharmony_ci    return *this;
3686d528ed9Sopenharmony_ci  }
3696d528ed9Sopenharmony_ci
3706d528ed9Sopenharmony_ci  // Increment and decrement.
3716d528ed9Sopenharmony_ci  circular_deque_iterator& operator++() {
3726d528ed9Sopenharmony_ci    base::Increment();
3736d528ed9Sopenharmony_ci    return *this;
3746d528ed9Sopenharmony_ci  }
3756d528ed9Sopenharmony_ci  circular_deque_iterator operator++(int) {
3766d528ed9Sopenharmony_ci    circular_deque_iterator ret = *this;
3776d528ed9Sopenharmony_ci    base::Increment();
3786d528ed9Sopenharmony_ci    return ret;
3796d528ed9Sopenharmony_ci  }
3806d528ed9Sopenharmony_ci  circular_deque_iterator& operator--() {
3816d528ed9Sopenharmony_ci    base::Decrement();
3826d528ed9Sopenharmony_ci    return *this;
3836d528ed9Sopenharmony_ci  }
3846d528ed9Sopenharmony_ci  circular_deque_iterator operator--(int) {
3856d528ed9Sopenharmony_ci    circular_deque_iterator ret = *this;
3866d528ed9Sopenharmony_ci    base::Decrement();
3876d528ed9Sopenharmony_ci    return ret;
3886d528ed9Sopenharmony_ci  }
3896d528ed9Sopenharmony_ci
3906d528ed9Sopenharmony_ci private:
3916d528ed9Sopenharmony_ci  circular_deque_iterator(const circular_deque<T>* parent, size_t index)
3926d528ed9Sopenharmony_ci      : circular_deque_const_iterator<T>(parent, index) {}
3936d528ed9Sopenharmony_ci};
3946d528ed9Sopenharmony_ci
3956d528ed9Sopenharmony_ci}  // namespace internal
3966d528ed9Sopenharmony_ci
3976d528ed9Sopenharmony_citemplate <typename T>
3986d528ed9Sopenharmony_ciclass circular_deque {
3996d528ed9Sopenharmony_ci private:
4006d528ed9Sopenharmony_ci  using VectorBuffer = internal::VectorBuffer<T>;
4016d528ed9Sopenharmony_ci
4026d528ed9Sopenharmony_ci public:
4036d528ed9Sopenharmony_ci  using value_type = T;
4046d528ed9Sopenharmony_ci  using size_type = std::size_t;
4056d528ed9Sopenharmony_ci  using difference_type = std::ptrdiff_t;
4066d528ed9Sopenharmony_ci  using reference = value_type&;
4076d528ed9Sopenharmony_ci  using const_reference = const value_type&;
4086d528ed9Sopenharmony_ci  using pointer = value_type*;
4096d528ed9Sopenharmony_ci  using const_pointer = const value_type*;
4106d528ed9Sopenharmony_ci
4116d528ed9Sopenharmony_ci  using iterator = internal::circular_deque_iterator<T>;
4126d528ed9Sopenharmony_ci  using const_iterator = internal::circular_deque_const_iterator<T>;
4136d528ed9Sopenharmony_ci  using reverse_iterator = std::reverse_iterator<iterator>;
4146d528ed9Sopenharmony_ci  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
4156d528ed9Sopenharmony_ci
4166d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
4176d528ed9Sopenharmony_ci  // Constructor
4186d528ed9Sopenharmony_ci
4196d528ed9Sopenharmony_ci  constexpr circular_deque() = default;
4206d528ed9Sopenharmony_ci
4216d528ed9Sopenharmony_ci  // Constructs with |count| copies of |value| or default constructed version.
4226d528ed9Sopenharmony_ci  circular_deque(size_type count) { resize(count); }
4236d528ed9Sopenharmony_ci  circular_deque(size_type count, const T& value) { resize(count, value); }
4246d528ed9Sopenharmony_ci
4256d528ed9Sopenharmony_ci  // Range constructor.
4266d528ed9Sopenharmony_ci  template <class InputIterator>
4276d528ed9Sopenharmony_ci  circular_deque(InputIterator first, InputIterator last) {
4286d528ed9Sopenharmony_ci    assign(first, last);
4296d528ed9Sopenharmony_ci  }
4306d528ed9Sopenharmony_ci
4316d528ed9Sopenharmony_ci  // Copy/move.
4326d528ed9Sopenharmony_ci  circular_deque(const circular_deque& other) : buffer_(other.size() + 1) {
4336d528ed9Sopenharmony_ci    assign(other.begin(), other.end());
4346d528ed9Sopenharmony_ci  }
4356d528ed9Sopenharmony_ci  circular_deque(circular_deque&& other) noexcept
4366d528ed9Sopenharmony_ci      : buffer_(std::move(other.buffer_)),
4376d528ed9Sopenharmony_ci        begin_(other.begin_),
4386d528ed9Sopenharmony_ci        end_(other.end_) {
4396d528ed9Sopenharmony_ci    other.begin_ = 0;
4406d528ed9Sopenharmony_ci    other.end_ = 0;
4416d528ed9Sopenharmony_ci  }
4426d528ed9Sopenharmony_ci
4436d528ed9Sopenharmony_ci  circular_deque(std::initializer_list<value_type> init) { assign(init); }
4446d528ed9Sopenharmony_ci
4456d528ed9Sopenharmony_ci  ~circular_deque() { DestructRange(begin_, end_); }
4466d528ed9Sopenharmony_ci
4476d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
4486d528ed9Sopenharmony_ci  // Assignments.
4496d528ed9Sopenharmony_ci  //
4506d528ed9Sopenharmony_ci  // All of these may invalidate iterators and references.
4516d528ed9Sopenharmony_ci
4526d528ed9Sopenharmony_ci  circular_deque& operator=(const circular_deque& other) {
4536d528ed9Sopenharmony_ci    if (&other == this)
4546d528ed9Sopenharmony_ci      return *this;
4556d528ed9Sopenharmony_ci
4566d528ed9Sopenharmony_ci    reserve(other.size());
4576d528ed9Sopenharmony_ci    assign(other.begin(), other.end());
4586d528ed9Sopenharmony_ci    return *this;
4596d528ed9Sopenharmony_ci  }
4606d528ed9Sopenharmony_ci  circular_deque& operator=(circular_deque&& other) noexcept {
4616d528ed9Sopenharmony_ci    if (&other == this)
4626d528ed9Sopenharmony_ci      return *this;
4636d528ed9Sopenharmony_ci
4646d528ed9Sopenharmony_ci    // We're about to overwrite the buffer, so don't free it in clear to
4656d528ed9Sopenharmony_ci    // avoid doing it twice.
4666d528ed9Sopenharmony_ci    ClearRetainCapacity();
4676d528ed9Sopenharmony_ci    buffer_ = std::move(other.buffer_);
4686d528ed9Sopenharmony_ci    begin_ = other.begin_;
4696d528ed9Sopenharmony_ci    end_ = other.end_;
4706d528ed9Sopenharmony_ci
4716d528ed9Sopenharmony_ci    other.begin_ = 0;
4726d528ed9Sopenharmony_ci    other.end_ = 0;
4736d528ed9Sopenharmony_ci
4746d528ed9Sopenharmony_ci    IncrementGeneration();
4756d528ed9Sopenharmony_ci    return *this;
4766d528ed9Sopenharmony_ci  }
4776d528ed9Sopenharmony_ci  circular_deque& operator=(std::initializer_list<value_type> ilist) {
4786d528ed9Sopenharmony_ci    reserve(ilist.size());
4796d528ed9Sopenharmony_ci    assign(std::begin(ilist), std::end(ilist));
4806d528ed9Sopenharmony_ci    return *this;
4816d528ed9Sopenharmony_ci  }
4826d528ed9Sopenharmony_ci
4836d528ed9Sopenharmony_ci  void assign(size_type count, const value_type& value) {
4846d528ed9Sopenharmony_ci    ClearRetainCapacity();
4856d528ed9Sopenharmony_ci    reserve(count);
4866d528ed9Sopenharmony_ci    for (size_t i = 0; i < count; i++)
4876d528ed9Sopenharmony_ci      emplace_back(value);
4886d528ed9Sopenharmony_ci    IncrementGeneration();
4896d528ed9Sopenharmony_ci  }
4906d528ed9Sopenharmony_ci
4916d528ed9Sopenharmony_ci  // This variant should be enabled only when InputIterator is an iterator.
4926d528ed9Sopenharmony_ci  template <typename InputIterator>
4936d528ed9Sopenharmony_ci  typename std::enable_if<::base::internal::is_iterator<InputIterator>::value,
4946d528ed9Sopenharmony_ci                          void>::type
4956d528ed9Sopenharmony_ci  assign(InputIterator first, InputIterator last) {
4966d528ed9Sopenharmony_ci    // Possible future enhancement, dispatch on iterator tag type. For forward
4976d528ed9Sopenharmony_ci    // iterators we can use std::difference to preallocate the space required
4986d528ed9Sopenharmony_ci    // and only do one copy.
4996d528ed9Sopenharmony_ci    ClearRetainCapacity();
5006d528ed9Sopenharmony_ci    for (; first != last; ++first)
5016d528ed9Sopenharmony_ci      emplace_back(*first);
5026d528ed9Sopenharmony_ci    IncrementGeneration();
5036d528ed9Sopenharmony_ci  }
5046d528ed9Sopenharmony_ci
5056d528ed9Sopenharmony_ci  void assign(std::initializer_list<value_type> value) {
5066d528ed9Sopenharmony_ci    reserve(std::distance(value.begin(), value.end()));
5076d528ed9Sopenharmony_ci    assign(value.begin(), value.end());
5086d528ed9Sopenharmony_ci  }
5096d528ed9Sopenharmony_ci
5106d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
5116d528ed9Sopenharmony_ci  // Accessors.
5126d528ed9Sopenharmony_ci  //
5136d528ed9Sopenharmony_ci  // Since this class assumes no exceptions, at() and operator[] are equivalent.
5146d528ed9Sopenharmony_ci
5156d528ed9Sopenharmony_ci  const value_type& at(size_type i) const {
5166d528ed9Sopenharmony_ci    DCHECK(i < size());
5176d528ed9Sopenharmony_ci    size_t right_size = buffer_.capacity() - begin_;
5186d528ed9Sopenharmony_ci    if (begin_ <= end_ || i < right_size)
5196d528ed9Sopenharmony_ci      return buffer_[begin_ + i];
5206d528ed9Sopenharmony_ci    return buffer_[i - right_size];
5216d528ed9Sopenharmony_ci  }
5226d528ed9Sopenharmony_ci  value_type& at(size_type i) {
5236d528ed9Sopenharmony_ci    return const_cast<value_type&>(
5246d528ed9Sopenharmony_ci        const_cast<const circular_deque*>(this)->at(i));
5256d528ed9Sopenharmony_ci  }
5266d528ed9Sopenharmony_ci
5276d528ed9Sopenharmony_ci  value_type& operator[](size_type i) { return at(i); }
5286d528ed9Sopenharmony_ci  const value_type& operator[](size_type i) const {
5296d528ed9Sopenharmony_ci    return const_cast<circular_deque*>(this)->at(i);
5306d528ed9Sopenharmony_ci  }
5316d528ed9Sopenharmony_ci
5326d528ed9Sopenharmony_ci  value_type& front() {
5336d528ed9Sopenharmony_ci    DCHECK(!empty());
5346d528ed9Sopenharmony_ci    return buffer_[begin_];
5356d528ed9Sopenharmony_ci  }
5366d528ed9Sopenharmony_ci  const value_type& front() const {
5376d528ed9Sopenharmony_ci    DCHECK(!empty());
5386d528ed9Sopenharmony_ci    return buffer_[begin_];
5396d528ed9Sopenharmony_ci  }
5406d528ed9Sopenharmony_ci
5416d528ed9Sopenharmony_ci  value_type& back() {
5426d528ed9Sopenharmony_ci    DCHECK(!empty());
5436d528ed9Sopenharmony_ci    return *(--end());
5446d528ed9Sopenharmony_ci  }
5456d528ed9Sopenharmony_ci  const value_type& back() const {
5466d528ed9Sopenharmony_ci    DCHECK(!empty());
5476d528ed9Sopenharmony_ci    return *(--end());
5486d528ed9Sopenharmony_ci  }
5496d528ed9Sopenharmony_ci
5506d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
5516d528ed9Sopenharmony_ci  // Iterators.
5526d528ed9Sopenharmony_ci
5536d528ed9Sopenharmony_ci  iterator begin() { return iterator(this, begin_); }
5546d528ed9Sopenharmony_ci  const_iterator begin() const { return const_iterator(this, begin_); }
5556d528ed9Sopenharmony_ci  const_iterator cbegin() const { return const_iterator(this, begin_); }
5566d528ed9Sopenharmony_ci
5576d528ed9Sopenharmony_ci  iterator end() { return iterator(this, end_); }
5586d528ed9Sopenharmony_ci  const_iterator end() const { return const_iterator(this, end_); }
5596d528ed9Sopenharmony_ci  const_iterator cend() const { return const_iterator(this, end_); }
5606d528ed9Sopenharmony_ci
5616d528ed9Sopenharmony_ci  reverse_iterator rbegin() { return reverse_iterator(end()); }
5626d528ed9Sopenharmony_ci  const_reverse_iterator rbegin() const {
5636d528ed9Sopenharmony_ci    return const_reverse_iterator(end());
5646d528ed9Sopenharmony_ci  }
5656d528ed9Sopenharmony_ci  const_reverse_iterator crbegin() const { return rbegin(); }
5666d528ed9Sopenharmony_ci
5676d528ed9Sopenharmony_ci  reverse_iterator rend() { return reverse_iterator(begin()); }
5686d528ed9Sopenharmony_ci  const_reverse_iterator rend() const {
5696d528ed9Sopenharmony_ci    return const_reverse_iterator(begin());
5706d528ed9Sopenharmony_ci  }
5716d528ed9Sopenharmony_ci  const_reverse_iterator crend() const { return rend(); }
5726d528ed9Sopenharmony_ci
5736d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
5746d528ed9Sopenharmony_ci  // Memory management.
5756d528ed9Sopenharmony_ci
5766d528ed9Sopenharmony_ci  // IMPORTANT NOTE ON reserve(...): This class implements auto-shrinking of
5776d528ed9Sopenharmony_ci  // the buffer when elements are deleted and there is "too much" wasted space.
5786d528ed9Sopenharmony_ci  // So if you call reserve() with a large size in anticipation of pushing many
5796d528ed9Sopenharmony_ci  // elements, but pop an element before the queue is full, the capacity you
5806d528ed9Sopenharmony_ci  // reserved may be lost.
5816d528ed9Sopenharmony_ci  //
5826d528ed9Sopenharmony_ci  // As a result, it's only worthwhile to call reserve() when you're adding
5836d528ed9Sopenharmony_ci  // many things at once with no intermediate operations.
5846d528ed9Sopenharmony_ci  void reserve(size_type new_capacity) {
5856d528ed9Sopenharmony_ci    if (new_capacity > capacity())
5866d528ed9Sopenharmony_ci      SetCapacityTo(new_capacity);
5876d528ed9Sopenharmony_ci  }
5886d528ed9Sopenharmony_ci
5896d528ed9Sopenharmony_ci  size_type capacity() const {
5906d528ed9Sopenharmony_ci    // One item is wasted to indicate end().
5916d528ed9Sopenharmony_ci    return buffer_.capacity() == 0 ? 0 : buffer_.capacity() - 1;
5926d528ed9Sopenharmony_ci  }
5936d528ed9Sopenharmony_ci
5946d528ed9Sopenharmony_ci  void shrink_to_fit() {
5956d528ed9Sopenharmony_ci    if (empty()) {
5966d528ed9Sopenharmony_ci      // Optimize empty case to really delete everything if there was
5976d528ed9Sopenharmony_ci      // something.
5986d528ed9Sopenharmony_ci      if (buffer_.capacity())
5996d528ed9Sopenharmony_ci        buffer_ = VectorBuffer();
6006d528ed9Sopenharmony_ci    } else {
6016d528ed9Sopenharmony_ci      SetCapacityTo(size());
6026d528ed9Sopenharmony_ci    }
6036d528ed9Sopenharmony_ci  }
6046d528ed9Sopenharmony_ci
6056d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
6066d528ed9Sopenharmony_ci  // Size management.
6076d528ed9Sopenharmony_ci
6086d528ed9Sopenharmony_ci  // This will additionally reset the capacity() to 0.
6096d528ed9Sopenharmony_ci  void clear() {
6106d528ed9Sopenharmony_ci    // This can't resize(0) because that requires a default constructor to
6116d528ed9Sopenharmony_ci    // compile, which not all contained classes may implement.
6126d528ed9Sopenharmony_ci    ClearRetainCapacity();
6136d528ed9Sopenharmony_ci    buffer_ = VectorBuffer();
6146d528ed9Sopenharmony_ci  }
6156d528ed9Sopenharmony_ci
6166d528ed9Sopenharmony_ci  bool empty() const { return begin_ == end_; }
6176d528ed9Sopenharmony_ci
6186d528ed9Sopenharmony_ci  size_type size() const {
6196d528ed9Sopenharmony_ci    if (begin_ <= end_)
6206d528ed9Sopenharmony_ci      return end_ - begin_;
6216d528ed9Sopenharmony_ci    return buffer_.capacity() - begin_ + end_;
6226d528ed9Sopenharmony_ci  }
6236d528ed9Sopenharmony_ci
6246d528ed9Sopenharmony_ci  // When reducing size, the elements are deleted from the end. When expanding
6256d528ed9Sopenharmony_ci  // size, elements are added to the end with |value| or the default
6266d528ed9Sopenharmony_ci  // constructed version. Even when using resize(count) to shrink, a default
6276d528ed9Sopenharmony_ci  // constructor is required for the code to compile, even though it will not
6286d528ed9Sopenharmony_ci  // be called.
6296d528ed9Sopenharmony_ci  //
6306d528ed9Sopenharmony_ci  // There are two versions rather than using a default value to avoid
6316d528ed9Sopenharmony_ci  // creating a temporary when shrinking (when it's not needed). Plus if
6326d528ed9Sopenharmony_ci  // the default constructor is desired when expanding usually just calling it
6336d528ed9Sopenharmony_ci  // for each element is faster than making a default-constructed temporary and
6346d528ed9Sopenharmony_ci  // copying it.
6356d528ed9Sopenharmony_ci  void resize(size_type count) {
6366d528ed9Sopenharmony_ci    // SEE BELOW VERSION if you change this. The code is mostly the same.
6376d528ed9Sopenharmony_ci    if (count > size()) {
6386d528ed9Sopenharmony_ci      // This could be slightly more efficient but expanding a queue with
6396d528ed9Sopenharmony_ci      // identical elements is unusual and the extra computations of emplacing
6406d528ed9Sopenharmony_ci      // one-by-one will typically be small relative to calling the constructor
6416d528ed9Sopenharmony_ci      // for every item.
6426d528ed9Sopenharmony_ci      ExpandCapacityIfNecessary(count - size());
6436d528ed9Sopenharmony_ci      while (size() < count)
6446d528ed9Sopenharmony_ci        emplace_back();
6456d528ed9Sopenharmony_ci    } else if (count < size()) {
6466d528ed9Sopenharmony_ci      size_t new_end = (begin_ + count) % buffer_.capacity();
6476d528ed9Sopenharmony_ci      DestructRange(new_end, end_);
6486d528ed9Sopenharmony_ci      end_ = new_end;
6496d528ed9Sopenharmony_ci
6506d528ed9Sopenharmony_ci      ShrinkCapacityIfNecessary();
6516d528ed9Sopenharmony_ci    }
6526d528ed9Sopenharmony_ci    IncrementGeneration();
6536d528ed9Sopenharmony_ci  }
6546d528ed9Sopenharmony_ci  void resize(size_type count, const value_type& value) {
6556d528ed9Sopenharmony_ci    // SEE ABOVE VERSION if you change this. The code is mostly the same.
6566d528ed9Sopenharmony_ci    if (count > size()) {
6576d528ed9Sopenharmony_ci      ExpandCapacityIfNecessary(count - size());
6586d528ed9Sopenharmony_ci      while (size() < count)
6596d528ed9Sopenharmony_ci        emplace_back(value);
6606d528ed9Sopenharmony_ci    } else if (count < size()) {
6616d528ed9Sopenharmony_ci      size_t new_end = (begin_ + count) % buffer_.capacity();
6626d528ed9Sopenharmony_ci      DestructRange(new_end, end_);
6636d528ed9Sopenharmony_ci      end_ = new_end;
6646d528ed9Sopenharmony_ci
6656d528ed9Sopenharmony_ci      ShrinkCapacityIfNecessary();
6666d528ed9Sopenharmony_ci    }
6676d528ed9Sopenharmony_ci    IncrementGeneration();
6686d528ed9Sopenharmony_ci  }
6696d528ed9Sopenharmony_ci
6706d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
6716d528ed9Sopenharmony_ci  // Insert and erase.
6726d528ed9Sopenharmony_ci  //
6736d528ed9Sopenharmony_ci  // Insertion and deletion in the middle is O(n) and invalidates all existing
6746d528ed9Sopenharmony_ci  // iterators.
6756d528ed9Sopenharmony_ci  //
6766d528ed9Sopenharmony_ci  // The implementation of insert isn't optimized as much as it could be. If
6776d528ed9Sopenharmony_ci  // the insertion requires that the buffer be grown, it will first be grown
6786d528ed9Sopenharmony_ci  // and everything moved, and then the items will be inserted, potentially
6796d528ed9Sopenharmony_ci  // moving some items twice. This simplifies the implementation substantially
6806d528ed9Sopenharmony_ci  // and means less generated templatized code. Since this is an uncommon
6816d528ed9Sopenharmony_ci  // operation for deques, and already relatively slow, it doesn't seem worth
6826d528ed9Sopenharmony_ci  // the benefit to optimize this.
6836d528ed9Sopenharmony_ci
6846d528ed9Sopenharmony_ci  void insert(const_iterator pos, size_type count, const T& value) {
6856d528ed9Sopenharmony_ci    ValidateIterator(pos);
6866d528ed9Sopenharmony_ci
6876d528ed9Sopenharmony_ci    // Optimize insert at the beginning.
6886d528ed9Sopenharmony_ci    if (pos == begin()) {
6896d528ed9Sopenharmony_ci      ExpandCapacityIfNecessary(count);
6906d528ed9Sopenharmony_ci      for (size_t i = 0; i < count; i++)
6916d528ed9Sopenharmony_ci        push_front(value);
6926d528ed9Sopenharmony_ci      return;
6936d528ed9Sopenharmony_ci    }
6946d528ed9Sopenharmony_ci
6956d528ed9Sopenharmony_ci    iterator insert_cur(this, pos.index_);
6966d528ed9Sopenharmony_ci    iterator insert_end;
6976d528ed9Sopenharmony_ci    MakeRoomFor(count, &insert_cur, &insert_end);
6986d528ed9Sopenharmony_ci    while (insert_cur < insert_end) {
6996d528ed9Sopenharmony_ci      new (&buffer_[insert_cur.index_]) T(value);
7006d528ed9Sopenharmony_ci      ++insert_cur;
7016d528ed9Sopenharmony_ci    }
7026d528ed9Sopenharmony_ci
7036d528ed9Sopenharmony_ci    IncrementGeneration();
7046d528ed9Sopenharmony_ci  }
7056d528ed9Sopenharmony_ci
7066d528ed9Sopenharmony_ci  // This enable_if keeps this call from getting confused with the (pos, count,
7076d528ed9Sopenharmony_ci  // value) version when value is an integer.
7086d528ed9Sopenharmony_ci  template <class InputIterator>
7096d528ed9Sopenharmony_ci  typename std::enable_if<::base::internal::is_iterator<InputIterator>::value,
7106d528ed9Sopenharmony_ci                          void>::type
7116d528ed9Sopenharmony_ci  insert(const_iterator pos, InputIterator first, InputIterator last) {
7126d528ed9Sopenharmony_ci    ValidateIterator(pos);
7136d528ed9Sopenharmony_ci
7146d528ed9Sopenharmony_ci    size_t inserted_items = std::distance(first, last);
7156d528ed9Sopenharmony_ci    if (inserted_items == 0)
7166d528ed9Sopenharmony_ci      return;  // Can divide by 0 when doing modulo below, so return early.
7176d528ed9Sopenharmony_ci
7186d528ed9Sopenharmony_ci    // Make a hole to copy the items into.
7196d528ed9Sopenharmony_ci    iterator insert_cur;
7206d528ed9Sopenharmony_ci    iterator insert_end;
7216d528ed9Sopenharmony_ci    if (pos == begin()) {
7226d528ed9Sopenharmony_ci      // Optimize insert at the beginning, nothing needs to be shifted and the
7236d528ed9Sopenharmony_ci      // hole is the |inserted_items| block immediately before |begin_|.
7246d528ed9Sopenharmony_ci      ExpandCapacityIfNecessary(inserted_items);
7256d528ed9Sopenharmony_ci      insert_end = begin();
7266d528ed9Sopenharmony_ci      begin_ =
7276d528ed9Sopenharmony_ci          (begin_ + buffer_.capacity() - inserted_items) % buffer_.capacity();
7286d528ed9Sopenharmony_ci      insert_cur = begin();
7296d528ed9Sopenharmony_ci    } else {
7306d528ed9Sopenharmony_ci      insert_cur = iterator(this, pos.index_);
7316d528ed9Sopenharmony_ci      MakeRoomFor(inserted_items, &insert_cur, &insert_end);
7326d528ed9Sopenharmony_ci    }
7336d528ed9Sopenharmony_ci
7346d528ed9Sopenharmony_ci    // Copy the items.
7356d528ed9Sopenharmony_ci    while (insert_cur < insert_end) {
7366d528ed9Sopenharmony_ci      new (&buffer_[insert_cur.index_]) T(*first);
7376d528ed9Sopenharmony_ci      ++insert_cur;
7386d528ed9Sopenharmony_ci      ++first;
7396d528ed9Sopenharmony_ci    }
7406d528ed9Sopenharmony_ci
7416d528ed9Sopenharmony_ci    IncrementGeneration();
7426d528ed9Sopenharmony_ci  }
7436d528ed9Sopenharmony_ci
7446d528ed9Sopenharmony_ci  // These all return an iterator to the inserted item. Existing iterators will
7456d528ed9Sopenharmony_ci  // be invalidated.
7466d528ed9Sopenharmony_ci  iterator insert(const_iterator pos, const T& value) {
7476d528ed9Sopenharmony_ci    return emplace(pos, value);
7486d528ed9Sopenharmony_ci  }
7496d528ed9Sopenharmony_ci  iterator insert(const_iterator pos, T&& value) {
7506d528ed9Sopenharmony_ci    return emplace(pos, std::move(value));
7516d528ed9Sopenharmony_ci  }
7526d528ed9Sopenharmony_ci  template <class... Args>
7536d528ed9Sopenharmony_ci  iterator emplace(const_iterator pos, Args&&... args) {
7546d528ed9Sopenharmony_ci    ValidateIterator(pos);
7556d528ed9Sopenharmony_ci
7566d528ed9Sopenharmony_ci    // Optimize insert at beginning which doesn't require shifting.
7576d528ed9Sopenharmony_ci    if (pos == cbegin()) {
7586d528ed9Sopenharmony_ci      emplace_front(std::forward<Args>(args)...);
7596d528ed9Sopenharmony_ci      return begin();
7606d528ed9Sopenharmony_ci    }
7616d528ed9Sopenharmony_ci
7626d528ed9Sopenharmony_ci    // Do this before we make the new iterators we return.
7636d528ed9Sopenharmony_ci    IncrementGeneration();
7646d528ed9Sopenharmony_ci
7656d528ed9Sopenharmony_ci    iterator insert_begin(this, pos.index_);
7666d528ed9Sopenharmony_ci    iterator insert_end;
7676d528ed9Sopenharmony_ci    MakeRoomFor(1, &insert_begin, &insert_end);
7686d528ed9Sopenharmony_ci    new (&buffer_[insert_begin.index_]) T(std::forward<Args>(args)...);
7696d528ed9Sopenharmony_ci
7706d528ed9Sopenharmony_ci    return insert_begin;
7716d528ed9Sopenharmony_ci  }
7726d528ed9Sopenharmony_ci
7736d528ed9Sopenharmony_ci  // Calling erase() won't automatically resize the buffer smaller like resize
7746d528ed9Sopenharmony_ci  // or the pop functions. Erase is slow and relatively uncommon, and for
7756d528ed9Sopenharmony_ci  // normal deque usage a pop will normally be done on a regular basis that
7766d528ed9Sopenharmony_ci  // will prevent excessive buffer usage over long periods of time. It's not
7776d528ed9Sopenharmony_ci  // worth having the extra code for every template instantiation of erase()
7786d528ed9Sopenharmony_ci  // to resize capacity downward to a new buffer.
7796d528ed9Sopenharmony_ci  iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
7806d528ed9Sopenharmony_ci  iterator erase(const_iterator first, const_iterator last) {
7816d528ed9Sopenharmony_ci    ValidateIterator(first);
7826d528ed9Sopenharmony_ci    ValidateIterator(last);
7836d528ed9Sopenharmony_ci
7846d528ed9Sopenharmony_ci    IncrementGeneration();
7856d528ed9Sopenharmony_ci
7866d528ed9Sopenharmony_ci    // First, call the destructor on the deleted items.
7876d528ed9Sopenharmony_ci    if (first.index_ == last.index_) {
7886d528ed9Sopenharmony_ci      // Nothing deleted. Need to return early to avoid falling through to
7896d528ed9Sopenharmony_ci      // moving items on top of themselves.
7906d528ed9Sopenharmony_ci      return iterator(this, first.index_);
7916d528ed9Sopenharmony_ci    } else if (first.index_ < last.index_) {
7926d528ed9Sopenharmony_ci      // Contiguous range.
7936d528ed9Sopenharmony_ci      buffer_.DestructRange(&buffer_[first.index_], &buffer_[last.index_]);
7946d528ed9Sopenharmony_ci    } else {
7956d528ed9Sopenharmony_ci      // Deleted range wraps around.
7966d528ed9Sopenharmony_ci      buffer_.DestructRange(&buffer_[first.index_],
7976d528ed9Sopenharmony_ci                            &buffer_[buffer_.capacity()]);
7986d528ed9Sopenharmony_ci      buffer_.DestructRange(&buffer_[0], &buffer_[last.index_]);
7996d528ed9Sopenharmony_ci    }
8006d528ed9Sopenharmony_ci
8016d528ed9Sopenharmony_ci    if (first.index_ == begin_) {
8026d528ed9Sopenharmony_ci      // This deletion is from the beginning. Nothing needs to be copied, only
8036d528ed9Sopenharmony_ci      // begin_ needs to be updated.
8046d528ed9Sopenharmony_ci      begin_ = last.index_;
8056d528ed9Sopenharmony_ci      return iterator(this, last.index_);
8066d528ed9Sopenharmony_ci    }
8076d528ed9Sopenharmony_ci
8086d528ed9Sopenharmony_ci    // In an erase operation, the shifted items all move logically to the left,
8096d528ed9Sopenharmony_ci    // so move them from left-to-right.
8106d528ed9Sopenharmony_ci    iterator move_src(this, last.index_);
8116d528ed9Sopenharmony_ci    iterator move_src_end = end();
8126d528ed9Sopenharmony_ci    iterator move_dest(this, first.index_);
8136d528ed9Sopenharmony_ci    for (; move_src < move_src_end; move_src++, move_dest++) {
8146d528ed9Sopenharmony_ci      buffer_.MoveRange(&buffer_[move_src.index_],
8156d528ed9Sopenharmony_ci                        &buffer_[move_src.index_ + 1],
8166d528ed9Sopenharmony_ci                        &buffer_[move_dest.index_]);
8176d528ed9Sopenharmony_ci    }
8186d528ed9Sopenharmony_ci
8196d528ed9Sopenharmony_ci    end_ = move_dest.index_;
8206d528ed9Sopenharmony_ci
8216d528ed9Sopenharmony_ci    // Since we did not reallocate and only changed things after the erase
8226d528ed9Sopenharmony_ci    // element(s), the input iterator's index points to the thing following the
8236d528ed9Sopenharmony_ci    // deletion.
8246d528ed9Sopenharmony_ci    return iterator(this, first.index_);
8256d528ed9Sopenharmony_ci  }
8266d528ed9Sopenharmony_ci
8276d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
8286d528ed9Sopenharmony_ci  // Begin/end operations.
8296d528ed9Sopenharmony_ci
8306d528ed9Sopenharmony_ci  void push_front(const T& value) { emplace_front(value); }
8316d528ed9Sopenharmony_ci  void push_front(T&& value) { emplace_front(std::move(value)); }
8326d528ed9Sopenharmony_ci
8336d528ed9Sopenharmony_ci  void push_back(const T& value) { emplace_back(value); }
8346d528ed9Sopenharmony_ci  void push_back(T&& value) { emplace_back(std::move(value)); }
8356d528ed9Sopenharmony_ci
8366d528ed9Sopenharmony_ci  template <class... Args>
8376d528ed9Sopenharmony_ci  reference emplace_front(Args&&... args) {
8386d528ed9Sopenharmony_ci    ExpandCapacityIfNecessary(1);
8396d528ed9Sopenharmony_ci    if (begin_ == 0)
8406d528ed9Sopenharmony_ci      begin_ = buffer_.capacity() - 1;
8416d528ed9Sopenharmony_ci    else
8426d528ed9Sopenharmony_ci      begin_--;
8436d528ed9Sopenharmony_ci    IncrementGeneration();
8446d528ed9Sopenharmony_ci    new (&buffer_[begin_]) T(std::forward<Args>(args)...);
8456d528ed9Sopenharmony_ci    return front();
8466d528ed9Sopenharmony_ci  }
8476d528ed9Sopenharmony_ci
8486d528ed9Sopenharmony_ci  template <class... Args>
8496d528ed9Sopenharmony_ci  reference emplace_back(Args&&... args) {
8506d528ed9Sopenharmony_ci    ExpandCapacityIfNecessary(1);
8516d528ed9Sopenharmony_ci    new (&buffer_[end_]) T(std::forward<Args>(args)...);
8526d528ed9Sopenharmony_ci    if (end_ == buffer_.capacity() - 1)
8536d528ed9Sopenharmony_ci      end_ = 0;
8546d528ed9Sopenharmony_ci    else
8556d528ed9Sopenharmony_ci      end_++;
8566d528ed9Sopenharmony_ci    IncrementGeneration();
8576d528ed9Sopenharmony_ci    return back();
8586d528ed9Sopenharmony_ci  }
8596d528ed9Sopenharmony_ci
8606d528ed9Sopenharmony_ci  void pop_front() {
8616d528ed9Sopenharmony_ci    DCHECK(size());
8626d528ed9Sopenharmony_ci    buffer_.DestructRange(&buffer_[begin_], &buffer_[begin_ + 1]);
8636d528ed9Sopenharmony_ci    begin_++;
8646d528ed9Sopenharmony_ci    if (begin_ == buffer_.capacity())
8656d528ed9Sopenharmony_ci      begin_ = 0;
8666d528ed9Sopenharmony_ci
8676d528ed9Sopenharmony_ci    ShrinkCapacityIfNecessary();
8686d528ed9Sopenharmony_ci
8696d528ed9Sopenharmony_ci    // Technically popping will not invalidate any iterators since the
8706d528ed9Sopenharmony_ci    // underlying buffer will be stable. But in the future we may want to add a
8716d528ed9Sopenharmony_ci    // feature that resizes the buffer smaller if there is too much wasted
8726d528ed9Sopenharmony_ci    // space. This ensures we can make such a change safely.
8736d528ed9Sopenharmony_ci    IncrementGeneration();
8746d528ed9Sopenharmony_ci  }
8756d528ed9Sopenharmony_ci  void pop_back() {
8766d528ed9Sopenharmony_ci    DCHECK(size());
8776d528ed9Sopenharmony_ci    if (end_ == 0)
8786d528ed9Sopenharmony_ci      end_ = buffer_.capacity() - 1;
8796d528ed9Sopenharmony_ci    else
8806d528ed9Sopenharmony_ci      end_--;
8816d528ed9Sopenharmony_ci    buffer_.DestructRange(&buffer_[end_], &buffer_[end_ + 1]);
8826d528ed9Sopenharmony_ci
8836d528ed9Sopenharmony_ci    ShrinkCapacityIfNecessary();
8846d528ed9Sopenharmony_ci
8856d528ed9Sopenharmony_ci    // See pop_front comment about why this is here.
8866d528ed9Sopenharmony_ci    IncrementGeneration();
8876d528ed9Sopenharmony_ci  }
8886d528ed9Sopenharmony_ci
8896d528ed9Sopenharmony_ci  // ---------------------------------------------------------------------------
8906d528ed9Sopenharmony_ci  // General operations.
8916d528ed9Sopenharmony_ci
8926d528ed9Sopenharmony_ci  void swap(circular_deque& other) {
8936d528ed9Sopenharmony_ci    std::swap(buffer_, other.buffer_);
8946d528ed9Sopenharmony_ci    std::swap(begin_, other.begin_);
8956d528ed9Sopenharmony_ci    std::swap(end_, other.end_);
8966d528ed9Sopenharmony_ci    IncrementGeneration();
8976d528ed9Sopenharmony_ci  }
8986d528ed9Sopenharmony_ci
8996d528ed9Sopenharmony_ci  friend void swap(circular_deque& lhs, circular_deque& rhs) { lhs.swap(rhs); }
9006d528ed9Sopenharmony_ci
9016d528ed9Sopenharmony_ci private:
9026d528ed9Sopenharmony_ci  friend internal::circular_deque_iterator<T>;
9036d528ed9Sopenharmony_ci  friend internal::circular_deque_const_iterator<T>;
9046d528ed9Sopenharmony_ci
9056d528ed9Sopenharmony_ci  // Moves the items in the given circular buffer to the current one. The
9066d528ed9Sopenharmony_ci  // source is moved from so will become invalid. The destination buffer must
9076d528ed9Sopenharmony_ci  // have already been allocated with enough size.
9086d528ed9Sopenharmony_ci  static void MoveBuffer(VectorBuffer& from_buf,
9096d528ed9Sopenharmony_ci                         size_t from_begin,
9106d528ed9Sopenharmony_ci                         size_t from_end,
9116d528ed9Sopenharmony_ci                         VectorBuffer* to_buf,
9126d528ed9Sopenharmony_ci                         size_t* to_begin,
9136d528ed9Sopenharmony_ci                         size_t* to_end) {
9146d528ed9Sopenharmony_ci    size_t from_capacity = from_buf.capacity();
9156d528ed9Sopenharmony_ci
9166d528ed9Sopenharmony_ci    *to_begin = 0;
9176d528ed9Sopenharmony_ci    if (from_begin < from_end) {
9186d528ed9Sopenharmony_ci      // Contiguous.
9196d528ed9Sopenharmony_ci      from_buf.MoveRange(&from_buf[from_begin], &from_buf[from_end],
9206d528ed9Sopenharmony_ci                         to_buf->begin());
9216d528ed9Sopenharmony_ci      *to_end = from_end - from_begin;
9226d528ed9Sopenharmony_ci    } else if (from_begin > from_end) {
9236d528ed9Sopenharmony_ci      // Discontiguous, copy the right side to the beginning of the new buffer.
9246d528ed9Sopenharmony_ci      from_buf.MoveRange(&from_buf[from_begin], &from_buf[from_capacity],
9256d528ed9Sopenharmony_ci                         to_buf->begin());
9266d528ed9Sopenharmony_ci      size_t right_size = from_capacity - from_begin;
9276d528ed9Sopenharmony_ci      // Append the left side.
9286d528ed9Sopenharmony_ci      from_buf.MoveRange(&from_buf[0], &from_buf[from_end],
9296d528ed9Sopenharmony_ci                         &(*to_buf)[right_size]);
9306d528ed9Sopenharmony_ci      *to_end = right_size + from_end;
9316d528ed9Sopenharmony_ci    } else {
9326d528ed9Sopenharmony_ci      // No items.
9336d528ed9Sopenharmony_ci      *to_end = 0;
9346d528ed9Sopenharmony_ci    }
9356d528ed9Sopenharmony_ci  }
9366d528ed9Sopenharmony_ci
9376d528ed9Sopenharmony_ci  // Expands the buffer size. This assumes the size is larger than the
9386d528ed9Sopenharmony_ci  // number of elements in the vector (it won't call delete on anything).
9396d528ed9Sopenharmony_ci  void SetCapacityTo(size_t new_capacity) {
9406d528ed9Sopenharmony_ci    // Use the capacity + 1 as the internal buffer size to differentiate
9416d528ed9Sopenharmony_ci    // empty and full (see definition of buffer_ below).
9426d528ed9Sopenharmony_ci    VectorBuffer new_buffer(new_capacity + 1);
9436d528ed9Sopenharmony_ci    MoveBuffer(buffer_, begin_, end_, &new_buffer, &begin_, &end_);
9446d528ed9Sopenharmony_ci    buffer_ = std::move(new_buffer);
9456d528ed9Sopenharmony_ci  }
9466d528ed9Sopenharmony_ci  void ExpandCapacityIfNecessary(size_t additional_elts) {
9476d528ed9Sopenharmony_ci    size_t min_new_capacity = size() + additional_elts;
9486d528ed9Sopenharmony_ci    if (capacity() >= min_new_capacity)
9496d528ed9Sopenharmony_ci      return;  // Already enough room.
9506d528ed9Sopenharmony_ci
9516d528ed9Sopenharmony_ci    min_new_capacity =
9526d528ed9Sopenharmony_ci        std::max(min_new_capacity, internal::kCircularBufferInitialCapacity);
9536d528ed9Sopenharmony_ci
9546d528ed9Sopenharmony_ci    // std::vector always grows by at least 50%. WTF::Deque grows by at least
9556d528ed9Sopenharmony_ci    // 25%. We expect queue workloads to generally stay at a similar size and
9566d528ed9Sopenharmony_ci    // grow less than a vector might, so use 25%.
9576d528ed9Sopenharmony_ci    size_t new_capacity =
9586d528ed9Sopenharmony_ci        std::max(min_new_capacity, capacity() + capacity() / 4);
9596d528ed9Sopenharmony_ci    SetCapacityTo(new_capacity);
9606d528ed9Sopenharmony_ci  }
9616d528ed9Sopenharmony_ci
9626d528ed9Sopenharmony_ci  void ShrinkCapacityIfNecessary() {
9636d528ed9Sopenharmony_ci    // Don't auto-shrink below this size.
9646d528ed9Sopenharmony_ci    if (capacity() <= internal::kCircularBufferInitialCapacity)
9656d528ed9Sopenharmony_ci      return;
9666d528ed9Sopenharmony_ci
9676d528ed9Sopenharmony_ci    // Shrink when 100% of the size() is wasted.
9686d528ed9Sopenharmony_ci    size_t sz = size();
9696d528ed9Sopenharmony_ci    size_t empty_spaces = capacity() - sz;
9706d528ed9Sopenharmony_ci    if (empty_spaces < sz)
9716d528ed9Sopenharmony_ci      return;
9726d528ed9Sopenharmony_ci
9736d528ed9Sopenharmony_ci    // Leave 1/4 the size as free capacity, not going below the initial
9746d528ed9Sopenharmony_ci    // capacity.
9756d528ed9Sopenharmony_ci    size_t new_capacity =
9766d528ed9Sopenharmony_ci        std::max(internal::kCircularBufferInitialCapacity, sz + sz / 4);
9776d528ed9Sopenharmony_ci    if (new_capacity < capacity()) {
9786d528ed9Sopenharmony_ci      // Count extra item to convert to internal capacity.
9796d528ed9Sopenharmony_ci      SetCapacityTo(new_capacity);
9806d528ed9Sopenharmony_ci    }
9816d528ed9Sopenharmony_ci  }
9826d528ed9Sopenharmony_ci
9836d528ed9Sopenharmony_ci  // Backend for clear() but does not resize the internal buffer.
9846d528ed9Sopenharmony_ci  void ClearRetainCapacity() {
9856d528ed9Sopenharmony_ci    // This can't resize(0) because that requires a default constructor to
9866d528ed9Sopenharmony_ci    // compile, which not all contained classes may implement.
9876d528ed9Sopenharmony_ci    DestructRange(begin_, end_);
9886d528ed9Sopenharmony_ci    begin_ = 0;
9896d528ed9Sopenharmony_ci    end_ = 0;
9906d528ed9Sopenharmony_ci    IncrementGeneration();
9916d528ed9Sopenharmony_ci  }
9926d528ed9Sopenharmony_ci
9936d528ed9Sopenharmony_ci  // Calls destructors for the given begin->end indices. The indices may wrap
9946d528ed9Sopenharmony_ci  // around. The buffer is not resized, and the begin_ and end_ members are
9956d528ed9Sopenharmony_ci  // not changed.
9966d528ed9Sopenharmony_ci  void DestructRange(size_t begin, size_t end) {
9976d528ed9Sopenharmony_ci    if (end == begin) {
9986d528ed9Sopenharmony_ci      return;
9996d528ed9Sopenharmony_ci    } else if (end > begin) {
10006d528ed9Sopenharmony_ci      buffer_.DestructRange(&buffer_[begin], &buffer_[end]);
10016d528ed9Sopenharmony_ci    } else {
10026d528ed9Sopenharmony_ci      buffer_.DestructRange(&buffer_[begin], &buffer_[buffer_.capacity()]);
10036d528ed9Sopenharmony_ci      buffer_.DestructRange(&buffer_[0], &buffer_[end]);
10046d528ed9Sopenharmony_ci    }
10056d528ed9Sopenharmony_ci  }
10066d528ed9Sopenharmony_ci
10076d528ed9Sopenharmony_ci  // Makes room for |count| items starting at |*insert_begin|. Since iterators
10086d528ed9Sopenharmony_ci  // are not stable across buffer resizes, |*insert_begin| will be updated to
10096d528ed9Sopenharmony_ci  // point to the beginning of the newly opened position in the new array (it's
10106d528ed9Sopenharmony_ci  // in/out), and the end of the newly opened position (it's out-only).
10116d528ed9Sopenharmony_ci  void MakeRoomFor(size_t count, iterator* insert_begin, iterator* insert_end) {
10126d528ed9Sopenharmony_ci    if (count == 0) {
10136d528ed9Sopenharmony_ci      *insert_end = *insert_begin;
10146d528ed9Sopenharmony_ci      return;
10156d528ed9Sopenharmony_ci    }
10166d528ed9Sopenharmony_ci
10176d528ed9Sopenharmony_ci    // The offset from the beginning will be stable across reallocations.
10186d528ed9Sopenharmony_ci    size_t begin_offset = insert_begin->OffsetFromBegin();
10196d528ed9Sopenharmony_ci    ExpandCapacityIfNecessary(count);
10206d528ed9Sopenharmony_ci
10216d528ed9Sopenharmony_ci    insert_begin->index_ = (begin_ + begin_offset) % buffer_.capacity();
10226d528ed9Sopenharmony_ci    *insert_end =
10236d528ed9Sopenharmony_ci        iterator(this, (insert_begin->index_ + count) % buffer_.capacity());
10246d528ed9Sopenharmony_ci
10256d528ed9Sopenharmony_ci    // Update the new end and prepare the iterators for copying.
10266d528ed9Sopenharmony_ci    iterator src = end();
10276d528ed9Sopenharmony_ci    end_ = (end_ + count) % buffer_.capacity();
10286d528ed9Sopenharmony_ci    iterator dest = end();
10296d528ed9Sopenharmony_ci
10306d528ed9Sopenharmony_ci    // Move the elements. This will always involve shifting logically to the
10316d528ed9Sopenharmony_ci    // right, so move in a right-to-left order.
10326d528ed9Sopenharmony_ci    while (true) {
10336d528ed9Sopenharmony_ci      if (src == *insert_begin)
10346d528ed9Sopenharmony_ci        break;
10356d528ed9Sopenharmony_ci      --src;
10366d528ed9Sopenharmony_ci      --dest;
10376d528ed9Sopenharmony_ci      buffer_.MoveRange(&buffer_[src.index_], &buffer_[src.index_ + 1],
10386d528ed9Sopenharmony_ci                        &buffer_[dest.index_]);
10396d528ed9Sopenharmony_ci    }
10406d528ed9Sopenharmony_ci  }
10416d528ed9Sopenharmony_ci
10426d528ed9Sopenharmony_ci#if DCHECK_IS_ON()
10436d528ed9Sopenharmony_ci  // Asserts the given index is dereferenceable. The index is an index into the
10446d528ed9Sopenharmony_ci  // buffer, not an index used by operator[] or at() which will be offsets from
10456d528ed9Sopenharmony_ci  // begin.
10466d528ed9Sopenharmony_ci  void CheckValidIndex(size_t i) const {
10476d528ed9Sopenharmony_ci    if (begin_ <= end_)
10486d528ed9Sopenharmony_ci      DCHECK(i >= begin_ && i < end_);
10496d528ed9Sopenharmony_ci    else
10506d528ed9Sopenharmony_ci      DCHECK((i >= begin_ && i < buffer_.capacity()) || i < end_);
10516d528ed9Sopenharmony_ci  }
10526d528ed9Sopenharmony_ci
10536d528ed9Sopenharmony_ci  // Asserts the given index is either dereferenceable or points to end().
10546d528ed9Sopenharmony_ci  void CheckValidIndexOrEnd(size_t i) const {
10556d528ed9Sopenharmony_ci    if (i != end_)
10566d528ed9Sopenharmony_ci      CheckValidIndex(i);
10576d528ed9Sopenharmony_ci  }
10586d528ed9Sopenharmony_ci
10596d528ed9Sopenharmony_ci  void ValidateIterator(const const_iterator& i) const {
10606d528ed9Sopenharmony_ci    DCHECK(i.parent_deque_ == this);
10616d528ed9Sopenharmony_ci    i.CheckUnstableUsage();
10626d528ed9Sopenharmony_ci  }
10636d528ed9Sopenharmony_ci
10646d528ed9Sopenharmony_ci  // See generation_ below.
10656d528ed9Sopenharmony_ci  void IncrementGeneration() { generation_++; }
10666d528ed9Sopenharmony_ci#else
10676d528ed9Sopenharmony_ci  // No-op versions of these functions for release builds.
10686d528ed9Sopenharmony_ci  void CheckValidIndex(size_t) const {}
10696d528ed9Sopenharmony_ci  void CheckValidIndexOrEnd(size_t) const {}
10706d528ed9Sopenharmony_ci  void ValidateIterator(const const_iterator& i) const {}
10716d528ed9Sopenharmony_ci  void IncrementGeneration() {}
10726d528ed9Sopenharmony_ci#endif
10736d528ed9Sopenharmony_ci
10746d528ed9Sopenharmony_ci  // Danger, the buffer_.capacity() is the "internal capacity" which is
10756d528ed9Sopenharmony_ci  // capacity() + 1 since there is an extra item to indicate the end. Otherwise
10766d528ed9Sopenharmony_ci  // being completely empty and completely full are indistinguishable (begin ==
10776d528ed9Sopenharmony_ci  // end). We could add a separate flag to avoid it, but that adds significant
10786d528ed9Sopenharmony_ci  // extra complexity since every computation will have to check for it. Always
10796d528ed9Sopenharmony_ci  // keeping one extra unused element in the buffer makes iterator computations
10806d528ed9Sopenharmony_ci  // much simpler.
10816d528ed9Sopenharmony_ci  //
10826d528ed9Sopenharmony_ci  // Container internal code will want to use buffer_.capacity() for offset
10836d528ed9Sopenharmony_ci  // computations rather than capacity().
10846d528ed9Sopenharmony_ci  VectorBuffer buffer_;
10856d528ed9Sopenharmony_ci  size_type begin_ = 0;
10866d528ed9Sopenharmony_ci  size_type end_ = 0;
10876d528ed9Sopenharmony_ci
10886d528ed9Sopenharmony_ci#if DCHECK_IS_ON()
10896d528ed9Sopenharmony_ci  // Incremented every time a modification is made that could affect iterator
10906d528ed9Sopenharmony_ci  // invalidations.
10916d528ed9Sopenharmony_ci  uint64_t generation_ = 0;
10926d528ed9Sopenharmony_ci#endif
10936d528ed9Sopenharmony_ci};
10946d528ed9Sopenharmony_ci
10956d528ed9Sopenharmony_ci// Implementations of base::Erase[If] (see base/stl_util.h).
10966d528ed9Sopenharmony_citemplate <class T, class Value>
10976d528ed9Sopenharmony_civoid Erase(circular_deque<T>& container, const Value& value) {
10986d528ed9Sopenharmony_ci  container.erase(std::remove(container.begin(), container.end(), value),
10996d528ed9Sopenharmony_ci                  container.end());
11006d528ed9Sopenharmony_ci}
11016d528ed9Sopenharmony_ci
11026d528ed9Sopenharmony_citemplate <class T, class Predicate>
11036d528ed9Sopenharmony_civoid EraseIf(circular_deque<T>& container, Predicate pred) {
11046d528ed9Sopenharmony_ci  container.erase(std::remove_if(container.begin(), container.end(), pred),
11056d528ed9Sopenharmony_ci                  container.end());
11066d528ed9Sopenharmony_ci}
11076d528ed9Sopenharmony_ci
11086d528ed9Sopenharmony_ci}  // namespace base
11096d528ed9Sopenharmony_ci
11106d528ed9Sopenharmony_ci#endif  // BASE_CONTAINERS_CIRCULAR_DEQUE_H_
1111