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