jaulib v1.3.0
Jau Support Library (C++, Java, ..)
packed_attribute.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Gothel Software e.K.
3 * Copyright (c) 2020 ZAFENA AB
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26#ifndef PACKED_ATTRIBUTE_HPP_
27#define PACKED_ATTRIBUTE_HPP_
28
29/** \addtogroup CppLang
30 *
31 * @{
32 */
33
34/** packed__: lead in macro, requires __packed lead out as well. Consider using __pack(...). */
35#ifndef packed__
36 #ifdef _MSC_VER
37 #define packed__ __pragma( pack(push, 1) )
38 #else
39 #define packed__
40 #endif
41#endif
42
43/** __packed: lead out macro, requires packed__ lead in as well. Consider using __pack(...). */
44#ifndef __packed
45 #ifdef _MSC_VER
46 #define __packed __pragma( pack(pop))
47 #else
48 #define __packed __attribute__ ((packed))
49 #endif
50#endif
51
52/** __pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros. */
53#ifndef __pack
54 #ifdef _MSC_VER
55 #define __pack(...) __pragma( pack(push, 1) ) __VA_ARGS__ __pragma( pack(pop))
56 #else
57 #define __pack(...) __VA_ARGS__ __attribute__ ((packed))
58 #endif
59#endif
60
61/**@}*/
62
63namespace jau {
64
65 /** \addtogroup CppLang
66 *
67 * @{
68 */
69
70 /**
71 * Support aligned memory transfer from and to potentially unaligned memory.
72 *
73 * This template causes little to no runtime costs.
74 *
75 * A casted data pointer to `packed_t<T>*` is similar to 'T * p = (T *) buffer', having `uint8_t * buffer`.
76 * However, `packed_t<T>*` doesn't have any intrinsic alignment corrections due to
77 * its used `__attribute__((__packed__))`.
78 *
79 * packed_t is used in \ref ByteUtils.
80 *
81 * @anchor packed_t_alignment_cast
82 * Background for using packed_t:
83 *
84 * Due to the potentially unaligned memory address of `buffer`,
85 * we can't just directly use pointer arithmetic like:
86 * <pre>
87 * // return uint16_t from memory
88 * return *( (uint16_t *) ( buffer ) );
89 *
90 * // store uint16_t to memory
91 * *( (uint16_t *) ( buffer ) ) = v;
92 * </pre>
93 *
94 * The universal alternative using `memcpy()` is costly:
95 * <pre>
96 * // return uint16_t from memory
97 * memcpy(&v, buffer, sizeof(v));
98 * return v;
99 *
100 * // store uint16_t to memory
101 * memcpy(buffer, &v, sizeof(v));
102 * </pre>
103 *
104 * Solution is to use the *free of costs* high performance *compiler magic* 'struct __attribute__((__packed__))'.<br />
105 * The offset memory is pointer_cast() into the desired packed_t type and its packed_t::store accessed thereafter:
106 * <pre>
107 * // return uint16_t from memory
108 * return pointer_cast<const packed_t<uint16_t>*>( buffer )->store;
109 *
110 * // store uint16_t to memory
111 * pointer_cast<packed_t<uint16_t>*>( buffer )->store = v;
112 * </pre>
113 */
114 template<typename T> __pack ( struct packed_t {
115 T store;
116 } ) ;
117
118 /**@}*/
119
120} // namespace jau
121
122/**@}*/
123
124#endif /* PACKED_ATTRIBUTE_HPP_ */
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32