Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(723)

Side by Side Diff: webrtc/rtc_base/array_view.h

Issue 3007763002: Move array_view.h to webrtc/api/ (Closed)
Patch Set: rebase Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/rtc_base/BUILD.gn ('k') | webrtc/rtc_base/array_view_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 // This header is for backwards compatibility only, and will be removed soon.
12 // Include webrtc/api/array_view.h instead.
13
11 #ifndef WEBRTC_RTC_BASE_ARRAY_VIEW_H_ 14 #ifndef WEBRTC_RTC_BASE_ARRAY_VIEW_H_
12 #define WEBRTC_RTC_BASE_ARRAY_VIEW_H_ 15 #define WEBRTC_RTC_BASE_ARRAY_VIEW_H_
13 16
14 #include "webrtc/rtc_base/checks.h" 17 #include "webrtc/api/array_view.h"
15 #include "webrtc/rtc_base/type_traits.h"
16
17 namespace rtc {
18
19 // Many functions read from or write to arrays. The obvious way to do this is
20 // to use two arguments, a pointer to the first element and an element count:
21 //
22 // bool Contains17(const int* arr, size_t size) {
23 // for (size_t i = 0; i < size; ++i) {
24 // if (arr[i] == 17)
25 // return true;
26 // }
27 // return false;
28 // }
29 //
30 // This is flexible, since it doesn't matter how the array is stored (C array,
31 // std::vector, rtc::Buffer, ...), but it's error-prone because the caller has
32 // to correctly specify the array length:
33 //
34 // Contains17(arr, arraysize(arr)); // C array
35 // Contains17(arr.data(), arr.size()); // std::vector
36 // Contains17(arr, size); // pointer + size
37 // ...
38 //
39 // It's also kind of messy to have two separate arguments for what is
40 // conceptually a single thing.
41 //
42 // Enter rtc::ArrayView<T>. It contains a T pointer (to an array it doesn't
43 // own) and a count, and supports the basic things you'd expect, such as
44 // indexing and iteration. It allows us to write our function like this:
45 //
46 // bool Contains17(rtc::ArrayView<const int> arr) {
47 // for (auto e : arr) {
48 // if (e == 17)
49 // return true;
50 // }
51 // return false;
52 // }
53 //
54 // And even better, because a bunch of things will implicitly convert to
55 // ArrayView, we can call it like this:
56 //
57 // Contains17(arr); // C array
58 // Contains17(arr); // std::vector
59 // Contains17(rtc::ArrayView<int>(arr, size)); // pointer + size
60 // Contains17(nullptr); // nullptr -> empty ArrayView
61 // ...
62 //
63 // ArrayView<T> stores both a pointer and a size, but you may also use
64 // ArrayView<T, N>, which has a size that's fixed at compile time (which means
65 // it only has to store the pointer).
66 //
67 // One important point is that ArrayView<T> and ArrayView<const T> are
68 // different types, which allow and don't allow mutation of the array elements,
69 // respectively. The implicit conversions work just like you'd hope, so that
70 // e.g. vector<int> will convert to either ArrayView<int> or ArrayView<const
71 // int>, but const vector<int> will convert only to ArrayView<const int>.
72 // (ArrayView itself can be the source type in such conversions, so
73 // ArrayView<int> will convert to ArrayView<const int>.)
74 //
75 // Note: ArrayView is tiny (just a pointer and a count if variable-sized, just
76 // a pointer if fix-sized) and trivially copyable, so it's probably cheaper to
77 // pass it by value than by const reference.
78
79 namespace impl {
80
81 // Magic constant for indicating that the size of an ArrayView is variable
82 // instead of fixed.
83 enum : std::ptrdiff_t { kArrayViewVarSize = -4711 };
84
85 // Base class for ArrayViews of fixed nonzero size.
86 template <typename T, std::ptrdiff_t Size>
87 class ArrayViewBase {
88 static_assert(Size > 0, "ArrayView size must be variable or non-negative");
89
90 public:
91 ArrayViewBase(T* data, size_t size) : data_(data) {}
92
93 static constexpr size_t size() { return Size; }
94 static constexpr bool empty() { return false; }
95 T* data() const { return data_; }
96
97 protected:
98 static constexpr bool fixed_size() { return true; }
99
100 private:
101 T* data_;
102 };
103
104 // Specialized base class for ArrayViews of fixed zero size.
105 template <typename T>
106 class ArrayViewBase<T, 0> {
107 public:
108 explicit ArrayViewBase(T* data, size_t size) {}
109
110 static constexpr size_t size() { return 0; }
111 static constexpr bool empty() { return true; }
112 T* data() const { return nullptr; }
113
114 protected:
115 static constexpr bool fixed_size() { return true; }
116 };
117
118 // Specialized base class for ArrayViews of variable size.
119 template <typename T>
120 class ArrayViewBase<T, impl::kArrayViewVarSize> {
121 public:
122 ArrayViewBase(T* data, size_t size)
123 : data_(size == 0 ? nullptr : data), size_(size) {}
124
125 size_t size() const { return size_; }
126 bool empty() const { return size_ == 0; }
127 T* data() const { return data_; }
128
129 protected:
130 static constexpr bool fixed_size() { return false; }
131
132 private:
133 T* data_;
134 size_t size_;
135 };
136
137 } // namespace impl
138
139 template <typename T, std::ptrdiff_t Size = impl::kArrayViewVarSize>
140 class ArrayView final : public impl::ArrayViewBase<T, Size> {
141 public:
142 using value_type = T;
143 using const_iterator = const T*;
144
145 // Construct an ArrayView from a pointer and a length.
146 template <typename U>
147 ArrayView(U* data, size_t size)
148 : impl::ArrayViewBase<T, Size>::ArrayViewBase(data, size) {
149 RTC_DCHECK_EQ(size == 0 ? nullptr : data, this->data());
150 RTC_DCHECK_EQ(size, this->size());
151 RTC_DCHECK_EQ(!this->data(),
152 this->size() == 0); // data is null iff size == 0.
153 }
154
155 // Construct an empty ArrayView. Note that fixed-size ArrayViews of size > 0
156 // cannot be empty.
157 ArrayView() : ArrayView(nullptr, 0) {}
158 ArrayView(std::nullptr_t) : ArrayView() {}
159 ArrayView(std::nullptr_t, size_t size)
160 : ArrayView(static_cast<T*>(nullptr), size) {
161 static_assert(Size == 0 || Size == impl::kArrayViewVarSize, "");
162 RTC_DCHECK_EQ(0, size);
163 }
164
165 // Construct an ArrayView from an array.
166 template <typename U, size_t N>
167 ArrayView(U (&array)[N]) : ArrayView(array, N) {
168 static_assert(Size == N || Size == impl::kArrayViewVarSize,
169 "Array size must match ArrayView size");
170 }
171
172 // (Only if size is fixed.) Construct an ArrayView from any type U that has a
173 // static constexpr size() method whose return value is equal to Size, and a
174 // data() method whose return value converts implicitly to T*. In particular,
175 // this means we allow conversion from ArrayView<T, N> to ArrayView<const T,
176 // N>, but not the other way around. We also don't allow conversion from
177 // ArrayView<T> to ArrayView<T, N>, or from ArrayView<T, M> to ArrayView<T,
178 // N> when M != N.
179 template <typename U,
180 typename std::enable_if<
181 Size != impl::kArrayViewVarSize &&
182 HasDataAndSize<U, T>::value>::type* = nullptr>
183 ArrayView(U& u) : ArrayView(u.data(), u.size()) {
184 static_assert(U::size() == Size, "Sizes must match exactly");
185 }
186
187 // (Only if size is variable.) Construct an ArrayView from any type U that
188 // has a size() method whose return value converts implicitly to size_t, and
189 // a data() method whose return value converts implicitly to T*. In
190 // particular, this means we allow conversion from ArrayView<T> to
191 // ArrayView<const T>, but not the other way around. Other allowed
192 // conversions include
193 // ArrayView<T, N> to ArrayView<T> or ArrayView<const T>,
194 // std::vector<T> to ArrayView<T> or ArrayView<const T>,
195 // const std::vector<T> to ArrayView<const T>,
196 // rtc::Buffer to ArrayView<uint8_t> or ArrayView<const uint8_t>, and
197 // const rtc::Buffer to ArrayView<const uint8_t>.
198 template <
199 typename U,
200 typename std::enable_if<Size == impl::kArrayViewVarSize &&
201 HasDataAndSize<U, T>::value>::type* = nullptr>
202 ArrayView(U& u) : ArrayView(u.data(), u.size()) {}
203
204 // Indexing and iteration. These allow mutation even if the ArrayView is
205 // const, because the ArrayView doesn't own the array. (To prevent mutation,
206 // use a const element type.)
207 T& operator[](size_t idx) const {
208 RTC_DCHECK_LT(idx, this->size());
209 RTC_DCHECK(this->data());
210 return this->data()[idx];
211 }
212 T* begin() const { return this->data(); }
213 T* end() const { return this->data() + this->size(); }
214 const T* cbegin() const { return this->data(); }
215 const T* cend() const { return this->data() + this->size(); }
216
217 ArrayView<T> subview(size_t offset, size_t size) const {
218 return offset < this->size()
219 ? ArrayView<T>(this->data() + offset,
220 std::min(size, this->size() - offset))
221 : ArrayView<T>();
222 }
223 ArrayView<T> subview(size_t offset) const {
224 return subview(offset, this->size());
225 }
226 };
227
228 // Comparing two ArrayViews compares their (pointer,size) pairs; it does *not*
229 // dereference the pointers.
230 template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2>
231 bool operator==(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) {
232 return a.data() == b.data() && a.size() == b.size();
233 }
234 template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2>
235 bool operator!=(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) {
236 return !(a == b);
237 }
238
239 // Variable-size ArrayViews are the size of two pointers; fixed-size ArrayViews
240 // are the size of one pointer. (And as a special case, fixed-size ArrayViews
241 // of size 0 require no storage.)
242 static_assert(sizeof(ArrayView<int>) == 2 * sizeof(int*), "");
243 static_assert(sizeof(ArrayView<int, 17>) == sizeof(int*), "");
244 static_assert(std::is_empty<ArrayView<int, 0>>::value, "");
245
246 template <typename T>
247 inline ArrayView<T> MakeArrayView(T* data, size_t size) {
248 return ArrayView<T>(data, size);
249 }
250
251 } // namespace rtc
252 18
253 #endif // WEBRTC_RTC_BASE_ARRAY_VIEW_H_ 19 #endif // WEBRTC_RTC_BASE_ARRAY_VIEW_H_
OLDNEW
« no previous file with comments | « webrtc/rtc_base/BUILD.gn ('k') | webrtc/rtc_base/array_view_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698