2

I have a legacy library that takes data from hardware and writes it to ostream. The method looks like following :

int sensors(ostream*) const; 

I am not skilled enough in Ancient Ways. How to convert this data to QByteArray? Or, at least, to char array of known size? I would have solved it myself, but there is an additional problem: the data in ostream seem to be arbitrary length and have several arbitrary '\0' symbols, so you can't count on it being null-terminated.

3 Answers 3

2

I think this is what OrcunC was getting at:

std::stringstream s; sensors( &s ); QByteArray( s.str().data(), (int) s.str().size() ); 

... but hopefully more clear :). See also std::stringstream and std::string for information on the classes/member functions used here. By the way, note that I am using str().data(), not str().c_str() -- I'm being really careful to handle those \0 characters, and I'm not assuming NULL termination.

Sign up to request clarification or add additional context in comments.

3 Comments

This copies the data twice. Once to the std::string s.str() and then again to the QByteArray. That is a shame.
std::stringstream does not guarantee that the data is stored sequentially, and the QByteArray absolutely requires construction with sequential data. You could get around that extra copy if you had an ostream-derived class which guaranteed sequential storage, but that's a much longer answer. I agree, however, that it's a shame.
See my non-stringstream suggestion below.
2

I have not tried it, but you need something like this :

ostream s (ios::out | ios::binary); //..Populate the stream //Convert it to string. string can hold \0 values too. string str = s.str (); QByteArray ba (str.data (),str.size ()); 

1 Comment

If you declare s as std::stringstream instead of ostream, this is much better than mine (no need to copy to a vector first)!
1

You can subclass std::ostream and use an object of the subclass to collect the bytes into your QByteArray.

/** * This helper class collects bytes that are passed to it * into a QByteArray. * * After https://stackoverflow.com/a/19933011/316578 */ class QByteArrayAppender : public std::ostream, public std::streambuf { private: QByteArray &m_byteArray; public: QByteArrayAppender(QByteArray &byteArray) : std::ostream(this), std::streambuf(), m_byteArray(byteArray) { } int overflow(int c) { m_byteArray.append(static_cast<char>(c)); return 0; } }; 

This avoids going via an std::string, which is an extra copy of the byte array.

Comments