chenjunfu2-nbt-cpp v2.1.0
一个基于CPP20的NBT(Named Binary Tag)库
载入中...
搜索中...
未找到
NBT_Endian.hpp
浏览该文件的文档.
1#pragma once
2
3#include <bit>//字节序
4#include <stdint.h>//定义
5#include <stddef.h>//size_t
6#include <utility>//std::index_sequence
7#include <type_traits>//std::make_unsigned_t
8
9#include "Compiler_Define.h"//编译器类型判断
10
13
15class NBT_Endian
16{
18 NBT_Endian(void) = delete;
20 ~NBT_Endian(void) = delete;
21
22public:
25 constexpr static bool IsLittleEndian(void) noexcept
26 {
27 return std::endian::native == std::endian::little;
28 }
29
32 constexpr static bool IsBigEndian(void) noexcept
33 {
34 return std::endian::native == std::endian::big;
35 }
36
37public:
43 template<typename T>
44 requires std::integral<T>
45 constexpr static T ByteSwapAny(T data) noexcept
46 {
47 //必须是2的倍数才能正确执行byteswap
48 static_assert(sizeof(T) % 2 == 0 || sizeof(T) == 1, "The size of T is not a multiple of 2 or equal to 1");
49
50 //如果大小是1直接返回
51 if constexpr (sizeof(T) == 1)
52 {
53 return data;
54 }
55
56 //统一到无符号类型
57 using UT = std::make_unsigned_t<T>;
58 static_assert(sizeof(UT) == sizeof(T), "Unsigned type size mismatch");
59
60 //获取静态大小
61 constexpr size_t szSize = sizeof(T);
62 constexpr size_t szHalf = sizeof(T) / 2;
63
64 //临时交换量
65 UT tmp = 0;
66
67 //(i < sizeof(T) / 2)前半,左移
68 [&] <size_t... i>(std::index_sequence<i...>) -> void
69 {
70 ((tmp |= ((UT)data & ((UT)0xFF << (8 * i))) << 8 * (szSize - (i * 2) - 1)), ...);
71 }(std::make_index_sequence<szHalf>{});
72
73 //(i + szHalf >= sizeof(T) / 2)后半,右移
74 [&] <size_t... i>(std::index_sequence<i...>) -> void
75 {
76 ((tmp |= ((UT)data & ((UT)0xFF << (8 * (i + szHalf)))) >> 8 * (i * 2 + 1)), ...);
77 }(std::make_index_sequence<szHalf>{});
78
79 //转换回原先的类型并返回
80 return (T)tmp;
81 }
82
87 static uint16_t ByteSwap16(uint16_t data) noexcept
88 {
89 //根据编译器切换内建指令或使用默认位移实现
90#if CJF2_NBT_CPP_COMPILER_MSVC
91 return _byteswap_ushort(data);
92#elif CJF2_NBT_CPP_COMPILER_GCC || CJF2_NBT_CPP_COMPILER_CLANG
93 return __builtin_bswap16(data);
94#else
95 return ByteSwapAny(data);
96#endif
97 }
98
103 static uint32_t ByteSwap32(uint32_t data) noexcept
104 {
105 //根据编译器切换内建指令或使用默认位移实现
106#if CJF2_NBT_CPP_COMPILER_MSVC
107 return _byteswap_ulong(data);
108#elif CJF2_NBT_CPP_COMPILER_GCC || CJF2_NBT_CPP_COMPILER_CLANG
109 return __builtin_bswap32(data);
110#else
111 return ByteSwapAny(data);
112#endif
113 }
114
119 static uint64_t ByteSwap64(uint64_t data) noexcept
120 {
121 //根据编译器切换内建指令或使用默认位移实现
122#if CJF2_NBT_CPP_COMPILER_MSVC
123 return _byteswap_uint64(data);
124#elif CJF2_NBT_CPP_COMPILER_GCC || CJF2_NBT_CPP_COMPILER_CLANG
125 return __builtin_bswap64(data);
126#else
127 return ByteSwapAny(data);
128#endif
129 }
130
136 template<typename T>
137 requires std::integral<T>
138 constexpr static T AutoByteSwap(T data) noexcept
139 {
140 //如果是已知大小,优先走重载,因为重载更有可能是指令集支持的高效实现
141 //否则走位操作实现,效率更低但是兼容性更好
142 if constexpr (sizeof(T) == sizeof(uint8_t))
143 {
144 return data;
145 }
146 else if constexpr (sizeof(T) == sizeof(uint16_t))
147 {
148 return (T)ByteSwap16((uint16_t)data);
149 }
150 else if constexpr (sizeof(T) == sizeof(uint32_t))
151 {
152 return (T)ByteSwap32((uint32_t)data);
153 }
154 else if constexpr (sizeof(T) == sizeof(uint64_t))
155 {
156 return (T)ByteSwap64((uint64_t)data);
157 }
158 else
159 {
160 return ByteSwapAny(data);
161 }
162 }
163
164 //------------------------------------------------------//
165
171 template<typename T>
172 requires std::integral<T>
173 static T NativeToBigAny(T data) noexcept
174 {
175 if constexpr (IsBigEndian())//当前也是big
176 {
177 return data;
178 }
179
180 //当前是little,little转换到big
181 return AutoByteSwap(data);
182 }
183
189 template<typename T>
190 requires std::integral<T>
191 static T NativeToLittleAny(T data) noexcept
192 {
193 if constexpr (IsLittleEndian())//当前也是little
194 {
195 return data;
196 }
197
198 //当前是big,big转换到little
199 return AutoByteSwap(data);
200 }
201
207 template<typename T>
208 requires std::integral<T>
209 static T BigToNativeAny(T data) noexcept
210 {
211 if constexpr (IsBigEndian())//当前也是big
212 {
213 return data;
214 }
215
216 //当前是little,big转换到little
217 return AutoByteSwap(data);
218 }
219
225 template<typename T>
226 requires std::integral<T>
227 static T LittleToNativeAny(T data) noexcept
228 {
229 if constexpr (IsLittleEndian())//当前也是little
230 {
231 return data;
232 }
233
234 //当前是big,little转换到big
235 return AutoByteSwap(data);
236 }
237};
编译器检测支持宏
static T LittleToNativeAny(T data) noexcept
从小端字节序转换到当前平台字节序,自动匹配位数
定义 NBT_Endian.hpp:227
static uint32_t ByteSwap32(uint32_t data) noexcept
颠倒字节序32位特化版
定义 NBT_Endian.hpp:103
static T NativeToBigAny(T data) noexcept
从当前平台字节序转换到大端字节序,自动匹配位数
定义 NBT_Endian.hpp:173
static constexpr T ByteSwapAny(T data) noexcept
颠倒字节序,需要整数字节数为2的倍数或字节数为1
定义 NBT_Endian.hpp:45
static constexpr T AutoByteSwap(T data) noexcept
颠倒字节序,自动匹配位数
定义 NBT_Endian.hpp:138
static uint16_t ByteSwap16(uint16_t data) noexcept
颠倒字节序16位特化版
定义 NBT_Endian.hpp:87
static uint64_t ByteSwap64(uint64_t data) noexcept
颠倒字节序32位特化版
定义 NBT_Endian.hpp:119
static constexpr bool IsBigEndian(void) noexcept
判断当前平台字节序是否是大端字节序
定义 NBT_Endian.hpp:32
static T BigToNativeAny(T data) noexcept
从大端字节序转换到当前平台字节序,自动匹配位数
定义 NBT_Endian.hpp:209
static constexpr bool IsLittleEndian(void) noexcept
判断当前平台字节序是否是小端字节序
定义 NBT_Endian.hpp:25
static T NativeToLittleAny(T data) noexcept
从当前平台字节序转换到小端字节序,自动匹配位数
定义 NBT_Endian.hpp:191