10

I want to write a function in which QByteArray is input to the function. I want to remove some header from receive data and store it into global QByteArray.

void abc::CopyData(const QByteArray &data)
{
    switch(RequestPacketCount)
    {
        case REQUEST_FIRST_PACKET:
        {
            ByteArrayData = data;
        }
            break;
        case REQUEST_SECOND_PACKET:
        case REQUEST_THIRD_PACKET:
            ByteArrayData.append(data);
    }
}

I want to remove 'n' no. of byte from start of 'data' and store remaining data into 'ByteArrayData'

Thanks in advance.

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
beparas
  • 1,927
  • 7
  • 24
  • 30

3 Answers3

7

What you seem to want is simply copy the original array and use remove;

ByteArrayData = data;
ByteArrayData.remove(0, n);            // Removes first n bytes of ByteArrayData,
                                       // leaving data unchanged

Since a QByteArray is implicitly shared, the construction of the copy takes constant time, and the modification (deletion) is what will make the actual copy when needed.

To append efficiently, you can just use data to get to the byte array, and append the part you want. That will prevent un-necessary temporary objects. That would look something like;

ByteArrayData.append(data.data() + n, data.size() - n);
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • Thanks, but I got following error, error: passing 'const QByteArray' as 'this' argument of 'QByteArray& QByteArray::remove(int, int)' discards qualifiers [-fpermissive] – beparas Mar 19 '14 at 05:35
  • @beparas Ah, true, I missed the `const`. I'll update. – Joachim Isaksson Mar 19 '14 at 05:37
  • Thanks, what about append() function. – beparas Mar 19 '14 at 05:51
  • @beparas You mean that you want to append all except the first n bytes in data to ByteArrayData? – Joachim Isaksson Mar 19 '14 at 05:54
  • my CopyData() function calls three times, every time 'data' having 'n' byte of fix header, your solution is work for case 1st :), but how to append data (removing header) in case 2nd and 3rd in above code. Thanks – beparas Mar 19 '14 at 06:01
2

You can use QByteArray::mid:

ByteArrayData = data.mid(n);
//...
ByteArrayData.append(data.mid(n));
Pavel Strakhov
  • 39,123
  • 5
  • 88
  • 127
0

Adding to Joachim's answer, in C++ it's rather unfortunate that some implementation details leak into the interface, but it's still preferred for performance reasons to let the compiler do the copying by passing the argument as value. So, paraphrasing, the best solution would be:

void abc::CopyData(QByteArray data)
{
  ...
  data.remove(0, n);
  ...
  ByteArrayData.append(data);
}

The only place where you definitely do not want to have such arguments passed by value is a signal declaration - signals never modify their data. It's fine for a slot to do so, though:

class MyClass : public QObject {
  Q_OBJECT
  ...
public:
  // pass by const reference in signals
  Q_SIGNAL void dataSource(const QByteArray &); // The only correct signal form
  // pass by const reference or value in slots, depending on use
  Q_SLOT void dataSink1(const QByteArray &); // Valid
  Q_SLOT void dataSink2(QByteArray); // Valid as well.
};

Connecting to either slot uses the same code whether it's Qt4 or Qt5 connection style. Thus you don't have to worry about such interface changes due to leaked implementation details breaking your code.

// Qt4 - you should elide const and reference anyway
connect(src, SIGNAL(dataSource(QByteArray)), dst, SLOT(dataSink1(QByteArray));
connect(src, SIGNAL(dataSource(QByteArray)), dst, SLOT(dataSink2(QByteArray));
// Qt5
connect(src, &MyClass::dataSource, dst, &MyClass::dataSink1);
connect(src, &MyClass::dataSource, dst, &MyClass::dataSink2);
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313