1#ifndef BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
2#define BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
3
4// Copyright 2019 Peter Dimov
5//
6// Distributed under the Boost Software License, Version 1.0.
7// http://www.boost.org/LICENSE_1_0.txt
8
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/endian/detail/static_assert.hpp>
14#include <type_traits>
15#include <cstddef>
16#include <cstring>
17
18namespace boost
19{
20namespace endian
21{
22
23namespace detail
24{
25
26template<class T, std::size_t N1, order O1, std::size_t N2, order O2> struct endian_store_impl
27{
28};
29
30} // namespace detail
31
32// Requires:
33//
34// sizeof(T) must be 1, 2, 4, or 8
35// 1 <= N <= sizeof(T)
36// T is TriviallyCopyable
37// if N < sizeof(T), T is integral or enum
38
39template<class T, std::size_t N, order Order>
40inline void endian_store( unsigned char * p, T const & v ) BOOST_NOEXCEPT
41{
42 BOOST_ENDIAN_STATIC_ASSERT( sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8 );
43 BOOST_ENDIAN_STATIC_ASSERT( N >= 1 && N <= sizeof(T) );
44
45 return detail::endian_store_impl<T, sizeof(T), order::native, N, Order>()( p, v );
46}
47
48namespace detail
49{
50
51// same endianness, same size
52
53template<class T, std::size_t N, order O> struct endian_store_impl<T, N, O, N, O>
54{
55 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
56 {
57 BOOST_ENDIAN_STATIC_ASSERT( is_trivially_copyable<T>::value );
58
59 std::memcpy( dest: p, src: &v, n: N );
60 }
61};
62
63// same size, reverse endianness
64
65template<class T, std::size_t N, order O1, order O2> struct endian_store_impl<T, N, O1, N, O2>
66{
67 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
68 {
69 BOOST_ENDIAN_STATIC_ASSERT( is_trivially_copyable<T>::value );
70
71 typename integral_by_size<N>::type tmp;
72 std::memcpy( dest: &tmp, src: &v, n: N );
73
74 endian_reverse_inplace( tmp );
75
76 std::memcpy( dest: p, src: &tmp, n: N );
77 }
78};
79
80// truncating store 2 -> 1
81
82template<class T, order Order> struct endian_store_impl<T, 2, Order, 1, order::little>
83{
84 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
85 {
86 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
87
88 unsigned char tmp[ 2 ];
89 boost::endian::endian_store<T, 2, order::little>( tmp, v );
90
91 p[0] = tmp[0];
92 }
93};
94
95template<class T, order Order> struct endian_store_impl<T, 2, Order, 1, order::big>
96{
97 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
98 {
99 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
100
101 unsigned char tmp[ 2 ];
102 boost::endian::endian_store<T, 2, order::big>( tmp, v );
103
104 p[0] = tmp[1];
105 }
106};
107
108// truncating store 4 -> 1
109
110template<class T, order Order> struct endian_store_impl<T, 4, Order, 1, order::little>
111{
112 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
113 {
114 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
115
116 unsigned char tmp[ 4 ];
117 boost::endian::endian_store<T, 4, order::little>( tmp, v );
118
119 p[0] = tmp[0];
120 }
121};
122
123template<class T, order Order> struct endian_store_impl<T, 4, Order, 1, order::big>
124{
125 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
126 {
127 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
128
129 unsigned char tmp[ 4 ];
130 boost::endian::endian_store<T, 4, order::big>( tmp, v );
131
132 p[0] = tmp[3];
133 }
134};
135
136// truncating store 4 -> 2
137
138template<class T, order Order> struct endian_store_impl<T, 4, Order, 2, order::little>
139{
140 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
141 {
142 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
143
144 unsigned char tmp[ 4 ];
145 boost::endian::endian_store<T, 4, order::little>( tmp, v );
146
147 p[0] = tmp[0];
148 p[1] = tmp[1];
149 }
150};
151
152template<class T, order Order> struct endian_store_impl<T, 4, Order, 2, order::big>
153{
154 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
155 {
156 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
157
158 unsigned char tmp[ 4 ];
159 boost::endian::endian_store<T, 4, order::big>( tmp, v );
160
161 p[0] = tmp[2];
162 p[1] = tmp[3];
163 }
164};
165
166// truncating store 4 -> 3
167
168template<class T, order Order> struct endian_store_impl<T, 4, Order, 3, order::little>
169{
170 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
171 {
172 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
173
174 unsigned char tmp[ 4 ];
175 boost::endian::endian_store<T, 4, order::little>( tmp, v );
176
177 p[0] = tmp[0];
178 p[1] = tmp[1];
179 p[2] = tmp[2];
180 }
181};
182
183template<class T, order Order> struct endian_store_impl<T, 4, Order, 3, order::big>
184{
185 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
186 {
187 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
188
189 unsigned char tmp[ 4 ];
190 boost::endian::endian_store<T, 4, order::big>( tmp, v );
191
192 p[0] = tmp[1];
193 p[1] = tmp[2];
194 p[2] = tmp[3];
195 }
196};
197
198// truncating store 8 -> 1
199
200template<class T, order Order> struct endian_store_impl<T, 8, Order, 1, order::little>
201{
202 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
203 {
204 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
205
206 unsigned char tmp[ 8 ];
207 boost::endian::endian_store<T, 8, order::little>( tmp, v );
208
209 p[0] = tmp[0];
210 }
211};
212
213template<class T, order Order> struct endian_store_impl<T, 8, Order, 1, order::big>
214{
215 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
216 {
217 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
218
219 unsigned char tmp[ 8 ];
220 boost::endian::endian_store<T, 8, order::big>( tmp, v );
221
222 p[0] = tmp[7];
223 }
224};
225
226// truncating store 8 -> 2
227
228template<class T, order Order> struct endian_store_impl<T, 8, Order, 2, order::little>
229{
230 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
231 {
232 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
233
234 unsigned char tmp[ 8 ];
235 boost::endian::endian_store<T, 8, order::little>( tmp, v );
236
237 p[0] = tmp[0];
238 p[1] = tmp[1];
239 }
240};
241
242template<class T, order Order> struct endian_store_impl<T, 8, Order, 2, order::big>
243{
244 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
245 {
246 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
247
248 unsigned char tmp[ 8 ];
249 boost::endian::endian_store<T, 8, order::big>( tmp, v );
250
251 p[0] = tmp[6];
252 p[1] = tmp[7];
253 }
254};
255
256// truncating store 8 -> 3
257
258template<class T, order Order> struct endian_store_impl<T, 8, Order, 3, order::little>
259{
260 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
261 {
262 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
263
264 unsigned char tmp[ 8 ];
265 boost::endian::endian_store<T, 8, order::little>( tmp, v );
266
267 p[0] = tmp[0];
268 p[1] = tmp[1];
269 p[2] = tmp[2];
270 }
271};
272
273template<class T, order Order> struct endian_store_impl<T, 8, Order, 3, order::big>
274{
275 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
276 {
277 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
278
279 unsigned char tmp[ 8 ];
280 boost::endian::endian_store<T, 8, order::big>( tmp, v );
281
282 p[0] = tmp[5];
283 p[1] = tmp[6];
284 p[2] = tmp[7];
285 }
286};
287
288// truncating store 8 -> 4
289
290template<class T, order Order> struct endian_store_impl<T, 8, Order, 4, order::little>
291{
292 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
293 {
294 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
295
296 unsigned char tmp[ 8 ];
297 boost::endian::endian_store<T, 8, order::little>( tmp, v );
298
299 p[0] = tmp[0];
300 p[1] = tmp[1];
301 p[2] = tmp[2];
302 p[3] = tmp[3];
303 }
304};
305
306template<class T, order Order> struct endian_store_impl<T, 8, Order, 4, order::big>
307{
308 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
309 {
310 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
311
312 unsigned char tmp[ 8 ];
313 boost::endian::endian_store<T, 8, order::big>( tmp, v );
314
315 p[0] = tmp[4];
316 p[1] = tmp[5];
317 p[2] = tmp[6];
318 p[3] = tmp[7];
319 }
320};
321
322// truncating store 8 -> 5
323
324template<class T, order Order> struct endian_store_impl<T, 8, Order, 5, order::little>
325{
326 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
327 {
328 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
329
330 unsigned char tmp[ 8 ];
331 boost::endian::endian_store<T, 8, order::little>( tmp, v );
332
333 p[0] = tmp[0];
334 p[1] = tmp[1];
335 p[2] = tmp[2];
336 p[3] = tmp[3];
337 p[4] = tmp[4];
338 }
339};
340
341template<class T, order Order> struct endian_store_impl<T, 8, Order, 5, order::big>
342{
343 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
344 {
345 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
346
347 unsigned char tmp[ 8 ];
348 boost::endian::endian_store<T, 8, order::big>( tmp, v );
349
350 p[0] = tmp[3];
351 p[1] = tmp[4];
352 p[2] = tmp[5];
353 p[3] = tmp[6];
354 p[4] = tmp[7];
355 }
356};
357
358// truncating store 8 -> 6
359
360template<class T, order Order> struct endian_store_impl<T, 8, Order, 6, order::little>
361{
362 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
363 {
364 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
365
366 unsigned char tmp[ 8 ];
367 boost::endian::endian_store<T, 8, order::little>( tmp, v );
368
369 p[0] = tmp[0];
370 p[1] = tmp[1];
371 p[2] = tmp[2];
372 p[3] = tmp[3];
373 p[4] = tmp[4];
374 p[5] = tmp[5];
375 }
376};
377
378template<class T, order Order> struct endian_store_impl<T, 8, Order, 6, order::big>
379{
380 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
381 {
382 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
383
384 unsigned char tmp[ 8 ];
385 boost::endian::endian_store<T, 8, order::big>( tmp, v );
386
387 p[0] = tmp[2];
388 p[1] = tmp[3];
389 p[2] = tmp[4];
390 p[3] = tmp[5];
391 p[4] = tmp[6];
392 p[5] = tmp[7];
393 }
394};
395
396// truncating store 8 -> 7
397
398template<class T, order Order> struct endian_store_impl<T, 8, Order, 7, order::little>
399{
400 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
401 {
402 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
403
404 unsigned char tmp[ 8 ];
405 boost::endian::endian_store<T, 8, order::little>( tmp, v );
406
407 p[0] = tmp[0];
408 p[1] = tmp[1];
409 p[2] = tmp[2];
410 p[3] = tmp[3];
411 p[4] = tmp[4];
412 p[5] = tmp[5];
413 p[6] = tmp[6];
414 }
415};
416
417template<class T, order Order> struct endian_store_impl<T, 8, Order, 7, order::big>
418{
419 inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
420 {
421 BOOST_ENDIAN_STATIC_ASSERT( std::is_integral<T>::value || std::is_enum<T>::value );
422
423 unsigned char tmp[ 8 ];
424 boost::endian::endian_store<T, 8, order::big>( tmp, v );
425
426 p[0] = tmp[1];
427 p[1] = tmp[2];
428 p[2] = tmp[3];
429 p[3] = tmp[4];
430 p[4] = tmp[5];
431 p[5] = tmp[6];
432 p[6] = tmp[7];
433 }
434};
435
436} // namespace detail
437
438} // namespace endian
439} // namespace boost
440
441#endif // BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
442

source code of boost/libs/endian/include/boost/endian/detail/endian_store.hpp