从 std::vector<无符号字符>切片中提取 int?

Extracting an int from slice of std::vector<unsigned char>?

本文关键字:切片 提取 gt int 无符号 std vector lt 字符      更新时间:2023-10-16

我正在解析一个二进制标头(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;
};

当然,在我发布这个问题之后,我找到了一个有效的解决方案。

这是我从这里找到的:

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

创建一个序列化器/反序列化器以自动将数据打包到字节数组中。下面我快速开发了一个序列化器,它只序列化整数类型。您可以将其扩展到字符串、向量和其他对象(使用递归(。

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(缓冲区(中。

要反序列化,您只需创建一个反序列化器类来执行反向 memcpy,而 packetHeader 类不需要更改。