1 // Copyright 2019 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef CORE_FXCRT_BYTEORDER_H_
6 #define CORE_FXCRT_BYTEORDER_H_
7
8 #include <stdint.h>
9
10 #include "build/build_config.h"
11 #include "core/fxcrt/span.h"
12
13 #if defined(COMPILER_MSVC)
14 #include <stdlib.h>
15 #endif
16
17 namespace fxcrt {
18
19 namespace internal {
20
21 #if defined(COMPILER_MSVC) && !defined(__clang__)
22 // TODO(thestig): See
23 // https://developercommunity.visualstudio.com/t/Mark-some-built-in-functions-as-constexp/362558
24 // https://developercommunity.visualstudio.com/t/constexpr-byte-swapping-optimization/983963
25 #define FXCRT_BYTESWAPS_CONSTEXPR
26 #else
27 #define FXCRT_BYTESWAPS_CONSTEXPR constexpr
28 #endif
29
30 // Returns a value with all bytes in |x| swapped, i.e. reverses the endianness.
31 // TODO(thestig): Once C++23 is available, replace with std::byteswap.
ByteSwap(uint16_t x)32 inline FXCRT_BYTESWAPS_CONSTEXPR uint16_t ByteSwap(uint16_t x) {
33 #if defined(COMPILER_MSVC) && !defined(__clang__)
34 return _byteswap_ushort(x);
35 #else
36 return __builtin_bswap16(x);
37 #endif
38 }
39
ByteSwap(uint32_t x)40 inline FXCRT_BYTESWAPS_CONSTEXPR uint32_t ByteSwap(uint32_t x) {
41 #if defined(COMPILER_MSVC) && !defined(__clang__)
42 return _byteswap_ulong(x);
43 #else
44 return __builtin_bswap32(x);
45 #endif
46 }
47
48 #undef FXCRT_BYTESWAPS_CONSTEXPR
49
50 } // namespace internal
51
52 // NOTE: Prefer From*() methods when data is known to be aligned.
53
54 // Converts the bytes in |x| from host order (endianness) to little endian, and
55 // returns the result.
FromLE16(uint16_t x)56 inline uint16_t FromLE16(uint16_t x) {
57 #if defined(ARCH_CPU_LITTLE_ENDIAN)
58 return x;
59 #else
60 return internal::ByteSwap(x);
61 #endif
62 }
63
FromLE32(uint32_t x)64 inline uint32_t FromLE32(uint32_t x) {
65 #if defined(ARCH_CPU_LITTLE_ENDIAN)
66 return x;
67 #else
68 return internal::ByteSwap(x);
69 #endif
70 }
71
72 // Converts the bytes in |x| from host order (endianness) to big endian, and
73 // returns the result.
FromBE16(uint16_t x)74 inline uint16_t FromBE16(uint16_t x) {
75 #if defined(ARCH_CPU_LITTLE_ENDIAN)
76 return internal::ByteSwap(x);
77 #else
78 return x;
79 #endif
80 }
81
FromBE32(uint32_t x)82 inline uint32_t FromBE32(uint32_t x) {
83 #if defined(ARCH_CPU_LITTLE_ENDIAN)
84 return internal::ByteSwap(x);
85 #else
86 return x;
87 #endif
88 }
89
90 // Transfer to/from spans irrespective of alignments.
GetUInt16MSBFirst(pdfium::span<const uint8_t,2> span)91 inline uint16_t GetUInt16MSBFirst(pdfium::span<const uint8_t, 2> span) {
92 return (static_cast<uint32_t>(span[0]) << 8) | static_cast<uint32_t>(span[1]);
93 }
94
GetUInt32MSBFirst(pdfium::span<const uint8_t,4> span)95 inline uint32_t GetUInt32MSBFirst(pdfium::span<const uint8_t, 4> span) {
96 return (static_cast<uint32_t>(span[0]) << 24) |
97 (static_cast<uint32_t>(span[1]) << 16) |
98 (static_cast<uint32_t>(span[2]) << 8) | static_cast<uint32_t>(span[3]);
99 }
100
GetUInt16LSBFirst(pdfium::span<const uint8_t,2> span)101 inline uint16_t GetUInt16LSBFirst(pdfium::span<const uint8_t, 2> span) {
102 return (static_cast<uint32_t>(span[1]) << 8) | static_cast<uint32_t>(span[0]);
103 }
104
GetUInt32LSBFirst(pdfium::span<const uint8_t,4> span)105 inline uint32_t GetUInt32LSBFirst(pdfium::span<const uint8_t, 4> span) {
106 return (static_cast<uint32_t>(span[3]) << 24) |
107 (static_cast<uint32_t>(span[2]) << 16) |
108 (static_cast<uint32_t>(span[1]) << 8) | static_cast<uint32_t>(span[0]);
109 }
110
PutUInt16MSBFirst(uint16_t value,pdfium::span<uint8_t,2> span)111 inline void PutUInt16MSBFirst(uint16_t value, pdfium::span<uint8_t, 2> span) {
112 span[0] = value >> 8;
113 span[1] = value & 0xff;
114 }
115
PutUInt32MSBFirst(uint32_t value,pdfium::span<uint8_t,4> span)116 inline void PutUInt32MSBFirst(uint32_t value, pdfium::span<uint8_t, 4> span) {
117 span[0] = value >> 24;
118 span[1] = (value >> 16) & 0xff;
119 span[2] = (value >> 8) & 0xff;
120 span[3] = value & 0xff;
121 }
122
PutUInt16LSBFirst(uint16_t value,pdfium::span<uint8_t,2> span)123 inline void PutUInt16LSBFirst(uint16_t value, pdfium::span<uint8_t, 2> span) {
124 span[1] = value >> 8;
125 span[0] = value & 0xff;
126 }
127
PutUInt32LSBFirst(uint32_t value,pdfium::span<uint8_t,4> span)128 inline void PutUInt32LSBFirst(uint32_t value, pdfium::span<uint8_t, 4> span) {
129 span[3] = value >> 24;
130 span[2] = (value >> 16) & 0xff;
131 span[1] = (value >> 8) & 0xff;
132 span[0] = value & 0xff;
133 }
134
135 } // namespace fxcrt
136
137 #endif // CORE_FXCRT_BYTEORDER_H_
138