// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_CONTAINERS_CIRCULAR_DEQUE_H_ #define BASE_CONTAINERS_CIRCULAR_DEQUE_H_ #include <algorithm> #include <cstddef> #include <iterator> #include <type_traits> #include <utility> #include "base/check.h" #include "base/containers/span.h" #include "base/containers/vector_buffer.h" #include "base/dcheck_is_on.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/numerics/checked_math.h" #include "base/numerics/safe_conversions.h" #include "base/ranges/algorithm.h" #include "base/ranges/from_range.h" #if DCHECK_IS_ON() #include <ostream> #endif // base::circular_deque is similar to std::deque. Unlike std::deque, the // storage is provided in a flat circular buffer conceptually similar to a // vector. The beginning and end will wrap around as necessary so that // pushes and pops will be constant time as long as a capacity expansion is // not required. // // The API should be identical to std::deque with the following differences: // // - ITERATORS ARE NOT STABLE. Mutating the container will invalidate all // iterators. // // - Insertions may resize the vector and so are not constant time (std::deque // guarantees constant time for insertions at the ends). // // - Container-wide comparisons are not implemented. If you want to compare // two containers, use an algorithm so the expensive iteration is explicit. // // If you want a similar container with only a queue API, use base::queue in // base/containers/queue.h. // // Constructors: // circular_deque(); // circular_deque(size_t count); // circular_deque(size_t count, const T& value); // circular_deque(InputIterator first, InputIterator last); // circular_deque(base::from_range_t, Range range); // circular_deque(const circular_deque&); // circular_deque(circular_deque&&); // circular_deque(std::initializer_list<value_type>); // // Assignment functions: // circular_deque& operator=(const circular_deque&); // circular_deque& operator=(circular_deque&&); // circular_deque& operator=(std::initializer_list<T>); // void assign(size_t count, const T& value); // void assign(InputIterator first, InputIterator last); // void assign(std::initializer_list<T> value); // void assign_range(Range range); // // Random accessors: // T& at(size_t); // const T& at(size_t) const; // T& operator[](size_t); // const T& operator[](size_t) const; // // End accessors: // T& front(); // const T& front() const; // T& back(); // const T& back() const; // // Iterator functions: // iterator begin(); // const_iterator begin() const; // const_iterator cbegin() const; // iterator end(); // const_iterator end() const; // const_iterator cend() const; // reverse_iterator rbegin(); // const_reverse_iterator rbegin() const; // const_reverse_iterator crbegin() const; // reverse_iterator rend(); // const_reverse_iterator rend() const; // const_reverse_iterator crend() const; // // Memory management: // void reserve(size_t); // SEE IMPLEMENTATION FOR SOME GOTCHAS. // size_t capacity() const; // void shrink_to_fit(); // // Size management: // void clear(); // bool empty() const; // size_t size() const; // void resize(size_t); // void resize(size_t count, const T& value); // // Positional insert and erase: // void insert(const_iterator pos, size_type count, const T& value); // void insert(const_iterator pos, // InputIterator first, InputIterator last); // iterator insert(const_iterator pos, const T& value); // iterator insert(const_iterator pos, T&& value); // iterator emplace(const_iterator pos, Args&&... args); // iterator erase(const_iterator pos); // iterator erase(const_iterator first, const_iterator last); // // End insert and erase: // void push_front(const T&); // void push_front(T&&); // void push_back(const T&); // void push_back(T&&); // T& emplace_front(Args&&...); // T& emplace_back(Args&&...); // void pop_front(); // void pop_back(); // // General: // void swap(circular_deque&); namespace base { template <class T> class circular_deque; namespace internal { // Start allocating nonempty buffers with this many entries. This is the // external capacity so the internal buffer will be one larger (= 4) which is // more even for the allocator. See the descriptions of internal vs. external // capacity on the comment above the buffer_ variable below. constexpr size_t kCircularBufferInitialCapacity = …; template <typename T> class circular_deque_const_iterator { … }; template <typename T> class circular_deque_iterator : public circular_deque_const_iterator<T> { … }; } // namespace internal template <typename T> class circular_deque { … }; // Implementations of base::Erase[If] (see base/stl_util.h). template <class T, class Value> size_t Erase(circular_deque<T>& container, const Value& value) { … } template <class T, class Predicate> size_t EraseIf(circular_deque<T>& container, Predicate pred) { … } } // namespace base #endif // BASE_CONTAINERS_CIRCULAR_DEQUE_H_