从std :: vector <unsigned char =“”>切片中提取一个int?

时间:2018-10-22 05:38:54

标签: c++

我正在解析二进制标头(std::vector<unsigned char>),并且需要提取四个无符号整数。

有时(对于其他标头)我有时还需要提取unsigned short,因此最好使用通用解决方案。

如何将std :: vector的切片转换为整数?

这是我尝试过的:

class PacketHeader {
public:
    static const unsigned short LENGTH = 16;

    PacketHeader(std::vector<unsigned char> &binary_data) {
      this->timestamp_seconds = ntohs(*reinterpret_cast<const unsigned int *>(&binary_data[0]));
      this->timestamp_ms_or_ns = ntohs(*reinterpret_cast<const unsigned int *>(&binary_data[4]));
      this->packet_data_length = ntohs(*reinterpret_cast<const unsigned int *>(&binary_data[8]));
      this->untruncated_packet_data_length = ntohs(*reinterpret_cast<const unsigned int *>(&binary_data[12]));
    }

    unsigned int get_timestamp_seconds();
    unsigned int get_timestamp_ms_or_ns();
    unsigned int get_packet_data_length();
    unsigned int get_untruncated_packet_data_length();
private:
    unsigned int timestamp_seconds;
    unsigned int timestamp_ms_or_ns;
    unsigned int packet_data_length;
    unsigned int untruncated_packet_data_length;
};

2 个答案:

答案 0 :(得分:0)

当然,在发布此问题后,我找到了可行的解决方案。

这是我从here中找到的内容:

template <typename T>
T extract(const vector<unsigned char> &v, int pos)
{
  T value;
  memcpy(&value, &v[pos], sizeof(T));
  return value;
}

答案 1 :(得分:0)

创建一个Serialiser / Deserialiser以自动将数据打包到字节数组中。在下面,我迅速介绍了一个序列化器,该序列化器仅序列化整数类型。您可以将其扩展到字符串,向量,其他对象(使用递归)。

using Buffer = std::vector<int>;

/*! 
 * Serialise all primitive data types (Intergrals: 8, 16, 32, 64)
 */
template <typename T>
void serialise(Buffer& buffer, uint32_t& offset, const T& data)
{
    uint32_t size = sizeof(data);           // Get size for memcpy
    buffer.resize(buffer.size()+size);      // Ensure data will fit
    memcpy( &buffer[offset], &data, sizeof(data) ); // Copy data (use ntohs aswell)
    offset += size;                         // Increase offset for next item
}

/*!
 * Primitive Serialiser class which should be applied to elements in a visitor-
 * pattern type construct. Fills buffer with packed binary data of elements.
 */
class Serialiser
{
    public:
        Buffer& buffer;   // resulting byte buffer (just a std::vector<uint8_t>)
        uint32_t offset;  // offset use internally

    public:
        Serialiser(Buffer& _buffer) : buffer(_buffer), offset(0)
        {}

        // Serialise singular data type
        template <typename T>
        operator() (const T& data)
        {
            serialise(buffer, offset, data);
        }

};

现在可以使用它!

struct PacketHeader
{
    private:
        uint32_t timestamp_seconds;
        uint32_t timestamp_ms_or_ns;

    public:
        PacketHeader()=default;
        // .. Extra constructors if you want?

    private:
        template<typename SER>
        void serialise(SER& ser)
        {
           ser(timestamp_seconds);
           ser(timestamp_ms_or_ns);
        }
};

int main()
{
    // Create Packet Struct with data?
    PacketHeader packet(...);

    Buffer buffer;
    Serialiser serialiser(buffer);

    // Serialise the packet INTO the buffer
    packet.serialise(serialiser);

    // DONE! Read data out
    // .. print bytes of buffer

    return 0;
}

因此,Serialiser类通过PacketHeader :: serialise方法将其()运算符应用于数据包类中的每个成员变量。将运算符应用到的每种方法,都会将该变量复制到std :: vector(缓冲区)中。

要反序列化,您只需创建一个反序列化器类即可,它执行反向操作,packetHeader类不需要更改。