DNA Calib 1.1
Project brief
ByteSwap.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#ifdef TERSE_ENABLE_SSE
6 #define ENABLE_SSE_BSWAP
7#endif // TERSE_ENABLE_SSE
8
10
11#ifdef _MSC_VER
12 #pragma warning(push)
13 #pragma warning(disable : 4365 4987)
14#endif
15#include <cstddef>
16#include <cstdint>
17#include <cstring>
18#include <type_traits>
19#ifdef _MSC_VER
20 #pragma warning(pop)
21#endif
22
23namespace terse {
24
25namespace traits {
26
27template<std::size_t size>
29 using type = typename std::conditional<(size == 1ul), std::uint8_t,
30 typename std::conditional<(size == 2ul), std::uint16_t,
31 typename std::conditional<(size <= 4ul), std::uint32_t,
32 std::uint64_t>::type>::type>::type;
33};
34
35} // namespace traits
36
37namespace impl {
38
39struct block128 {
40
41 static constexpr std::size_t alignment() {
42 #if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64)
43 return std::alignment_of<std::max_align_t>::value;
44 #else
45 return 16ul;
46 #endif
47 }
48
49};
50
51} // namespace impl
52
53enum class Endianness {
54 Little,
55 Big,
56 Network = Big
57};
58
59template<Endianness EByteOrder>
61
62template<>
64
65 template<typename T>
66 static void swap(T& value) {
67 #ifdef TARGET_LITTLE_ENDIAN
68 static_cast<void>(value);
69 #else
70 using UIntType = typename traits::uint_of_size<sizeof(T)>::type;
71 static_assert(sizeof(T) == sizeof(UIntType), "No matching unsigned integral type found for the given type.");
72 // Using memcpy is the only well-defined way of reconstructing arbitrary types from raw bytes.
73 // The seemingly unnecessary copies and memcpy calls are all optimized away,
74 // compiler knows what's up.
75 UIntType swapped;
76 std::memcpy(&swapped, &value, sizeof(T));
77 swapped = bswap(swapped);
78 std::memcpy(&value, &swapped, sizeof(T));
79 #endif // TARGET_LITTLE_ENDIAN
80 }
81
82 template<typename T>
83 static void swap(T* values) {
84 #ifdef TARGET_LITTLE_ENDIAN
85 static_cast<void>(values);
86 #else
87 using UIntType = typename traits::uint_of_size<sizeof(T)>::type;
88 static_assert(sizeof(T) == sizeof(UIntType), "No matching unsigned integral type found for the given type.");
89 // Using memcpy is the only well-defined way of reconstructing arbitrary types from raw bytes.
90 // The seemingly unnecessary copies and memcpy calls are all optimized away,
91 // compiler knows what's up.
92 alignas(impl::block128::alignment()) UIntType swapped[16ul / sizeof(T)];
93 std::memcpy(static_cast<UIntType*>(swapped), values, 16ul);
94 bswap(static_cast<UIntType*>(swapped));
95 std::memcpy(values, static_cast<UIntType*>(swapped), 16ul);
96 #endif // TARGET_LITTLE_ENDIAN
97 }
98
99};
100
101template<>
103
104 template<typename T>
105 static void swap(T& value) {
106 #ifdef TARGET_LITTLE_ENDIAN
107 using UIntType = typename traits::uint_of_size<sizeof(T)>::type;
108 static_assert(sizeof(T) == sizeof(UIntType), "No matching unsigned integral type found for the given type.");
109 // Using memcpy is the only well-defined way of reconstructing arbitrary types from raw bytes.
110 // The seemingly unnecessary copies and memcpy calls are all optimized away,
111 // compiler knows what's up.
112 UIntType swapped;
113 std::memcpy(&swapped, &value, sizeof(T));
114 swapped = bswap(swapped);
115 std::memcpy(&value, &swapped, sizeof(T));
116 #else
117 static_cast<void>(value);
118 #endif // TARGET_LITTLE_ENDIAN
119 }
120
121 template<typename T>
122 static void swap(T* values) {
123 #ifdef TARGET_LITTLE_ENDIAN
124 using UIntType = typename traits::uint_of_size<sizeof(T)>::type;
125 static_assert(sizeof(T) == sizeof(UIntType), "No matching unsigned integral type found for the given type.");
126 // Using memcpy is the only well-defined way of reconstructing arbitrary types from raw bytes.
127 // The seemingly unnecessary copies and memcpy calls are all optimized away,
128 // compiler knows what's up.
129 alignas(impl::block128::alignment()) UIntType swapped[16ul / sizeof(T)];
130 std::memcpy(static_cast<UIntType*>(swapped), values, 16ul);
131 bswap(static_cast<UIntType*>(swapped));
132 std::memcpy(values, static_cast<UIntType*>(swapped), 16ul);
133 #else
134 static_cast<void>(values);
135 #endif // TARGET_LITTLE_ENDIAN
136 }
137
138};
139
140template<Endianness EByteOrder>
142
143template<Endianness EByteOrder>
145
146template<typename T>
147inline void networkToHost(T& value) {
149}
150
151template<typename T>
152inline void networkToHost128(T* values) {
154}
155
156template<typename T>
157inline void hostToNetwork(T& value) {
159}
160
161template<typename T>
162inline void hostToNetwork128(T* values) {
164}
165
166} // namespace terse
std::uint8_t bswap(std::uint8_t x)
Definition: Endianness.h:310
Definition: Archive.h:14
void networkToHost(T &value)
Definition: ByteSwap.h:147
void networkToHost128(T *values)
Definition: ByteSwap.h:152
void hostToNetwork128(T *values)
Definition: ByteSwap.h:162
Endianness
Definition: ByteSwap.h:53
void hostToNetwork(T &value)
Definition: ByteSwap.h:157
static void swap(T &value)
Definition: ByteSwap.h:105
static void swap(T *values)
Definition: ByteSwap.h:122
static void swap(T &value)
Definition: ByteSwap.h:66
static void swap(T *values)
Definition: ByteSwap.h:83
Definition: ByteSwap.h:60
Definition: ByteSwap.h:39
static constexpr std::size_t alignment()
Definition: ByteSwap.h:41
Definition: ByteSwap.h:28
typename std::conditional<(size==1ul), std::uint8_t, typename std::conditional<(size==2ul), std::uint16_t, typename std::conditional<(size<=4ul), std::uint32_t, std::uint64_t >::type >::type >::type type
Definition: ByteSwap.h:32