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)) 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) + 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) + 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 void emplace(TArgs... args)
175 {
176 ETL_STATIC_ASSERT(Size >= sizeof(T), "Type size is too large");
177
178 ::new (static_cast<void*>(buffer)) T(etl::forward<TArgs>(args)...);
179 }
180
181 //***********************************
183 //***********************************
184 template <typename T, typename... TArgs>
185 void emplace_at_offset(size_t offset, TArgs... args)
186 {
187 char* p = static_cast<char*>(buffer) + offset;
188 ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
189
190 ::new (p) T(etl::forward<TArgs>(args)...);
191 }
192
193 //***********************************
195 //***********************************
196 template <typename T, size_t Offset, typename... TArgs>
197 void emplace_at_offset(TArgs... args)
198 {
199 char* p = static_cast<char*>(buffer) + Offset;
200 ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large");
201
202 ::new (p) T(etl::forward<TArgs>(args)...);
203 }
204#endif
205
206 //***********************************
208 //***********************************
209 template <typename T>
210 ETL_NODISCARD T& ref()
211 {
212 ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large");
213
214 return *static_cast<T*>(buffer);
215 }
216
217 //***********************************
219 //***********************************
220 template <typename T>
221 ETL_NODISCARD const T& ref() const
222 {
223 ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large");
224
225 return *static_cast<const T*>(buffer);
226 }
227
228 //***********************************
230 //***********************************
231 template <typename T>
232 ETL_NODISCARD T& ref_at_offset(size_t offset)
233 {
234 ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
235
236 char* p = buffer + offset;
237
238 return *static_cast<T*>(p);
239 }
240
241 //***********************************
243 //***********************************
244 template <typename T>
245 ETL_NODISCARD const T& ref_at_offset(size_t offset) const
246 {
247 ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception));
248
249 char* p = buffer + offset;
250
251 return *static_cast<const T*>(p);
252 }
253
254 //***********************************
256 //***********************************
257 template <typename T, size_t Offset>
258 ETL_NODISCARD T& ref_at_offset()
259 {
260 ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of T is too large");
261
262 char* p = buffer + Offset;
263
264 return *static_cast<T*>(p);
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 T is too large");
274
275 char* p = buffer + Offset;
276
277 return *static_cast<const T*>(p);
278 }
279
280 //***********************************
282 //***********************************
283 ETL_NODISCARD static ETL_CONSTEXPR size_t size()
284 {
285 return Size;
286 }
287
288 //***********************************
290 //***********************************
291 ETL_NODISCARD static ETL_CONSTEXPR size_t alignment()
292 {
293 return Alignment;
294 }
295
296 //***********************************
298 //***********************************
299 ETL_NODISCARD char* data()
300 {
301 return buffer;
302 }
303
304 //***********************************
306 //***********************************
307 ETL_NODISCARD const char* data() const
308 {
309 return buffer;
310 }
311
312 private:
313
316 };
317
318 template <size_t Size_, size_t Alignment_>
319 ETL_CONSTANT size_t mem_cast<Size_, Alignment_>::Size;
320
321 template <size_t Size_, size_t Alignment_>
322 ETL_CONSTANT size_t mem_cast<Size_, Alignment_>::Alignment;
323
324 //*****************************************************************************
326 //*****************************************************************************
328 {
329 public:
330
331 static ETL_CONSTANT size_t Undefined_Size = etl::integral_limits<size_t>::max;
332
333 //***********************************
335 //***********************************
337 : pbuffer(ETL_NULLPTR)
338 , buffer_size(Undefined_Size)
339 {
340 }
341
342 //***********************************
344 //***********************************
345 mem_cast_ptr(char* pbuffer_, size_t buffer_size_ = Undefined_Size)
346 : pbuffer(pbuffer_)
347 , buffer_size(buffer_size_)
348 {
349 }
350
351 //***********************************
353 //***********************************
355 : pbuffer(other.pbuffer)
356 , buffer_size(other.buffer_size)
357 {
358 }
359
360 //***********************************
362 //***********************************
364 {
365 pbuffer = rhs.pbuffer;
366 buffer_size = rhs.buffer_size;
367
368 return *this;
369 }
370
371 //***********************************
373 //***********************************
374 template <typename T>
375 void assign(const T& value)
376 {
377 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
378 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
379
380 ::new (pbuffer) T(value);
381 }
382
383 //***********************************
385 //***********************************
386 template <typename T>
387 void assign_at_offset(size_t offset, const T& value)
388 {
389 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
390 char* p = pbuffer + offset;
391 ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
392
393 ::new (p) T(value);
394 }
395
396 //***********************************
398 //***********************************
399 template <typename T, size_t Offset>
400 void assign_at_offset(const T& value)
401 {
402 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
403 char* p = pbuffer + Offset;
404 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
405
406 ::new (p) T(value);
407 }
408
409#if ETL_USING_CPP11
410 //***********************************
412 //***********************************
413 template <typename T, typename... TArgs>
414 void emplace(TArgs... args)
415 {
416 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
417 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
418
419 ::new (pbuffer) T(etl::forward<TArgs>(args)...);
420 }
421
422 //***********************************
424 //***********************************
425 template <typename T, typename... TArgs>
426 void 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
435 //***********************************
437 //***********************************
438 template <typename T, size_t Offset, typename... TArgs>
439 void emplace_at_offset(TArgs... args)
440 {
441 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
442 char* p = pbuffer + Offset;
443 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
444
445 ::new (p) T(etl::forward<TArgs>(args)...);
446 }
447#endif
448
449 //***********************************
451 //***********************************
452 template <typename T>
453 ETL_NODISCARD T& ref()
454 {
455 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
456 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
457
458 return *reinterpret_cast<T*>(pbuffer);
459 }
460
461 //***********************************
463 //***********************************
464 template <typename T>
465 ETL_NODISCARD const T& ref() const
466 {
467 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
468 ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception));
469
470 return *reinterpret_cast<const T*>(pbuffer);
471 }
472
473 //***********************************
475 //***********************************
476 template <typename T>
477 ETL_NODISCARD T& ref_at_offset(size_t offset)
478 {
479 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
480 char* p = pbuffer + offset;
481 ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
482
483 return *reinterpret_cast<T*>(p);
484 }
485
486 //***********************************
488 //***********************************
489 template <typename T>
490 ETL_NODISCARD const T& ref_at_offset(size_t offset) const
491 {
492 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
493 char* p = pbuffer + offset;
494 ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception));
495
496 return *reinterpret_cast<const T*>(p);
497 }
498
499 //***********************************
501 //***********************************
502 template <typename T, size_t Offset>
503 ETL_NODISCARD T& ref_at_offset()
504 {
505 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
506 char* p = pbuffer + Offset;
507 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
508
509 return *reinterpret_cast<T*>(p);
510 }
511
512 //***********************************
514 //***********************************
515 template <typename T, size_t Offset>
516 ETL_NODISCARD const T& ref_at_offset() const
517 {
518 ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception));
519 char* p = pbuffer + Offset;
520 ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception));
521
522 return *reinterpret_cast<const T*>(p);
523 }
524
525 //***********************************
527 //***********************************
528 ETL_NODISCARD size_t size() const
529 {
530 return buffer_size;
531 }
532
533 //***********************************
535 //***********************************
536 ETL_NODISCARD size_t alignment() const
537 {
538 typedef typename etl::smallest_uint_for_bits<sizeof(uintptr_t)* CHAR_BIT>::type type;
539
540 const type p = reinterpret_cast<type>(pbuffer);
541
542 return size_t(1U) << etl::count_trailing_zeros(p);
543 }
544
545 //***********************************
547 //***********************************
548 void data(char* pbuffer_, size_t buffer_size_ = Undefined_Size)
549 {
550 pbuffer = pbuffer_;
551 buffer_size = buffer_size_;
552 }
553
554 //***********************************
556 //***********************************
557 ETL_NODISCARD char* data()
558 {
559 return pbuffer;
560 }
561
562 //***********************************
564 //***********************************
565 ETL_NODISCARD const char* data() const
566 {
567 return pbuffer;
568 }
569
570 private:
571
573 char* pbuffer;
574 size_t buffer_size;
575 };
576
577 //*****************************************************************************
580 //*****************************************************************************
581#if ETL_USING_CPP11 && !defined(ETL_MEM_CAST_FORCE_CPP03_IMPLEMENTATION)
582 template <typename... TTypes>
583 using mem_cast_types = etl::mem_cast<etl::largest<TTypes...>::size, etl::largest<TTypes...>::alignment>;
584#else
585 template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char,
586 typename T5 = char, typename T6 = char, typename T7 = char, typename T8 = char,
587 typename T9 = char, typename T10 = char, typename T11 = char, typename T12 = char,
588 typename T13 = char, typename T14 = char, typename T15 = char, typename T16 = char>
589 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,
590 etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment>
591 {
592 };
593#endif
594}
595
596#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:328
ETL_NODISCARD T & ref_at_offset()
Get a reference to T at offset (static)
Definition mem_cast.h:503
ETL_NODISCARD size_t size() const
Get the size of the buffer.
Definition mem_cast.h:528
ETL_NODISCARD char * data()
Get a pointer to the external buffer.
Definition mem_cast.h:557
ETL_NODISCARD const char * data() const
Get const a pointer to the external buffer.
Definition mem_cast.h:565
void assign_at_offset(size_t offset, const T &value)
Assign from value at offset.
Definition mem_cast.h:387
ETL_NODISCARD const T & ref_at_offset(size_t offset) const
Get a const reference to T at offset (dynamic)
Definition mem_cast.h:490
ETL_NODISCARD const T & ref_at_offset() const
Get a const reference to T at offset (static)
Definition mem_cast.h:516
ETL_NODISCARD T & ref_at_offset(size_t offset)
Get a reference to T at offset (dynamic)
Definition mem_cast.h:477
ETL_NODISCARD const T & ref() const
Get a const reference to T.
Definition mem_cast.h:465
mem_cast_ptr & operator=(const mem_cast_ptr &rhs)
Assignment operator.
Definition mem_cast.h:363
ETL_NODISCARD T & ref()
Get a reference to T.
Definition mem_cast.h:453
mem_cast_ptr(const mem_cast_ptr &other)
Copy construct.
Definition mem_cast.h:354
mem_cast_ptr(char *pbuffer_, size_t buffer_size_=Undefined_Size)
Construct with pointer to buffer and optional size.
Definition mem_cast.h:345
void assign(const T &value)
Assign from value.
Definition mem_cast.h:375
ETL_NODISCARD size_t alignment() const
Get the alignment of the buffer.
Definition mem_cast.h:536
void data(char *pbuffer_, size_t buffer_size_=Undefined_Size)
Set the pointer to the external buffer.
Definition mem_cast.h:548
void assign_at_offset(const T &value)
Assign from value at offset.
Definition mem_cast.h:400
mem_cast_ptr()
Default constructor.
Definition mem_cast.h:336
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:245
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:299
ETL_NODISCARD T & ref_at_offset(size_t offset)
Get a reference to T at offset (dynamic)
Definition mem_cast.h:232
ETL_NODISCARD T & ref()
Get a reference to T.
Definition mem_cast.h:210
static ETL_NODISCARD ETL_CONSTEXPR size_t alignment()
Get the alignment of the buffer.
Definition mem_cast.h:291
ETL_NODISCARD T & ref_at_offset()
Get a reference to T at offset (static)
Definition mem_cast.h:258
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:307
static ETL_NODISCARD ETL_CONSTEXPR size_t size()
Get the size of the buffer.
Definition mem_cast.h:283
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:221
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:316
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
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1187
Definition mem_cast.h:591
pair holds two objects of arbitrary type
Definition utility.h:164