Vanetza
Loading...
Searching...
No Matches
byte_order.hpp
1#ifndef BYTE_ORDER_HPP_LPUJ094I
2#define BYTE_ORDER_HPP_LPUJ094I
3
4#include <cstdint>
5#include <functional>
6#include <iosfwd>
7#include <type_traits>
8#include <boost/endian/conversion.hpp>
9
10namespace vanetza
11{
12
13template<class T>
14T hton(T host_value)
15{
16 return boost::endian::native_to_big(host_value);
17}
18
19template<class T>
20T ntoh(T network_value)
21{
22 return boost::endian::big_to_native(network_value);
23}
24
25
26enum class ByteOrder {
27 BigEndian,
28 LittleEndian
29};
30
31
32namespace detail
33{
34
35#if BYTE_ORDER == LITTLE_ENDIAN
36 static constexpr ByteOrder host_byte_order = ByteOrder::LittleEndian;
37#elif BYTE_ORDER == BIG_ENDIAN
38 static constexpr ByteOrder host_byte_order = ByteOrder::BigEndian;
39#else
40# error "Unknown byte order"
41#endif
42
43} // namespace detail
44
45constexpr ByteOrder getHostByteOrder() { return detail::host_byte_order; }
46
47template<typename T, ByteOrder ORDER = getHostByteOrder()>
48class EndianType;
49
50/**
51 * Explicitly forge a plain type to an EndianType.
52 * It is assumed the passed value is already in the stated byte order,
53 * i.e. endian_cast does _not_ trigger any automatic conversions.
54 * \param value A plain value in byte order ORDER
55 * \return EndianType capable to carry value type
56 */
57template<ByteOrder ORDER, typename T>
58EndianType<T, ORDER> endian_cast(T value)
59{
60 return static_cast< EndianType<T, ORDER> >(value);
61}
62
63/**
64 * Cast POD type to EndianType in host byte order
65 * \param value POD in host byte order
66 * \return EndianType carrying value
67 */
68template<typename T>
69EndianType<T, getHostByteOrder()> host_cast(T value)
70{
71 return endian_cast<getHostByteOrder()>(value);
72}
73
74/**
75 * Cast POD type to EndianType in network byte order
76 * \param value POD in network byte order
77 * \return EndianType carrying value
78 */
79template<typename T>
80EndianType<T, ByteOrder::BigEndian> network_cast(T value)
81{
82 return endian_cast<ByteOrder::BigEndian>(value);
83}
84
85
86namespace detail
87{
88
89template<typename T, ByteOrder FROM, ByteOrder TO>
91{
92 T operator()(const T&) const;
93};
94
95template<typename T, ByteOrder ORDER>
96struct EndianConverter<T, ORDER, ORDER>
97{
98 T operator()(const T& t) const { return t; }
99};
100
101template<typename T>
102struct EndianConverter<T, ByteOrder::LittleEndian, ByteOrder::BigEndian>
103{
104 T operator()(const T& t) const { return boost::endian::endian_reverse(t); }
105};
106
107template<typename T>
108struct EndianConverter<T, ByteOrder::BigEndian, ByteOrder::LittleEndian>
109{
110 T operator()(const T& t) const { return boost::endian::endian_reverse(t); }
111};
112
113template<typename T, ByteOrder FROM, ByteOrder TO>
114T convert_endian(const T& t)
115{
116 EndianConverter<T, FROM, TO> converter;
117 return converter(t);
118}
119
120} // namespace detail
121
122
123template<typename T, ByteOrder ORDER>
125{
126public:
127 static_assert(std::is_arithmetic<T>::value == true, "EndianType is only availabe for arithmetic types");
128 typedef T value_type;
129 typedef EndianType<T, getHostByteOrder()> host_type;
130 typedef EndianType<T, ByteOrder::BigEndian> network_type;
131
132 EndianType() = default;
133 explicit EndianType(T value) { m_value = value; }
134
135 EndianType(const EndianType&) = default;
136 EndianType& operator=(const EndianType&) = default;
137
138 template<ByteOrder OTHER_ORDER>
139 EndianType(const EndianType<T, OTHER_ORDER>& other) :
140 m_value(detail::convert_endian<T, OTHER_ORDER, ORDER>(other.m_value))
141 {
142 }
143
144 template<ByteOrder OTHER_ORDER>
145 EndianType& operator=(const EndianType<T, OTHER_ORDER>& other)
146 {
147 m_value = detail::convert_endian<T, OTHER_ORDER, ORDER>(other.m_value);
148 return *this;
149 }
150
151 bool operator==(const EndianType& other) const
152 {
153 return m_value == other.m_value;
154 }
155
156 bool operator!=(const EndianType& other) const
157 {
158 return !(*this == other);
159 }
160
161 bool operator<(const EndianType& other) const
162 {
163 return m_value < other.m_value;
164 }
165
166 value_type net() const
167 {
168 return detail::convert_endian<T, ORDER, ByteOrder::BigEndian>(m_value);
169 }
170
171 value_type host() const
172 {
173 return detail::convert_endian<T, ORDER, getHostByteOrder()>(m_value);
174 }
175
176 value_type get() const
177 {
178 return m_value;
179 }
180
181private:
182 friend class EndianType<T, ByteOrder::BigEndian>;
183 friend class EndianType<T, ByteOrder::LittleEndian>;
184
185 T m_value;
186};
187
188
189/**
190 * Print to ostream in network byte order
191 * \param os output stream
192 * \param t endian type object
193 * \return os
194 */
195template<typename T, ByteOrder ORDER>
196std::ostream& operator<<(std::ostream& os, const EndianType<T, ORDER>& t)
197{
198 os << t.net();
199 return os;
200}
201
202typedef EndianType<uint8_t, ByteOrder::BigEndian> uint8be_t;
203typedef EndianType<uint16_t, ByteOrder::BigEndian> uint16be_t;
204typedef EndianType<uint32_t, ByteOrder::BigEndian> uint32be_t;
205typedef EndianType<uint64_t, ByteOrder::BigEndian> uint64be_t;
206
207typedef EndianType<int8_t, ByteOrder::BigEndian> int8be_t;
208typedef EndianType<int16_t, ByteOrder::BigEndian> int16be_t;
209typedef EndianType<int32_t, ByteOrder::BigEndian> int32be_t;
210typedef EndianType<int64_t, ByteOrder::BigEndian> int64be_t;
211
212} // namespace vanetza
213
214namespace std
215{
216
217template<typename T, vanetza::ByteOrder ORDER>
218struct hash<vanetza::EndianType<T, ORDER>>
219{
220 size_t operator()(const vanetza::EndianType<T, ORDER>& t) const
221 {
222 return hash<T>()(t.get());
223 }
224};
225
226} // namespace std
227
228#endif /* BYTE_ORDER_HPP_LPUJ094I */
static constexpr T mask
static constexpr std::size_t bits
Link layer header used by ITS-G5 stations.
Logical Link Control header with SNAP extension.
Frame Control field in IEEE 802.11 MAC header.
QoS Control field in IEEE 802.11 MAC header.
Sequence Control field in IEEE 802.11 MAC header.