Line data Source code
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 0 : static inline uint16_t SkEndianSwap16(uint16_t value) {
31 0 : 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 0 : static constexpr uint32_t SkEndianSwap32(uint32_t value) {
54 0 : return ((value & 0xFF) << 24) |
55 0 : ((value & 0xFF00) << 8) |
56 0 : ((value & 0xFF0000) >> 8) |
57 0 : (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
|