MongoDB C++ Driver  legacy-1.1.2
endian.h
1 /* Copyright 2014 MongoDB Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include "mongo/config.h"
19 
20 #include <climits>
21 #include <cstring>
22 #include <boost/static_assert.hpp>
23 #include <boost/mpl/if.hpp>
24 #include <boost/type_traits/is_signed.hpp>
25 #include "mongo/platform/cstdint.h"
26 
27 #pragma push_macro("MONGO_UINT16_SWAB")
28 #pragma push_macro("MONGO_UINT32_SWAB")
29 #pragma push_macro("MONGO_UINT64_SWAB")
30 #pragma push_macro("MONGO_LITTLE_ENDIAN")
31 #pragma push_macro("MONGO_BIG_ENDIAN")
32 #pragma push_macro("htobe16")
33 #pragma push_macro("htobe32")
34 #pragma push_macro("htobe64")
35 #pragma push_macro("htole16")
36 #pragma push_macro("htole32")
37 #pragma push_macro("htole64")
38 #pragma push_macro("be16toh")
39 #pragma push_macro("be32toh")
40 #pragma push_macro("be64toh")
41 #pragma push_macro("le16toh")
42 #pragma push_macro("le32toh")
43 #pragma push_macro("le64toh")
44 
45 #undef MONGO_UINT16_SWAB
46 #undef MONGO_UINT32_SWAB
47 #undef MONGO_UINT64_SWAB
48 #undef MONGO_LITTLE_ENDIAN
49 #undef MONGO_BIG_ENDIAN
50 #undef htobe16
51 #undef htobe32
52 #undef htobe64
53 #undef htole16
54 #undef htole32
55 #undef htole64
56 #undef be16toh
57 #undef be32toh
58 #undef be64toh
59 #undef le16toh
60 #undef le32toh
61 #undef le64toh
62 
63 #define MONGO_LITTLE_ENDIAN 1234
64 #define MONGO_BIG_ENDIAN 4321
65 
66 #if defined(_MSC_VER) && (_MSC_VER >= 1300)
67 #include <cstdlib>
68 #define MONGO_UINT16_SWAB(v) _byteswap_ushort(v)
69 #define MONGO_UINT32_SWAB(v) _byteswap_ulong(v)
70 #define MONGO_UINT64_SWAB(v) _byteswap_uint64(v)
71 #elif defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) && \
72  (__clang_major__ >= 3) && (__clang_minor__ >= 1)
73 #if __has_builtin(__builtin_bswap16)
74 #define MONGO_UINT16_SWAB(v) __builtin_bswap16(v)
75 #endif
76 #if __has_builtin(__builtin_bswap32)
77 #define MONGO_UINT32_SWAB(v) __builtin_bswap32(v)
78 #endif
79 #if __has_builtin(__builtin_bswap64)
80 #define MONGO_UINT64_SWAB(v) __builtin_bswap64(v)
81 #endif
82 #elif defined(__GNUC__) && (__GNUC__ >= 4)
83 #if __GNUC__ >= 4 && defined(__GNUC_MINOR__) && __GNUC_MINOR__ >= 3
84 #define MONGO_UINT32_SWAB(v) __builtin_bswap32(v)
85 #define MONGO_UINT64_SWAB(v) __builtin_bswap64(v)
86 #endif
87 #if __GNUC__ >= 4 && defined(__GNUC_MINOR__) && __GNUC_MINOR__ >= 8
88 #define MONGO_UINT16_SWAB(v) __builtin_bswap16(v)
89 #endif
90 #elif defined(__sun)
91 #include <sys/byteorder.h>
92 #define MONGO_UINT16_SWAB(v) BSWAP_16(v)
93 #define MONGO_UINT32_SWAB(v) BSWAP_32(v)
94 #define MONGO_UINT64_SWAB(v) BSWAP_64(v)
95 #endif
96 
97 #ifndef MONGO_UINT16_SWAB
98 #define MONGO_UINT16_SWAB(v) endian::bswap_slow16(v)
99 #endif
100 
101 #ifndef MONGO_UINT32_SWAB
102 #define MONGO_UINT32_SWAB(v) endian::bswap_slow32(v)
103 #endif
104 
105 #ifndef MONGO_UINT64_SWAB
106 #define MONGO_UINT64_SWAB(v) endian::bswap_slow64(v)
107 #endif
108 
109 #if MONGO_BYTE_ORDER == MONGO_LITTLE_ENDIAN
110 #define htobe16(v) MONGO_UINT16_SWAB(v)
111 #define htobe32(v) MONGO_UINT32_SWAB(v)
112 #define htobe64(v) MONGO_UINT64_SWAB(v)
113 #define htole16(v) (v)
114 #define htole32(v) (v)
115 #define htole64(v) (v)
116 #define be16toh(v) MONGO_UINT16_SWAB(v)
117 #define be32toh(v) MONGO_UINT32_SWAB(v)
118 #define be64toh(v) MONGO_UINT64_SWAB(v)
119 #define le16toh(v) (v)
120 #define le32toh(v) (v)
121 #define le64toh(v) (v)
122 #elif MONGO_BYTE_ORDER == MONGO_BIG_ENDIAN
123 #define htobe16(v) (v)
124 #define htobe32(v) (v)
125 #define htobe64(v) (v)
126 #define htole16(v) MONGO_UINT16_SWAB(v)
127 #define htole32(v) MONGO_UINT32_SWAB(v)
128 #define htole64(v) MONGO_UINT64_SWAB(v)
129 #define be16toh(v) (v)
130 #define be32toh(v) (v)
131 #define be64toh(v) (v)
132 #define le16toh(v) MONGO_UINT16_SWAB(v)
133 #define le32toh(v) MONGO_UINT32_SWAB(v)
134 #define le64toh(v) MONGO_UINT64_SWAB(v)
135 #else
136 #error \
137  "The endianness of target architecture is unknown. " \
138  "Please define MONGO_BYTE_ORDER"
139 #endif
140 
141 namespace mongo {
142 namespace endian {
143 
144 static inline uint16_t bswap_slow16(uint16_t v) {
145  return ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
146 }
147 
148 static inline uint32_t bswap_slow32(uint32_t v) {
149  return ((v & 0x000000FFUL) << 24) | ((v & 0x0000FF00UL) << 8) | ((v & 0x00FF0000UL) >> 8) |
150  ((v & 0xFF000000UL) >> 24);
151 }
152 
153 static inline uint64_t bswap_slow64(uint64_t v) {
154  return ((v & 0x00000000000000FFULL) << 56) | ((v & 0x000000000000FF00ULL) << 40) |
155  ((v & 0x0000000000FF0000ULL) << 24) | ((v & 0x00000000FF000000ULL) << 8) |
156  ((v & 0x000000FF00000000ULL) >> 8) | ((v & 0x0000FF0000000000ULL) >> 24) |
157  ((v & 0x00FF000000000000ULL) >> 40) | ((v & 0xFF00000000000000ULL) >> 56);
158 }
159 
160 template <typename T>
162 
163 template <>
164 struct ByteOrderConverter<uint8_t> {
165  typedef uint8_t T;
166 
167  inline static T nativeToBig(T t) {
168  return t;
169  }
170 
171  inline static T bigToNative(T t) {
172  return t;
173  }
174 
175  inline static T nativeToLittle(T t) {
176  return t;
177  }
178 
179  inline static T littleToNative(T t) {
180  return t;
181  }
182 };
183 
184 template <>
185 struct ByteOrderConverter<uint16_t> {
186  typedef uint16_t T;
187 
188  inline static T nativeToBig(T t) {
189  return htobe16(t);
190  }
191 
192  inline static T bigToNative(T t) {
193  return be16toh(t);
194  }
195 
196  inline static T nativeToLittle(T t) {
197  return htole16(t);
198  }
199 
200  inline static T littleToNative(T t) {
201  return le16toh(t);
202  }
203 };
204 
205 template <>
206 struct ByteOrderConverter<uint32_t> {
207  typedef uint32_t T;
208 
209  inline static T nativeToBig(T t) {
210  return htobe32(t);
211  }
212 
213  inline static T bigToNative(T t) {
214  return be32toh(t);
215  }
216 
217  inline static T nativeToLittle(T t) {
218  return htole32(t);
219  }
220 
221  inline static T littleToNative(T t) {
222  return le32toh(t);
223  }
224 };
225 
226 template <>
227 struct ByteOrderConverter<uint64_t> {
228  typedef uint64_t T;
229 
230  inline static T nativeToBig(T t) {
231  return htobe64(t);
232  }
233 
234  inline static T bigToNative(T t) {
235  return be64toh(t);
236  }
237 
238  inline static T nativeToLittle(T t) {
239  return htole64(t);
240  }
241 
242  inline static T littleToNative(T t) {
243  return le64toh(t);
244  }
245 };
246 
247 template <>
248 struct ByteOrderConverter<int8_t> {
249  typedef int8_t T;
250 
251  inline static T nativeToBig(T t) {
252  return t;
253  }
254 
255  inline static T bigToNative(T t) {
256  return t;
257  }
258 
259  inline static T nativeToLittle(T t) {
260  return t;
261  }
262 
263  inline static T littleToNative(T t) {
264  return t;
265  }
266 };
267 
268 template <>
269 struct ByteOrderConverter<int16_t> {
270  typedef int16_t T;
271 
272  inline static T nativeToBig(T t) {
273  return htobe16(static_cast<uint16_t>(t));
274  }
275 
276  inline static T bigToNative(T t) {
277  return be16toh(static_cast<uint16_t>(t));
278  }
279 
280  inline static T nativeToLittle(T t) {
281  return htole16(static_cast<uint16_t>(t));
282  }
283 
284  inline static T littleToNative(T t) {
285  return le16toh(static_cast<uint16_t>(t));
286  }
287 };
288 
289 template <>
290 struct ByteOrderConverter<int32_t> {
291  typedef int32_t T;
292 
293  inline static T nativeToBig(T t) {
294  return htobe32(static_cast<uint32_t>(t));
295  }
296 
297  inline static T bigToNative(T t) {
298  return be32toh(static_cast<uint32_t>(t));
299  }
300 
301  inline static T nativeToLittle(T t) {
302  return htole32(static_cast<uint32_t>(t));
303  }
304 
305  inline static T littleToNative(T t) {
306  return le32toh(static_cast<uint32_t>(t));
307  }
308 };
309 
310 template <>
311 struct ByteOrderConverter<int64_t> {
312  typedef int64_t T;
313 
314  inline static T nativeToBig(T t) {
315  return htobe64(static_cast<uint64_t>(t));
316  }
317 
318  inline static T bigToNative(T t) {
319  return be64toh(static_cast<uint64_t>(t));
320  }
321 
322  inline static T nativeToLittle(T t) {
323  return htole64(static_cast<uint64_t>(t));
324  }
325 
326  inline static T littleToNative(T t) {
327  return le64toh(static_cast<uint64_t>(t));
328  }
329 };
330 
331 template <>
332 struct ByteOrderConverter<float> {
333  typedef float T;
334 
335  inline static T nativeToBig(T t) {
336  BOOST_STATIC_ASSERT(sizeof(T) == sizeof(uint32_t));
337 
338  uint32_t temp;
339  std::memcpy(&temp, &t, sizeof(t));
340  temp = htobe32(temp);
341  std::memcpy(&t, &temp, sizeof(t));
342  return t;
343  }
344 
345  inline static T bigToNative(T t) {
346  uint32_t temp;
347  std::memcpy(&temp, &t, sizeof(t));
348  temp = be32toh(temp);
349  std::memcpy(&t, &temp, sizeof(t));
350  return t;
351  }
352 
353  inline static T nativeToLittle(T t) {
354  uint32_t temp;
355  std::memcpy(&temp, &t, sizeof(t));
356  temp = htole32(temp);
357  std::memcpy(&t, &temp, sizeof(t));
358  return t;
359  }
360 
361  inline static T littleToNative(T t) {
362  uint32_t temp;
363  std::memcpy(&temp, &t, sizeof(t));
364  temp = le32toh(temp);
365  std::memcpy(&t, &temp, sizeof(t));
366  return t;
367  }
368 };
369 
370 template <>
371 struct ByteOrderConverter<double> {
372  typedef double T;
373 
374  inline static T nativeToBig(T t) {
375  BOOST_STATIC_ASSERT(sizeof(T) == sizeof(uint64_t));
376 
377  uint64_t temp;
378  std::memcpy(&temp, &t, sizeof(t));
379  temp = htobe64(temp);
380  std::memcpy(&t, &temp, sizeof(t));
381  return t;
382  }
383 
384  inline static T bigToNative(T t) {
385  uint64_t temp;
386  std::memcpy(&temp, &t, sizeof(t));
387  temp = be64toh(temp);
388  std::memcpy(&t, &temp, sizeof(t));
389  return t;
390  }
391 
392  inline static T nativeToLittle(T t) {
393  uint64_t temp;
394  std::memcpy(&temp, &t, sizeof(t));
395  temp = htole64(temp);
396  std::memcpy(&t, &temp, sizeof(t));
397  return t;
398  }
399 
400  inline static T littleToNative(T t) {
401  uint64_t temp;
402  std::memcpy(&temp, &t, sizeof(t));
403  temp = le64toh(temp);
404  std::memcpy(&t, &temp, sizeof(t));
405  return t;
406  }
407 };
408 
409 // Use a typemape to normalize non-fixed-width integral types to the associated fixed width
410 // types.
411 
412 template <typename T>
414  typedef T type;
415 };
416 
417 template <>
418 struct IntegralTypeMap<signed char> {
419  BOOST_STATIC_ASSERT(CHAR_BIT == 8);
420  typedef int8_t type;
421 };
422 
423 template <>
424 struct IntegralTypeMap<unsigned char> {
425  BOOST_STATIC_ASSERT(CHAR_BIT == 8);
426  typedef uint8_t type;
427 };
428 
429 template <>
430 struct IntegralTypeMap<char> {
431  BOOST_STATIC_ASSERT(CHAR_BIT == 8);
432  typedef boost::mpl::if_c<boost::is_signed<char>::value, int8_t, uint8_t>::type type;
433 };
434 
435 template <>
436 struct IntegralTypeMap<long long> {
437  BOOST_STATIC_ASSERT(sizeof(long long) == sizeof(int64_t));
438  typedef int64_t type;
439 };
440 
441 template <>
442 struct IntegralTypeMap<unsigned long long> {
443  BOOST_STATIC_ASSERT(sizeof(unsigned long long) == sizeof(uint64_t));
444  typedef uint64_t type;
445 };
446 
447 template <typename T>
448 inline T nativeToBig(T t) {
450 }
451 
452 template <typename T>
453 inline T bigToNative(T t) {
454  return ByteOrderConverter<typename IntegralTypeMap<T>::type>::bigToNative(t);
455 }
456 
457 template <typename T>
458 inline T nativeToLittle(T t) {
459  return ByteOrderConverter<typename IntegralTypeMap<T>::type>::nativeToLittle(t);
460 }
461 
462 template <typename T>
463 inline T littleToNative(T t) {
464  return ByteOrderConverter<typename IntegralTypeMap<T>::type>::littleToNative(t);
465 }
466 
467 } // namespace endian
468 } // namespace mongo
469 
470 #undef MONGO_UINT16_SWAB
471 #undef MONGO_UINT32_SWAB
472 #undef MONGO_UINT64_SWAB
473 #undef MONGO_LITTLE_ENDIAN
474 #undef MONGO_BIG_ENDIAN
475 #undef htobe16
476 #undef htobe32
477 #undef htobe64
478 #undef htole16
479 #undef htole32
480 #undef htole64
481 #undef be16toh
482 #undef be32toh
483 #undef be64toh
484 #undef le16toh
485 #undef le32toh
486 #undef le64toh
487 
488 #pragma pop_macro("MONGO_UINT16_SWAB")
489 #pragma pop_macro("MONGO_UINT32_SWAB")
490 #pragma pop_macro("MONGO_UINT64_SWAB")
491 #pragma pop_macro("MONGO_LITTLE_ENDIAN")
492 #pragma pop_macro("MONGO_BIG_ENDIAN")
493 #pragma pop_macro("htobe16")
494 #pragma pop_macro("htobe32")
495 #pragma pop_macro("htobe64")
496 #pragma pop_macro("htole16")
497 #pragma pop_macro("htole32")
498 #pragma pop_macro("htole64")
499 #pragma pop_macro("be16toh")
500 #pragma pop_macro("be32toh")
501 #pragma pop_macro("be64toh")
502 #pragma pop_macro("le16toh")
503 #pragma pop_macro("le32toh")
504 #pragma pop_macro("le64toh")
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20
Definition: endian.h:161
Definition: endian.h:413