1 #ifndef BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
2 #define BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
4 // Copyright 2019 Peter Dimov
6 // Distributed under the Boost Software License, Version 1.0.
7 // http://www.boost.org/LICENSE_1_0.txt
9 #include <boost/endian/detail/endian_reverse.hpp>
10 #include <boost/endian/detail/order.hpp>
11 #include <boost/endian/detail/integral_by_size.hpp>
12 #include <boost/endian/detail/is_trivially_copyable.hpp>
13 #include <boost/type_traits/is_integral.hpp>
14 #include <boost/type_traits/is_enum.hpp>
15 #include <boost/static_assert.hpp>
27 template<class T, std::size_t N1, BOOST_SCOPED_ENUM(order) O1, std::size_t N2, BOOST_SCOPED_ENUM(order) O2> struct endian_store_impl
35 // sizeof(T) must be 1, 2, 4, or 8
36 // 1 <= N <= sizeof(T)
37 // T is TriviallyCopyable
38 // if N < sizeof(T), T is integral or enum
40 template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) Order>
41 inline void endian_store( unsigned char * p, T const & v ) BOOST_NOEXCEPT
43 BOOST_STATIC_ASSERT( sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8 );
44 BOOST_STATIC_ASSERT( N >= 1 && N <= sizeof(T) );
46 return detail::endian_store_impl<T, sizeof(T), order::native, N, Order>()( p, v );
52 // same endianness, same size
54 template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O> struct endian_store_impl<T, N, O, N, O>
56 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
58 BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
60 std::memcpy( p, &v, N );
64 // same size, reverse endianness
66 template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O1, BOOST_SCOPED_ENUM(order) O2> struct endian_store_impl<T, N, O1, N, O2>
68 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
70 BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
72 typename integral_by_size<N>::type tmp;
73 std::memcpy( &tmp, &v, N );
75 endian_reverse_inplace( tmp );
77 std::memcpy( p, &tmp, N );
81 // truncating store 2 -> 1
83 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 2, Order, 1, order::little>
85 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
87 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
89 unsigned char tmp[ 2 ];
90 boost::endian::endian_store<T, 2, order::little>( tmp, v );
96 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 2, Order, 1, order::big>
98 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
100 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
102 unsigned char tmp[ 2 ];
103 boost::endian::endian_store<T, 2, order::big>( tmp, v );
109 // truncating store 4 -> 1
111 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 1, order::little>
113 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
115 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
117 unsigned char tmp[ 4 ];
118 boost::endian::endian_store<T, 4, order::little>( tmp, v );
124 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 1, order::big>
126 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
128 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
130 unsigned char tmp[ 4 ];
131 boost::endian::endian_store<T, 4, order::big>( tmp, v );
137 // truncating store 4 -> 2
139 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 2, order::little>
141 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
143 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
145 unsigned char tmp[ 4 ];
146 boost::endian::endian_store<T, 4, order::little>( tmp, v );
153 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 2, order::big>
155 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
157 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
159 unsigned char tmp[ 4 ];
160 boost::endian::endian_store<T, 4, order::big>( tmp, v );
167 // truncating store 4 -> 3
169 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 3, order::little>
171 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
173 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
175 unsigned char tmp[ 4 ];
176 boost::endian::endian_store<T, 4, order::little>( tmp, v );
184 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 3, order::big>
186 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
188 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
190 unsigned char tmp[ 4 ];
191 boost::endian::endian_store<T, 4, order::big>( tmp, v );
199 // truncating store 8 -> 1
201 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 1, order::little>
203 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
205 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
207 unsigned char tmp[ 8 ];
208 boost::endian::endian_store<T, 8, order::little>( tmp, v );
214 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 1, order::big>
216 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
218 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
220 unsigned char tmp[ 8 ];
221 boost::endian::endian_store<T, 8, order::big>( tmp, v );
227 // truncating store 8 -> 2
229 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 2, order::little>
231 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
233 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
235 unsigned char tmp[ 8 ];
236 boost::endian::endian_store<T, 8, order::little>( tmp, v );
243 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 2, order::big>
245 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
247 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
249 unsigned char tmp[ 8 ];
250 boost::endian::endian_store<T, 8, order::big>( tmp, v );
257 // truncating store 8 -> 3
259 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 3, order::little>
261 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
263 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
265 unsigned char tmp[ 8 ];
266 boost::endian::endian_store<T, 8, order::little>( tmp, v );
274 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 3, order::big>
276 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
278 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
280 unsigned char tmp[ 8 ];
281 boost::endian::endian_store<T, 8, order::big>( tmp, v );
289 // truncating store 8 -> 4
291 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 4, order::little>
293 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
295 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
297 unsigned char tmp[ 8 ];
298 boost::endian::endian_store<T, 8, order::little>( tmp, v );
307 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 4, order::big>
309 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
311 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
313 unsigned char tmp[ 8 ];
314 boost::endian::endian_store<T, 8, order::big>( tmp, v );
323 // truncating store 8 -> 5
325 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 5, order::little>
327 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
329 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
331 unsigned char tmp[ 8 ];
332 boost::endian::endian_store<T, 8, order::little>( tmp, v );
342 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 5, order::big>
344 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
346 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
348 unsigned char tmp[ 8 ];
349 boost::endian::endian_store<T, 8, order::big>( tmp, v );
359 // truncating store 8 -> 6
361 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 6, order::little>
363 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
365 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
367 unsigned char tmp[ 8 ];
368 boost::endian::endian_store<T, 8, order::little>( tmp, v );
379 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 6, order::big>
381 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
383 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
385 unsigned char tmp[ 8 ];
386 boost::endian::endian_store<T, 8, order::big>( tmp, v );
397 // truncating store 8 -> 7
399 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 7, order::little>
401 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
403 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
405 unsigned char tmp[ 8 ];
406 boost::endian::endian_store<T, 8, order::little>( tmp, v );
418 template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 7, order::big>
420 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
422 BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
424 unsigned char tmp[ 8 ];
425 boost::endian::endian_store<T, 8, order::big>( tmp, v );
437 } // namespace detail
439 } // namespace endian
442 #endif // BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED