函数模板编写通用字节序转换接口
摘自轻量级开源跨平台网络库: yasio
namespace yasio
{
// clang-format off
# define YASIO__SWAP_SHORT(s) ((((s) >> 8) & 0x00ff) | (((s) << 8) & 0xff00))
/*
* Byte order conversion functions for 64-bit integers and 32 + 64 bit
* floating-point numbers. IEEE big-endian format is used for the
* network floating point format.
*/
#define YASIO__SWAP_LONG(l) \
( ( ((l) >> 24) & 0x000000FFL ) | \
( ((l) >> 8) & 0x0000FF00L ) | \
( ((l) << 8) & 0x00FF0000L ) | \
( ((l) << 24) & 0xFF000000L ) )
#define YASIO__SWAP_LONGLONG(l) \
( ( ((l) >> 56) & 0x00000000000000FFLL ) | \
( ((l) >> 40) & 0x000000000000FF00LL ) | \
( ((l) >> 24) & 0x0000000000FF0000LL ) | \
( ((l) >> 8) & 0x00000000FF000000LL ) | \
( ((l) << 8) & 0x000000FF00000000LL ) | \
( ((l) << 24) & 0x0000FF0000000000LL ) | \
( ((l) << 40) & 0x00FF000000000000LL ) | \
( ((l) << 56) & 0xFF00000000000000LL ) )
// clang-format on
inline uint64_t(htonll)(uint64_t Value)
{
const uint64_t Retval = YASIO__SWAP_LONGLONG(Value);
return Retval;
}
inline uint64_t(ntohll)(uint64_t Value)
{
const uint64_t Retval = YASIO__SWAP_LONGLONG(Value);
return Retval;
}
inline namespace endian
{
template <typename _Ty, size_t n> struct byte_order_impl {};
template <typename _Ty> struct byte_order_impl<_Ty, sizeof(int8_t)> {
static inline _Ty host_to_network(_Ty value) { return static_cast<_Ty>(value); }
static inline _Ty network_to_host(_Ty value) { return static_cast<_Ty>(value); }
};
template <typename _Ty> struct byte_order_impl<_Ty, sizeof(int16_t)> {
static inline _Ty host_to_network(_Ty value) { return static_cast<_Ty>(htons(static_cast<u_short>(value))); }
static inline _Ty network_to_host(_Ty value) { return static_cast<_Ty>(ntohs(static_cast<u_short>(value))); }
};
template <typename _Ty> struct byte_order_impl<_Ty, sizeof(int32_t)> {
static inline _Ty host_to_network(_Ty value) { return static_cast<_Ty>(htonl(static_cast<uint32_t>(value))); }
static inline _Ty network_to_host(_Ty value) { return static_cast<_Ty>(ntohl(static_cast<uint32_t>(value))); }
};
template <typename _Ty> struct byte_order_impl<_Ty, sizeof(int64_t)> {
static inline _Ty host_to_network(_Ty value) { return static_cast<_Ty>(htonll(static_cast<uint64_t>(value))); }
static inline _Ty network_to_host(_Ty value) { return static_cast<_Ty>(ntohll(static_cast<uint64_t>(value))); }
};
#if defined(YASIO_HAVE_HALF_FLOAT)
template <> struct byte_order_impl<fp16_t, sizeof(fp16_t)> {
static inline fp16_t host_to_network(fp16_t value)
{
uint16_t* p = (uint16_t*)&value;
*p = YASIO__SWAP_SHORT(*p);
return value;
}
static inline fp16_t network_to_host(fp16_t value) { return host_to_network(value); }
};
#endif
template <> struct byte_order_impl<float, sizeof(float)> {
static inline float host_to_network(float value)
{
uint32_t* p = (uint32_t*)&value;
*p = _WS2_32_WINSOCK_SWAP_LONG(*p);
return value;
}
static inline float network_to_host(float value) { return host_to_network(value); }
};
template <> struct byte_order_impl<double, sizeof(double)> {
static inline double host_to_network(double value)
{
uint64_t* p = (uint64_t*)&value;
*p = _WS2_32_WINSOCK_SWAP_LONGLONG(*p);
return value;
}
static inline double network_to_host(double value) { return host_to_network(value); }
};
template <typename _Ty> inline _Ty host_to_network(_Ty value) { return byte_order_impl<_Ty, sizeof(_Ty)>::host_to_network(value); }
template <typename _Ty> inline _Ty network_to_host(_Ty value) { return byte_order_impl<_Ty, sizeof(_Ty)>::network_to_host(value); }
}
}
使用以上模板,我们用起来就非常方便了:
using namespace yasio;
bool bval = true;
char cval = 90;
short sval = 100;
int ival = 930014;
long long i64val = 0x1122334455667788;
float fval = 100.93f;
double lfval = 193023456.233;
auto net_bval = host_to_network(bval);
auto net_cval = host_to_network(cval);
auto net_sval = host_to_network(sval);
auto net_ival = host_to_network(ival);
auto net_i64val = host_to_network(i64val);
auto net_fval = host_to_network(fval);
auto net_lfval = host_to_network(lfval);
怎么样,一个函数模板,匹配全部数值类型