1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkEndian_DEFINED 9 #define SkEndian_DEFINED 10 11 #include "SkTypes.h" 12 13 /** \file SkEndian.h 14 15 Macros and helper functions for handling 16 and 32 bit values in 16 big and little endian formats. 17 */ 18 19 #if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN) 20 #error "can't have both LENDIAN and BENDIAN defined" 21 #endif 22 23 #if !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN) 24 #error "need either LENDIAN or BENDIAN defined" 25 #endif 26 27 /** Swap the two bytes in the low 16bits of the parameters. 28 e.g. 0x1234 -> 0x3412 29 */ 30 static inline uint16_t SkEndianSwap16(uint16_t value) { 31 return static_cast<uint16_t>((value >> 8) | (value << 8)); 32 } 33 34 template<uint16_t N> struct SkTEndianSwap16 { 35 static const uint16_t value = static_cast<uint16_t>((N >> 8) | ((N & 0xFF) << 8)); 36 }; 37 38 /** Vector version of SkEndianSwap16(), which swaps the 39 low two bytes of each value in the array. 40 */ 41 static inline void SkEndianSwap16s(uint16_t array[], int count) { 42 SkASSERT(count == 0 || array != nullptr); 43 44 while (--count >= 0) { 45 *array = SkEndianSwap16(*array); 46 array += 1; 47 } 48 } 49 50 /** Reverse all 4 bytes in a 32bit value. 51 e.g. 0x12345678 -> 0x78563412 52 */ 53 static constexpr uint32_t SkEndianSwap32(uint32_t value) { 54 return ((value & 0xFF) << 24) | 55 ((value & 0xFF00) << 8) | 56 ((value & 0xFF0000) >> 8) | 57 (value >> 24); 58 } 59 60 template<uint32_t N> struct SkTEndianSwap32 { 61 static const uint32_t value = ((N & 0xFF) << 24) | 62 ((N & 0xFF00) << 8) | 63 ((N & 0xFF0000) >> 8) | 64 (N >> 24); 65 }; 66 67 /** Vector version of SkEndianSwap32(), which swaps the 68 bytes of each value in the array. 69 */ 70 static inline void SkEndianSwap32s(uint32_t array[], int count) { 71 SkASSERT(count == 0 || array != nullptr); 72 73 while (--count >= 0) { 74 *array = SkEndianSwap32(*array); 75 array += 1; 76 } 77 } 78 79 /** Reverse all 8 bytes in a 64bit value. 80 e.g. 0x1122334455667788 -> 0x8877665544332211 81 */ 82 static inline uint64_t SkEndianSwap64(uint64_t value) { 83 return (((value & 0x00000000000000FFULL) << (8*7)) | 84 ((value & 0x000000000000FF00ULL) << (8*5)) | 85 ((value & 0x0000000000FF0000ULL) << (8*3)) | 86 ((value & 0x00000000FF000000ULL) << (8*1)) | 87 ((value & 0x000000FF00000000ULL) >> (8*1)) | 88 ((value & 0x0000FF0000000000ULL) >> (8*3)) | 89 ((value & 0x00FF000000000000ULL) >> (8*5)) | 90 ((value) >> (8*7))); 91 } 92 template<uint64_t N> struct SkTEndianSwap64 { 93 static const uint64_t value = (((N & 0x00000000000000FFULL) << (8*7)) | 94 ((N & 0x000000000000FF00ULL) << (8*5)) | 95 ((N & 0x0000000000FF0000ULL) << (8*3)) | 96 ((N & 0x00000000FF000000ULL) << (8*1)) | 97 ((N & 0x000000FF00000000ULL) >> (8*1)) | 98 ((N & 0x0000FF0000000000ULL) >> (8*3)) | 99 ((N & 0x00FF000000000000ULL) >> (8*5)) | 100 ((N) >> (8*7))); 101 }; 102 103 /** Vector version of SkEndianSwap64(), which swaps the 104 bytes of each value in the array. 105 */ 106 static inline void SkEndianSwap64s(uint64_t array[], int count) { 107 SkASSERT(count == 0 || array != nullptr); 108 109 while (--count >= 0) { 110 *array = SkEndianSwap64(*array); 111 array += 1; 112 } 113 } 114 115 #ifdef SK_CPU_LENDIAN 116 #define SkEndian_SwapBE16(n) SkEndianSwap16(n) 117 #define SkEndian_SwapBE32(n) SkEndianSwap32(n) 118 #define SkEndian_SwapBE64(n) SkEndianSwap64(n) 119 #define SkEndian_SwapLE16(n) (n) 120 #define SkEndian_SwapLE32(n) (n) 121 #define SkEndian_SwapLE64(n) (n) 122 123 #define SkTEndian_SwapBE16(n) SkTEndianSwap16<n>::value 124 #define SkTEndian_SwapBE32(n) SkTEndianSwap32<n>::value 125 #define SkTEndian_SwapBE64(n) SkTEndianSwap64<n>::value 126 #define SkTEndian_SwapLE16(n) (n) 127 #define SkTEndian_SwapLE32(n) (n) 128 #define SkTEndian_SwapLE64(n) (n) 129 #else // SK_CPU_BENDIAN 130 #define SkEndian_SwapBE16(n) (n) 131 #define SkEndian_SwapBE32(n) (n) 132 #define SkEndian_SwapBE64(n) (n) 133 #define SkEndian_SwapLE16(n) SkEndianSwap16(n) 134 #define SkEndian_SwapLE32(n) SkEndianSwap32(n) 135 #define SkEndian_SwapLE64(n) SkEndianSwap64(n) 136 137 #define SkTEndian_SwapBE16(n) (n) 138 #define SkTEndian_SwapBE32(n) (n) 139 #define SkTEndian_SwapBE64(n) (n) 140 #define SkTEndian_SwapLE16(n) SkTEndianSwap16<n>::value 141 #define SkTEndian_SwapLE32(n) SkTEndianSwap32<n>::value 142 #define SkTEndian_SwapLE64(n) SkTEndianSwap64<n>::value 143 #endif 144 145 // When a bytestream is embedded in a 32-bit word, how far we need to 146 // shift the word to extract each byte from the low 8 bits by anding with 0xff. 147 #ifdef SK_CPU_LENDIAN 148 #define SkEndian_Byte0Shift 0 149 #define SkEndian_Byte1Shift 8 150 #define SkEndian_Byte2Shift 16 151 #define SkEndian_Byte3Shift 24 152 #else // SK_CPU_BENDIAN 153 #define SkEndian_Byte0Shift 24 154 #define SkEndian_Byte1Shift 16 155 #define SkEndian_Byte2Shift 8 156 #define SkEndian_Byte3Shift 0 157 #endif 158 159 160 #if defined(SK_UINT8_BITFIELD_LENDIAN) && defined(SK_UINT8_BITFIELD_BENDIAN) 161 #error "can't have both bitfield LENDIAN and BENDIAN defined" 162 #endif 163 164 #if !defined(SK_UINT8_BITFIELD_LENDIAN) && !defined(SK_UINT8_BITFIELD_BENDIAN) 165 #ifdef SK_CPU_LENDIAN 166 #define SK_UINT8_BITFIELD_LENDIAN 167 #else 168 #define SK_UINT8_BITFIELD_BENDIAN 169 #endif 170 #endif 171 172 #ifdef SK_UINT8_BITFIELD_LENDIAN 173 #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \ 174 SK_OT_BYTE f0 : 1; \ 175 SK_OT_BYTE f1 : 1; \ 176 SK_OT_BYTE f2 : 1; \ 177 SK_OT_BYTE f3 : 1; \ 178 SK_OT_BYTE f4 : 1; \ 179 SK_OT_BYTE f5 : 1; \ 180 SK_OT_BYTE f6 : 1; \ 181 SK_OT_BYTE f7 : 1; 182 #else 183 #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \ 184 SK_OT_BYTE f7 : 1; \ 185 SK_OT_BYTE f6 : 1; \ 186 SK_OT_BYTE f5 : 1; \ 187 SK_OT_BYTE f4 : 1; \ 188 SK_OT_BYTE f3 : 1; \ 189 SK_OT_BYTE f2 : 1; \ 190 SK_OT_BYTE f1 : 1; \ 191 SK_OT_BYTE f0 : 1; 192 #endif 193 194 #endif 195