将数据流式传输到字节数组中
stream data into a byte array
我不得不承认我现在有点困惑,如果问题不是很清楚或不琐碎(实际上我希望是后者),我很抱歉......
我正在通过网络发送一个字节数组,并想在发送端做这样的事情:
size_t max_size = 100;
uint8_t buffer[size];
idontknowwhat_t x{buffer};
uint16_t size = 11; // total number of bytes in the buffer
uint16_t id_a,id_b,id_c; // some ids
uint8_t a,b,c; // some data
x << size << id_a << a << id_b << b << id_c << c;
someMethodToSend(buffer,size);
在接收端是这样的:
size_t max_size = 100;
uint8_t buffer[size];
someMethodToReceive(buffer);
idontknowwhat_t x{buffer};
uint16_t size;
x >> size;
for (uint16_t i=0; i<size-2; i++) {
uint16_t id;
uint8_t data;
x >> id >> data;
std::cout << id << " " << data;
}
所以我的目标基本上是避免丑陋的转换和手动递增指针,同时能够在缓冲区中包含 uint8_t
和 uint16_t
(可能还有 uint32_t
)。我在此处放入缓冲区的数据只是一个示例,我知道在通过网络发送时我需要注意字节顺序(如果我必须这样做就好了 "manually") .
有什么东西可以代替我假设的 idontknowwhat_t
吗?
你试过std::list了吗?您可以将元素分组到类型中,然后将它们放入具有适当类型的列表中。然后你可以创建一个 std::list of std::lists.
你无法真正避免进行丑陋的转换,但至少你可以将它们隐藏到 idontknowwhat_t
class 的 operator>>
和 operator<<
函数中。使用模板,您可以将代码中的转换次数限制在最低限度。
class idontknowwhat_t
{
uint8_t* _data;
public:
idontknowwhat_t(uint8_t* buffer)
: _data(buffer)
{}
template<typename insert_type>
idontknowwhat_t& operator<<(insert_type value)
{
*reinterpret_cast<insert_type*>(_data) = value;
_data += sizeof(insert_type);
return *this;
}
template<typename extract_type>
idontknowwhat_t& operator>>(extract_type& value)
{
value = *reinterpret_cast<extract_type*>(_data);
_data += sizeof(extract_type);
return *this;
}
};
我认为这实际上可以直接与您的代码一起使用。在此示例中,idontknowwhat_t
class 不拥有缓冲区,只是将原始指针保存到它希望读取或写入的下一位数据。出于实际目的,我建议让 idontknowwhat_t
class 管理缓冲区内存。
此外,此页面上的代码 none 实际上负责数据的字节顺序,这肯定是 idontknowwhat_t
class 的责任。有一个 boost library 。我不会在这里记录该库的使用,因为我认为它会分散问题的实际意义。
我不得不承认我现在有点困惑,如果问题不是很清楚或不琐碎(实际上我希望是后者),我很抱歉......
我正在通过网络发送一个字节数组,并想在发送端做这样的事情:
size_t max_size = 100;
uint8_t buffer[size];
idontknowwhat_t x{buffer};
uint16_t size = 11; // total number of bytes in the buffer
uint16_t id_a,id_b,id_c; // some ids
uint8_t a,b,c; // some data
x << size << id_a << a << id_b << b << id_c << c;
someMethodToSend(buffer,size);
在接收端是这样的:
size_t max_size = 100;
uint8_t buffer[size];
someMethodToReceive(buffer);
idontknowwhat_t x{buffer};
uint16_t size;
x >> size;
for (uint16_t i=0; i<size-2; i++) {
uint16_t id;
uint8_t data;
x >> id >> data;
std::cout << id << " " << data;
}
所以我的目标基本上是避免丑陋的转换和手动递增指针,同时能够在缓冲区中包含 uint8_t
和 uint16_t
(可能还有 uint32_t
)。我在此处放入缓冲区的数据只是一个示例,我知道在通过网络发送时我需要注意字节顺序(如果我必须这样做就好了 "manually") .
有什么东西可以代替我假设的 idontknowwhat_t
吗?
你试过std::list了吗?您可以将元素分组到类型中,然后将它们放入具有适当类型的列表中。然后你可以创建一个 std::list of std::lists.
你无法真正避免进行丑陋的转换,但至少你可以将它们隐藏到 idontknowwhat_t
class 的 operator>>
和 operator<<
函数中。使用模板,您可以将代码中的转换次数限制在最低限度。
class idontknowwhat_t
{
uint8_t* _data;
public:
idontknowwhat_t(uint8_t* buffer)
: _data(buffer)
{}
template<typename insert_type>
idontknowwhat_t& operator<<(insert_type value)
{
*reinterpret_cast<insert_type*>(_data) = value;
_data += sizeof(insert_type);
return *this;
}
template<typename extract_type>
idontknowwhat_t& operator>>(extract_type& value)
{
value = *reinterpret_cast<extract_type*>(_data);
_data += sizeof(extract_type);
return *this;
}
};
我认为这实际上可以直接与您的代码一起使用。在此示例中,idontknowwhat_t
class 不拥有缓冲区,只是将原始指针保存到它希望读取或写入的下一位数据。出于实际目的,我建议让 idontknowwhat_t
class 管理缓冲区内存。
此外,此页面上的代码 none 实际上负责数据的字节顺序,这肯定是 idontknowwhat_t
class 的责任。有一个 boost library 。我不会在这里记录该库的使用,因为我认为它会分散问题的实际意义。