aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkEndian.h
blob: 39e5dd8fb4372689a3338913d284d977c64c2e5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkEndian_DEFINED
#define SkEndian_DEFINED

#include "SkTypes.h"

/** \file SkEndian.h

    Macros and helper functions for handling 16 and 32 bit values in
    big and little endian formats.
*/

#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
    #error "can't have both LENDIAN and BENDIAN defined"
#endif

#if !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
    #error "need either LENDIAN or BENDIAN defined"
#endif

/** Swap the two bytes in the low 16bits of the parameters.
    e.g. 0x1234 -> 0x3412
*/
static inline uint16_t SkEndianSwap16(uint16_t value) {
    return static_cast<uint16_t>((value >> 8) | (value << 8));
}

template<uint16_t N> struct SkTEndianSwap16 {
    static const uint16_t value = static_cast<uint16_t>((N >> 8) | ((N & 0xFF) << 8));
};

/** Vector version of SkEndianSwap16(), which swaps the
    low two bytes of each value in the array.
*/
static inline void SkEndianSwap16s(uint16_t array[], int count) {
    SkASSERT(count == 0 || array != nullptr);

    while (--count >= 0) {
        *array = SkEndianSwap16(*array);
        array += 1;
    }
}

/** Reverse all 4 bytes in a 32bit value.
    e.g. 0x12345678 -> 0x78563412
*/
static constexpr uint32_t SkEndianSwap32(uint32_t value) {
    return ((value & 0xFF) << 24) |
           ((value & 0xFF00) << 8) |
           ((value & 0xFF0000) >> 8) |
            (value >> 24);
}

template<uint32_t N> struct SkTEndianSwap32 {
    static const uint32_t value = ((N & 0xFF) << 24) |
                                  ((N & 0xFF00) << 8) |
                                  ((N & 0xFF0000) >> 8) |
                                  (N >> 24);
};

/** Vector version of SkEndianSwap32(), which swaps the
    bytes of each value in the array.
*/
static inline void SkEndianSwap32s(uint32_t array[], int count) {
    SkASSERT(count == 0 || array != nullptr);

    while (--count >= 0) {
        *array = SkEndianSwap32(*array);
        array += 1;
    }
}

/** Reverse all 8 bytes in a 64bit value.
    e.g. 0x1122334455667788 -> 0x8877665544332211
*/
static inline uint64_t SkEndianSwap64(uint64_t value) {
    return (((value & 0x00000000000000FFULL) << (8*7)) |
            ((value & 0x000000000000FF00ULL) << (8*5)) |
            ((value & 0x0000000000FF0000ULL) << (8*3)) |
            ((value & 0x00000000FF000000ULL) << (8*1)) |
            ((value & 0x000000FF00000000ULL) >> (8*1)) |
            ((value & 0x0000FF0000000000ULL) >> (8*3)) |
            ((value & 0x00FF000000000000ULL) >> (8*5)) |
            ((value)                         >> (8*7)));
}
template<uint64_t N> struct SkTEndianSwap64 {
    static const uint64_t value = (((N & 0x00000000000000FFULL) << (8*7)) |
                                   ((N & 0x000000000000FF00ULL) << (8*5)) |
                                   ((N & 0x0000000000FF0000ULL) << (8*3)) |
                                   ((N & 0x00000000FF000000ULL) << (8*1)) |
                                   ((N & 0x000000FF00000000ULL) >> (8*1)) |
                                   ((N & 0x0000FF0000000000ULL) >> (8*3)) |
                                   ((N & 0x00FF000000000000ULL) >> (8*5)) |
                                   ((N)                         >> (8*7)));
};

/** Vector version of SkEndianSwap64(), which swaps the
    bytes of each value in the array.
*/
static inline void SkEndianSwap64s(uint64_t array[], int count) {
    SkASSERT(count == 0 || array != nullptr);

    while (--count >= 0) {
        *array = SkEndianSwap64(*array);
        array += 1;
    }
}

#ifdef SK_CPU_LENDIAN
    #define SkEndian_SwapBE16(n)    SkEndianSwap16(n)
    #define SkEndian_SwapBE32(n)    SkEndianSwap32(n)
    #define SkEndian_SwapBE64(n)    SkEndianSwap64(n)
    #define SkEndian_SwapLE16(n)    (n)
    #define SkEndian_SwapLE32(n)    (n)
    #define SkEndian_SwapLE64(n)    (n)

    #define SkTEndian_SwapBE16(n)    SkTEndianSwap16<n>::value
    #define SkTEndian_SwapBE32(n)    SkTEndianSwap32<n>::value
    #define SkTEndian_SwapBE64(n)    SkTEndianSwap64<n>::value
    #define SkTEndian_SwapLE16(n)    (n)
    #define SkTEndian_SwapLE32(n)    (n)
    #define SkTEndian_SwapLE64(n)    (n)
#else   // SK_CPU_BENDIAN
    #define SkEndian_SwapBE16(n)    (n)
    #define SkEndian_SwapBE32(n)    (n)
    #define SkEndian_SwapBE64(n)    (n)
    #define SkEndian_SwapLE16(n)    SkEndianSwap16(n)
    #define SkEndian_SwapLE32(n)    SkEndianSwap32(n)
    #define SkEndian_SwapLE64(n)    SkEndianSwap64(n)

    #define SkTEndian_SwapBE16(n)    (n)
    #define SkTEndian_SwapBE32(n)    (n)
    #define SkTEndian_SwapBE64(n)    (n)
    #define SkTEndian_SwapLE16(n)    SkTEndianSwap16<n>::value
    #define SkTEndian_SwapLE32(n)    SkTEndianSwap32<n>::value
    #define SkTEndian_SwapLE64(n)    SkTEndianSwap64<n>::value
#endif

// When a bytestream is embedded in a 32-bit word, how far we need to
// shift the word to extract each byte from the low 8 bits by anding with 0xff.
#ifdef SK_CPU_LENDIAN
    #define SkEndian_Byte0Shift 0
    #define SkEndian_Byte1Shift 8
    #define SkEndian_Byte2Shift 16
    #define SkEndian_Byte3Shift 24
#else   // SK_CPU_BENDIAN
    #define SkEndian_Byte0Shift 24
    #define SkEndian_Byte1Shift 16
    #define SkEndian_Byte2Shift 8
    #define SkEndian_Byte3Shift 0
#endif


#if defined(SK_UINT8_BITFIELD_LENDIAN) && defined(SK_UINT8_BITFIELD_BENDIAN)
    #error "can't have both bitfield LENDIAN and BENDIAN defined"
#endif

#if !defined(SK_UINT8_BITFIELD_LENDIAN) && !defined(SK_UINT8_BITFIELD_BENDIAN)
    #ifdef SK_CPU_LENDIAN
        #define SK_UINT8_BITFIELD_LENDIAN
    #else
        #define SK_UINT8_BITFIELD_BENDIAN
    #endif
#endif

#ifdef SK_UINT8_BITFIELD_LENDIAN
    #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \
        SK_OT_BYTE f0 : 1; \
        SK_OT_BYTE f1 : 1; \
        SK_OT_BYTE f2 : 1; \
        SK_OT_BYTE f3 : 1; \
        SK_OT_BYTE f4 : 1; \
        SK_OT_BYTE f5 : 1; \
        SK_OT_BYTE f6 : 1; \
        SK_OT_BYTE f7 : 1;
#else
    #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \
        SK_OT_BYTE f7 : 1; \
        SK_OT_BYTE f6 : 1; \
        SK_OT_BYTE f5 : 1; \
        SK_OT_BYTE f4 : 1; \
        SK_OT_BYTE f3 : 1; \
        SK_OT_BYTE f2 : 1; \
        SK_OT_BYTE f1 : 1; \
        SK_OT_BYTE f0 : 1;
#endif

#endif