PDA

View Full Version : QDataStream >>QByteArray [was QByteArray resize not working?!]



pdoria
24th July 2009, 15:52
Hi

I have this piece of code:



records >> sPacket.size_app_payload; // == 15
sPacket.app_payload.resize( sPacket.size_app_payload );

printf("Application Payload array size: %d\r\n", sPacket.app_payload.size() );


the
sPacket.size_app_payload returns 15

the
sPacket.app_payload.size() returns 0 !!! :confused:

Unless I'm finally going mad or short of spotting something very obvious this is weird!

TIA,
Pedro.

Lykurg
24th July 2009, 16:19
QByteArray ba("qtcentre.org");
qWarning() << ba.size(); // 12
ba.resize(4);
qWarning() << ba.size(); // 4

works just fine, so what type is your sPacket? and what is the output of


records >> sPacket.size_app_payload;
qWarning() << sPacket.size_app_payload << sPacket.app_payload.size();
sPacket.app_payload.resize( sPacket.size_app_payload );
qWarning() << sPacket.size_app_payload << sPacket.app_payload.size();

pdoria
24th July 2009, 16:37
Hi Lykurg. Txs for replying :)

I've somewhat pinpointed the problem...
The resize actually works :o

The problem is when I throw data into the byte array as exemplified:



records >> sPacket.size_app_payload;
printf ("size_app_payload: %d\r\n", sPacket.size_app_payload);
sPacket.app_payload.resize( sPacket.size_app_payload );
printf ("app_payload size after resize(): %d\r\n",sPacket.app_payload.size() );
records >> sPacket.app_payload; //! problem line!
printf ("app_payload size after records >> : %d\r\n",sPacket.app_payload.size() );


this is the output:
size_app_payload: 15
app_payload size after resize(): 15
app_payload size after records >> : 0

the sPacket is of:


typedef struct {
quint8 DLE; // ASCII DLE character (16 decimal)
quint8 packet_id; // packet ID
// types:
// 6 - ACK
// 10 - Command
// 14 - Date/Time Data
// 21 - NAK
// 38 - Unit ID/ESN
// 51 - PVT (Position, Velocity, Time) Data
// 135 - Legacy Stop message
// 136 - Legacy text message
// 161 - Fleet Management packet
quint8 size_app_payload; // number of bytes of packet data (bytes 3 to n-4)
QByteArray app_payload; // 0 to 255 bytes
quint8 checksum; // 2's complement of the sum of all bytes from byte 1 to byte n-4 (end of the payload)
quint8 DLE_end; // same as DLE
quint8 ETX; // End of text - ASCII ETX character (3 decimal)
} serial_packet_format;


and I know there's data pending in the datastream ...

So... the above code compiles without a problem... I'm wondering if there's a problem with
records >> sPacket.app_payload; this syntax ...:confused:

TIA,
Pedro.

pdoria
25th July 2009, 09:03
bump :(
anyone?

pdoria
25th July 2009, 10:40
Gurus out there... :)

I know I can solve it with


qint8 c;
for (int i = 0; i < sPacket.size_app_payload; i++) {
records >> c;
sPacket.app_payload[i] = c;
}

... but that's rather inefficient, right?

Given the fact that the QByteArray sPacket.app_payload has already been re-sized one assumes that the >> operator fetches sPacket.app_payload.size() bytes, right?

So why does
records >> sPacket.app_payload; call fail? :confused:

TIA,
Pedro

wysota
25th July 2009, 12:31
Does the data sitting in the stream actually represent a byte array? How was it written to the stream?

pdoria
25th July 2009, 12:45
Hi wysota. txs for taking an interest! :)

The datastream has been filled by data coming from a socket so, yes, it's conceptually a byte array.

As a sample, from inspecting it byte-by-byte:



11 |
8 | Driver ID update 0x0811 (quint16)
1 |
0 |
0 |
0 | status_change_id (quint32)
bd |
25 |
bb |
24 | time_type (quint32)
4d | "M"
47 | "G"
50 | "P"
53 | driver_id "S" (variable length, null terminated, string)
0 | null-termination
3e | checksum
10 | DLE
3 | ETX

All multi-byte numeric values represented here come in little-endian format which are (will be) dealt with by means of qToBigEndian.

I'm also having trouble extracting values from the QByteArray .. like:
I want to extract the first two bytes from it to a quint16 and then perform qToBigEndian on it. I'm also miserably failing to do that ... :crying:

TIA,
Pedro.

wysota
25th July 2009, 12:48
The datastream has been filled by data coming from a socket so, yes, it's conceptually a byte array.
Is it an array of bytes or a byte array object?
Because if you are expecting QDataStream to build a QByteArray object from an arbitrary binary content, this will obviously not work. The same as it is not possible to ask QColor for hardware address of your network card.

pdoria
25th July 2009, 13:08
Well ... it's an array of bytes of arbitrary binary content...

funny thing the compiler is perfectly happy with QDataStream >> QByteArray...
Why does it fail the call is still beyond me... (and this is exactly the kind of thing that gets you stuck for hours on end :D )

To be honest, and never forgetting my place (newbie), I'd call this one a bug on QT4.
This call should fetch myQByteArray.size bytes from the stream, regardless of content.
Reading the docs for QByteArray it's stated "QByteArray can be used to store both raw bytes..." so it shouldn't matter what kind of content, or where it came from, one puts in it...


Bottom line: is there no other (optimized) way than being stuck with this?


qint8 c;
for (int i = 0; i < sPacket.size_app_payload; i++) {
records >> c;
sPacket.app_payload[i] = c;
}

Regarding my other difficulty ...
I want to extract the first two bytes from it to a quint16

Could you please show me a way?

TIA,
Pedro.

wysota
25th July 2009, 13:27
Well ... it's an array of bytes of arbitrary binary content...
So it won't work.


funny thing the compiler is perfectly happy with QDataStream >> QByteArray...
Because this is syntactically correct.


Why does it fail the call is still beyond me... (and this is exactly the kind of thing that gets you stuck for hours on end :D )
Then read the first sentence of QDataStream documentation and then use QIODevice::read() on the socket directly.


To be honest, and never forgetting my place (newbie), I'd call this one a bug on QT4.
It's not a bug, it's a misunderstanding of what QDataStream is.


This call should fetch myQByteArray.size bytes from the stream, regardless of content.
No. Make the following experiment:

QFile f("test.bin");
f.open(QFile::WriteOnly);
QDataStream dstream(&f);
dstream << 7;
f.close();
Now go and take a look at size of the created file and its content and everything will become clear.