Embedded Template Library 1.0
Loading...
Searching...
No Matches
mem_cast.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2021 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_MEM_CAST_INCLUDED
32#define ETL_MEM_CAST_INCLUDED
33
34#include "platform.h"
35#include "memory.h"
36#include "static_assert.h"
37#include "largest.h"
38#include "utility.h"
39#include "placement_new.h"
40#include "exception.h"
41#include "error_handler.h"
42#include "file_error_numbers.h"
43#include "binary.h"
44
45#include <stdint.h>
46#include <string.h>
47
48namespace etl
49{
50 //***************************************************************************
52 //***************************************************************************
62
63 //***************************************************************************
65 //***************************************************************************
67 {
68 public:
69
71 : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:size", ETL_MEM_CAST_FILE_ID"A"), file_name_, line_number_)
72 {
73 }
74 };
75
76 //***************************************************************************
78 //***************************************************************************
80 {
81 public:
82
84 : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:null pointer", ETL_MEM_CAST_FILE_ID"B"), file_name_, line_number_)
85 {
86 }
87 };
88
89 //*****************************************************************************
91 //*****************************************************************************
92 template <size_t Size_, size_t Alignment_>
94 {
95 public:
96
97 static ETL_CONSTANT size_t Size = Size_;
98 static ETL_CONSTANT size_t Alignment = Alignment_;
99
100 ETL_STATIC_ASSERT((Alignment == 1) || etl::is_power_of_2<Alignment>::value, "Alignment must be a power of 2");
101
102 //***********************************
104 //***********************************
106 : buffer()
107 {
108 }
109
110 //***********************************
112 //***********************************
113 template <size_t Other_Size, size_t Other_Alignment>
115 {
116 ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large");
117
118 memcpy(buffer, other.buffer, Size_);
119 }
120
121 //***********************************
123 //***********************************
124 template <size_t Other_Size, size_t Other_Alignment>
126 {
127 ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large");
128
129 memcpy(buffer, rhs.buffer, Size_);
130
131 return *this;
132 }
133
134 //***********************************
136 //***********************************
137 template <typename T>
138 void assign(const T& value)
139 {
140 ETL_STATIC_ASSERT(Size >= sizeof(T), "Type size is too large");
141
142 ::new (static_cast<void*>(buffer.raw)) T(value);
143 }
144
145 //***********************************
147 //***********************************
148 template <typename T>
149 void assign_at_offset(size_t offset, const T& value)
150 {
151 char* p = static_cast<char*>(buffer.raw) + offset;
152 ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
153
154 ::new (p) T(value);
155 }
156
157 //***********************************
159 //***********************************
160 template <typename T, size_t Offset>
161 void assign_at_offset(const T& value)
162 {
163 char* p = static_cast<char*>(buffer.raw) + Offset;
164 ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large");
165
166 ::new (p) T(value);
167 }
168
169#if ETL_USING_CPP11
170 //***********************************
172 //***********************************
173 template <typename T, typename... TArgs>
174 T& emplace(TArgs... args)
175 {
176 ETL_STATIC_ASSERT(Size >= sizeof(T), "Type size is too large");
177
178 ::new (static_cast<void*>(buffer.raw)) T(etl::forward<TArgs>(args)...);
179
180 return ref<T>();
181 }
182
183 //***********************************
185 //***********************************
187 T& emplace_at_offset(size_t offset, TArgs... args)
188 {
189 char* p = static_cast<char*>(buffer.raw) + offset;
190 ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
191
192 ::new (p) T(etl::forward<TArgs>(args)...);
193
194 return ref_at_offset<T>(offset);
195 }
196
197 //***********************************
199 //***********************************
200 template <typename T, size_t Offset, typename... TArgs>
201 T& emplace_at_offset(TArgs... args)
202 {
203 char* p = static_cast<char*>(buffer.raw) + Offset;
204 ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large");
205
206 ::new (p) T(etl::forward<TArgs>(args)...);
207
208 return ref_at_offset<T, Offset>();
209 }
210#endif
211
212 //***********************************
214 //***********************************
215 template <typename T>
216 ETL_NODISCARD T& ref()
217 {
218 ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of type too large for storage");
219
220 return *reinterpret_cast<T*>(buffer.raw);
221 }
222
223 //***********************************
225 //***********************************
226 template <typename T>
227 ETL_NODISCARD const T& ref() const
228 {
229 ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of type too large for storage");
230
231 return *reinterpret_cast<const T*>(buffer.raw);
232 }
233
234 //***********************************
236 //***********************************
237 template <typename T>
238 ETL_NODISCARD T& ref_at_offset(size_t offset)
239 {
240 ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
241
242 return *reinterpret_cast<T*>(buffer.raw + offset);
243 }
244
245 //***********************************
247 //***********************************
248 template <typename T>
249 ETL_NODISCARD const T& ref_at_offset(size_t offset) const
250 {
251 ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
252
253 return *reinterpret_cast<const T*>(buffer.raw + offset);
254 }
255
256 //***********************************
258 //***********************************
259 template <typename T, size_t Offset>
260 ETL_NODISCARD T& ref_at_offset()
261 {
262 ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of type too large for storage");
263
264 return *reinterpret_cast<T*>(buffer.raw + Offset);
265 }
266
267 //***********************************
269 //***********************************
270 template <typename T, size_t Offset>
271 ETL_NODISCARD const T& ref_at_offset() const
272 {
273 ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of type too large for storage");
274
275 return *reinterpret_cast<const T*>(buffer.raw + Offset);
276 }
277
278 //***********************************
280 //***********************************
281 ETL_NODISCARD static ETL_CONSTEXPR size_t size()
282 {
283 return Size;
284 }
285
286 //***********************************
288 //***********************************
289 ETL_NODISCARD static ETL_CONSTEXPR size_t alignment()
290 {
291 return Alignment;
292 }
293
294 //***********************************
296 //***********************************
297 ETL_NODISCARD char* data()
298 {
299 return buffer;
300 }
301
302 //***********************************
304 //***********************************
305 ETL_NODISCARD const char* data() const
306 {
307 return buffer;
308 }
309
310 private:
311
314 };
315
316 template <size_t Size_, size_t Alignment_>
317 ETL_CONSTANT size_t mem_cast<Size_, Alignment_>::Size;
318
319 template <size_t Size_, size_t Alignment_>
320 ETL_CONSTANT size_t mem_cast<Size_, Alignment_>::Alignment;
321
322 //*****************************************************************************
324 //*****************************************************************************
326 {
327 public:
328
329 static ETL_CONSTANT size_t Undefined_Size = etl::integral_limits<size_t>::max;
330
331 //***********************************
333 //***********************************
335 : pbuffer(ETL_NULLPTR)
336 , buffer_size(Undefined_Size)
337 {
338 }
339
340 //***********************************
342 //***********************************
343 mem_cast_ptr(char* pbuffer_, size_t buffer_size_ = Undefined_Size)
344 : pbuffer(pbuffer_)
345 , buffer_size(buffer_size_)
346 {
347 }
348
349 //***********************************
351 //***********************************
353 : pbuffer(other.pbuffer)
354 , buffer_size(other.buffer_size)
355 {
356 }
357
358 //***********************************
360 //***********************************
362 {
363 pbuffer = rhs.pbuffer;
364 buffer_size = rhs.buffer_size;
365
366 return *this;
367 }
368
369 //***********************************
371 //***********************************
372 template <typename T>
373 void assign(const T& value)
374 {
375 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
376 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
377
378 ::new (pbuffer) T(value);
379 }
380
381 //***********************************
383 //***********************************
384 template <typename T>
385 void assign_at_offset(size_t offset, const T& value)
386 {
387 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
388 char* p = pbuffer + offset;
389 ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
390
391 ::new (p) T(value);
392 }
393
394 //***********************************
396 //***********************************
397 template <typename T, size_t Offset>
398 void assign_at_offset(const T& value)
399 {
400 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
401 char* p = pbuffer + Offset;
402 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
403
404 ::new (p) T(value);
405 }
406
407#if ETL_USING_CPP11
408 //***********************************
410 //***********************************
411 template <typename T, typename... TArgs>
412 T& emplace(TArgs... args)
413 {
414 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
415 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
416
417 ::new (pbuffer) T(etl::forward<TArgs>(args)...);
418
419 return ref<T>();
420 }
421
422 //***********************************
424 //***********************************
425 template <typename T, typename... TArgs>
426 T& emplace_at_offset(size_t offset, TArgs... args)
427 {
428 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
429 char* p = pbuffer + offset;
430 ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
431
432 ::new (p) T(etl::forward<TArgs>(args)...);
433
434 return ref_at_offset<T>(offset);
435 }
436
437 //***********************************
439 //***********************************
440 template <typename T, size_t Offset, typename... TArgs>
441 T& emplace_at_offset(TArgs... args)
442 {
443 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
444 char* p = pbuffer + Offset;
445 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
446
447 ::new (p) T(etl::forward<TArgs>(args)...);
448
449 return ref_at_offset<T, Offset>();
450 }
451#endif
452
453 //***********************************
455 //***********************************
456 template <typename T>
457 ETL_NODISCARD T& ref()
458 {
459 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
460 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
461
462 T* p = reinterpret_cast<T*>(pbuffer);
463
464 return *p;
465 }
466
467 //***********************************
469 //***********************************
470 template <typename T>
471 ETL_NODISCARD const T& ref() const
472 {
473 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
474 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
475
476 const T* p = reinterpret_cast<const T*>(pbuffer);
477
478 return *p;
479 }
480
481 //***********************************
483 //***********************************
484 template <typename T>
485 ETL_NODISCARD T& ref_at_offset(size_t offset)
486 {
487 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
488 ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
489
490 T* p = reinterpret_cast<T*>(pbuffer + offset);
491
492 return *p;
493 }
494
495 //***********************************
497 //***********************************
498 template <typename T>
499 ETL_NODISCARD const T& ref_at_offset(size_t offset) const
500 {
501 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
502 ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
503
504 const T* p = reinterpret_cast<const T*>(pbuffer + offset);
505
506 return *p;
507 }
508
509 //***********************************
511 //***********************************
512 template <typename T, size_t Offset>
513 ETL_NODISCARD T& ref_at_offset()
514 {
515 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
516 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
517
518 T* p = reinterpret_cast<T*>(pbuffer + Offset);
519
520 return *p;
521 }
522
523 //***********************************
525 //***********************************
526 template <typename T, size_t Offset>
527 ETL_NODISCARD const T& ref_at_offset() const
528 {
529 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
530 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
531
532 const T* p = reinterpret_cast<const T*>(pbuffer + Offset);
533
534 return *p;
535 }
536
537 //***********************************
539 //***********************************
540 ETL_NODISCARD size_t size() const
541 {
542 return buffer_size;
543 }
544
545 //***********************************
547 //***********************************
548 ETL_NODISCARD size_t alignment() const
549 {
550 typedef typename etl::smallest_uint_for_bits<sizeof(uintptr_t)* CHAR_BIT>::type type;
551
552 const type p = reinterpret_cast<type>(pbuffer);
553
554 return size_t(1U) << etl::count_trailing_zeros(p);
555 }
556
557 //***********************************
559 //***********************************
560 void data(char* pbuffer_, size_t buffer_size_ = Undefined_Size)
561 {
562 pbuffer = pbuffer_;
563 buffer_size = buffer_size_;
564 }
565
566 //***********************************
568 //***********************************
569 ETL_NODISCARD char* data()
570 {
571 return pbuffer;
572 }
573
574 //***********************************
576 //***********************************
577 ETL_NODISCARD const char* data() const
578 {
579 return pbuffer;
580 }
581
582 private:
583
585 char* pbuffer;
586 size_t buffer_size;
587 };
588
589 //*****************************************************************************
592 //*****************************************************************************
593#if ETL_USING_CPP11 && !defined(ETL_MEM_CAST_FORCE_CPP03_IMPLEMENTATION)
594 template <typename... TTypes>
595 using mem_cast_types = etl::mem_cast<etl::largest<TTypes...>::size, etl::largest<TTypes...>::alignment>;
596#else
597 template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char,
598 typename T5 = char, typename T6 = char, typename T7 = char, typename T8 = char,
599 typename T9 = char, typename T10 = char, typename T11 = char, typename T12 = char,
600 typename T13 = char, typename T14 = char, typename T15 = char, typename T16 = char>
601 struct mem_cast_types : public etl::mem_cast<etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size,
602 etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment>
603 {
604 };
605#endif
606}
607
608#endif
The base class for array_wrapper exceptions.
Definition mem_cast.h:54
The exception thrown when the pointer is null.
Definition mem_cast.h:80
mem_cast_ptr
Definition mem_cast.h:326
ETL_NODISCARD T & ref_at_offset()
Get a reference to T at offset (static)
Definition mem_cast.h:513
ETL_NODISCARD size_t size() const
Get the size of the buffer.
Definition mem_cast.h:540
ETL_NODISCARD char * data()
Get a pointer to the external buffer.
Definition mem_cast.h:569
ETL_NODISCARD const char * data() const
Get const a pointer to the external buffer.
Definition mem_cast.h:577
void assign_at_offset(size_t offset, const T &value)
Assign from value at offset.
Definition mem_cast.h:385
ETL_NODISCARD const T & ref_at_offset(size_t offset) const
Get a const reference to T at offset (dynamic)
Definition mem_cast.h:499
ETL_NODISCARD const T & ref_at_offset() const
Get a const reference to T at offset (static)
Definition mem_cast.h:527
ETL_NODISCARD T & ref_at_offset(size_t offset)
Get a reference to T at offset (dynamic)
Definition mem_cast.h:485
ETL_NODISCARD const T & ref() const
Get a const reference to T.
Definition mem_cast.h:471
ETL_NODISCARD T & ref()
Get a reference to T.
Definition mem_cast.h:457
mem_cast_ptr(const mem_cast_ptr &other)
Copy construct.
Definition mem_cast.h:352
mem_cast_ptr(char *pbuffer_, size_t buffer_size_=Undefined_Size)
Construct with pointer to buffer and optional size.
Definition mem_cast.h:343
void assign(const T &value)
Assign from value.
Definition mem_cast.h:373
ETL_NODISCARD size_t alignment() const
Get the alignment of the buffer.
Definition mem_cast.h:548
void data(char *pbuffer_, size_t buffer_size_=Undefined_Size)
Set the pointer to the external buffer.
Definition mem_cast.h:560
void assign_at_offset(const T &value)
Assign from value at offset.
Definition mem_cast.h:398
mem_cast_ptr()
Default constructor.
Definition mem_cast.h:334
The exception thrown when the type size is too large.
Definition mem_cast.h:67
mem_cast
Definition mem_cast.h:94
void assign_at_offset(size_t offset, const T &value)
Assign from value at offset.
Definition mem_cast.h:149
mem_cast(const mem_cast< Other_Size, Other_Alignment > &other)
Copy constructor.
Definition mem_cast.h:114
void assign_at_offset(const T &value)
Assign from value at offset.
Definition mem_cast.h:161
mem_cast()
Default constructor.
Definition mem_cast.h:105
ETL_NODISCARD const T & ref_at_offset(size_t offset) const
Get a const reference to T at offset (dynamic)
Definition mem_cast.h:249
void assign(const T &value)
Assign from value.
Definition mem_cast.h:138
ETL_NODISCARD char * data()
Get a pointer to the internal buffer.
Definition mem_cast.h:297
ETL_NODISCARD T & ref_at_offset(size_t offset)
Get a reference to T at offset (dynamic)
Definition mem_cast.h:238
ETL_NODISCARD T & ref()
Get a reference to T.
Definition mem_cast.h:216
static ETL_NODISCARD ETL_CONSTEXPR size_t alignment()
Get the alignment of the buffer.
Definition mem_cast.h:289
ETL_NODISCARD T & ref_at_offset()
Get a reference to T at offset (static)
Definition mem_cast.h:260
ETL_NODISCARD const T & ref_at_offset() const
Get a const reference to T at offset (static)
Definition mem_cast.h:271
ETL_NODISCARD const char * data() const
Get a const pointer to the internal buffer.
Definition mem_cast.h:305
static ETL_NODISCARD ETL_CONSTEXPR size_t size()
Get the size of the buffer.
Definition mem_cast.h:281
mem_cast & operator=(const mem_cast< Other_Size, Other_Alignment > &rhs)
Assignment operator.
Definition mem_cast.h:125
ETL_NODISCARD const T & ref() const
Get a const reference to T.
Definition mem_cast.h:227
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_unsigned< T >::value &&(etl::integral_limits< T >::bits==16U), uint_least8_t >::type count_trailing_zeros(T value)
Definition binary.h:1141
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
Definition exception.h:47
Definition integral_limits.h:516
Definition largest.h:367
Definition power.h:186
Template to determine the smallest unsigned int type that can contain a value with the specified numb...
Definition smallest_generator.h:323
bitset_ext
Definition absolute.h:38
Definition mem_cast.h:603
pair holds two objects of arbitrary type
Definition utility.h:164