OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 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 #ifndef WEBRTC_BASE_BUFFER_H_ | 11 #ifndef WEBRTC_BASE_BUFFER_H_ |
12 #define WEBRTC_BASE_BUFFER_H_ | 12 #define WEBRTC_BASE_BUFFER_H_ |
13 | 13 |
14 #include <algorithm> // std::swap (pre-C++11) | |
15 #include <cassert> | 14 #include <cassert> |
16 #include <cstring> | 15 #include <cstring> |
17 #include <memory> | 16 #include <memory> |
18 #include <utility> // std::swap (C++11 and later) | 17 #include <utility> |
19 | 18 |
| 19 #include "webrtc/base/array_view.h" |
| 20 #include "webrtc/base/checks.h" |
20 #include "webrtc/base/constructormagic.h" | 21 #include "webrtc/base/constructormagic.h" |
21 #include "webrtc/base/deprecation.h" | 22 #include "webrtc/base/deprecation.h" |
22 | 23 |
23 namespace rtc { | 24 namespace rtc { |
24 | 25 |
25 namespace internal { | 26 namespace internal { |
26 | 27 |
27 // (Internal; please don't use outside this file.) ByteType<T>::t is int if T | 28 // (Internal; please don't use outside this file.) ByteType<T>::t is int if T |
28 // is uint8_t, int8_t, or char; otherwise, it's a compilation error. Use like | 29 // is uint8_t, int8_t, or char; otherwise, it's a compilation error. Use like |
29 // this: | 30 // this: |
(...skipping 25 matching lines...) Expand all Loading... |
55 | 56 |
56 // Construct a buffer with the specified number of uninitialized bytes. | 57 // Construct a buffer with the specified number of uninitialized bytes. |
57 explicit Buffer(size_t size); | 58 explicit Buffer(size_t size); |
58 Buffer(size_t size, size_t capacity); | 59 Buffer(size_t size, size_t capacity); |
59 | 60 |
60 // Construct a buffer and copy the specified number of bytes into it. The | 61 // Construct a buffer and copy the specified number of bytes into it. The |
61 // source array may be (const) uint8_t*, int8_t*, or char*. | 62 // source array may be (const) uint8_t*, int8_t*, or char*. |
62 template <typename T, typename internal::ByteType<T>::t = 0> | 63 template <typename T, typename internal::ByteType<T>::t = 0> |
63 Buffer(const T* data, size_t size) | 64 Buffer(const T* data, size_t size) |
64 : Buffer(data, size, size) {} | 65 : Buffer(data, size, size) {} |
| 66 |
65 template <typename T, typename internal::ByteType<T>::t = 0> | 67 template <typename T, typename internal::ByteType<T>::t = 0> |
66 Buffer(const T* data, size_t size, size_t capacity) | 68 Buffer(const T* data, size_t size, size_t capacity) |
67 : Buffer(size, capacity) { | 69 : Buffer(size, capacity) { |
68 std::memcpy(data_.get(), data, size); | 70 std::memcpy(data_.get(), data, size); |
69 } | 71 } |
70 | 72 |
71 // Construct a buffer from the contents of an array. | 73 // Construct a buffer from the contents of an array. |
72 template <typename T, size_t N, typename internal::ByteType<T>::t = 0> | 74 template <typename T, size_t N, typename internal::ByteType<T>::t = 0> |
73 Buffer(const T(&array)[N]) | 75 Buffer(const T(&array)[N]) |
74 : Buffer(array, N) {} | 76 : Buffer(array, N) {} |
75 | 77 |
76 ~Buffer(); | 78 ~Buffer(); |
77 | 79 |
78 // Get a pointer to the data. Just .data() will give you a (const) uint8_t*, | 80 // Get a pointer to the data. Just .data() will give you a (const) uint8_t*, |
79 // but you may also use .data<int8_t>() and .data<char>(). | 81 // but you may also use .data<int8_t>() and .data<char>(). |
80 template <typename T = uint8_t, typename internal::ByteType<T>::t = 0> | 82 template <typename T = uint8_t, typename internal::ByteType<T>::t = 0> |
81 const T* data() const { | 83 const T* data() const { |
82 assert(IsConsistent()); | 84 assert(IsConsistent()); |
83 return reinterpret_cast<T*>(data_.get()); | 85 return reinterpret_cast<T*>(data_.get()); |
84 } | 86 } |
| 87 |
85 template <typename T = uint8_t, typename internal::ByteType<T>::t = 0> | 88 template <typename T = uint8_t, typename internal::ByteType<T>::t = 0> |
86 T* data() { | 89 T* data() { |
87 assert(IsConsistent()); | 90 assert(IsConsistent()); |
88 return reinterpret_cast<T*>(data_.get()); | 91 return reinterpret_cast<T*>(data_.get()); |
89 } | 92 } |
90 | 93 |
91 size_t size() const { | 94 size_t size() const { |
92 assert(IsConsistent()); | 95 assert(IsConsistent()); |
93 return size_; | 96 return size_; |
94 } | 97 } |
| 98 |
95 size_t capacity() const { | 99 size_t capacity() const { |
96 assert(IsConsistent()); | 100 assert(IsConsistent()); |
97 return capacity_; | 101 return capacity_; |
98 } | 102 } |
99 | 103 |
100 Buffer& operator=(const Buffer& buf) { | 104 Buffer& operator=(const Buffer& buf) { |
101 if (&buf != this) | 105 if (&buf != this) |
102 SetData(buf.data(), buf.size()); | 106 SetData(buf.data(), buf.size()); |
103 return *this; | 107 return *this; |
104 } | 108 } |
| 109 |
105 Buffer& operator=(Buffer&& buf) { | 110 Buffer& operator=(Buffer&& buf) { |
106 assert(IsConsistent()); | 111 assert(IsConsistent()); |
107 assert(buf.IsConsistent()); | 112 assert(buf.IsConsistent()); |
108 size_ = buf.size_; | 113 size_ = buf.size_; |
109 capacity_ = buf.capacity_; | 114 capacity_ = buf.capacity_; |
110 data_ = std::move(buf.data_); | 115 data_ = std::move(buf.data_); |
111 buf.OnMovedFrom(); | 116 buf.OnMovedFrom(); |
112 return *this; | 117 return *this; |
113 } | 118 } |
114 | 119 |
115 bool operator==(const Buffer& buf) const { | 120 bool operator==(const Buffer& buf) const { |
116 assert(IsConsistent()); | 121 assert(IsConsistent()); |
117 return size_ == buf.size() && memcmp(data_.get(), buf.data(), size_) == 0; | 122 return size_ == buf.size() && memcmp(data_.get(), buf.data(), size_) == 0; |
118 } | 123 } |
119 | 124 |
120 bool operator!=(const Buffer& buf) const { return !(*this == buf); } | 125 bool operator!=(const Buffer& buf) const { return !(*this == buf); } |
121 | 126 |
122 // Replace the contents of the buffer. Accepts the same types as the | 127 // The SetData functions replace the contents of the buffer. They accept the |
123 // constructors. | 128 // same input types as the constructors. |
124 template <typename T, typename internal::ByteType<T>::t = 0> | 129 template <typename T, typename internal::ByteType<T>::t = 0> |
125 void SetData(const T* data, size_t size) { | 130 void SetData(const T* data, size_t size) { |
126 assert(IsConsistent()); | 131 assert(IsConsistent()); |
127 size_ = 0; | 132 size_ = 0; |
128 AppendData(data, size); | 133 AppendData(data, size); |
129 } | 134 } |
| 135 |
130 template <typename T, size_t N, typename internal::ByteType<T>::t = 0> | 136 template <typename T, size_t N, typename internal::ByteType<T>::t = 0> |
131 void SetData(const T(&array)[N]) { | 137 void SetData(const T(&array)[N]) { |
132 SetData(array, N); | 138 SetData(array, N); |
133 } | 139 } |
| 140 |
134 void SetData(const Buffer& buf) { SetData(buf.data(), buf.size()); } | 141 void SetData(const Buffer& buf) { SetData(buf.data(), buf.size()); } |
135 | 142 |
136 // Append data to the buffer. Accepts the same types as the constructors. | 143 // Replace the data in the buffer with at most |max_bytes| of data, using the |
| 144 // function |setter|, which should have the following signature: |
| 145 // size_t setter(ArrayView<T> view) |
| 146 // |setter| is given an appropriately typed ArrayView of the area in which to |
| 147 // write the data (i.e. starting at the beginning of the buffer) and should |
| 148 // return the number of bytes actually written. This number must be <= |
| 149 // |max_bytes|. |
| 150 template <typename T = uint8_t, typename F, |
| 151 typename internal::ByteType<T>::t = 0> |
| 152 size_t SetData(size_t max_bytes, F&& setter) { |
| 153 RTC_DCHECK(IsConsistent()); |
| 154 size_ = 0; |
| 155 return AppendData<T>(max_bytes, std::forward<F>(setter)); |
| 156 } |
| 157 |
| 158 // The AppendData functions adds data to the end of the buffer. They accept |
| 159 // the same input types as the constructors. |
137 template <typename T, typename internal::ByteType<T>::t = 0> | 160 template <typename T, typename internal::ByteType<T>::t = 0> |
138 void AppendData(const T* data, size_t size) { | 161 void AppendData(const T* data, size_t size) { |
139 assert(IsConsistent()); | 162 assert(IsConsistent()); |
140 const size_t new_size = size_ + size; | 163 const size_t new_size = size_ + size; |
141 EnsureCapacity(new_size); | 164 EnsureCapacity(new_size); |
142 std::memcpy(data_.get() + size_, data, size); | 165 std::memcpy(data_.get() + size_, data, size); |
143 size_ = new_size; | 166 size_ = new_size; |
144 assert(IsConsistent()); | 167 assert(IsConsistent()); |
145 } | 168 } |
| 169 |
146 template <typename T, size_t N, typename internal::ByteType<T>::t = 0> | 170 template <typename T, size_t N, typename internal::ByteType<T>::t = 0> |
147 void AppendData(const T(&array)[N]) { | 171 void AppendData(const T(&array)[N]) { |
148 AppendData(array, N); | 172 AppendData(array, N); |
149 } | 173 } |
| 174 |
150 void AppendData(const Buffer& buf) { AppendData(buf.data(), buf.size()); } | 175 void AppendData(const Buffer& buf) { AppendData(buf.data(), buf.size()); } |
151 | 176 |
| 177 // Append at most |max_bytes| of data to the end of the buffer, using the |
| 178 // function |setter|, which should have the following signature: |
| 179 // size_t setter(ArrayView<T> view) |
| 180 // |setter| is given an appropriately typed ArrayView of the area in which to |
| 181 // write the data (i.e. starting at the former end of the buffer) and should |
| 182 // return the number of bytes actually written. This number must be <= |
| 183 // |max_bytes|. |
| 184 template <typename T = uint8_t, typename F, |
| 185 typename internal::ByteType<T>::t = 0> |
| 186 size_t AppendData(size_t max_bytes, F&& setter) { |
| 187 RTC_DCHECK(IsConsistent()); |
| 188 const size_t old_size = size_; |
| 189 SetSize(old_size + max_bytes); |
| 190 T *base_ptr = data<T>() + old_size; |
| 191 size_t written_bytes = |
| 192 setter(rtc::ArrayView<T>(base_ptr, max_bytes)); |
| 193 |
| 194 RTC_CHECK_LE(written_bytes, max_bytes); |
| 195 size_ = old_size + written_bytes; |
| 196 RTC_DCHECK(IsConsistent()); |
| 197 return written_bytes; |
| 198 } |
| 199 |
152 // Sets the size of the buffer. If the new size is smaller than the old, the | 200 // Sets the size of the buffer. If the new size is smaller than the old, the |
153 // buffer contents will be kept but truncated; if the new size is greater, | 201 // buffer contents will be kept but truncated; if the new size is greater, |
154 // the existing contents will be kept and the new space will be | 202 // the existing contents will be kept and the new space will be |
155 // uninitialized. | 203 // uninitialized. |
156 void SetSize(size_t size) { | 204 void SetSize(size_t size) { |
157 EnsureCapacity(size); | 205 EnsureCapacity(size); |
158 size_ = size; | 206 size_ = size; |
159 } | 207 } |
160 | 208 |
161 // Ensure that the buffer size can be increased to at least capacity without | 209 // Ensure that the buffer size can be increased to at least capacity without |
162 // further reallocation. (Of course, this operation might need to reallocate | 210 // further reallocation. (Of course, this operation might need to reallocate |
163 // the buffer.) | 211 // the buffer.) |
164 void EnsureCapacity(size_t capacity) { | 212 void EnsureCapacity(size_t capacity) { |
165 assert(IsConsistent()); | 213 assert(IsConsistent()); |
166 if (capacity <= capacity_) | 214 if (capacity <= capacity_) |
167 return; | 215 return; |
168 std::unique_ptr<uint8_t[]> new_data(new uint8_t[capacity]); | 216 std::unique_ptr<uint8_t[]> new_data(new uint8_t[capacity]); |
169 std::memcpy(new_data.get(), data_.get(), size_); | 217 std::memcpy(new_data.get(), data_.get(), size_); |
170 data_ = std::move(new_data); | 218 data_ = std::move(new_data); |
171 capacity_ = capacity; | 219 capacity_ = capacity; |
172 assert(IsConsistent()); | 220 assert(IsConsistent()); |
173 } | 221 } |
174 | 222 |
175 // b.Pass() does the same thing as std::move(b). | 223 // b.Pass() does the same thing as std::move(b). |
176 // Deprecated; remove in March 2016 (bug 5373). | 224 // Deprecated; remove in March 2016 (bug 5373). |
177 RTC_DEPRECATED Buffer&& Pass() { return DEPRECATED_Pass(); } | 225 RTC_DEPRECATED Buffer&& Pass() { return DEPRECATED_Pass(); } |
| 226 |
178 Buffer&& DEPRECATED_Pass() { | 227 Buffer&& DEPRECATED_Pass() { |
179 assert(IsConsistent()); | 228 assert(IsConsistent()); |
180 return std::move(*this); | 229 return std::move(*this); |
181 } | 230 } |
182 | 231 |
183 // Resets the buffer to zero size without altering capacity. Works even if the | 232 // Resets the buffer to zero size without altering capacity. Works even if the |
184 // buffer has been moved from. | 233 // buffer has been moved from. |
185 void Clear() { | 234 void Clear() { |
186 size_ = 0; | 235 size_ = 0; |
187 assert(IsConsistent()); | 236 assert(IsConsistent()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 269 } |
221 | 270 |
222 size_t size_; | 271 size_t size_; |
223 size_t capacity_; | 272 size_t capacity_; |
224 std::unique_ptr<uint8_t[]> data_; | 273 std::unique_ptr<uint8_t[]> data_; |
225 }; | 274 }; |
226 | 275 |
227 } // namespace rtc | 276 } // namespace rtc |
228 | 277 |
229 #endif // WEBRTC_BASE_BUFFER_H_ | 278 #endif // WEBRTC_BASE_BUFFER_H_ |
OLD | NEW |