| /* | 
 |  *  Copyright 2020 The WebRTC Project Authors. All rights reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #ifndef RTC_BASE_BOUNDED_INLINE_VECTOR_H_ | 
 | #define RTC_BASE_BOUNDED_INLINE_VECTOR_H_ | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <memory> | 
 | #include <type_traits> | 
 | #include <utility> | 
 |  | 
 | #include "rtc_base/bounded_inline_vector_impl.h" | 
 | #include "rtc_base/checks.h" | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | // A small std::vector-like type whose capacity is a compile-time constant. It | 
 | // stores all data inline and never heap allocates (beyond what its element type | 
 | // requires). Trying to grow it beyond its constant capacity is an error. | 
 | // | 
 | // TODO(bugs.webrtc.org/11391): Comparison operators. | 
 | // TODO(bugs.webrtc.org/11391): Methods for adding and deleting elements. | 
 | template <typename T, int fixed_capacity> | 
 | class BoundedInlineVector { | 
 |   static_assert(!std::is_const<T>::value, "T may not be const"); | 
 |   static_assert(fixed_capacity > 0, "Capacity must be strictly positive"); | 
 |  | 
 |  public: | 
 |   using size_type = int; | 
 |   using value_type = T; | 
 |   using const_iterator = const T*; | 
 |  | 
 |   BoundedInlineVector() = default; | 
 |   BoundedInlineVector(const BoundedInlineVector&) = default; | 
 |   BoundedInlineVector(BoundedInlineVector&&) = default; | 
 |   BoundedInlineVector& operator=(const BoundedInlineVector&) = default; | 
 |   BoundedInlineVector& operator=(BoundedInlineVector&&) = default; | 
 |   ~BoundedInlineVector() = default; | 
 |  | 
 |   // This constructor is implicit, to make it possible to write e.g. | 
 |   // | 
 |   //   BoundedInlineVector<double, 7> x = {2.72, 3.14}; | 
 |   // | 
 |   // and | 
 |   // | 
 |   //   BoundedInlineVector<double, 7> GetConstants() { | 
 |   //     return {2.72, 3.14}; | 
 |   //   } | 
 |   template <typename... Ts, | 
 |             typename std::enable_if_t< | 
 |                 bounded_inline_vector_impl::AllConvertible<T, Ts...>::value>* = | 
 |                 nullptr> | 
 |   BoundedInlineVector(Ts&&... elements)  // NOLINT(runtime/explicit) | 
 |       : storage_(std::forward<Ts>(elements)...) { | 
 |     static_assert(sizeof...(Ts) <= fixed_capacity, ""); | 
 |   } | 
 |  | 
 |   template < | 
 |       int other_capacity, | 
 |       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> | 
 |   BoundedInlineVector(const BoundedInlineVector<T, other_capacity>& other) { | 
 |     RTC_DCHECK_LE(other.size(), fixed_capacity); | 
 |     bounded_inline_vector_impl::CopyElements(other.data(), other.size(), | 
 |                                              storage_.data, &storage_.size); | 
 |   } | 
 |  | 
 |   template < | 
 |       int other_capacity, | 
 |       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> | 
 |   BoundedInlineVector(BoundedInlineVector<T, other_capacity>&& other) { | 
 |     RTC_DCHECK_LE(other.size(), fixed_capacity); | 
 |     bounded_inline_vector_impl::MoveElements(other.data(), other.size(), | 
 |                                              storage_.data, &storage_.size); | 
 |   } | 
 |  | 
 |   template < | 
 |       int other_capacity, | 
 |       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> | 
 |   BoundedInlineVector& operator=( | 
 |       const BoundedInlineVector<T, other_capacity>& other) { | 
 |     bounded_inline_vector_impl::DestroyElements(storage_.data, storage_.size); | 
 |     RTC_DCHECK_LE(other.size(), fixed_capacity); | 
 |     bounded_inline_vector_impl::CopyElements(other.data(), other.size(), | 
 |                                              storage_.data, &storage_.size); | 
 |     return *this; | 
 |   } | 
 |  | 
 |   template < | 
 |       int other_capacity, | 
 |       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr> | 
 |   BoundedInlineVector& operator=( | 
 |       BoundedInlineVector<T, other_capacity>&& other) { | 
 |     bounded_inline_vector_impl::DestroyElements(storage_.data, storage_.size); | 
 |     RTC_DCHECK_LE(other.size(), fixed_capacity); | 
 |     bounded_inline_vector_impl::MoveElements(other.data(), other.size(), | 
 |                                              storage_.data, &storage_.size); | 
 |     return *this; | 
 |   } | 
 |  | 
 |   bool empty() const { return storage_.size == 0; } | 
 |   int size() const { return storage_.size; } | 
 |   constexpr int capacity() const { return fixed_capacity; } | 
 |  | 
 |   // Resizes the BoundedInlineVector to the given size, which must not exceed | 
 |   // its constant capacity. If the size is increased, the added elements are | 
 |   // default constructed. | 
 |   void resize(int new_size) { | 
 |     RTC_DCHECK_GE(new_size, 0); | 
 |     RTC_DCHECK_LE(new_size, fixed_capacity); | 
 |     if (new_size > storage_.size) { | 
 |       bounded_inline_vector_impl::DefaultInitializeElements( | 
 |           storage_.data + storage_.size, new_size - storage_.size); | 
 |     } else if (new_size < storage_.size) { | 
 |       bounded_inline_vector_impl::DestroyElements(storage_.data + new_size, | 
 |                                                   storage_.size - new_size); | 
 |     } | 
 |     storage_.size = new_size; | 
 |   } | 
 |  | 
 |   const T* data() const { return storage_.data; } | 
 |   T* data() { return storage_.data; } | 
 |  | 
 |   const T& operator[](int index) const { | 
 |     RTC_DCHECK_GE(index, 0); | 
 |     RTC_DCHECK_LT(index, storage_.size); | 
 |     return storage_.data[index]; | 
 |   } | 
 |   T& operator[](int index) { | 
 |     RTC_DCHECK_GE(index, 0); | 
 |     RTC_DCHECK_LT(index, storage_.size); | 
 |     return storage_.data[index]; | 
 |   } | 
 |  | 
 |   T* begin() { return storage_.data; } | 
 |   T* end() { return storage_.data + storage_.size; } | 
 |   const T* begin() const { return storage_.data; } | 
 |   const T* end() const { return storage_.data + storage_.size; } | 
 |   const T* cbegin() const { return storage_.data; } | 
 |   const T* cend() const { return storage_.data + storage_.size; } | 
 |  | 
 |  private: | 
 |   bounded_inline_vector_impl::Storage<T, fixed_capacity> storage_; | 
 | }; | 
 |  | 
 | }  // namespace webrtc | 
 |  | 
 | #endif  // RTC_BASE_BOUNDED_INLINE_VECTOR_H_ |