18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkEndian_DEFINED
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkEndian_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypes.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \file SkEndian.h
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Macros and helper functions for handling 16 and 32 bit values in
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    big and little endian formats.
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #error "can't have both LENDIAN and BENDIAN defined"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #error "need either LENDIAN or BENDIAN defined"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Swap the two bytes in the low 16bits of the parameters.
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    e.g. 0x1234 -> 0x3412
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
30f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.orgstatic inline uint16_t SkEndianSwap16(uint16_t value) {
31f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    return static_cast<uint16_t>((value >> 8) | (value << 8));
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
33f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org
34f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.comtemplate<uint16_t N> struct SkTEndianSwap16 {
35f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    static const uint16_t value = static_cast<uint16_t>((N >> 8) | ((N & 0xFF) << 8));
36f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com};
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Vector version of SkEndianSwap16(), which swaps the
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    low two bytes of each value in the array.
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
41ad91799832b9ba2a3de30c0f57968148b4be17afreed@google.comstatic inline void SkEndianSwap16s(uint16_t array[], int count) {
4296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(count == 0 || array != nullptr);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
44ad91799832b9ba2a3de30c0f57968148b4be17afreed@google.com    while (--count >= 0) {
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *array = SkEndianSwap16(*array);
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        array += 1;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Reverse all 4 bytes in a 32bit value.
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    e.g. 0x12345678 -> 0x78563412
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
53ab926f0a1bca1c6e17520803d964a0344b4f79b4msarettstatic constexpr uint32_t SkEndianSwap32(uint32_t value) {
54f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org    return ((value & 0xFF) << 24) |
55f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org           ((value & 0xFF00) << 8) |
56f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org           ((value & 0xFF0000) >> 8) |
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (value >> 24);
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
59f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org
60f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.comtemplate<uint32_t N> struct SkTEndianSwap32 {
61f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    static const uint32_t value = ((N & 0xFF) << 24) |
62f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com                                  ((N & 0xFF00) << 8) |
63f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com                                  ((N & 0xFF0000) >> 8) |
64f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com                                  (N >> 24);
65f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com};
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com/** Vector version of SkEndianSwap32(), which swaps the
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bytes of each value in the array.
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
70ad91799832b9ba2a3de30c0f57968148b4be17afreed@google.comstatic inline void SkEndianSwap32s(uint32_t array[], int count) {
7196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(count == 0 || array != nullptr);
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
73ad91799832b9ba2a3de30c0f57968148b4be17afreed@google.com    while (--count >= 0) {
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *array = SkEndianSwap32(*array);
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        array += 1;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
79b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com/** Reverse all 8 bytes in a 64bit value.
80b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    e.g. 0x1122334455667788 -> 0x8877665544332211
81b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com*/
82b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.comstatic inline uint64_t SkEndianSwap64(uint64_t value) {
83b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    return (((value & 0x00000000000000FFULL) << (8*7)) |
84b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com            ((value & 0x000000000000FF00ULL) << (8*5)) |
85b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com            ((value & 0x0000000000FF0000ULL) << (8*3)) |
86b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com            ((value & 0x00000000FF000000ULL) << (8*1)) |
87b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com            ((value & 0x000000FF00000000ULL) >> (8*1)) |
88b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com            ((value & 0x0000FF0000000000ULL) >> (8*3)) |
89b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com            ((value & 0x00FF000000000000ULL) >> (8*5)) |
90b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com            ((value)                         >> (8*7)));
91b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com}
92b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.comtemplate<uint64_t N> struct SkTEndianSwap64 {
93b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    static const uint64_t value = (((N & 0x00000000000000FFULL) << (8*7)) |
94b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com                                   ((N & 0x000000000000FF00ULL) << (8*5)) |
95b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com                                   ((N & 0x0000000000FF0000ULL) << (8*3)) |
96b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com                                   ((N & 0x00000000FF000000ULL) << (8*1)) |
97b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com                                   ((N & 0x000000FF00000000ULL) >> (8*1)) |
98b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com                                   ((N & 0x0000FF0000000000ULL) >> (8*3)) |
99b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com                                   ((N & 0x00FF000000000000ULL) >> (8*5)) |
100b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com                                   ((N)                         >> (8*7)));
101b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com};
102b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com
103b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com/** Vector version of SkEndianSwap64(), which swaps the
104b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    bytes of each value in the array.
105b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com*/
106b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.comstatic inline void SkEndianSwap64s(uint64_t array[], int count) {
10796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(count == 0 || array != nullptr);
108b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com
109b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    while (--count >= 0) {
110b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com        *array = SkEndianSwap64(*array);
111b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com        array += 1;
112b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    }
113b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com}
114b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_CPU_LENDIAN
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapBE16(n)    SkEndianSwap16(n)
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapBE32(n)    SkEndianSwap32(n)
118b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkEndian_SwapBE64(n)    SkEndianSwap64(n)
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapLE16(n)    (n)
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapLE32(n)    (n)
121b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkEndian_SwapLE64(n)    (n)
122f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com
123f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapBE16(n)    SkTEndianSwap16<n>::value
124f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapBE32(n)    SkTEndianSwap32<n>::value
125b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkTEndian_SwapBE64(n)    SkTEndianSwap64<n>::value
126f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapLE16(n)    (n)
127f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapLE32(n)    (n)
128b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkTEndian_SwapLE64(n)    (n)
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else   // SK_CPU_BENDIAN
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapBE16(n)    (n)
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapBE32(n)    (n)
132b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkEndian_SwapBE64(n)    (n)
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapLE16(n)    SkEndianSwap16(n)
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkEndian_SwapLE32(n)    SkEndianSwap32(n)
135b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkEndian_SwapLE64(n)    SkEndianSwap64(n)
136f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com
137f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapBE16(n)    (n)
138f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapBE32(n)    (n)
139b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkTEndian_SwapBE64(n)    (n)
140f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapLE16(n)    SkTEndianSwap16<n>::value
141f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SkTEndian_SwapLE32(n)    SkTEndianSwap32<n>::value
142b4ca46d748364236e82fdaccc08022dd89e29d40epoger@google.com    #define SkTEndian_SwapLE64(n)    SkTEndianSwap64<n>::value
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com// When a bytestream is embedded in a 32-bit word, how far we need to
14601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com// shift the word to extract each byte from the low 8 bits by anding with 0xff.
14701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#ifdef SK_CPU_LENDIAN
14801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte0Shift 0
14901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte1Shift 8
15001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte2Shift 16
15101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte3Shift 24
15201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#else   // SK_CPU_BENDIAN
15301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte0Shift 24
15401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte1Shift 16
15501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte2Shift 8
15601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com    #define SkEndian_Byte3Shift 0
15701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#endif
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
159f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com
160f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com#if defined(SK_UINT8_BITFIELD_LENDIAN) && defined(SK_UINT8_BITFIELD_BENDIAN)
161f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #error "can't have both bitfield LENDIAN and BENDIAN defined"
162f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com#endif
163f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com
164f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com#if !defined(SK_UINT8_BITFIELD_LENDIAN) && !defined(SK_UINT8_BITFIELD_BENDIAN)
165f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #ifdef SK_CPU_LENDIAN
166f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        #define SK_UINT8_BITFIELD_LENDIAN
167f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #else
168f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        #define SK_UINT8_BITFIELD_BENDIAN
169f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #endif
170f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com#endif
171f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com
172f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com#ifdef SK_UINT8_BITFIELD_LENDIAN
173f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \
174f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f0 : 1; \
175f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f1 : 1; \
176f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f2 : 1; \
177f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f3 : 1; \
178f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f4 : 1; \
179f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f5 : 1; \
180f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f6 : 1; \
181f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f7 : 1;
182f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com#else
183f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com    #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \
184f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f7 : 1; \
185f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f6 : 1; \
186f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f5 : 1; \
187f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f4 : 1; \
188f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f3 : 1; \
189f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f2 : 1; \
190f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f1 : 1; \
191f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com        SK_OT_BYTE f0 : 1;
192f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com#endif
193f8d1aee2526a384a570b082b17f3a19fe72bd15ebungeman@google.com
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
195