libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | 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_