Chromium Code Reviews| 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 // insert the data (i.e. starting at the beginning of the buffer) and should | |
|
kwiberg-webrtc
2016/02/23 10:06:10
"insert" -> "write", maybe?
ossu
2016/02/23 10:11:39
Yeah, that's probably clearer. I'll change that.
| |
| 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 // insert the data (i.e. starting at the former end of the buffer) and should | |
|
kwiberg-webrtc
2016/02/23 10:06:10
insert -> write
ossu
2016/02/23 10:11:39
Acknowledged.
| |
| 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 |