Embedded Template Library 1.0
unaligned_type.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) 2022 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_UNALIGNED_TYPE_INCLUDED
32#define ETL_UNALIGNED_TYPE_INCLUDED
33
37
38#include "platform.h"
39#include "type_traits.h"
40#include "endianness.h"
41#include "iterator.h"
42#include "algorithm.h"
43
44#include <string.h>
45
46namespace etl
47{
48 namespace private_unaligned_type
49 {
50 //*************************************************************************
53 //*************************************************************************
54 template <size_t Size_>
56 {
57 public:
58
59 static ETL_CONSTANT size_t Size = Size_;
60
61 typedef unsigned char storage_type;
62 typedef storage_type* pointer;
63 typedef const storage_type* const_pointer;
64 typedef storage_type* iterator;
65 typedef const storage_type* const_iterator;
68
69 //*************************************************************************
71 //*************************************************************************
72 ETL_CONSTEXPR unaligned_type_common()
73 : storage()
74 {
75 }
76
77 //*************************************************************************
79 //*************************************************************************
80 ETL_CONSTEXPR size_t size() const
81 {
82 return Size;
83 }
84
85 //*************************************************************************
87 //*************************************************************************
88 pointer data()
89 {
90 return storage;
91 }
92
93 //*************************************************************************
95 //*************************************************************************
96 ETL_CONSTEXPR const_pointer data() const
97 {
98 return storage;
99 }
100
101 //*************************************************************************
103 //*************************************************************************
104 iterator begin()
105 {
106 return iterator(storage);
107 }
108
109 //*************************************************************************
111 //*************************************************************************
112 ETL_CONSTEXPR const_iterator begin() const
113 {
114 return const_iterator(storage);
115 }
116
117 //*************************************************************************
119 //*************************************************************************
120 ETL_CONSTEXPR const_iterator cbegin() const
121 {
122 return const_iterator(storage);
123 }
124
125 //*************************************************************************
127 //*************************************************************************
129 {
130 return reverse_iterator(storage + Size);
131 }
132
133 //*************************************************************************
135 //*************************************************************************
136 ETL_CONSTEXPR14 const_reverse_iterator rbegin() const
137 {
138 return const_reverse_iterator(storage + Size);
139 }
140
141 //*************************************************************************
143 //*************************************************************************
144 ETL_CONSTEXPR14 const_reverse_iterator crbegin() const
145 {
146 return const_reverse_iterator(storage + Size);
147 }
148
149 //*************************************************************************
151 //*************************************************************************
152 iterator end()
153 {
154 return iterator(storage + Size);
155 }
156
157 //*************************************************************************
159 //*************************************************************************
160 ETL_CONSTEXPR const_iterator end() const
161 {
162 return const_iterator(storage + Size);
163 }
164
165 //*************************************************************************
167 //*************************************************************************
168 ETL_CONSTEXPR const_iterator cend() const
169 {
170 return const_iterator(storage + Size);
171 }
172
173 //*************************************************************************
175 //*************************************************************************
177 {
178 return reverse_iterator(storage);
179 }
180
181 //*************************************************************************
183 //*************************************************************************
184 ETL_CONSTEXPR14 const_reverse_iterator rend() const
185 {
186 return const_reverse_iterator(storage);
187 }
188
189 //*************************************************************************
191 //*************************************************************************
192 ETL_CONSTEXPR14 const_reverse_iterator crend() const
193 {
194 return const_reverse_iterator(storage);
195 }
196
197 //*************************************************************************
199 //*************************************************************************
200 storage_type& operator[](int i)
201 {
202 return storage[i];
203 }
204
205 //*************************************************************************
207 //*************************************************************************
208 ETL_CONSTEXPR const storage_type& operator[](int i) const
209 {
210 return storage[i];
211 }
212
213 protected:
214
215 unsigned char storage[Size];
216 };
217
218 template <size_t Size_>
219 ETL_CONSTANT size_t unaligned_type_common<Size_>::Size;
220 }
221
222 //*************************************************************************
227 //*************************************************************************
228 template <typename T, int Endian_>
230 {
231 public:
232
233 ETL_STATIC_ASSERT(etl::is_integral<T>::value || etl::is_floating_point<T>::value, "Unaligned type must be integral or floating point");
234
235 typedef T value_type;
236
237 typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::storage_type storage_type;
238 typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::pointer pointer;
239 typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::const_pointer const_pointer;
240 typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::iterator iterator;
241 typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::const_iterator const_iterator;
242 typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::reverse_iterator reverse_iterator;
243 typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::const_reverse_iterator const_reverse_iterator;
244
245 static ETL_CONSTANT int Endian = Endian_;
246 static ETL_CONSTANT size_t Size = private_unaligned_type::unaligned_type_common<sizeof(T)>::Size;
247
248 //*************************************************************************
250 //*************************************************************************
251 ETL_CONSTEXPR unaligned_type()
252 {
253 }
254
255 //*************************************************************************
257 //*************************************************************************
258 ETL_CONSTEXPR14 unaligned_type(T value)
259 {
260 unaligned_copy<T>::copy(value, this->storage);
261 }
262
263 //*************************************************************************
265 //*************************************************************************
266 template <int Endian_Other>
268 {
269 unaligned_copy<T>::copy(other.data(), Endian_Other, this->storage);
270 }
271
272 //*************************************************************************
274 //*************************************************************************
275 ETL_CONSTEXPR14 unaligned_type& operator =(T value)
276 {
277 unaligned_copy<T>::copy(value, this->storage);
278
279 return *this;
280 }
281
282 //*************************************************************************
284 //*************************************************************************
285 template <int Endian_Other>
287 {
288 unaligned_copy<T>::copy(other.data(), Endian_Other, this->storage);
289
290 return *this;
291 }
292
293 //*************************************************************************
295 //*************************************************************************
296 friend ETL_CONSTEXPR14 bool operator ==(const unaligned_type& lhs, const unaligned_type& rhs)
297 {
298 return etl::equal(lhs.data(), lhs.data() + lhs.Size, rhs.data());
299 }
300
301 //*************************************************************************
303 //*************************************************************************
304 friend ETL_CONSTEXPR14 bool operator ==(const unaligned_type& lhs, T rhs)
305 {
306 T lhs_value = lhs;
307 return (lhs_value == rhs);
308 }
309
310 //*************************************************************************
312 //*************************************************************************
313 friend ETL_CONSTEXPR14 bool operator ==(T lhs, const unaligned_type& rhs)
314 {
315 T rhs_value = rhs;
316 return (lhs == rhs_value);
317 }
318
319 //*************************************************************************
321 //*************************************************************************
322 friend ETL_CONSTEXPR14 bool operator !=(const unaligned_type& lhs, T rhs)
323 {
324 return !(lhs == rhs);
325 }
326
327 //*************************************************************************
329 //*************************************************************************
330 friend ETL_CONSTEXPR14 bool operator !=(const unaligned_type& lhs, const unaligned_type& rhs)
331 {
332 return !(lhs == rhs);
333 }
334
335 //*************************************************************************
337 //*************************************************************************
338 friend ETL_CONSTEXPR14 bool operator !=(T lhs, const unaligned_type& rhs)
339 {
340 return !(lhs == rhs);
341 }
342
343 //*************************************************************************
345 //*************************************************************************
346 ETL_CONSTEXPR14 operator T() const
347 {
348 T value = T();
349
350 unaligned_copy<T>::copy(this->storage, value);
351
352 return value;
353 }
354
355 //*************************************************************************
357 //*************************************************************************
358 ETL_CONSTEXPR14 T value() const
359 {
360 T value = T();
361
362 unaligned_copy<T>::copy(this->storage, value);
363
364 return value;
365 }
366
367 //*************************************************************************
369 //*************************************************************************
370 template <typename U, size_t Size = sizeof(U)>
372
373 //*******************************************
376 //*******************************************
377 template <typename U>
378 struct unaligned_copy<U, 1U>
379 {
380 //*******************************
381 static ETL_CONSTEXPR14 void copy(T value, pointer store)
382 {
383 store[0] = static_cast<storage_type>(value);
384 }
385
386 //*******************************
387 static ETL_CONSTEXPR14 void copy(const_pointer store, T& value)
388 {
389 value = static_cast<T>(store[0]);
390 }
391
392 //*******************************
393 static ETL_CONSTEXPR14 void copy(const_pointer src, int /*endian_src*/, unsigned char* dst)
394 {
395 dst[0] = src[0];
396 }
397 };
398
399 //*******************************************
402 //*******************************************
403 template <typename U>
404 struct unaligned_copy<U, 2U>
405 {
406 //*******************************
407 static ETL_CONSTEXPR14 void copy(T value, unsigned char* store)
408 {
409 if (Endian == etl::endianness::value())
410 {
411 store[0] = static_cast<storage_type>(value);
412 store[1] = static_cast<storage_type>(value >> (1U * CHAR_BIT));
413 }
414 else
415 {
416 store[1] = static_cast<storage_type>(value);
417 store[0] = static_cast<storage_type>(value >> (1U * CHAR_BIT));
418 }
419 }
420
421 //*******************************
422 static ETL_CONSTEXPR14 void copy(const_pointer store, T& value)
423 {
424 if (Endian == etl::endianness::value())
425 {
426 value = static_cast<T>(static_cast<unsigned char>(store[0]));
427 value |= static_cast<T>(static_cast<unsigned char>(store[1])) << (1U * CHAR_BIT);
428 }
429 else
430 {
431 value = static_cast<T>(static_cast<unsigned char>(store[1]));
432 value |= static_cast<T>(static_cast<unsigned char>(store[0])) << (1U * CHAR_BIT);
433 }
434 }
435
436 //*******************************
437 static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst)
438 {
439 if (Endian == endian_src)
440 {
441 dst[0] = src[0];
442 dst[1] = src[1];
443 }
444 else
445 {
446 dst[0] = src[1];
447 dst[1] = src[0];
448 }
449 }
450 };
451
452 //*******************************************
455 //*******************************************
456 template <typename U>
457 struct unaligned_copy<U, 4U>
458 {
459 static ETL_CONSTEXPR14 void copy(T value, unsigned char* store)
460 {
461 if (Endian == etl::endianness::value())
462 {
463 store[0] = static_cast<storage_type>(value);
464 store[1] = static_cast<storage_type>(value >> (1U * CHAR_BIT));
465 store[2] = static_cast<storage_type>(value >> (2U * CHAR_BIT));
466 store[3] = static_cast<storage_type>(value >> (3U * CHAR_BIT));
467 }
468 else
469 {
470 store[3] = static_cast<storage_type>(value);
471 store[2] = static_cast<storage_type>(value >> (1U * CHAR_BIT));
472 store[1] = static_cast<storage_type>(value >> (2U * CHAR_BIT));
473 store[0] = static_cast<storage_type>(value >> (3U * CHAR_BIT));
474 }
475 }
476
477 //*******************************
478 static ETL_CONSTEXPR14 void copy(const_pointer store, T& value)
479 {
480 if (Endian == etl::endianness::value())
481 {
482 value = static_cast<T>(static_cast<unsigned char>(store[0]));
483 value |= static_cast<T>(static_cast<unsigned char>(store[1])) << (1U * CHAR_BIT);
484 value |= static_cast<T>(static_cast<unsigned char>(store[2])) << (2U * CHAR_BIT);
485 value |= static_cast<T>(static_cast<unsigned char>(store[3])) << (3U * CHAR_BIT);
486 }
487 else
488 {
489 value = static_cast<T>(static_cast<unsigned char>(store[3]));
490 value |= static_cast<T>(static_cast<unsigned char>(store[2])) << (1U * CHAR_BIT);
491 value |= static_cast<T>(static_cast<unsigned char>(store[1])) << (2U * CHAR_BIT);
492 value |= static_cast<T>(static_cast<unsigned char>(store[0])) << (3U * CHAR_BIT);
493 }
494 }
495
496 //*******************************
497 static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst)
498 {
499 if (Endian == endian_src)
500 {
501 dst[0] = src[0];
502 dst[1] = src[1];
503 dst[2] = src[2];
504 dst[3] = src[3];
505 }
506 else
507 {
508 dst[0] = src[3];
509 dst[1] = src[2];
510 dst[2] = src[1];
511 dst[3] = src[0];
512 }
513 }
514 };
515
516 //*******************************************
519 //*******************************************
520 template <typename U>
521 struct unaligned_copy<U, 8U>
522 {
523 static ETL_CONSTEXPR14 void copy(T value, unsigned char* store)
524 {
525 if (Endian == etl::endianness::value())
526 {
527 store[0] = static_cast<storage_type>(value);
528 store[1] = static_cast<storage_type>(value >> (1U * CHAR_BIT));
529 store[2] = static_cast<storage_type>(value >> (2U * CHAR_BIT));
530 store[3] = static_cast<storage_type>(value >> (3U * CHAR_BIT));
531 store[4] = static_cast<storage_type>(value >> (4U * CHAR_BIT));
532 store[5] = static_cast<storage_type>(value >> (5U * CHAR_BIT));
533 store[6] = static_cast<storage_type>(value >> (6U * CHAR_BIT));
534 store[7] = static_cast<storage_type>(value >> (7U * CHAR_BIT));
535 }
536 else
537 {
538 store[7] = static_cast<storage_type>(value);
539 store[6] = static_cast<storage_type>(value >> (1U * CHAR_BIT));
540 store[5] = static_cast<storage_type>(value >> (2U * CHAR_BIT));
541 store[4] = static_cast<storage_type>(value >> (3U * CHAR_BIT));
542 store[3] = static_cast<storage_type>(value >> (4U * CHAR_BIT));
543 store[2] = static_cast<storage_type>(value >> (5U * CHAR_BIT));
544 store[1] = static_cast<storage_type>(value >> (6U * CHAR_BIT));
545 store[0] = static_cast<storage_type>(value >> (7U * CHAR_BIT));
546 }
547 }
548
549 //*******************************
550 static ETL_CONSTEXPR14 void copy(const_pointer store, T& value)
551 {
552 if (Endian == etl::endianness::value())
553 {
554 value = static_cast<T>(static_cast<unsigned char>(store[0]));
555 value |= static_cast<T>(static_cast<unsigned char>(store[1])) << (1U * CHAR_BIT);
556 value |= static_cast<T>(static_cast<unsigned char>(store[2])) << (2U * CHAR_BIT);
557 value |= static_cast<T>(static_cast<unsigned char>(store[3])) << (3U * CHAR_BIT);
558 value |= static_cast<T>(static_cast<unsigned char>(store[4])) << (4U * CHAR_BIT);
559 value |= static_cast<T>(static_cast<unsigned char>(store[5])) << (5U * CHAR_BIT);
560 value |= static_cast<T>(static_cast<unsigned char>(store[6])) << (6U * CHAR_BIT);
561 value |= static_cast<T>(static_cast<unsigned char>(store[7])) << (7U * CHAR_BIT);
562 }
563 else
564 {
565 value = static_cast<T>(static_cast<unsigned char>(store[7]));
566 value |= static_cast<T>(static_cast<unsigned char>(store[6])) << (1U * CHAR_BIT);
567 value |= static_cast<T>(static_cast<unsigned char>(store[5])) << (2U * CHAR_BIT);
568 value |= static_cast<T>(static_cast<unsigned char>(store[4])) << (3U * CHAR_BIT);
569 value |= static_cast<T>(static_cast<unsigned char>(store[3])) << (4U * CHAR_BIT);
570 value |= static_cast<T>(static_cast<unsigned char>(store[2])) << (5U * CHAR_BIT);
571 value |= static_cast<T>(static_cast<unsigned char>(store[1])) << (6U * CHAR_BIT);
572 value |= static_cast<T>(static_cast<unsigned char>(store[0])) << (7U * CHAR_BIT);
573 }
574 }
575
576 //*******************************
577 static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst)
578 {
579 if (Endian == endian_src)
580 {
581 dst[0] = src[0];
582 dst[1] = src[1];
583 dst[2] = src[2];
584 dst[3] = src[3];
585 dst[4] = src[4];
586 dst[5] = src[5];
587 dst[6] = src[6];
588 dst[7] = src[7];
589 }
590 else
591 {
592 dst[0] = src[7];
593 dst[1] = src[6];
594 dst[2] = src[5];
595 dst[3] = src[4];
596 dst[4] = src[3];
597 dst[5] = src[2];
598 dst[6] = src[1];
599 dst[7] = src[0];
600 }
601 }
602 };
603 };
604
605 template <typename T, int Endian_>
606 ETL_CONSTANT int unaligned_type<T, Endian_>::Endian;
607
608 template <typename T, int Endian_>
609 ETL_CONSTANT size_t unaligned_type<T, Endian_>::Size;
610
611#if ETL_HAS_CONSTEXPR_ENDIANNESS
612 // Host order
613 typedef unaligned_type<char, etl::endianness::value()> host_char_t;
614 typedef unaligned_type<signed char, etl::endianness::value()> host_schar_t;
615 typedef unaligned_type<unsigned char, etl::endianness::value()> host_uchar_t;
616 typedef unaligned_type<short, etl::endianness::value()> host_short_t;
617 typedef unaligned_type<unsigned short, etl::endianness::value()> host_ushort_t;
618 typedef unaligned_type<int, etl::endianness::value()> host_int_t;
619 typedef unaligned_type<unsigned int, etl::endianness::value()> host_uint_t;
620 typedef unaligned_type<long, etl::endianness::value()> host_long_t;
621 typedef unaligned_type<unsigned long, etl::endianness::value()> host_ulong_t;
622 typedef unaligned_type<long long, etl::endianness::value()> host_long_long_t;
623 typedef unaligned_type<unsigned long long, etl::endianness::value()> host_ulong_long_t;
624#if ETL_USING_8BIT_TYPES
625 typedef unaligned_type<int8_t, etl::endianness::value()> host_int8_t;
626 typedef unaligned_type<uint8_t, etl::endianness::value()> host_uint8_t;
627#endif
628 typedef unaligned_type<int16_t, etl::endianness::value()> host_int16_t;
629 typedef unaligned_type<uint16_t, etl::endianness::value()> host_uint16_t;
630 typedef unaligned_type<int32_t, etl::endianness::value()> host_int32_t;
631 typedef unaligned_type<uint32_t, etl::endianness::value()> host_uint32_t;
632#if ETL_USING_64BIT_TYPES
633 typedef unaligned_type<int64_t, etl::endianness::value()> host_int64_t;
634 typedef unaligned_type<uint64_t, etl::endianness::value()> host_uint64_t;
635#endif
636 typedef unaligned_type<float, etl::endianness::value()> host_float_t;
637 typedef unaligned_type<double, etl::endianness::value()> host_double_t;
638 typedef unaligned_type<long double, etl::endianness::value()> host_long_double_t;
639#endif
640
641 // Little Endian
653#if ETL_USING_8BIT_TYPES
656#endif
661#if ETL_USING_64BIT_TYPES
664#endif
668
669 // Big Endian
681#if ETL_USING_8BIT_TYPES
684#endif
689#if ETL_USING_64BIT_TYPES
692#endif
696
697 // Network Order
698 typedef be_char_t net_char_t;
699 typedef be_schar_t net_schar_t;
700 typedef be_uchar_t net_uchar_t;
701 typedef be_short_t net_short_t;
703 typedef be_int_t net_int_t;
704 typedef be_uint_t net_uint_t;
705 typedef be_long_t net_long_t;
706 typedef be_ulong_t net_ulong_t;
709#if ETL_USING_8BIT_TYPES
710 typedef be_int8_t net_int8_t;
711 typedef be_uint8_t net_uint8_t;
712#endif
713 typedef be_int16_t net_int16_t;
715 typedef be_int32_t net_int32_t;
717#if ETL_USING_64BIT_TYPES
718 typedef be_int64_t net_int64_t;
720#endif
721 typedef be_float_t net_float_t;
724
725#if ETL_USING_CPP11
726 template <typename T, int Endian>
727 using unaligned_type_t = typename etl::unaligned_type<T, Endian>::type;
728#endif
729
730#if ETL_USING_CPP17
731 template <typename T, int Endian>
732 constexpr size_t unaligned_type_v = etl::unaligned_type<T, Endian>::Size;
733#endif
734}
735
736#endif
ETL_CONSTEXPR14 const_reverse_iterator crend() const
Const reverse iterator to the end of the storage.
Definition: unaligned_type.h:192
iterator begin()
Iterator to the beginning of the storage.
Definition: unaligned_type.h:104
storage_type & operator[](int i)
Index operator.
Definition: unaligned_type.h:200
ETL_CONSTEXPR const_iterator cbegin() const
Const iterator to the beginning of the storage.
Definition: unaligned_type.h:120
reverse_iterator rend()
Reverse iterator to the end of the storage.
Definition: unaligned_type.h:176
iterator end()
Iterator to the end of the storage.
Definition: unaligned_type.h:152
reverse_iterator rbegin()
Reverse iterator to the beginning of the storage.
Definition: unaligned_type.h:128
ETL_CONSTEXPR unaligned_type_common()
Default constructor.
Definition: unaligned_type.h:72
pointer data()
Pointer to the beginning of the storage.
Definition: unaligned_type.h:88
ETL_CONSTEXPR size_t size() const
Size of the storage.
Definition: unaligned_type.h:80
ETL_CONSTEXPR const_iterator cend() const
Const iterator to the end of the storage.
Definition: unaligned_type.h:168
ETL_CONSTEXPR14 const_reverse_iterator crbegin() const
Const reverse iterator to the beginning of the storage.
Definition: unaligned_type.h:144
Definition: iterator.h:228
Allows an arithmetic type to be stored at an unaligned address.
Definition: unaligned_type.h:230
friend ETL_CONSTEXPR14 bool operator!=(const unaligned_type &lhs, T rhs)
Inequality operator.
Definition: unaligned_type.h:322
ETL_CONSTEXPR14 unaligned_type & operator=(T value)
Assignment operator.
Definition: unaligned_type.h:275
ETL_CONSTEXPR14 T value() const
Get the value.
Definition: unaligned_type.h:358
friend ETL_CONSTEXPR14 bool operator==(const unaligned_type &lhs, const unaligned_type &rhs)
Equality operator.
Definition: unaligned_type.h:296
ETL_CONSTEXPR unaligned_type()
Default constructor.
Definition: unaligned_type.h:251
is_floating_point
Definition: type_traits_generator.h:1031
is_integral
Definition: type_traits_generator.h:1001
bitset_ext
Definition: absolute.h:38
Unaligned copy.
Definition: unaligned_type.h:371