xref: /aosp_15_r20/external/webrtc/rtc_base/bounded_inline_vector.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef RTC_BASE_BOUNDED_INLINE_VECTOR_H_
12 #define RTC_BASE_BOUNDED_INLINE_VECTOR_H_
13 
14 #include <stdint.h>
15 
16 #include <memory>
17 #include <type_traits>
18 #include <utility>
19 
20 #include "rtc_base/bounded_inline_vector_impl.h"
21 #include "rtc_base/checks.h"
22 
23 namespace webrtc {
24 
25 // A small std::vector-like type whose capacity is a compile-time constant. It
26 // stores all data inline and never heap allocates (beyond what its element type
27 // requires). Trying to grow it beyond its constant capacity is an error.
28 //
29 // TODO(bugs.webrtc.org/11391): Comparison operators.
30 // TODO(bugs.webrtc.org/11391): Methods for adding and deleting elements.
31 template <typename T, int fixed_capacity>
32 class BoundedInlineVector {
33   static_assert(!std::is_const<T>::value, "T may not be const");
34   static_assert(fixed_capacity > 0, "Capacity must be strictly positive");
35 
36  public:
37   using size_type = int;
38   using value_type = T;
39   using const_iterator = const T*;
40 
41   BoundedInlineVector() = default;
42   BoundedInlineVector(const BoundedInlineVector&) = default;
43   BoundedInlineVector(BoundedInlineVector&&) = default;
44   BoundedInlineVector& operator=(const BoundedInlineVector&) = default;
45   BoundedInlineVector& operator=(BoundedInlineVector&&) = default;
46   ~BoundedInlineVector() = default;
47 
48   // This constructor is implicit, to make it possible to write e.g.
49   //
50   //   BoundedInlineVector<double, 7> x = {2.72, 3.14};
51   //
52   // and
53   //
54   //   BoundedInlineVector<double, 7> GetConstants() {
55   //     return {2.72, 3.14};
56   //   }
57   template <typename... Ts,
58             typename std::enable_if_t<
59                 bounded_inline_vector_impl::AllConvertible<T, Ts...>::value>* =
60                 nullptr>
BoundedInlineVector(Ts &&...elements)61   BoundedInlineVector(Ts&&... elements)  // NOLINT(runtime/explicit)
62       : storage_(std::forward<Ts>(elements)...) {
63     static_assert(sizeof...(Ts) <= fixed_capacity, "");
64   }
65 
66   template <
67       int other_capacity,
68       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr>
BoundedInlineVector(const BoundedInlineVector<T,other_capacity> & other)69   BoundedInlineVector(const BoundedInlineVector<T, other_capacity>& other) {
70     RTC_DCHECK_LE(other.size(), fixed_capacity);
71     bounded_inline_vector_impl::CopyElements(other.data(), other.size(),
72                                              storage_.data, &storage_.size);
73   }
74 
75   template <
76       int other_capacity,
77       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr>
BoundedInlineVector(BoundedInlineVector<T,other_capacity> && other)78   BoundedInlineVector(BoundedInlineVector<T, other_capacity>&& other) {
79     RTC_DCHECK_LE(other.size(), fixed_capacity);
80     bounded_inline_vector_impl::MoveElements(other.data(), other.size(),
81                                              storage_.data, &storage_.size);
82   }
83 
84   template <
85       int other_capacity,
86       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr>
87   BoundedInlineVector& operator=(
88       const BoundedInlineVector<T, other_capacity>& other) {
89     bounded_inline_vector_impl::DestroyElements(storage_.data, storage_.size);
90     RTC_DCHECK_LE(other.size(), fixed_capacity);
91     bounded_inline_vector_impl::CopyElements(other.data(), other.size(),
92                                              storage_.data, &storage_.size);
93     return *this;
94   }
95 
96   template <
97       int other_capacity,
98       typename std::enable_if_t<other_capacity != fixed_capacity>* = nullptr>
99   BoundedInlineVector& operator=(
100       BoundedInlineVector<T, other_capacity>&& other) {
101     bounded_inline_vector_impl::DestroyElements(storage_.data, storage_.size);
102     RTC_DCHECK_LE(other.size(), fixed_capacity);
103     bounded_inline_vector_impl::MoveElements(other.data(), other.size(),
104                                              storage_.data, &storage_.size);
105     return *this;
106   }
107 
empty()108   bool empty() const { return storage_.size == 0; }
size()109   int size() const { return storage_.size; }
capacity()110   constexpr int capacity() const { return fixed_capacity; }
111 
112   // Resizes the BoundedInlineVector to the given size, which must not exceed
113   // its constant capacity. If the size is increased, the added elements are
114   // default constructed.
resize(int new_size)115   void resize(int new_size) {
116     RTC_DCHECK_GE(new_size, 0);
117     RTC_DCHECK_LE(new_size, fixed_capacity);
118     if (new_size > storage_.size) {
119       bounded_inline_vector_impl::DefaultInitializeElements(
120           storage_.data + storage_.size, new_size - storage_.size);
121     } else if (new_size < storage_.size) {
122       bounded_inline_vector_impl::DestroyElements(storage_.data + new_size,
123                                                   storage_.size - new_size);
124     }
125     storage_.size = new_size;
126   }
127 
data()128   const T* data() const { return storage_.data; }
data()129   T* data() { return storage_.data; }
130 
131   const T& operator[](int index) const {
132     RTC_DCHECK_GE(index, 0);
133     RTC_DCHECK_LT(index, storage_.size);
134     return storage_.data[index];
135   }
136   T& operator[](int index) {
137     RTC_DCHECK_GE(index, 0);
138     RTC_DCHECK_LT(index, storage_.size);
139     return storage_.data[index];
140   }
141 
begin()142   T* begin() { return storage_.data; }
end()143   T* end() { return storage_.data + storage_.size; }
begin()144   const T* begin() const { return storage_.data; }
end()145   const T* end() const { return storage_.data + storage_.size; }
cbegin()146   const T* cbegin() const { return storage_.data; }
cend()147   const T* cend() const { return storage_.data + storage_.size; }
148 
149  private:
150   bounded_inline_vector_impl::Storage<T, fixed_capacity> storage_;
151 };
152 
153 }  // namespace webrtc
154 
155 #endif  // RTC_BASE_BOUNDED_INLINE_VECTOR_H_
156