C++函数模板编写通用字节序转接口

函数模板编写通用字节序转换接口

摘自轻量级开源跨平台网络库: 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);

怎么样,一个函数模板,匹配全部数值类型

其他参考链接:

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值