1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBTEXTCLASSIFIER_UTILS_BASE_ENDIAN_H_ 18 #define LIBTEXTCLASSIFIER_UTILS_BASE_ENDIAN_H_ 19 20 #include "utils/base/integral_types.h" 21 22 namespace libtextclassifier3 { 23 24 #if defined OS_LINUX || defined OS_CYGWIN || defined OS_ANDROID || \ 25 defined(__ANDROID__) 26 #include <endian.h> 27 #elif defined(__APPLE__) 28 #include <machine/endian.h> 29 // Add linux style defines. 30 #ifndef __BYTE_ORDER 31 #define __BYTE_ORDER BYTE_ORDER 32 #endif // __BYTE_ORDER 33 #ifndef __LITTLE_ENDIAN 34 #define __LITTLE_ENDIAN LITTLE_ENDIAN 35 #endif // __LITTLE_ENDIAN 36 #ifndef __BIG_ENDIAN 37 #define __BIG_ENDIAN BIG_ENDIAN 38 #endif // __BIG_ENDIAN 39 #endif 40 41 // The following guarantees declaration of the byte swap functions, and 42 // defines __BYTE_ORDER for MSVC 43 #if defined(__GLIBC__) || defined(__BIONIC__) || defined(__CYGWIN__) 44 #include <byteswap.h> // IWYU pragma: export 45 // The following section defines the byte swap functions for OS X / iOS, 46 // which does not ship with byteswap.h. 47 #elif defined(__APPLE__) 48 // Make sure that byte swap functions are not already defined. 49 #if !defined(bswap_16) 50 #include <libkern/OSByteOrder.h> 51 #define bswap_16(x) OSSwapInt16(x) 52 #define bswap_32(x) OSSwapInt32(x) 53 #define bswap_64(x) OSSwapInt64(x) 54 #endif // !defined(bswap_16) 55 #else 56 #define int64_t {x} x##LL 57 #define uint64_t {x} x##ULL 58 static inline uint16 bswap_16(uint16 x) { 59 return (uint16)(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); // NOLINT 60 } 61 #define bswap_16(x) bswap_16(x) 62 static inline uint32 bswap_32(uint32 x) { 63 return (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | 64 ((x & 0xFF000000) >> 24)); 65 } 66 #define bswap_32(x) bswap_32(x) 67 static inline uint64 bswap_64(uint64 x) { 68 return (((x & uint64_t{0xFF}) << 56) | ((x & uint64_t{0xFF00}) << 40) | 69 ((x & uint64_t{0xFF0000}) << 24) | ((x & uint64_t{0xFF000000}) << 8) | 70 ((x & uint64_t{0xFF00000000}) >> 8) | 71 ((x & uint64_t{0xFF0000000000}) >> 24) | 72 ((x & uint64_t{0xFF000000000000}) >> 40) | 73 ((x & uint64_t{0xFF00000000000000}) >> 56)); 74 } 75 #define bswap_64(x) bswap_64(x) 76 #endif 77 78 // define the macros IS_LITTLE_ENDIAN or IS_BIG_ENDIAN 79 // using the above endian definitions from endian.h if 80 // endian.h was included 81 #ifdef __BYTE_ORDER 82 #if __BYTE_ORDER == __LITTLE_ENDIAN 83 #define IS_LITTLE_ENDIAN 84 #endif 85 86 #if __BYTE_ORDER == __BIG_ENDIAN 87 #define IS_BIG_ENDIAN 88 #endif 89 90 #else 91 92 #if defined(__LITTLE_ENDIAN__) 93 #define IS_LITTLE_ENDIAN 94 #elif defined(__BIG_ENDIAN__) 95 #define IS_BIG_ENDIAN 96 #endif 97 98 // there is also PDP endian ... 99 100 #endif // __BYTE_ORDER 101 102 class LittleEndian { 103 public: 104 // Conversion functions. 105 #ifdef IS_LITTLE_ENDIAN 106 FromHost16(uint16 x)107 static uint16 FromHost16(uint16 x) { return x; } ToHost16(uint16 x)108 static uint16 ToHost16(uint16 x) { return x; } 109 FromHost32(uint32 x)110 static uint32 FromHost32(uint32 x) { return x; } ToHost32(uint32 x)111 static uint32 ToHost32(uint32 x) { return x; } 112 FromHost64(uint64 x)113 static uint64 FromHost64(uint64 x) { return x; } ToHost64(uint64 x)114 static uint64 ToHost64(uint64 x) { return x; } 115 IsLittleEndian()116 static bool IsLittleEndian() { return true; } 117 118 #elif defined IS_BIG_ENDIAN 119 120 static uint16 FromHost16(uint16 x) { return gbswap_16(x); } 121 static uint16 ToHost16(uint16 x) { return gbswap_16(x); } 122 123 static uint32 FromHost32(uint32 x) { return gbswap_32(x); } 124 static uint32 ToHost32(uint32 x) { return gbswap_32(x); } 125 126 static uint64 FromHost64(uint64 x) { return gbswap_64(x); } 127 static uint64 ToHost64(uint64 x) { return gbswap_64(x); } 128 129 static bool IsLittleEndian() { return false; } 130 131 #endif /* ENDIAN */ 132 }; 133 134 } // namespace libtextclassifier3 135 136 #endif // LIBTEXTCLASSIFIER_UTILS_BASE_ENDIAN_H_ 137