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 GG_LONGLONG(x) x##LL 57 #define GG_ULONGLONG(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 & GG_ULONGLONG(0xFF)) << 56) | 69 ((x & GG_ULONGLONG(0xFF00)) << 40) | 70 ((x & GG_ULONGLONG(0xFF0000)) << 24) | 71 ((x & GG_ULONGLONG(0xFF000000)) << 8) | 72 ((x & GG_ULONGLONG(0xFF00000000)) >> 8) | 73 ((x & GG_ULONGLONG(0xFF0000000000)) >> 24) | 74 ((x & GG_ULONGLONG(0xFF000000000000)) >> 40) | 75 ((x & GG_ULONGLONG(0xFF00000000000000)) >> 56)); 76 } 77 #define bswap_64(x) bswap_64(x) 78 #endif 79 80 // define the macros IS_LITTLE_ENDIAN or IS_BIG_ENDIAN 81 // using the above endian definitions from endian.h if 82 // endian.h was included 83 #ifdef __BYTE_ORDER 84 #if __BYTE_ORDER == __LITTLE_ENDIAN 85 #define IS_LITTLE_ENDIAN 86 #endif 87 88 #if __BYTE_ORDER == __BIG_ENDIAN 89 #define IS_BIG_ENDIAN 90 #endif 91 92 #else 93 94 #if defined(__LITTLE_ENDIAN__) 95 #define IS_LITTLE_ENDIAN 96 #elif defined(__BIG_ENDIAN__) 97 #define IS_BIG_ENDIAN 98 #endif 99 100 // there is also PDP endian ... 101 102 #endif // __BYTE_ORDER 103 104 class LittleEndian { 105 public: 106 // Conversion functions. 107 #ifdef IS_LITTLE_ENDIAN 108 109 static uint16 FromHost16(uint16 x) { return x; } 110 static uint16 ToHost16(uint16 x) { return x; } 111 112 static uint32 FromHost32(uint32 x) { return x; } 113 static uint32 ToHost32(uint32 x) { return x; } 114 115 static uint64 FromHost64(uint64 x) { return x; } 116 static uint64 ToHost64(uint64 x) { return x; } 117 118 static bool IsLittleEndian() { return true; } 119 120 #elif defined IS_BIG_ENDIAN 121 122 static uint16 FromHost16(uint16 x) { return gbswap_16(x); } 123 static uint16 ToHost16(uint16 x) { return gbswap_16(x); } 124 125 static uint32 FromHost32(uint32 x) { return gbswap_32(x); } 126 static uint32 ToHost32(uint32 x) { return gbswap_32(x); } 127 128 static uint64 FromHost64(uint64 x) { return gbswap_64(x); } 129 static uint64 ToHost64(uint64 x) { return gbswap_64(x); } 130 131 static bool IsLittleEndian() { return false; } 132 133 #endif /* ENDIAN */ 134 }; 135 136 } // namespace libtextclassifier3 137 138 #endif // LIBTEXTCLASSIFIER_UTILS_BASE_ENDIAN_H_ 139