PDA

View Full Version : QByteArray overrides



squidge
10th January 2010, 23:42
I'm creating an array to send across the network, so decided on QByteArray, which seems ideal for the task, except I want to insert some 32-bit values in the array, and it doesn't seem to support this other than by creating another array with the value and then appending that array to the first one, which seems a little daft.

I really don't want to have to shift, mask, and insert each byte seperately, but is there another option? I could be doing this 20 times or more per packet, but thinking there must be a better way than creating a method that takes a QByteArray and inserts each byte at the end.

ecanela
11th January 2010, 03:54
You can use the union keyword to make to make the conversion from qint32 to char *, and the just use the funcion
QByteArray::append ( const char * str, int len ) to append the value32bits to a QByteArray




union {
qint32 value32bits;
char char32bits[4];
} castValue;

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QByteArray array;
qint32 myValue = 87000; // some 32 bits value
castValue.value32bits = myValue;
array.append(castValue.char32bits, 4);
qDebug() << array;

return a.exec();
}

is a low level, but using union you can make the bit convertion.

ChrisW67
11th January 2010, 05:03
If you use this approach though you might need to very careful about byte order.

ecanela
11th January 2010, 06:49
I'm creating an array to send across the network, so decided on QByteArray, which seems ideal for the task, except I want to insert some 32-bit values in the array, and it doesn't seem to support this other than by creating another array with the value and then appending that array to the first one, which seems a little daft.


if the QByteArray data are send across the network, using a QDataStream resolve the issues about the byte order f the machine.

The QByteArray is filled whit data in the native byte order, and then is send if a portable way using QDataStream.


or use a code like ...

if ( QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
...
}
else{ //QSysInfo::BigEndian
...
}

and using the function provide in QtEndian header.

sorry about the incomplete code . i don´t remember how work whit the endianess of the machine. one litle disadvantages of programming of QT :)

squidge
11th January 2010, 09:02
Thanks, you've given me a brilliant idea. I noticed that all of these 32 bit values appear at the start of the packet, and that the byte ordering is the same as Intel, so I can just create an array of quint32's, calculate the size and either cast or use a union to copy X amount of bytes from that array to the packet. Perfect.

wysota
11th January 2010, 11:05
You don't have to cast nor to use unions.
The scheme is:

QByteArray ba;
ba.resize(1000);
int x, y, z;
char *data = ba.data();
memcpy(data, &x, sizeof(x));
memcpy(data+sizeof(x), &y, sizeof(y));
memcpy(data+sizeof(x)+sizeof(y), &z, sizeof(z));

squidge
11th January 2010, 11:43
Thanks wysota, I didn't know whether or not accessing the internal data of a QByteArray was frowned upon or not, or could cause potential problems. I was also going to use append as it guarantees the space is available, and resizes if not, but I guess I can calculate the amount of space required by the quint32's at least (at the moment, I just over-estimate and 'reserve' the amount rather than a resize).