PDA

View Full Version : QDataStream and Google Protocol Buffers



sunburns
29th January 2021, 22:10
I have a QDataStream that contains both text messages and GPBs. The stream has 24 bytes that serve as a header for the next message. The header tells me if it's text or GPB, and how many bytes the message is. If it's text, I simply read that many bytes, then read in the next 24 bytes of the next header. If the next message is GPB, the header also tells me what message it is. I want to use the ParseFromIstream() method for that message, but the argument for that method is an fstream.

So I guess my question is, is there a way to convert the QDataStream into an fstream? Better yet, does Qt have some way to parse data stored as a GPB?

I suppose I could just toss the QDataStream and use an fstream, but I would rather not.

d_stranz
30th January 2021, 01:59
You might consider extracting the char * array from the raw data and using it to construct a QByteArray which gives you a huge number of ways to iterate through and extract things from it. If it is non-binary, you could use QString which gives you similar functions as well as the ability to use QRegularExpression if you want to match patterns.

ChrisW67
31st January 2021, 04:55
A QDataStream is almost certainly not the tool for the job. Assuming that the I/O has to be Qt then get the data into a QByteArray directly from the underlying QIODevice (socket, file, whatever) and then use some generic C++ code to make an in-memory buffer for a std::istream sub-class. Something like this example from Stack Overflow (https://stackoverflow.com/questions/13059091/creating-an-input-stream-from-constant-memory):


#include <streambuf>
#include <istream>

struct membuf: std::streambuf {
membuf(char const* base, size_t size) {
char* p(const_cast<char*>(base));
this->setg(p, p, p + size);
}
};
struct imemstream: virtual membuf, std::istream {
imemstream(char const* base, size_t size)
: membuf(base, size)
, std::istream(static_cast<std::streambuf*>(this)) {
}
};
In your Qt code:


QByteArray buffer; // << contains the data from whatever source
imemstream stream(buffer.constData(), buffer.size());
// Pass &stream to the Google ParseFromIstream(istream* input) function.
// Be careful of object lifetime: buffer has to stay in existence until the parse is complete

sunburns
8th February 2021, 22:06
Thanks, looks like that will work for me. It's very helpful to know that QDataStream isn't the right object.