c++ 巧妙的字节编码转换设计

业余时间写一些程序,想用c++ 设计一些字节转换功能函数,比如说主机字节序和网络字节序的转换,参考了envoy 中的设计

发现envoy的设计真的很巧妙,在这里记录一下

envoy中的字节转换主要是依赖linux 的头文件

#include <endian.h>

这个头文件在mac上不存在,envoy巧妙的做了兼容

#ifdef __APPLE__

#include <libkern/OSByteOrder.h>

#define htole16(x) OSSwapHostToLittleInt16((x))
#define htole32(x) OSSwapHostToLittleInt32((x))
#define htole64(x) OSSwapHostToLittleInt64((x))
#define le16toh(x) OSSwapLittleToHostInt16((x))
#define le32toh(x) OSSwapLittleToHostInt32((x))
#define le64toh(x) OSSwapLittleToHostInt64((x))

#define htobe16(x) OSSwapHostToBigInt16((x))
#define htobe32(x) OSSwapHostToBigInt32((x))
#define htobe64(x) OSSwapHostToBigInt64((x))
#define be16toh(x) OSSwapBigToHostInt16((x))
#define be32toh(x) OSSwapBigToHostInt32((x))
#define be64toh(x) OSSwapBigToHostInt64((x))

#else

#include <endian.h>

#endif

定义编码类型:

大端、小端、主机字节序

enum class ByteOrder { Host, LittleEndian, BigEndian };

定义转换函数

// convenience function that converts an integer from host byte-order to a specified endianness
template <ByteOrder Endianness, typename T> inline T toEndianness(T value) {
return EndiannessConverter<Endianness, T>::to(value);
}


// convenience function that converts an integer from a specified endianness to host byte-order
template <ByteOrder Endianness, typename T> inline T fromEndianness(T value) {
return EndiannessConverter<Endianness, T>::from(value);
}
toEndianness 是把主机字节序转换为对应的编码
fromEndianness 是把不同的编码转换为主机字节序

::from ::to会传入不同类型的变量,从而触发下面的模板


// Implementation details below

// implementation details of EndiannessConverter for 8-bit host endianness integers
template <typename T> struct EndiannessConverter<ByteOrder::Host, T, sizeof(uint8_t)> {
    static_assert(sizeof(T) == sizeof(uint8_t), "incorrect type width");

    static T to(T value) { return value; }

    static T from(T value) { return value; }
};

// implementation details of EndiannessConverter for 16-bit host endianness integers
template <typename T> struct EndiannessConverter<ByteOrder::Host, T, sizeof(uint16_t)> {
    static_assert(sizeof(T) == sizeof(uint16_t), "incorrect type width");

    static T to(T value) { return value; }

    static T from(T value) { return value; }
};

// implementation details of EndiannessConverter for 32-bit host endianness integers
template <typename T> struct EndiannessConverter<ByteOrder::Host, T, sizeof(uint32_t)> {
    static_assert(sizeof(T) == sizeof(uint32_t), "incorrect type width");

    static T to(T value) { return value; }

    static T from(T value) { return value; }
};

// implementation details of EndiannessConverter for 64-bit host endianness integers
template <typename T> struct EndiannessConverter<ByteOrder::Host, T, sizeof(uint64_t)> {
    static_assert(sizeof(T) == sizeof(uint64_t), "incorrect type width");

    static T to(T value) { return value; }

    static T from(T value) { return value; }
};

// implementation details of EndiannessConverter for 8-bit little endian integers
template <typename T> struct EndiannessConverter<ByteOrder::LittleEndian, T, sizeof(uint8_t)> {
    static_assert(sizeof(T) == sizeof(uint8_t), "incorrect type width");

    static T to(T value) { return value; }

    static T from(T value) { return value; }
};

// implementation details of EndiannessConverter for 16-bit little endian integers
template <typename T> struct EndiannessConverter<ByteOrder::LittleEndian, T, sizeof(uint16_t)> {
    static_assert(sizeof(T) == sizeof(uint16_t), "incorrect type width");

    static T to(T value) { return static_cast<T>(htole16(static_cast<uint16_t>(value))); }

    static T from(T value) { return static_cast<T>(le16toh(static_cast<uint16_t>(value))); }
};

// implementation details of EndiannessConverter for 32-bit little endian integers
template <typename T> struct EndiannessConverter<ByteOrder::LittleEndian, T, sizeof(uint32_t)> {
    static_assert(sizeof(T) == sizeof(uint32_t), "incorrect type width");

    static T to(T value) { return static_cast<T>(htole32(static_cast<uint32_t>(value))); }

    static T from(T value) { return static_cast<T>(le32toh(static_cast<uint32_t>(value))); }
};

// implementation details of EndiannessConverter for 64-bit little endian integers
template <typename T> struct EndiannessConverter<ByteOrder::LittleEndian, T, sizeof(uint64_t)> {
    static_assert(sizeof(T) == sizeof(uint64_t), "incorrect type width");

    static T to(T value) { return static_cast<T>(htole64(static_cast<uint64_t>(value))); }

    static T from(T value) { return static_cast<T>(le64toh(static_cast<uint64_t>(value))); }
};

// implementation details of EndiannessConverter for 8-bit big endian integers
template <typename T> struct EndiannessConverter<ByteOrder::BigEndian, T, sizeof(uint8_t)> {
    static_assert(sizeof(T) == sizeof(uint8_t), "incorrect type width");

    static T to(T value) { return value; }

    static T from(T value) { return value; }
};

// implementation details of EndiannessConverter for 16-bit big endian integers
template <typename T> struct EndiannessConverter<ByteOrder::BigEndian, T, sizeof(uint16_t)> {
    static_assert(sizeof(T) == sizeof(uint16_t), "incorrect type width");

    static T to(T value) { return static_cast<T>(htobe16(static_cast<uint16_t>(value))); }

    static T from(T value) { return static_cast<T>(be16toh(static_cast<uint16_t>(value))); }
};

// implementation details of EndiannessConverter for 32-bit big endian integers
template <typename T> struct EndiannessConverter<ByteOrder::BigEndian, T, sizeof(uint32_t)> {
    static_assert(sizeof(T) == sizeof(uint32_t), "incorrect type width");

    static T to(T value) { return static_cast<T>(htobe32(static_cast<uint32_t>(value))); }

    static T from(T value) { return static_cast<T>(be32toh(static_cast<uint32_t>(value))); }
};

// implementation details of EndiannessConverter for 64-bit big endian integers
template <typename T> struct EndiannessConverter<ByteOrder::BigEndian, T, sizeof(uint64_t)> {
    static_assert(sizeof(T) == sizeof(uint64_t), "incorrect type width");

    static T to(T value) { return static_cast<T>(htobe64(static_cast<uint64_t>(value))); }

    static T from(T value) { return static_cast<T>(be64toh(static_cast<uint64_t>(value))); }
};

设计的非常巧妙,这样就可以很潇洒的做到大小端转化了,比自己用c去写宏定义简洁了很多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值