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