基于C++的ButeBuf封装

1、说明

nettyByteBuf 中的 readerIndexwriterIndex 的设置十分巧妙,它内部对读取和写入位置进行控制,避免自己处理index的时候的各种麻烦,大大减少业务处理时的代码量

用 C++ 重构一下,删减了 nettyByteBuf 中的一些不常用的接口

代码中其中只用到了 STLstringunique_ptr,除此以外,再无其他依赖,轻量,易用,至少需要C++11以上的支持

直接上代码(含注释)

2、代码

ByteBuf.h

#ifndef SH_BYTE_BUF_H
#define SH_BYTE_BUF_H

#include <string>
#include <memory>

class ByteBufData;
namespace sh
{

enum Case
{
    Lower = 0,  //小写
    Upper,      //大写
};
/**
 * ByteBuf封装,内置readerIndex和writerIndex基数,用于记录当前读取和写入的位置
 *
 * +-------------------+------------------+------------------+
 * | discardable bytes |  readable bytes  |  writable bytes  |
 * |                   |     (CONTENT)    |                  |
 * +-------------------+------------------+------------------+
 * |                   |                  |                  |
 * 0      <=      readerIndex   <=   writerIndex    <=    capacity
 *
 * @author: sherlock_lht
 */
class ByteBuf
{
public:
    static char toHexLower(uint32_t value) noexcept;
    static char toHexUpper(uint32_t value) noexcept;
    static int32_t fromHex(uint32_t c) noexcept;
    static ByteBuf fromHex(const std::string &hexEncoded) noexcept;

public:
    explicit ByteBuf();
    explicit ByteBuf(const char *data, int32_t size = -1);
    explicit ByteBuf(const std::string &data);
    explicit ByteBuf(int32_t size, char ch);
    ByteBuf(const ByteBuf &other);
    virtual ~ByteBuf();

    ByteBuf &operator=(const ByteBuf &other);

    /**
     * 转换成16进制字符串
     */
    std::string toHexString(Case type = Case::Lower, const std::string &fill_str = "") const;

    /**
     * 返回现有的字节数组
     */
    const char *data() const noexcept;

    /**
     * 从readerIndex开始(包括readerIndex),到writerIndex结束(不包括writerIndex),找到buff内第一次出现的value的位置
     * 该方法不会改变readerIndex和writerIndex
     *
     * @return value出现的位置到readerIndex之间的字节数,如果没找到则返回-1
     */
    int32_t bytesBefore(char value);

    /**
     * 从readerIndex开始(包括readerIndex),到writerIndex结束(不包括writerIndex),找到buff内第一次出现连续长度为length的value的位置
     * 该方法不会改变readerIndex和writerIndex
     *
     * @return value出现的位置到readerIndex之间的字节数,如果没找到则返回-1
     */
    int32_t bytesBefore(int32_t length, char value);

    /**
     * 从index开始(包括index),到writerIndex结束(不包括writerIndex),找到buff内第一次出现连续长度为length的value的位置
     * 该方法不会改变readerIndex和writerIndex
     *
     * @return value出现的位置到readerIndex之间的字节数,如果没找到则返回-1
     */
    int32_t bytesBefore(int32_t index, int32_t length, char value);

    /**
     * 返回为对象分配的存储空间大小
     */
    int32_t capacity() const;

    /**
     * 重新分配对象的存储空间大小,如果new_capacity不够存储现有的数据,则capacity保持不变
     */
    ByteBuf &capacity(int32_t new_capacity);

    /**
     * readerIndex和writerIndex全部归零,等同于setIndex(0, 0)
     */
    ByteBuf &clear();

    /**
     * 比较缓存区的数据内容,同strcmp
     */
    int32_t compareTo(const ByteBuf &buffer) const;

    /**
     * 返回对象的可读字节数据的副本,即从readerIndex开始到writerIndex结束的数据
     * 等同于 buf.copy(buf.readerIndex(), buf.readableBytes())
     * 不影响原始对象的readerIndex和writerIndex,且两个对象互不影响
     */
    ByteBuf copy() const;

    /**
     * 返回对象数据从index开始,长度的length的数据的副本
     * 不影响原始对象的readerIndex和writerIndex,且两个对象互不影响
     */
    ByteBuf copy(int32_t index, int32_t length) const;

    /**
     * 丢弃从0th到readerIndex之间的所有数据
     * 即移动readerIndex到writerIndex之间的数据到0th,并且设置readerIndex和writerIndex为0
     */
    ByteBuf &discardReadBytes();

    /**
     * 从buffer中定位第一次出现的value字符,搜索从fromIndex(包括fromIndex)到toIndex(不包括toIndex)
     * 该方法不会改变readerIndex和writerIndex
     *
     * @return value第一次出现的下表,没找到返回-1
     */
    int32_t indexOf(int32_t fromIndex, int32_t toIndex, char value) const;

    /**
     * 设置readerIndex和writerIndex,如果buffer内无数据,则无效;
     * 如果readerIndex超出了buffer内数据的长度,则readerIndex = buffer.length() - 1;
     * 如果writerIndex超出了buffer内数据的长度,则writerIndex = buffer.length()
     */
    ByteBuf setIndex(int32_t readerIndex, int32_t writerIndex);

    /**
     * 只有当this.writerIndex - this.readerIndex大于0时,返回true
     */
    bool isReadable() const;

    /**
     * 只有当this.writerIndex - this.readerIndex大于size时,返回true
     */
    bool isReadable(int32_t size);

    /**
     * 标记当前的readerIndex,后面可以使用resetReaderIndex()撤回readerIndex到标记位置,初始标记位置为0
     */
    ByteBuf &markReaderIndex();

    /**
     * 标记当前的writerIndex,后面可以使用resetWriterIndex()撤回resetWriterIndex到标记位置,初始标记位置为0
     */
    ByteBuf &markWriterIndex();

    /**
     * 返回readerIndex
     */
    int32_t readerIndex() const;

    /**
     * 设置readerIndex
     */
    ByteBuf &readerIndex(int32_t reader_index);

    /**
     * 重新定位readerIndex到标记的readerIndex位置
     */
    ByteBuf &resetReaderIndex();

    /**
     * 返回writerIndex
     */
    int32_t writerIndex() const;

    /**
     * 设置writerIndex
     */
    ByteBuf &writerIndex(int32_t writer_index);

    /**
     * 重新定位writerIndex到标记的writerIndex位置
     */
    ByteBuf &resetWriterIndex();

    /**
     * 返回当前buffer中的可读的字节数,等同于(this.writerIndex - this.readerIndex)
     */
    int32_t readableBytes() const;

    /**
     * 获取指定下标的字符
     * 该方法不会修改readerIndex和writerIndex
     *
     * @return 如果index超出buffer数据长度,返回0
     */
    char getByte(int32_t index) const;

    /**
     * 从指定的index位置,获取符合条件的字符,该方法不会修改readerIndex和writerIndex
     *
     *  @return 返回实际获取的字符数目
     */
    int32_t getBytes(int32_t index, char *dst) const;
    int32_t getBytes(int32_t index, char *dst, int32_t length) const;

    /**
     * 从指定的index位置,获取符合条件的字符,该方法不会修改readerIndex和writerIndex
     */
    ByteBuf getBytes(int32_t index) const;
    ByteBuf getBytes(int32_t index, int32_t length) const;
    ByteBuf getBytes(int32_t index, int32_t dstIndex, int32_t length) const;

    /**
     * 以下方法分别从index位置读取8/16/32/64位的数据,不会修改readerIndex和writerIndex
     */
    int8_t getChar(int32_t index) const;
    uint8_t getUnsignedChar(int32_t index) const;

    int16_t getShort(int32_t index) const;
    int16_t getShortLE(int32_t index) const;

    uint16_t getUnsignedShort(int32_t index) const;
    uint16_t getUnsignedShortLE(int32_t index) const;

    int32_t getInt(int32_t index) const;
    int32_t getIntLE(int32_t index) const;

    uint32_t getUnsignedInt(int32_t index) const;
    uint32_t getUnsignedIntLE(int32_t index) const;

    int64_t getLong(int32_t index) const;
    int64_t getLongLE(int32_t index) const;

    uint64_t getUnsignedLong(int32_t index) const;
    uint64_t getUnsignedLongLE(int32_t index) const;

    float getFloat(int32_t index) const;
    float getFloatLE(int32_t index) const;

    double getDouble(int32_t index) const;
    double getDoubleLE(int32_t index) const;

    /**
     * 以下方法分别从readerIndex位置读取8/16/32/64位的数据,readerIndex根据实际读出的位数增加
     */
    int8_t readChar();
    uint8_t readUnsignedChar();

    int16_t readShort();
    int16_t readShortLE();

    uint16_t readUnsignedShort();
    uint16_t readUnsignedShortLE();

    int32_t readInt();
    int32_t readIntLE();

    uint32_t readUnsignedInt();
    uint32_t readUnsignedIntLE();

    int64_t readLong();
    int64_t readLongLE();

    uint64_t readUnsignedLong();
    uint64_t readUnsignedLongLE();

    ByteBuf readBytes(int32_t length);

    double readDouble();
    double readDoubleLE();

    /**
     * readerIndex增加指定长度
     */
    ByteBuf &skipBytes(int32_t length);

    /**
     * 以下方法在index位置写入8/16/32/64位的数据,如果index超出现有数据范围,则追加,否则插入,不会修改readerIndex和writerIndex
     */
    ByteBuf &setChar(int32_t index, int8_t value);
    ByteBuf &setUnsignedChar(int32_t index, uint8_t value);

    ByteBuf &setShort(int32_t index, int16_t value);
    ByteBuf &setShortLE(int32_t index, int16_t value);

    ByteBuf &setUnsignedShort(int32_t index, uint16_t value);
    ByteBuf &setUnsignedShortLE(int32_t index, uint16_t value);

    ByteBuf &setInt(int32_t index, int32_t value);
    ByteBuf &setIntLE(int32_t index, int32_t value);

    ByteBuf &setUnsignedInt(int32_t index, uint32_t value);
    ByteBuf &setUnsignedIntLE(int32_t index, uint32_t value);

    ByteBuf &setLong(int32_t index, int64_t value);
    ByteBuf &setLongLE(int32_t index, int64_t value);

    ByteBuf &setUnsignedLong(int32_t index, uint64_t value);
    ByteBuf &setUnsignedLongLE(int32_t index, uint64_t value);

    ByteBuf &setBytes(int32_t index, const ByteBuf &buf);
    ByteBuf &setBytes(int32_t index, const char *data, int32_t size);

    /**
     * 从index位置填充指定长度的0,index超出现有数据,则追加,否则,插入,readerIndex和writerIndex不会改变
     */
    ByteBuf &setZero(int32_t index, int32_t length);

    /**
     * 以下方法会在writerIndex位置写入8/16/32/64位数据,若writerIndex超出现有数据范围,则追加并调整,否则插入,writerIndex根据实际写入的情况调整位置
     */
    ByteBuf &writeChar(int8_t value);

    ByteBuf &writeUnsignedChar(uint8_t value);

    ByteBuf &writeShort(int16_t value);
    ByteBuf &writeShortLE(int16_t value);

    ByteBuf &writeUnsignedShort(uint16_t value);
    ByteBuf &writeUnsignedShortLE(uint16_t value);

    ByteBuf &writeInt(int32_t value);
    ByteBuf &writeIntLE(int32_t value);

    ByteBuf &writeUnsignedInt(uint32_t value);
    ByteBuf &writeUnsignedIntLE(uint32_t value);

    ByteBuf &writeLong(int64_t value);
    ByteBuf &writeLongLE(int64_t value);

    ByteBuf &writeUnsignedLong(uint64_t value);
    ByteBuf &writeUnsignedLongLE(uint64_t value);

    ByteBuf &writeBytes(const ByteBuf &buf);
    ByteBuf &writeBytes(const char *data, int32_t size);

    /**
     * 从writerIndex位置填充指定长度的0,writerIndex超出现有数据,则追加并调整,否则插入,writerIndex根据实际写入的情况调整位置
     */
    ByteBuf &writeZero(int32_t length);

private:
    std::unique_ptr<ByteBufData> d;
};
}

#endif//SH_BYTE_BUF_H

ByteBuf.cpp

#include "ByteBuf.h"

namespace
{
#define INT8_BIT sizeof(int8_t)
#define INT16_BIT sizeof(int16_t)
#define INT32_BIT sizeof(int32_t)
#define INT64_BIT sizeof(int64_t)
#define FLOAT_BIT sizeof(float)
#define DOUBLE_BIT sizeof(double)
}

class ByteBufData
{
public:
    ByteBufData()
        : readerIndex(0), writerIndex(0), markedReaderIndex(0), markedWriterIndex(0)
    {}

private:
    friend class sh::ByteBuf;
    std::string originData;
    int32_t readerIndex;
    int32_t writerIndex;
    int32_t markedReaderIndex;
    int32_t markedWriterIndex;

private:
    template<class T>
    T getT(int32_t index, uint8_t max_bit) const
    {
        if (originData.length() - index < max_bit)
        {
            return 0;
        }
        T value = 0;
        for (uint8_t delta = 0; delta < max_bit; delta++)
        {
            value += (originData.at(delta + index) & 0xff) << (8 * (max_bit - delta - 1));
        }
        return value;
    }

    template<class T>
    T getTLE(int32_t index, uint8_t max_bit) const
    {
        if (originData.length() - index < max_bit)
        {
            return 0;
        }
        T value = 0;
        for (uint8_t delta = 0; delta < max_bit; delta++)
        {
            value += (originData.at(delta + index) & 0xff) << (8 * delta);
        }
        return value;
    }

    template<class T>
    T readT(uint8_t max_bit)
    {
        if (originData.length() - readerIndex < max_bit)
        {
            return 0;
        }
        T value = 0;
        for (uint8_t delta = 0; delta < max_bit; delta++)
        {
            value += (originData.at(delta + readerIndex) & 0xff) << (8 * (max_bit - delta - 1));
        }
        readerIndex += max_bit;
        return value;
    }

    template<class T>
    T readTLE(uint8_t max_bit)
    {
        if (originData.length() - readerIndex < max_bit)
        {
            return 0;
        }
        T value = 0;
        for (uint8_t delta = 0; delta < max_bit; delta++)
        {
            value += (originData.at(delta + readerIndex) & 0xff) << (8 * delta);
        }
        readerIndex += max_bit;
        return value;
    }

    template<class T>
    void setT(int32_t index, T value)
    {
        setData(index, toBinary(value));
    }

    template<class T>
    void setTLE(int32_t index, T value)
    {
        setData(index, toBinaryLE(value));
    }

    void setData(int32_t index, const std::string &data)
    {
        if (index > originData.length())
        {
            originData.append(data);
        }
        else
        {
            originData.insert(index, data);
        }
    }

    template<class T>
    void writeT(T value)
    {
        writeData(toBinary(value));
    }

    template<class T>
    void writeTLE(T value)
    {
        writeData(toBinaryLE(value));
    }

    void writeData(const std::string &data)
    {
        if (writerIndex > originData.length())
        {
            originData.append(data);
            writerIndex = (int32_t) originData.length();
        }
        else
        {
            originData.insert(writerIndex, data);
            writerIndex += (int32_t) data.length();
        }
    }

    template<class T>
    std::string toBinary(T value)
    {
        std::string result;
        int8_t max_bit = sizeof(T);
        for (uint8_t index = 0; index < max_bit; index++)
        {
            result.push_back(value >> (8 * (max_bit - index - 1)) & 0xff);
        }
        return result;
    }

    template<class T>
    std::string toBinaryLE(T value)
    {
        std::string result;
        int8_t max_bit = sizeof(T);
        for (uint8_t index = 0; index < max_bit; index++)
        {
            result.push_back(value >> (8 * index) & 0xff);
        }
        return result;
    }
};

sh::ByteBuf::ByteBuf()
{
    d = std::unique_ptr<::ByteBufData>(new ByteBufData());
}
sh::ByteBuf::ByteBuf(const char *data, int32_t size)
{
    d = std::unique_ptr<::ByteBufData>(new ByteBufData());
    d->originData.append(data, size);
    d->writerIndex += size;
}
sh::ByteBuf::ByteBuf(const std::string &data)
{
    d = std::unique_ptr<::ByteBufData>(new ByteBufData());
    d->originData.append(data);
    d->writerIndex += data.length();
}
sh::ByteBuf::ByteBuf(int32_t size, char ch)
{
    d = std::unique_ptr<::ByteBufData>(new ByteBufData());
    d->originData.append(size, ch);
    d->writerIndex += size;
}
sh::ByteBuf::ByteBuf(const sh::ByteBuf &other)
{
    d = std::unique_ptr<::ByteBufData>(new ByteBufData());
    d->originData.append(other.d->originData);
    d->readerIndex = other.d->readerIndex;
    d->writerIndex = other.d->writerIndex;
    d->markedReaderIndex = other.d->markedReaderIndex;
    d->markedWriterIndex = other.d->markedWriterIndex;
}
sh::ByteBuf::~ByteBuf() = default;

sh::ByteBuf &sh::ByteBuf::operator=(const sh::ByteBuf &other)
{
    if (&other != this)
    {
        d->originData.append(other.d->originData);
        d->readerIndex = other.d->readerIndex;
        d->writerIndex = other.d->writerIndex;
        d->markedReaderIndex = other.d->markedReaderIndex;
        d->markedWriterIndex = other.d->markedWriterIndex;
    }
    return *this;
}

std::string sh::ByteBuf::toHexString(Case type, const std::string &fill_str) const
{
    std::string result;
    for (char ch: d->originData)
    {
        if (Case::Lower == type)
        {
            result.push_back(toHexLower(ch >> 4));
            result.push_back(toHexLower(ch & 0xF));
        }
        else
        {
            result.push_back(toHexUpper(ch >> 4));
            result.push_back(toHexUpper(ch & 0xF));
        }
        result.append(fill_str);
    }
    return result;
}

const char *sh::ByteBuf::data() const noexcept
{
    return d->originData.data();
}
int32_t sh::ByteBuf::bytesBefore(char value)
{
    for (int32_t index = d->readerIndex; index < d->writerIndex; index++)
    {
        if (d->originData.at(index) == value)
        {
            return index - d->readerIndex;
        }
    }
    return -1;
}
int32_t sh::ByteBuf::bytesBefore(int32_t length, char value)
{
    return bytesBefore(d->readerIndex, length, value);
}
int32_t sh::ByteBuf::bytesBefore(int32_t index, int32_t length, char value)
{
    bool last_ok;
    int32_t second_index;
    for (; index < d->writerIndex - length; index++)
    {
        //找到第一个符合 && 剩余的长度足够
        if (d->originData.at(index) == value && (index + length) < d->writerIndex)
        {
            last_ok = true;
            //从后一个开始检查length-1个字符
            for (second_index = index + 1; second_index < (index + length); second_index++)
            {
                if (d->originData.at(second_index) != value)
                {
                    last_ok = false;
                    break;
                }
            }
            if (last_ok)
            {
                return index - d->readerIndex;
            }
        }
    }
    return -1;
}
int32_t sh::ByteBuf::capacity() const
{
    return (int32_t) d->originData.capacity();
}
sh::ByteBuf &sh::ByteBuf::capacity(int32_t new_capacity)
{
    d->originData.reserve(new_capacity);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::clear()
{
    d->readerIndex = 0;
    d->writerIndex = 0;
    return *this;
}
int32_t sh::ByteBuf::compareTo(const sh::ByteBuf &buffer) const
{
    return d->originData.compare(buffer.d->originData);
}
sh::ByteBuf sh::ByteBuf::copy() const
{
    return sh::ByteBuf(d->originData);
}
sh::ByteBuf sh::ByteBuf::copy(int32_t index, int32_t length) const
{
    return sh::ByteBuf(d->originData.substr(index, length));
}
sh::ByteBuf &sh::ByteBuf::discardReadBytes()
{
    d->originData = d->originData.substr(d->readerIndex + 1);
    d->readerIndex = 0;
    d->writerIndex = 0;
    return *this;
}

int32_t sh::ByteBuf::indexOf(int32_t fromIndex, int32_t toIndex, char value) const
{
    for (int32_t index = fromIndex; index < d->originData.length() && index < toIndex; index++)
    {
        if (d->originData.at(index) == value)
        {
            return index;
        }
    }
    return -1;
}
sh::ByteBuf sh::ByteBuf::setIndex(int32_t readerIndex, int32_t writerIndex)
{
    if (d->originData.empty())
    {
        return *this;
    }
    d->readerIndex = readerIndex;
    d->writerIndex = writerIndex;
    if (d->readerIndex >= d->originData.length())
    {
        d->readerIndex = (int32_t) d->originData.length() - 1;
    }
    if (d->writerIndex > d->originData.length())
    {
        d->writerIndex = (int32_t) d->originData.length();
    }
    return *this;
}
bool sh::ByteBuf::isReadable() const
{
    return (d->writerIndex - d->readerIndex) > 0;
}
bool sh::ByteBuf::isReadable(int32_t size)
{
    return (d->writerIndex - d->readerIndex) >= size;
}
sh::ByteBuf &sh::ByteBuf::markReaderIndex()
{
    d->markedReaderIndex = d->readerIndex;
    return *this;
}
sh::ByteBuf &sh::ByteBuf::markWriterIndex()
{
    d->markedWriterIndex = d->writerIndex;
    return *this;
}
int32_t sh::ByteBuf::readerIndex() const
{
    return d->readerIndex;
}

sh::ByteBuf &sh::ByteBuf::readerIndex(int32_t reader_index)
{
    if (reader_index <= d->writerIndex)
    {
        d->readerIndex = reader_index;
    }
    return *this;
}
sh::ByteBuf &sh::ByteBuf::resetReaderIndex()
{
    d->readerIndex = d->markedReaderIndex;
    return *this;
}
int32_t sh::ByteBuf::writerIndex() const
{
    return d->writerIndex;
}
sh::ByteBuf &sh::ByteBuf::writerIndex(int32_t writer_index)
{
    if (writer_index < d->originData.length())
    {
        d->writerIndex = writer_index;
    }
    return *this;
}
sh::ByteBuf &sh::ByteBuf::resetWriterIndex()
{
    d->writerIndex = d->markedWriterIndex;
    return *this;
}
int32_t sh::ByteBuf::readableBytes() const
{
    return d->writerIndex - d->readerIndex;
}
char sh::ByteBuf::getByte(int32_t index) const
{
    if (index >= d->originData.length())
    {
        return 0;
    }
    return d->originData.at(index);
}
int32_t sh::ByteBuf::getBytes(int32_t index, char *dst) const
{
    if (index >= d->originData.length())
    {
        return 0;
    }
    std::string res = d->originData.substr(index);
    *dst = *res.data();
    return (int32_t) res.length();
}
int32_t sh::ByteBuf::getBytes(int32_t index, char *dst, int32_t length) const
{
    if (index >= d->originData.length())
    {
        return 0;
    }
    std::string res = d->originData.substr(index, length);
    *dst = *res.data();
    return (int32_t) res.length();
}
sh::ByteBuf sh::ByteBuf::getBytes(int32_t index) const
{
    if (index >= d->originData.length())
    {
        return sh::ByteBuf();
    }
    std::string res = d->originData.substr(index);
    return sh::ByteBuf(res);
}
sh::ByteBuf sh::ByteBuf::getBytes(int32_t index, int32_t length) const
{
    if (index >= d->originData.length())
    {
        return sh::ByteBuf();
    }
    std::string res = d->originData.substr(index, length);
    return sh::ByteBuf(res);
}
sh::ByteBuf sh::ByteBuf::getBytes(int32_t index, int32_t dstIndex, int32_t length) const
{
    if (index >= d->originData.length())
    {
        return sh::ByteBuf();
    }
    sh::ByteBuf data(dstIndex, 0);
    std::string res = d->originData.substr(index, length);
    data.writeBytes(res.data(), (int32_t) res.length());
    return data;
}
int8_t sh::ByteBuf::getChar(int32_t index) const
{
    if (index >= d->originData.length())
    {
        return 0;
    }
    return d->originData.at(index);
}
uint8_t sh::ByteBuf::getUnsignedChar(int32_t index) const
{
    return getChar(index);
}
int16_t sh::ByteBuf::getShort(int32_t index) const
{
    return d->getT<int16_t>(index, INT16_BIT);
}
int16_t sh::ByteBuf::getShortLE(int32_t index) const
{
    return d->getTLE<int16_t>(index, INT16_BIT);
}
uint16_t sh::ByteBuf::getUnsignedShort(int32_t index) const
{
    return d->getT<int16_t>(index, INT16_BIT);
}
uint16_t sh::ByteBuf::getUnsignedShortLE(int32_t index) const
{
    return d->getTLE<int16_t>(index, INT16_BIT);
}
int32_t sh::ByteBuf::getInt(int32_t index) const
{
    return d->getT<int32_t>(index, INT32_BIT);
}
int32_t sh::ByteBuf::getIntLE(int32_t index) const
{
    return d->getTLE<int32_t>(index, INT32_BIT);
}
uint32_t sh::ByteBuf::getUnsignedInt(int32_t index) const
{
    return d->getT<int32_t>(index, INT32_BIT);
}
uint32_t sh::ByteBuf::getUnsignedIntLE(int32_t index) const
{
    return d->getTLE<int32_t>(index, INT32_BIT);
}
int64_t sh::ByteBuf::getLong(int32_t index) const
{
    return d->getT<int64_t>(index, INT64_BIT);
}
int64_t sh::ByteBuf::getLongLE(int32_t index) const
{
    return d->getTLE<int64_t>(index, INT64_BIT);
}
uint64_t sh::ByteBuf::getUnsignedLong(int32_t index) const
{
    return d->getT<int64_t>(index, INT64_BIT);
}
uint64_t sh::ByteBuf::getUnsignedLongLE(int32_t index) const
{
    return d->getTLE<int64_t>(index, INT64_BIT);
}
float sh::ByteBuf::getFloat(int32_t index) const
{
    float result = 0.00;
    if (d->originData.length() - index < FLOAT_BIT)
    {
        return 0.00;
    }
    char *p = (char *) &result;
    for (; index < index + FLOAT_BIT; index++)
    {
        *(p + index) = d->originData.at(index);
    }
    return result;
}
float sh::ByteBuf::getFloatLE(int32_t index) const
{
    float result = 0.00;
    if (d->originData.length() - index < FLOAT_BIT)
    {
        return 0.00;
    }
    char *p = (char *) &result;
    for (; index < index + FLOAT_BIT; index++)
    {
        *(p + index) = d->originData.at(FLOAT_BIT - index - 1);
    }
    return result;
}

double sh::ByteBuf::getDouble(int32_t index) const
{
    double result = 0.00;
    if (d->originData.length() - index < DOUBLE_BIT)
    {
        return 0.00;
    }
    char *p = (char *) &result;
    for (; index < index + DOUBLE_BIT; index++)
    {
        *(p + index) = d->originData.at(index);
    }
    return result;
}
double sh::ByteBuf::getDoubleLE(int32_t index) const
{
    double result = 0.00;
    if (d->originData.length() - index < DOUBLE_BIT)
    {
        return 0.00;
    }
    char *p = (char *) &result;
    for (; index < index + DOUBLE_BIT; index++)
    {
        *(p + index) = d->originData.at(DOUBLE_BIT - index - 1);
    }
    return result;
}
int8_t sh::ByteBuf::readChar()
{
    if (d->originData.length() - d->readerIndex < INT8_BIT)
    {
        return 0;
    }
    return d->originData.at(d->readerIndex++);
}
uint8_t sh::ByteBuf::readUnsignedChar()
{
    return readChar();
}
int16_t sh::ByteBuf::readShort()
{
    return d->readT<int16_t>(INT16_BIT);
}
int16_t sh::ByteBuf::readShortLE()
{
    return d->readTLE<int16_t>(INT16_BIT);
}
uint16_t sh::ByteBuf::readUnsignedShort()
{
    return d->readT<int16_t>(INT16_BIT);
}
uint16_t sh::ByteBuf::readUnsignedShortLE()
{
    return d->readTLE<int16_t>(INT16_BIT);
}
int32_t sh::ByteBuf::readInt()
{
    return d->readT<int32_t>(INT32_BIT);
}
int32_t sh::ByteBuf::readIntLE()
{
    return d->readTLE<int32_t>(INT32_BIT);
}
uint32_t sh::ByteBuf::readUnsignedInt()
{
    return d->readT<int32_t>(INT32_BIT);
}
uint32_t sh::ByteBuf::readUnsignedIntLE()
{
    return d->readTLE<int32_t>(INT32_BIT);
}
int64_t sh::ByteBuf::readLong()
{
    return d->readT<int64_t>(INT64_BIT);
}
int64_t sh::ByteBuf::readLongLE()
{
    return d->readTLE<int64_t>(INT64_BIT);
}
uint64_t sh::ByteBuf::readUnsignedLong()
{
    return d->readT<int64_t>(INT64_BIT);
}
uint64_t sh::ByteBuf::readUnsignedLongLE()
{
    return d->readTLE<int64_t>(INT64_BIT);
}
sh::ByteBuf sh::ByteBuf::readBytes(int32_t length)
{
    std::string data = d->originData.substr(d->readerIndex, length);
    d->readerIndex += (int32_t) data.length();
    return sh::ByteBuf(data);
}
double sh::ByteBuf::readDouble()
{
    double result = 0.00;
    if (d->originData.length() - d->readerIndex < DOUBLE_BIT)
    {
        return 0.00;
    }
    char *p = (char *) &result;
    for (; d->readerIndex < d->readerIndex + DOUBLE_BIT; d->readerIndex++)
    {
        *(p + d->readerIndex) = d->originData.at(d->readerIndex);
    }
    return result;
}
double sh::ByteBuf::readDoubleLE()
{
    double result = 0.00;
    if (d->originData.length() - d->readerIndex < DOUBLE_BIT)
    {
        return 0.00;
    }
    char *p = (char *) &result;
    for (; d->readerIndex < d->readerIndex + DOUBLE_BIT; d->readerIndex++)
    {
        *(p + d->readerIndex) = d->originData.at(DOUBLE_BIT - d->readerIndex - 1);
    }
    return result;
}
sh::ByteBuf &sh::ByteBuf::skipBytes(int32_t length)
{
    d->readerIndex += length;
    if (d->readerIndex > d->originData.length())
    {
        d->readerIndex = (int32_t) d->originData.length();
    }
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setChar(int32_t index, int8_t value)
{
    d->setT(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setUnsignedChar(int32_t index, uint8_t value)
{
    d->setT(index, value);
    return *this;
}

sh::ByteBuf &sh::ByteBuf::setShort(int32_t index, int16_t value)
{
    d->setT(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setShortLE(int32_t index, int16_t value)
{
    d->setTLE(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setUnsignedShort(int32_t index, uint16_t value)
{
    d->setT(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setUnsignedShortLE(int32_t index, uint16_t value)
{
    d->setTLE(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setInt(int32_t index, int32_t value)
{
    d->setT(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setIntLE(int32_t index, int32_t value)
{
    d->setTLE(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setUnsignedInt(int32_t index, uint32_t value)
{
    d->setT(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setUnsignedIntLE(int32_t index, uint32_t value)
{
    d->setTLE(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setLong(int32_t index, int64_t value)
{
    d->setT(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setLongLE(int32_t index, int64_t value)
{
    d->setTLE(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setUnsignedLong(int32_t index, uint64_t value)
{
    d->setT(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setUnsignedLongLE(int32_t index, uint64_t value)
{
    d->setTLE(index, value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setBytes(int32_t index, const ByteBuf &buf)
{
    d->setData(index, buf.data());
    return *this;
}
sh::ByteBuf &sh::ByteBuf::setBytes(int32_t index, const char *data, int32_t size)
{
    d->setData(index, std::string(data, size));
    return *this;
}

sh::ByteBuf &sh::ByteBuf::setZero(int32_t index, int32_t length)
{
    d->setData(index, std::string(length, 0));
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeChar(int8_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeUnsignedChar(uint8_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeShort(int16_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeShortLE(int16_t value)
{
    d->writeTLE(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeUnsignedShort(uint16_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeUnsignedShortLE(uint16_t value)
{
    d->writeTLE(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeInt(int32_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeIntLE(int32_t value)
{
    d->writeTLE(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeUnsignedInt(uint32_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeUnsignedIntLE(uint32_t value)
{
    d->writeTLE(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeLong(int64_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeLongLE(int64_t value)
{
    d->writeTLE(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeUnsignedLong(uint64_t value)
{
    d->writeT(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeUnsignedLongLE(uint64_t value)
{
    d->writeTLE(value);
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeBytes(const ByteBuf &buf)
{
    d->writeData(buf.data());
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeBytes(const char *data, int32_t size)
{
    d->writeData(std::string(data, size));
    return *this;
}
sh::ByteBuf &sh::ByteBuf::writeZero(int32_t length)
{
    d->writeData(std::string(length, 0));
    return *this;
}
char sh::ByteBuf::toHexLower(uint32_t value) noexcept
{
    return "0123456789abcdef"[value & 0xF];
}
char sh::ByteBuf::toHexUpper(uint32_t value) noexcept
{
    return "0123456789ABCDEF"[value & 0xF];
}
int32_t sh::ByteBuf::fromHex(uint32_t c) noexcept
{
    return ((c >= '0') && (c <= '9')) ? int32_t(c - '0') :
           ((c >= 'A') && (c <= 'F')) ? int32_t(c - 'A' + 10) :
           ((c >= 'a') && (c <= 'f')) ? int32_t(c - 'a' + 10) :
           /* otherwise */              -1;
}
sh::ByteBuf sh::ByteBuf::fromHex(const std::string &hexEncoded) noexcept
{
    sh::ByteBuf data;
    char ch = 0x00;
    for (int32_t index = 0; index < hexEncoded.length() - 1; index++)
    {
        ch |= (char) fromHex(hexEncoded.at(index++)) << 4;
        ch |= (char) fromHex(hexEncoded.at(index));
        data.writeChar(ch);
        ch = 0x00;
    }
    return data;
}
Tags: