4

In my project I'm working with QByteArrays appending data to them as the program goes. Most of the time, a simple quint8 gets appended just fine using QByteArray::append(). But when a quint16 gets appended, only 1 byte gets appended instead of 2.

QByteArray ba = QByteArray::fromHex("010203");
quint number(300);//300 in hex is 012c

ba.append(number);//What should be appended instead of just number?

//the current incorrect result is
ba.toHex() == "0102032c"

//the desired result is
ba.toHex() == "010203012c"

I've already tried this, but it just inserts the value as a string (4 bytes):

ba.append(QByteArray::number(number, 16));

What should I append to the QByteArray so both bytes of "number" get appended instead of just one byte? Also, the fastest method possible is preferred since this program needs to have great performance times. So absolutely no converting to QStrings.

Thanks for your time.

mrg95
  • 2,371
  • 11
  • 46
  • 89
  • What endianness do you expect when appending a `quint16`? – Matteo Italia Jun 05 '15 at 07:01
  • I believe big endian. It should be 012c getting appended – mrg95 Jun 05 '15 at 07:02
  • Reading the doc I see no trace of a `QByteArray.append(quint)`... – Thomas Ayoub Jun 05 '15 at 07:10
  • Why not just use a `QList`? – cmannett85 Jun 05 '15 at 07:32
  • 1
    Because the QByteArray isn't just a bunch of quint16's as stated in the post. – mrg95 Jun 05 '15 at 07:35
  • But a `quint16` can hold a `quint8`, so a single `QList` can hold all of your data. Maybe you should explain what you're using your `QByteArray` for once you've finished populating it - because as your question stands, it just looks like you're trying to put `quint16` into a `quint8` and wondering why it's not working. – cmannett85 Jun 05 '15 at 07:45
  • I'm taking elements (sometimes bytes, sometimes ints, or shorts, strings, floats, doubles, etc...) from a QByteArray containing a huge file, and editing them, then putting them into a new QByteArray that is organized differently. I'm sticking with QByteArrays. There are even Byte and Int arrays WITHIN the QByteArray itself. – mrg95 Jun 05 '15 at 07:49
  • I was more or less asking how to turn quint16 into two seperate quint8's – mrg95 Jun 05 '15 at 07:57

1 Answers1

8

On its own, QByteArray only supports appending bytes; to append a big-endian representation of fixed-size integer types you can build your own operator<< (or what you prefer) overloads using the appropriate bit shifts:

QByteArray &operator<<(QByteArray &l, quint8 r)
{
    l.append(r);
    return l;
}

QByteArray &operator<<(QByteArray &l, quint16 r)
{
    return l<<quint8(r>>8)<<quint8(r);
}

QByteArray &operator<<(QByteArray &l, quint32 r)
{
    return l<<quint16(r>>16)<<quint16(r);
}

This allows you to write code like:

QByteArray b;
b<<quint16(300);     // appends 0x01 0x2c
b<<quint8(4);        // appends 0x04
b<<quint16(4);       // appends 0x00 0x04
b<<quint32(123456);  // appends 0x00 0x01 0xe2 0x40
b<<quint8(1)<<quin16(2)<<quint32(3); // appends 0x01 0x00 0x02 0x00 0x00 0x00 0x03

You should probably avoid writing

QByteArray b;
b<<1;

because in theory the output depends on the size of the current platform integer (although AFAIK on all platforms supported by Qt int is 32 bit).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • Works flawlessly. Thanks so much for the quick answer :) – mrg95 Jun 05 '15 at 07:12
  • Hate to ask this, but how about going backwards? So from a QByteArray containing "012c" to a qint16? I already tried ba.mid(3,2).toUShort(0,16) however that won't work since it's not looking at the binary data. – mrg95 Jun 05 '15 at 07:37
  • 1
    To read a big-endian value to an integer the normal way is "for each byte read left shift the target by 8 and OR the read byte into the target". That is more easily done with an actual stream that keeps track of the read position. – Matteo Italia Jun 05 '15 at 12:04