tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

byte_order.h (7548B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #ifndef LIB_JXL_BASE_BYTE_ORDER_H_
      7 #define LIB_JXL_BASE_BYTE_ORDER_H_
      8 
      9 #include <jxl/types.h>
     10 #include <stdint.h>
     11 #include <string.h>  // memcpy
     12 
     13 #include "lib/jxl/base/compiler_specific.h"
     14 
     15 #if JXL_COMPILER_MSVC
     16 #include <intrin.h>  // _byteswap_*
     17 #endif
     18 
     19 #if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
     20 #define JXL_BYTE_ORDER_LITTLE 1
     21 #else
     22 // This means that we don't know that the byte order is little endian, in
     23 // this case we use endian-neutral code that works for both little- and
     24 // big-endian.
     25 #define JXL_BYTE_ORDER_LITTLE 0
     26 #endif
     27 
     28 // Returns whether the system is little-endian (least-significant byte first).
     29 #if JXL_BYTE_ORDER_LITTLE
     30 static constexpr bool IsLittleEndian() { return true; }
     31 #else
     32 static inline bool IsLittleEndian() {
     33  const uint32_t multibyte = 1;
     34  uint8_t byte;
     35  memcpy(&byte, &multibyte, 1);
     36  return byte == 1;
     37 }
     38 #endif
     39 
     40 static inline bool SwapEndianness(JxlEndianness endianness) {
     41  return ((endianness == JXL_BIG_ENDIAN && IsLittleEndian()) ||
     42          (endianness == JXL_LITTLE_ENDIAN && !IsLittleEndian()));
     43 }
     44 
     45 #if JXL_COMPILER_MSVC
     46 #define JXL_BSWAP16(x) _byteswap_ushort(x)
     47 #define JXL_BSWAP32(x) _byteswap_ulong(x)
     48 #define JXL_BSWAP64(x) _byteswap_uint64(x)
     49 #else
     50 #define JXL_BSWAP16(x) __builtin_bswap16(x)
     51 #define JXL_BSWAP32(x) __builtin_bswap32(x)
     52 #define JXL_BSWAP64(x) __builtin_bswap64(x)
     53 #endif
     54 
     55 static JXL_INLINE uint32_t LoadBE16(const uint8_t* p) {
     56  const uint32_t byte1 = p[0];
     57  const uint32_t byte0 = p[1];
     58  return (byte1 << 8) | byte0;
     59 }
     60 
     61 static JXL_INLINE uint32_t LoadLE16(const uint8_t* p) {
     62  const uint32_t byte0 = p[0];
     63  const uint32_t byte1 = p[1];
     64  return (byte1 << 8) | byte0;
     65 }
     66 
     67 static JXL_INLINE uint32_t LoadBE32(const uint8_t* p) {
     68 #if JXL_BYTE_ORDER_LITTLE
     69  uint32_t big;
     70  memcpy(&big, p, 4);
     71  return JXL_BSWAP32(big);
     72 #else
     73  // Byte-order-independent - can't assume this machine is big endian.
     74  const uint32_t byte3 = p[0];
     75  const uint32_t byte2 = p[1];
     76  const uint32_t byte1 = p[2];
     77  const uint32_t byte0 = p[3];
     78  return (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
     79 #endif
     80 }
     81 
     82 static JXL_INLINE uint64_t LoadBE64(const uint8_t* p) {
     83 #if JXL_BYTE_ORDER_LITTLE
     84  uint64_t big;
     85  memcpy(&big, p, 8);
     86  return JXL_BSWAP64(big);
     87 #else
     88  // Byte-order-independent - can't assume this machine is big endian.
     89  const uint64_t byte7 = p[0];
     90  const uint64_t byte6 = p[1];
     91  const uint64_t byte5 = p[2];
     92  const uint64_t byte4 = p[3];
     93  const uint64_t byte3 = p[4];
     94  const uint64_t byte2 = p[5];
     95  const uint64_t byte1 = p[6];
     96  const uint64_t byte0 = p[7];
     97  return (byte7 << 56ull) | (byte6 << 48ull) | (byte5 << 40ull) |
     98         (byte4 << 32ull) | (byte3 << 24ull) | (byte2 << 16ull) |
     99         (byte1 << 8ull) | byte0;
    100 #endif
    101 }
    102 
    103 static JXL_INLINE uint32_t LoadLE32(const uint8_t* p) {
    104 #if JXL_BYTE_ORDER_LITTLE
    105  uint32_t little;
    106  memcpy(&little, p, 4);
    107  return little;
    108 #else
    109  // Byte-order-independent - can't assume this machine is big endian.
    110  const uint32_t byte0 = p[0];
    111  const uint32_t byte1 = p[1];
    112  const uint32_t byte2 = p[2];
    113  const uint32_t byte3 = p[3];
    114  return (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
    115 #endif
    116 }
    117 
    118 static JXL_INLINE uint64_t LoadLE64(const uint8_t* p) {
    119 #if JXL_BYTE_ORDER_LITTLE
    120  uint64_t little;
    121  memcpy(&little, p, 8);
    122  return little;
    123 #else
    124  // Byte-order-independent - can't assume this machine is big endian.
    125  const uint64_t byte0 = p[0];
    126  const uint64_t byte1 = p[1];
    127  const uint64_t byte2 = p[2];
    128  const uint64_t byte3 = p[3];
    129  const uint64_t byte4 = p[4];
    130  const uint64_t byte5 = p[5];
    131  const uint64_t byte6 = p[6];
    132  const uint64_t byte7 = p[7];
    133  return (byte7 << 56) | (byte6 << 48) | (byte5 << 40) | (byte4 << 32) |
    134         (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
    135 #endif
    136 }
    137 
    138 // Loads a Big-Endian float
    139 static JXL_INLINE float LoadBEFloat(const uint8_t* p) {
    140  uint32_t u = LoadBE32(p);
    141  float result;
    142  memcpy(&result, &u, 4);
    143  return result;
    144 }
    145 
    146 // Loads a Little-Endian float
    147 static JXL_INLINE float LoadLEFloat(const uint8_t* p) {
    148  uint32_t u = LoadLE32(p);
    149  float result;
    150  memcpy(&result, &u, 4);
    151  return result;
    152 }
    153 
    154 static JXL_INLINE void StoreBE16(const uint32_t native, uint8_t* p) {
    155  p[0] = (native >> 8) & 0xFF;
    156  p[1] = native & 0xFF;
    157 }
    158 
    159 static JXL_INLINE void StoreLE16(const uint32_t native, uint8_t* p) {
    160  p[1] = (native >> 8) & 0xFF;
    161  p[0] = native & 0xFF;
    162 }
    163 
    164 static JXL_INLINE void StoreBE32(const uint32_t native, uint8_t* p) {
    165 #if JXL_BYTE_ORDER_LITTLE
    166  const uint32_t big = JXL_BSWAP32(native);
    167  memcpy(p, &big, 4);
    168 #else
    169  // Byte-order-independent - can't assume this machine is big endian.
    170  p[0] = native >> 24;
    171  p[1] = (native >> 16) & 0xFF;
    172  p[2] = (native >> 8) & 0xFF;
    173  p[3] = native & 0xFF;
    174 #endif
    175 }
    176 
    177 static JXL_INLINE void StoreBE64(const uint64_t native, uint8_t* p) {
    178 #if JXL_BYTE_ORDER_LITTLE
    179  const uint64_t big = JXL_BSWAP64(native);
    180  memcpy(p, &big, 8);
    181 #else
    182  // Byte-order-independent - can't assume this machine is big endian.
    183  p[0] = native >> 56ull;
    184  p[1] = (native >> 48ull) & 0xFF;
    185  p[2] = (native >> 40ull) & 0xFF;
    186  p[3] = (native >> 32ull) & 0xFF;
    187  p[4] = (native >> 24ull) & 0xFF;
    188  p[5] = (native >> 16ull) & 0xFF;
    189  p[6] = (native >> 8ull) & 0xFF;
    190  p[7] = native & 0xFF;
    191 #endif
    192 }
    193 
    194 static JXL_INLINE void StoreLE32(const uint32_t native, uint8_t* p) {
    195 #if JXL_BYTE_ORDER_LITTLE
    196  const uint32_t little = native;
    197  memcpy(p, &little, 4);
    198 #else
    199  // Byte-order-independent - can't assume this machine is big endian.
    200  p[3] = native >> 24;
    201  p[2] = (native >> 16) & 0xFF;
    202  p[1] = (native >> 8) & 0xFF;
    203  p[0] = native & 0xFF;
    204 #endif
    205 }
    206 
    207 static JXL_INLINE void StoreLE64(const uint64_t native, uint8_t* p) {
    208 #if JXL_BYTE_ORDER_LITTLE
    209  const uint64_t little = native;
    210  memcpy(p, &little, 8);
    211 #else
    212  // Byte-order-independent - can't assume this machine is big endian.
    213  p[7] = native >> 56;
    214  p[6] = (native >> 48) & 0xFF;
    215  p[5] = (native >> 40) & 0xFF;
    216  p[4] = (native >> 32) & 0xFF;
    217  p[3] = (native >> 24) & 0xFF;
    218  p[2] = (native >> 16) & 0xFF;
    219  p[1] = (native >> 8) & 0xFF;
    220  p[0] = native & 0xFF;
    221 #endif
    222 }
    223 
    224 static JXL_INLINE float BSwapFloat(float x) {
    225  uint32_t u;
    226  memcpy(&u, &x, 4);
    227  uint32_t uswap = JXL_BSWAP32(u);
    228  float xswap;
    229  memcpy(&xswap, &uswap, 4);
    230  return xswap;
    231 }
    232 
    233 // Big/Little Endian order.
    234 struct OrderBE {};
    235 struct OrderLE {};
    236 
    237 // Wrappers for calling from generic code.
    238 static JXL_INLINE void Store16(OrderBE /*tag*/, const uint32_t native,
    239                               uint8_t* p) {
    240  StoreBE16(native, p);
    241 }
    242 
    243 static JXL_INLINE void Store16(OrderLE /*tag*/, const uint32_t native,
    244                               uint8_t* p) {
    245  StoreLE16(native, p);
    246 }
    247 
    248 static JXL_INLINE void Store32(OrderBE /*tag*/, const uint32_t native,
    249                               uint8_t* p) {
    250  StoreBE32(native, p);
    251 }
    252 
    253 static JXL_INLINE void Store32(OrderLE /*tag*/, const uint32_t native,
    254                               uint8_t* p) {
    255  StoreLE32(native, p);
    256 }
    257 
    258 static JXL_INLINE uint32_t Load16(OrderBE /*tag*/, const uint8_t* p) {
    259  return LoadBE16(p);
    260 }
    261 
    262 static JXL_INLINE uint32_t Load16(OrderLE /*tag*/, const uint8_t* p) {
    263  return LoadLE16(p);
    264 }
    265 
    266 static JXL_INLINE uint32_t Load32(OrderBE /*tag*/, const uint8_t* p) {
    267  return LoadBE32(p);
    268 }
    269 
    270 static JXL_INLINE uint32_t Load32(OrderLE /*tag*/, const uint8_t* p) {
    271  return LoadLE32(p);
    272 }
    273 
    274 #endif  // LIB_JXL_BASE_BYTE_ORDER_H_