#pragma once
#include <cstdint>
#include <climits>
#include <type_traits> // 用于类型检查// 端序宏获取(保持原有逻辑)
#if __has_include(<endian.h>)#include <endian.h>
#elif __has_include(<bits/endian.h>)#include <bits/endian.h>
#endif// 编译期端序判断(增加 constexpr 定义)
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__)constexpr bool host_is_little_endian = (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);constexpr bool host_is_big_endian = (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__);
#elseconstexpr bool host_is_little_endian = true; // 默认小端(x86 为主)constexpr bool host_is_big_endian = false;
#endif// 字节交换:使用 constexpr + noexcept 增强
constexpr uint16_t bswap16(uint16_t x) noexcept {
#if defined(__GNUC__) || defined(__clang__)return __builtin_bswap16(x);
#elsereturn static_cast<uint16_t>((x << 8) | (x >> 8));
#endif
}constexpr uint32_t bswap32(uint32_t x) noexcept {
#if defined(__GNUC__) || defined(__clang__)return __builtin_bswap32(x);
#elsereturn (x << 24) |((x & 0x0000FF00u) << 8) |((x & 0x00FF0000u) >> 8) |(x >> 24);
#endif
}constexpr uint64_t bswap64(uint64_t x) noexcept {
#if defined(__GNUC__) || defined(__clang__)return __builtin_bswap64(x);
#elsereturn (x << 56) |((x & 0x00FF000000000000ull) >> 40) |((x & 0x0000FF0000000000ull) >> 24) |((x & 0x000000FF00000000ull) >> 8 ) |((x & 0x00000000FF000000ull) << 8 ) |((x & 0x0000000000FF0000ull) << 24) |((x & 0x000000000000FF00ull) << 40) |(x >> 56);
#endif
}// 重载函数:统一命名 + 类型约束(更符合 C++ 风格)
template <typename T>
constexpr typename std::enable_if<std::is_same<T, uint16_t>::value, T>::type
to_network(T v) noexcept {return host_is_little_endian ? bswap16(v) : v;
}template <typename T>
constexpr typename std::enable_if<std::is_same<T, uint32_t>::value, T>::type
to_network(T v) noexcept {return host_is_little_endian ? bswap32(v) : v;
}template <typename T>
constexpr typename std::enable_if<std::is_same<T, uint64_t>::value, T>::type
to_network(T v) noexcept {return host_is_little_endian ? bswap64(v) : v;
}// 网络序转主机序(与主机转网络序逻辑相同,直接复用)
template <typename T>
constexpr T to_host(T v) noexcept {return to_network(v);
}// 8 位无需转换(增加类型约束)
constexpr uint8_t to_network(uint8_t v) noexcept { return v; }
constexpr uint8_t to_host(uint8_t v) noexcept { return v; }// 有符号类型转换(封装为函数,减少手动转换错误)
template <typename T>
constexpr typename std::enable_if<std::is_signed<T>::value && (sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8), T>::type
to_network_signed(T v) noexcept {using UnsignedT = typename std::make_unsigned<T>::type;return static_cast<T>(to_network(static_cast<UnsignedT>(v)));
}template <typename T>
constexpr typename std::enable_if<std::is_signed<T>::value && (sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8), T>::type
to_host_signed(T v) noexcept {return to_network_signed(v); // 与网络转主机逻辑相同
}
编译期端序判断
通过__BYTE_ORDER__
等 GCC 宏直接在编译期确定主机端序(大端 / 小端),避免运行时开销。对于不支持这些宏的环境,默认使用小端(符合多数 Linux/x86 平台特性),兼顾兼容性。高效字节交换实现
- 优先使用 GCC/Clang 内建函数
__builtin_bswap16/32/64
,这些函数通常被编译为单条机器指令(如bswap
),性能最优。 - 对其他编译器提供手动移位实现作为降级方案,保证功能正确性。
- 优先使用 GCC/Clang 内建函数
清晰的转换逻辑
网络字节序固定为大端,因此:- 若主机是小端:转换时需要字节交换。
- 若主机是大端:无需转换(直接返回原值)。
逻辑简洁且高效,避免冗余操作。
完整的类型覆盖
支持 8/16/32/64 位无符号整数,同时提供有符号整数的转换建议(通过无符号类型中转,避免符号位问题)。