// Copyright 2019 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CORE_FXCRT_BYTEORDER_H_ #define CORE_FXCRT_BYTEORDER_H_ #include #include "build/build_config.h" #include "core/fxcrt/span.h" #if defined(COMPILER_MSVC) #include #endif namespace fxcrt { namespace internal { #if defined(COMPILER_MSVC) && !defined(__clang__) // TODO(thestig): See // https://developercommunity.visualstudio.com/t/Mark-some-built-in-functions-as-constexp/362558 // https://developercommunity.visualstudio.com/t/constexpr-byte-swapping-optimization/983963 #define FXCRT_BYTESWAPS_CONSTEXPR #else #define FXCRT_BYTESWAPS_CONSTEXPR constexpr #endif // Returns a value with all bytes in |x| swapped, i.e. reverses the endianness. // TODO(thestig): Once C++23 is available, replace with std::byteswap. inline FXCRT_BYTESWAPS_CONSTEXPR uint16_t ByteSwap(uint16_t x) { #if defined(COMPILER_MSVC) && !defined(__clang__) return _byteswap_ushort(x); #else return __builtin_bswap16(x); #endif } inline FXCRT_BYTESWAPS_CONSTEXPR uint32_t ByteSwap(uint32_t x) { #if defined(COMPILER_MSVC) && !defined(__clang__) return _byteswap_ulong(x); #else return __builtin_bswap32(x); #endif } #undef FXCRT_BYTESWAPS_CONSTEXPR } // namespace internal // NOTE: Prefer From*() methods when data is known to be aligned. // Converts the bytes in |x| from host order (endianness) to little endian, and // returns the result. inline uint16_t FromLE16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else return internal::ByteSwap(x); #endif } inline uint32_t FromLE32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else return internal::ByteSwap(x); #endif } // Converts the bytes in |x| from host order (endianness) to big endian, and // returns the result. inline uint16_t FromBE16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return internal::ByteSwap(x); #else return x; #endif } inline uint32_t FromBE32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return internal::ByteSwap(x); #else return x; #endif } // Transfer to/from spans irrespective of alignments. inline uint16_t GetUInt16MSBFirst(pdfium::span span) { return (static_cast(span[0]) << 8) | static_cast(span[1]); } inline uint32_t GetUInt32MSBFirst(pdfium::span span) { return (static_cast(span[0]) << 24) | (static_cast(span[1]) << 16) | (static_cast(span[2]) << 8) | static_cast(span[3]); } inline uint16_t GetUInt16LSBFirst(pdfium::span span) { return (static_cast(span[1]) << 8) | static_cast(span[0]); } inline uint32_t GetUInt32LSBFirst(pdfium::span span) { return (static_cast(span[3]) << 24) | (static_cast(span[2]) << 16) | (static_cast(span[1]) << 8) | static_cast(span[0]); } inline void PutUInt16MSBFirst(uint16_t value, pdfium::span span) { span[0] = value >> 8; span[1] = value & 0xff; } inline void PutUInt32MSBFirst(uint32_t value, pdfium::span span) { span[0] = value >> 24; span[1] = (value >> 16) & 0xff; span[2] = (value >> 8) & 0xff; span[3] = value & 0xff; } inline void PutUInt16LSBFirst(uint16_t value, pdfium::span span) { span[1] = value >> 8; span[0] = value & 0xff; } inline void PutUInt32LSBFirst(uint32_t value, pdfium::span span) { span[3] = value >> 24; span[2] = (value >> 16) & 0xff; span[1] = (value >> 8) & 0xff; span[0] = value & 0xff; } } // namespace fxcrt #endif // CORE_FXCRT_BYTEORDER_H_