Qt QByteArray issue - qt

I've tried the following:
qDebug() << QByteArray("\x00\x10\x00\x00").size();
and i get 0 instead of 4 witch i would espect.
What would be a good data type to hold this 4 bytes of data as i need to later write them to a socket so they must remain exactly like you see them above?

The constructor QByteArray(const char* str) uses qstrlen on the argument. Since your string starts with a 0x00 byte, qstrlen returns 0, thus the resulting QByteArray is 0 bytes long.
To avoid the qstrlen check, use the QByteArray(const char* str, int size) constructor:
qDebug() << QByteArray("\x00\x10\x00\x00", 4).size();
will print 4 as you expect.

Related

How to read an unsigned int from a std::unique_ptr<unsigned char[]>?

So basically I'm working on a file reader and the binary file gets loaded into a std::unique_ptr<unsigned char[]> containing all the bytes from the file.
I'm trying to read an unsigned int from the start of it. Usually, if it were just a raw pointer (unsigned char*) it would be as follows:
unsigned int magic = *(reinterpret_cast<unsigned int*>(buffer));
However, I'm currently trying to the same, where buffer is the smart pointer. So far I've came up with this:
unsigned int magic = *(reinterpret_cast<unsigned int*>(classFile_.get()));
Upon outputting magic like this:
std::cout << std::hex << magic;
I get 1. Where I should be getting: 0xbebafeca (this is a Java class file reader, 0xCAFEBABE is the unsigned int magic number).
Any ideas as to why it's not working? I'm also not sure if storing a smart pointer for the unsigned char* is good practice rather than doing something like storing a raw pointer and deleting the allocated array in the de-constructor.

checking EOF on unix cp program

I'm writing a unix cp program, but I'm unclear about checking for EOF. The code I have is:
int main(int argc, const char * argv[]) {
int in, out;
char buf[BUFFER_SIZE];
if (argc != 3)
cout << "Error: incorrect number of params" << endl;
if ((in = open(argv[1], O_RDONLY, 0666)) == -1)
cout << "Error: cannot open input file" << endl;
if ((out = open(argv[2], O_WRONLY | O_CREAT, 0666)) == -1)
cout << "Cannot create output file" << endl;
else
while ((read(in, buf, BUFFER_SIZE)) != -1)
write(out, buf, BUFFER_SIZE);
return 0;
}
It reads and writes fine, but writes past EOF when writing the output file. So I get a couple lines of gibberish past the end of the file. Am I just not checking for EOF correctly? I appreciate the input.
You should read the man page for the read function.
On end-of-file, read returns 0. It returns -1 only if there's an error.
read can read fewer bytes than you asked to (and it must do so if there aren't that many bytes remaining to be read). Your write call assumes that read actually read BUFFER_SIZE bytes.
You need to save the result returned by read and write only that many bytes -- and you need to terminate the loop when read returns 0 (indicating end-of-file) or -1 (indicating an error). In the latter case, you should probably do something to handle the error, or at least inform the user.
Incidentally, you don't need the 0666 mode argument when calling open to open the file for reading; that applies only with O_CREAT. Since open is actually a variadic function (like printf), you don't have to supply all the arguments.
The man page is not clear on this point; it pretends that there are two different forms of the open function:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
but in fact that's not legal in C. The POSIX description correctly shows the declaration as:
int open(const char *path, int oflag, ...);

Get a string representation of a single byte from QByteArray?

I have a QByteArray i create manually:
QByteArray hexArray(QByteArray::fromHex("495676"));
If this was encoded ASCII it would be "IVv".
If I want to get a single byte of data from that array.
I can do that like this:
qDebug() << messageToBeSent_raw[0];
However, that outputs I, which is correct but I would like to get 49. What I'm looking for is an equivalent of the QByteArray::toHex() just for a single byte. Is there a way to do it?
You can use QString::number.
qDebug() << QString::number(hexArray[0], 16);

Does QVariant expect a null-terminated QByteArray?

I need to construct a QVariant object from a QByteArray. Does the QVariant constructor QVariant(const QByteArray & val) expect the raw bytes in the QByteArray to be null-terminated?
Background info:
My QByteArray object was constructed with QByteArray::fromRawData(const char * data, int size) and is not null-terminated.
My objective is to copy the raw bytes in my QByteArray object into a database with QSqlQuery::bindValue() which expects a Qvariant object as one of its arguments.
My guess is the the bytes in QByteArray must be null-terminated. I don't see any other way how QVariant(const QByteArray & val) constructor could be implemented.
Many thanks!
The bytes added in QByteArray may or may not be 0-terminated. If you convert QByteArray to QVariant, it will contain all bytes that have been added to the array regardless of their values. It's possible because QByteArray stores bytes count. When you have char* pointer and byte count, you can safely operate with bytes without knowing if there are 0s there or not.
Actually, when you call data() to get char* pointer, the data is always null-terminated. But it really is behind the scenes. If you use data() and pass that pointer to some function without size, 0-termination will protect you from segfault. But it is not important in your question.
I'll try to illustrate that using example.
Raw data: 1 2 3 4 ....
calling fromRawData(pointer, 4)
QByteArray contents: 1 2 3 4
Underlying QByteArray's buffer contents: 1 2 3 4 0 ...
Raw data: 1 2 3 0 ....
calling fromRawData(pointer, 4)
QByteArray contents: 1 2 3 0
Underlying QByteArray's buffer contents: 1 2 3 0 ...
Raw data: 1 0 2 3
calling fromRawData(pointer, 4)
QByteArray contents: 1 0 2 3
Underlying QByteArray's buffer contents: 1 0 2 3 0 ...
And QVariant will contain the same bytes as "QByteArray contents".
Edited for newcomers. Look at comments.
From docs:
QByteArray can be used to store both raw bytes (including '\0's) and
traditional 8-bit '\0'-terminated strings. Using QByteArray is much
more convenient than using const char *. Behind the scenes, it always
ensures that the data is followed by a '\0' terminator
It means, even if you dont make it null terminated, QByteArray will ensure it. But only when it creates a deep copy... Check size()
int QByteArray::size() const
Returns the number of bytes in this byte
array. The last byte in the byte array is at position size() - 1. In
addition, QByteArray ensures that the byte at position size() is
always '\0', so that you can use the return value of data() and
constData() as arguments to functions that expect '\0'-terminated
strings. If the QByteArray object was created from a raw data that
didn't include the trailing null-termination character then QByteArray
doesn't add it automaticall unless the deep copy is created.
As prolly QVariant will use the constData() method, you cant be sure it will be null terminated. Look at this gist

Is there a way to receive data as unsigned char over UDP on Qt?

I need to send floating point numbers using a UDP connection to a Qt application. Now in Qt the only function available is
qint64 readDatagram ( char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0 )
which accepts data in the form of signed character buffer. I can convert my float into a string and send it but it will obviously not be very efficient converting a 4 byte float into a much longer sized character buffer.
I got hold of these 2 functions to convert a 4 byte float into an unsinged 32 bit integer to transfer over network which works fine for a simple C++ UDP program but for Qt I need to receive the data as unsigned char.
Is it possible to avoid converting the floatinf point data into a string and then sending it?
uint32_t htonf(float f)
{
uint32_t p;
uint32_t sign;
if (f < 0) { sign = 1; f = -f; }
else { sign = 0; }
p = ((((uint32_t)f)&0x7fff)<<16) | (sign<<31); // Whole part and sign.
p |= (uint32_t)(((f - (int)f) * 65536.0f))&0xffff; // Fraction.
return p;
}
float ntohf(uint32_t p)
{
float f = ((p>>16)&0x7fff); // Whole part.
f += (p&0xffff) / 65536.0f; // Fraction.
if (((p>>31)&0x1) == 0x1) { f = -f; } // Sign bit set.
return f;
}
Have you tried using readDatagram? Or converting the data to a QByteArray after reading? In many cases a char* is really just a byte array. This is one of those cases. Note that the writeDatagram can take a QByteArray.
Generally every thing sent across sockets is in bytes not strings, layers on either end do the conversions. Take a look here, especially the Broadcaster examples. They show how to create a QByteArray for broadcast and receive.
Not sure why the downvote, since the question is vague in requirements.
A 4-byte float is simply a 4 character buffer, if cast as one. If the systems are homogenous, the float can be sent as a signed char *, and bit for bit it'll be the same read into the signed char * on the receiver directly, no conversion needed. If the systems are heterogenous, then this won't work and you need to convert it to a portable format, anyway. IEEE format is often used, but my question is still, what are the requirements, is the float format the same between systems?
If I read it correctly, your primary question seems to be how to receive data of type unsigned char with QT's readDatagram function which uses a pointer to a buffer of type char.
The short answer is use a cast along these lines:
const size_t MAXSIZE = 1024;
unsigned char* data = malloc(MAXSIZE);
readDatagram ( (unsigned char *)data, MAXSIZE, address, port )
I'm going to assume you have multiple machines which use the same IEEE floating point format but some of which are big endian and some of which are little endian. See this SO post for a good discussion of this issue.
In that case you could do something a bit simpler like this:
const size_t FCOUNT = 256;
float* data = malloc(FCOUNT * sizeof(*data));
readDatagram ( (char *)data, FCOUNT * sizeof(*data), address, port )
for (int i = 0; i != FCOUNT; ++i)
data[i] = ntohf(*((uint32_t*)&data[i]));
The thing to remember is that as far as networking functions like readDatagram are concerned, the data is just a bunch of bits and it doesn't care what type those bits are interpreted as.
If both ends of your UDP connection use Qt, I would suggest looking at QDataStream. You can create this from a QByteArray each time you read a datagram, and then read whatever values you require - floats, maps, lists, QVariants, and of course string.
Similarly, on the sending side, you'd create a data stream, push data into it, then send the resulting QByteArray over writeDatagram.
Obviously this only works if both ends use Qt - the data encoding is well-defined, but non-trivial to generate by hand.
(If you want stream orientated behaviour, you could use the fact that QUDPSocket is a QIODevice with a data-stream, but it sounds as if you want per-datagram behaviour)

Resources