1/*!
2 * Copyright (c) 2017 by Contributors
3 * \file endian.h
4 * \brief Endian testing, need c++11
5 */
6#ifndef DMLC_ENDIAN_H_
7#define DMLC_ENDIAN_H_
8
9#include "./base.h"
10
11#ifdef DMLC_CMAKE_LITTLE_ENDIAN
12 // If compiled with CMake, use CMake's endian detection logic
13 #define DMLC_LITTLE_ENDIAN DMLC_CMAKE_LITTLE_ENDIAN
14#else
15 #if defined(__APPLE__) || defined(_WIN32)
16 #define DMLC_LITTLE_ENDIAN 1
17 #elif defined(__GLIBC__) || defined(__GNU_LIBRARY__) \
18 || defined(__ANDROID__) || defined(__RISCV__)
19 #include <endian.h>
20 #define DMLC_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
21 #elif defined(__FreeBSD__) || defined(__OpenBSD__)
22 #include <sys/endian.h>
23 #define DMLC_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
24 #elif defined(__EMSCRIPTEN__) || defined(__hexagon__)
25 #define DMLC_LITTLE_ENDIAN 1
26 #elif defined(__sun) || defined(sun)
27 #include <sys/isa_defs.h>
28 #if defined(_LITTLE_ENDIAN)
29 #define DMLC_LITTLE_ENDIAN 1
30 #else
31 #define DMLC_LITTLE_ENDIAN 0
32 #endif
33 #else
34 #error "Unable to determine endianness of your machine; use CMake to compile"
35 #endif
36#endif
37
38/*! \brief whether serialize using little endian */
39#define DMLC_IO_NO_ENDIAN_SWAP (DMLC_LITTLE_ENDIAN == DMLC_IO_USE_LITTLE_ENDIAN)
40
41namespace dmlc {
42
43/*!
44 * \brief A generic inplace byte swapping function.
45 * \param data The data pointer.
46 * \param elem_bytes The number of bytes of the data elements
47 * \param num_elems Number of elements in the data.
48 * \note Always try pass in constant elem_bytes to enable
49 * compiler optimization
50 */
51inline void ByteSwap(void* data, size_t elem_bytes, size_t num_elems) {
52 for (size_t i = 0; i < num_elems; ++i) {
53 uint8_t* bptr = reinterpret_cast<uint8_t*>(data) + elem_bytes * i;
54 for (size_t j = 0; j < elem_bytes / 2; ++j) {
55 uint8_t v = bptr[elem_bytes - 1 - j];
56 bptr[elem_bytes - 1 - j] = bptr[j];
57 bptr[j] = v;
58 }
59 }
60}
61
62} // namespace dmlc
63#endif // DMLC_ENDIAN_H_
64