CARLA
 
载入中...
搜索中...
未找到
carla/Buffer.h
浏览该文件的文档.
1// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#pragma once
8
9#include "carla/Debug.h"
10#include "carla/Exception.h"
11#include "carla/Logging.h"
12
13#include <boost/asio/buffer.hpp>
14
15#include <cstdint>
16#include <limits>
17#include <memory>
18#include <type_traits>
19
20#ifdef LIBCARLA_INCLUDED_FROM_UE4
22#include "Containers/Array.h"
24#endif // LIBCARLA_INCLUDED_FROM_UE4
25
26namespace carla {
27
28 class BufferPool;
29 class BufferView;
30
31 /// A piece of raw data.
32 ///
33 /// Note that if more capacity is needed, a new memory block is allocated and
34 /// the old one is deleted. This means that by default the buffer can only
35 /// grow. To release the memory use `clear` or `pop`.
36 ///
37 /// This is a move-only type, meant to be cheap to pass by value. If the
38 /// buffer is retrieved from a BufferPool, the memory is automatically pushed
39 /// back to the pool on destruction.
40 ///
41 /// @warning Creating a buffer bigger than max_size() is undefined.
42 class Buffer {
43
44 // =========================================================================
45 /// @name Member types
46 // =========================================================================
47 /// @{
48
49 public:
50
51 using value_type = unsigned char;
52
53 using size_type = uint32_t;
54
56
57 using const_iterator = const value_type *;
58
59 /// @}
60 // =========================================================================
61 /// @name Construction and destruction
62 // =========================================================================
63 /// @{
64
65 public:
66
67 /// Create an empty buffer.
68 Buffer() = default;
69
70 /// Create a buffer with @a size bytes allocated.
72 : _size(size),
74 _data(std::make_unique<value_type[]>(size)) {}
75
76 /// @copydoc Buffer(size_type)
77 explicit Buffer(uint64_t size)
78 : Buffer([size]() {
79 if (size > max_size()) {
80 throw_exception(std::invalid_argument("message size too big"));
81 }
82 return static_cast<size_type>(size);
83 } ()) {}
84
85 /// Copy @a source into this buffer. Allocates the necessary memory.
86 template <typename T>
87 explicit Buffer(const T &source) {
88 copy_from(source);
89 }
90
91 explicit Buffer(const value_type *data, size_type size) {
93 }
94
95 /// @copydoc Buffer(size_type)
96 explicit Buffer(const value_type *data, uint64_t size)
97 : Buffer(data, [size]() {
98 if (size > max_size()) {
99 throw_exception(std::invalid_argument("message size too big"));
100 }
101 return static_cast<size_type>(size);
102 } ()) {}
103
104 Buffer(const Buffer &) = delete;
105
106 Buffer(Buffer &&rhs) noexcept
107 : _parent_pool(std::move(rhs._parent_pool)),
108 _size(rhs._size),
109 _capacity(rhs._capacity),
110 _data(rhs.pop()) {}
111
113 if (_capacity > 0u) {
115 }
116 }
117
118 /// @}
119 // =========================================================================
120 /// @name Assignment
121 // =========================================================================
122 /// @{
123
124 public:
125
126 Buffer &operator=(const Buffer &) = delete;
127
128 Buffer &operator=(Buffer &&rhs) noexcept {
129 _parent_pool = std::move(rhs._parent_pool);
130 _size = rhs._size;
131 _capacity = rhs._capacity;
132 _data = rhs.pop();
133 return *this;
134 }
135
136 /// @}
137 // =========================================================================
138 /// @name Data access
139 // =========================================================================
140 /// @{
141
142 public:
143
144 /// Access the byte at position @a i.
145 const value_type &operator[](size_t i) const {
146 return _data[i];
147 }
148
149 /// Access the byte at position @a i.
151 return _data[i];
152 }
153
154 /// Direct access to the allocated memory or nullptr if no memory is
155 /// allocated.
156 const value_type *data() const noexcept {
157 return _data.get();
158 }
159
160 /// Direct access to the allocated memory or nullptr if no memory is
161 /// allocated.
162 value_type *data() noexcept {
163 return _data.get();
164 }
165
166 /// Make a boost::asio::buffer from this buffer.
167 ///
168 /// @warning Boost.Asio buffers do not own the data, it's up to the caller
169 /// to not delete the memory that this buffer holds until the asio buffer is
170 /// no longer used.
171 boost::asio::const_buffer cbuffer() const noexcept {
172 return {data(), size()};
173 }
174
175 /// @copydoc cbuffer()
176 boost::asio::const_buffer buffer() const noexcept {
177 return cbuffer();
178 }
179
180 /// @copydoc cbuffer()
181 boost::asio::mutable_buffer buffer() noexcept {
182 return {data(), size()};
183 }
184
185 /// @}
186 // =========================================================================
187 /// @name Capacity
188 // =========================================================================
189 /// @{
190
191 public:
192
193 bool empty() const noexcept {
194 return _size == 0u;
195 }
196
197 size_type size() const noexcept {
198 return _size;
199 }
200
201 static constexpr size_type max_size() noexcept {
202 return (std::numeric_limits<size_type>::max)();
203 }
204
205 size_type capacity() const noexcept {
206 return _capacity;
207 }
208
209 /// @}
210 // =========================================================================
211 /// @name Iterators
212 // =========================================================================
213 /// @{
214
215 public:
216
217 const_iterator cbegin() const noexcept {
218 return _data.get();
219 }
220
221 const_iterator begin() const noexcept {
222 return cbegin();
223 }
224
225 iterator begin() noexcept {
226 return _data.get();
227 }
228
229 const_iterator cend() const noexcept {
230 return cbegin() + size();
231 }
232
233 const_iterator end() const noexcept {
234 return cend();
235 }
236
237 iterator end() noexcept {
238 return begin() + size();
239 }
240
241 /// @}
242 // =========================================================================
243 /// @name Modifiers
244 // =========================================================================
245 /// @{
246
247 public:
248
249 /// Reset the size of this buffer. If the capacity is not enough, the
250 /// current memory is discarded and a new block of size @a size is
251 /// allocated.
253 if (_capacity < size) {
254 log_debug("allocating buffer of", size, "bytes");
255 _data = std::make_unique<value_type[]>(size);
256 _capacity = size;
257 }
258 _size = size;
259 }
260
261 /// @copydoc reset(size_type)
262 void reset(uint64_t size) {
263 if (size > max_size()) {
264 throw_exception(std::invalid_argument("message size too big"));
265 }
266 reset(static_cast<size_type>(size));
267 }
268
269 /// Resize the buffer, a new block of size @a size is
270 /// allocated if the capacity is not enough and the data is copied.
271 void resize(uint64_t size) {
272 if(_capacity < size) {
273 std::unique_ptr<value_type[]> data = std::move(_data);
274 uint64_t old_size = size;
275 reset(size);
276 copy_from(data.get(), static_cast<size_type>(old_size));
277 }
278 _size = static_cast<size_type>(size);
279 }
280
281 /// Release the contents of this buffer and set its size and capacity to
282 /// zero.
283 std::unique_ptr<value_type[]> pop() noexcept {
284 _size = 0u;
285 _capacity = 0u;
286 return std::move(_data);
287 }
288
289 /// Clear the contents of this buffer and set its size and capacity to zero.
290 /// Deletes allocated memory.
291 void clear() noexcept {
292 pop();
293 }
294
295 /// @}
296 // =========================================================================
297 /// @name copy_from
298 // =========================================================================
299 /// @{
300
301 public:
302
303 /// Copy @a source into this buffer. Allocates memory if necessary.
304 template <typename T>
305 void copy_from(const T &source) {
306 copy_from(0u, source);
307 }
308
309 /// Copy @a size bytes of the memory pointed by @a data into this buffer.
310 /// Allocates memory if necessary.
312 copy_from(0u, data, size);
313 }
314
315 /// Copy @a source into this buffer leaving at the front an offset of @a
316 /// offset bytes uninitialized. Allocates memory if necessary.
317 void copy_from(size_type offset, const Buffer &rhs) {
318 copy_from(offset, rhs.buffer());
319 }
320
321 /// @copydoc copy_from(size_type, const Buffer &)
322 template <typename T>
323 typename std::enable_if<boost::asio::is_const_buffer_sequence<T>::value>::type
324 copy_from(size_type offset, const T &source) {
325 reset(boost::asio::buffer_size(source) + offset);
326 DEBUG_ASSERT(boost::asio::buffer_size(source) == size() - offset);
327 DEBUG_ONLY(auto bytes_copied = )
328 boost::asio::buffer_copy(buffer() + offset, source);
329 DEBUG_ASSERT(bytes_copied == size() - offset);
330 }
331
332 /// @copydoc copy_from(size_type, const Buffer &)
333 template <typename T>
334 typename std::enable_if<!boost::asio::is_const_buffer_sequence<T>::value>::type
335 copy_from(size_type offset, const T &source) {
336 copy_from(offset, boost::asio::buffer(source));
337 }
338
339#ifdef LIBCARLA_INCLUDED_FROM_UE4
340 /// @copydoc copy_from(size_type, const Buffer &)
341 template <typename T>
342 void copy_from(size_type offset, const TArray<T> &source) {
343 copy_from(
344 offset,
345 reinterpret_cast<const value_type *>(source.GetData()),
346 sizeof(T) * source.Num());
347 }
348#endif // LIBCARLA_INCLUDED_FROM_UE4
349
350 /// Copy @a size bytes of the memory pointed by @a data into this buffer,
351 /// leaving at the front an offset of @a offset bytes uninitialized.
352 /// Allocates memory if necessary.
354 copy_from(offset, boost::asio::buffer(data, size));
355 }
356
357 /// @}
358
359 private:
360
361 void ReuseThisBuffer();
362
363 friend class BufferPool;
364 friend class BufferView;
365
366 std::weak_ptr<BufferPool> _parent_pool;
367
369
371
372 std::unique_ptr<value_type[]> _data = nullptr;
373 };
374
375} // namespace carla
#define DEBUG_ASSERT(predicate)
Definition Debug.h:66
#define DEBUG_ONLY(code)
Definition Debug.h:55
A pool of Buffer.
Definition BufferPool.h:30
Creating a constant view from an existing buffer
Definition BufferView.h:32
A piece of raw data.
std::unique_ptr< value_type[]> _data
Buffer & operator=(const Buffer &)=delete
const_iterator begin() const noexcept
const value_type * data() const noexcept
Direct access to the allocated memory or nullptr if no memory is allocated.
size_type _size
static constexpr size_type max_size() noexcept
std::enable_if<!boost::asio::is_const_buffer_sequence< T >::value >::type copy_from(size_type offset, const T &source)
Copy source into this buffer leaving at the front an offset of offset bytes uninitialized.
void reset(size_type size)
Reset the size of this buffer.
size_type size() const noexcept
const_iterator cend() const noexcept
Buffer()=default
Create an empty buffer.
void copy_from(size_type offset, const Buffer &rhs)
Copy source into this buffer leaving at the front an offset of offset bytes uninitialized.
std::unique_ptr< value_type[]> pop() noexcept
Release the contents of this buffer and set its size and capacity to zero.
value_type & operator[](size_t i)
Access the byte at position i.
void copy_from(const T &source)
Copy source into this buffer. Allocates memory if necessary.
void resize(uint64_t size)
Resize the buffer, a new block of size size is allocated if the capacity is not enough and the data i...
void ReuseThisBuffer()
boost::asio::const_buffer buffer() const noexcept
Make a boost::asio::buffer from this buffer.
Buffer(size_type size)
Create a buffer with size bytes allocated.
size_type capacity() const noexcept
uint32_t size_type
size_type _capacity
Buffer & operator=(Buffer &&rhs) noexcept
void copy_from(const value_type *data, size_type size)
Copy size bytes of the memory pointed by data into this buffer.
std::weak_ptr< BufferPool > _parent_pool
boost::asio::mutable_buffer buffer() noexcept
Make a boost::asio::buffer from this buffer.
std::enable_if< boost::asio::is_const_buffer_sequence< T >::value >::type copy_from(size_type offset, const T &source)
Copy source into this buffer leaving at the front an offset of offset bytes uninitialized.
bool empty() const noexcept
Buffer(const value_type *data, size_type size)
Buffer(const T &source)
Copy source into this buffer. Allocates the necessary memory.
const value_type * const_iterator
void copy_from(size_type offset, const value_type *data, size_type size)
Copy size bytes of the memory pointed by data into this buffer, leaving at the front an offset of off...
Buffer(const value_type *data, uint64_t size)
Create a buffer with size bytes allocated.
iterator begin() noexcept
const_iterator cbegin() const noexcept
const_iterator end() const noexcept
value_type * data() noexcept
Direct access to the allocated memory or nullptr if no memory is allocated.
value_type * iterator
Buffer(Buffer &&rhs) noexcept
boost::asio::const_buffer cbuffer() const noexcept
Make a boost::asio::buffer from this buffer.
void reset(uint64_t size)
Reset the size of this buffer.
void clear() noexcept
Clear the contents of this buffer and set its size and capacity to zero.
iterator end() noexcept
Buffer(uint64_t size)
Create a buffer with size bytes allocated.
Buffer(const Buffer &)=delete
unsigned char value_type
const value_type & operator[](size_t i) const
Access the byte at position i.
This file contains definitions of common data structures used in traffic manager.
Definition Carla.cpp:133
void throw_exception(const std::exception &e)
Definition Carla.cpp:135
static void log_debug(Args &&... args)
Definition Logging.h:68