#include <string.h>
#include <stdlib.h>
-#define IS_RAW_DATA(d) ((d)->data != (d)->array)
+#define IS_RAW_DATA(d) ((d)->offset != 0)
QT_BEGIN_NAMESPACE
qWarning("qUncompress: Input data is corrupted");
return QByteArray();
}
- QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc));
+ QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc + 1));
if (!p) {
// we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
qWarning("qUncompress: could not allocate enough memory to uncompress data");
}
d.take(); // realloc was successful
d.reset(p);
+ d->offset = 0;
- int res = ::uncompress((uchar*)d->array, &len,
+ int res = ::uncompress((uchar*)d->data(), &len,
(uchar*)data+4, nbytes-4);
switch (res) {
qWarning("qUncompress: Input data is corrupted");
return QByteArray();
}
- QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len));
+ QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len + 1));
if (!p) {
// we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
qWarning("qUncompress: could not allocate enough memory to uncompress data");
d.reset(p);
}
d->ref = 1;
- d->alloc = d->size = len;
- d->data = d->array;
- d->array[len] = 0;
+ d->size = len;
+ d->alloc = len;
+ d->capacityReserved = false;
+ d->offset = 0;
+ d->data()[len] = 0;
return QByteArray(d.take(), 0, 0);
return c;
}
-QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
- 0, 0, shared_null.array, {0} };
-QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
- 0, 0, shared_empty.array, {0} };
+QConstByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZER(-1),
+ 0, 0, 0, { 0 } }, { 0 } };
+QConstByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1),
+ 0, 0, 0, { 0 } }, { 0 } };
/*!
\class QByteArray
{
Data *x;
if (!str) {
- x = &shared_null;
+ x = const_cast<Data *>(&shared_null.ba);
} else if (!*str) {
- x = &shared_empty;
+ x = const_cast<Data *>(&shared_empty.ba);
} else {
int len = qstrlen(str);
if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1))
realloc(len);
x = d;
- memcpy(x->data, str, len + 1); // include null terminator
+ memcpy(x->data(), str, len + 1); // include null terminator
x->size = len;
}
x->ref.ref();
QByteArray::QByteArray(const char *str)
{
if (!str) {
- d = &shared_null;
+ d = const_cast<Data *>(&shared_null.ba);
} else if (!*str) {
- d = &shared_empty;
+ d = const_cast<Data *>(&shared_empty.ba);
} else {
int len = qstrlen(str);
- d = static_cast<Data *>(qMalloc(sizeof(Data)+len));
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + len + 1));
Q_CHECK_PTR(d);
- d->ref = 0;;
- d->alloc = d->size = len;
- d->data = d->array;
- memcpy(d->array, str, len+1); // include null terminator
+ d->ref = 1;
+ d->size = len;
+ d->alloc = len;
+ d->capacityReserved = false;
+ d->offset = 0;
+ memcpy(d->data(), str, len+1); // include null terminator
}
- d->ref.ref();
}
/*!
QByteArray::QByteArray(const char *data, int size)
{
if (!data) {
- d = &shared_null;
+ d = const_cast<Data *>(&shared_null.ba);
} else if (size <= 0) {
- d = &shared_empty;
+ d = const_cast<Data *>(&shared_empty.ba);
} else {
- d = static_cast<Data *>(qMalloc(sizeof(Data) + size));
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
- d->ref = 0;
- d->alloc = d->size = size;
- d->data = d->array;
- memcpy(d->array, data, size);
- d->array[size] = '\0';
+ d->ref = 1;
+ d->size = size;
+ d->alloc = size;
+ d->capacityReserved = false;
+ d->offset = 0;
+ memcpy(d->data(), data, size);
+ d->data()[size] = '\0';
}
- d->ref.ref();
}
/*!
QByteArray::QByteArray(int size, char ch)
{
if (size <= 0) {
- d = &shared_null;
+ d = const_cast<Data *>(&shared_null.ba);
} else {
- d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
- d->ref = 0;
- d->alloc = d->size = size;
- d->data = d->array;
- d->array[size] = '\0';
- memset(d->array, ch, size);
+ d->ref = 1;
+ d->size = size;
+ d->alloc = size;
+ d->capacityReserved = false;
+ d->offset = 0;
+ memset(d->data(), ch, size);
+ d->data()[size] = '\0';
}
- d->ref.ref();
}
/*!
QByteArray::QByteArray(int size, Qt::Initialization)
{
- d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ d = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
d->ref = 1;
- d->alloc = d->size = size;
- d->data = d->array;
- d->array[size] = '\0';
+ d->size = size;
+ d->alloc = size;
+ d->capacityReserved = false;
+ d->offset = 0;
+ d->data()[size] = '\0';
}
/*!
void QByteArray::resize(int size)
{
- if (size <= 0) {
- Data *x = &shared_empty;
- x->ref.ref();
+ if (size < 0)
+ size = 0;
+
+ if (d->offset && d->ref == 1 && size < d->size) {
+ d->size = size;
+ return;
+ }
+
+ if (size == 0 && !d->capacityReserved) {
+ Data *x = const_cast<Data *>(&shared_empty.ba);
if (!d->ref.deref())
qFree(d);
d = x;
- } else if (d == &shared_null) {
+ } else if (d == &shared_null.ba || d == &shared_empty.ba) {
//
// Optimize the idiom:
// QByteArray a;
// which is used in place of the Qt 3 idiom:
// QByteArray a(sz);
//
- Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size));
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(x);
x->ref = 1;
- x->alloc = x->size = size;
- x->data = x->array;
- x->array[size] = '\0';
- (void) d->ref.deref(); // cannot be 0, x points to shared_null
+ x->size = size;
+ x->alloc = size;
+ x->capacityReserved = false;
+ x->offset = 0;
+ x->data()[size] = '\0';
d = x;
} else {
- if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
+ if (d->ref != 1 || size > d->alloc || (!d->capacityReserved && size < d->size && size < d->alloc >> 1))
realloc(qAllocMore(size, sizeof(Data)));
if (d->alloc >= size) {
d->size = size;
- if (d->data == d->array) {
- d->array[size] = '\0';
- }
+ d->data()[size] = '\0';
}
}
}
{
resize(size < 0 ? d->size : size);
if (d->size)
- memset(d->data, ch, d->size);
+ memset(d->data(), ch, d->size);
return *this;
}
void QByteArray::realloc(int alloc)
{
- if (d->ref != 1 || d->data != d->array) {
- Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
+ if (d->ref != 1 || d->offset) {
+ Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc + 1));
Q_CHECK_PTR(x);
- x->size = qMin(alloc, d->size);
- ::memcpy(x->array, d->data, x->size);
- x->array[x->size] = '\0';
x->ref = 1;
+ x->size = qMin(alloc, d->size);
x->alloc = alloc;
- x->data = x->array;
+ x->capacityReserved = d->capacityReserved;
+ x->offset = 0;
+ ::memcpy(x->data(), d->data(), x->size);
+ x->data()[x->size] = '\0';
if (!d->ref.deref())
qFree(d);
d = x;
} else {
- Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
+ Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc + 1));
Q_CHECK_PTR(x);
x->alloc = alloc;
- x->data = x->array;
+ x->offset = 0;
d = x;
}
}
QByteArray QByteArray::nulTerminated() const
{
// is this fromRawData?
- if (d->data == d->array)
+ if (!d->offset)
return *this; // no, then we're sure we're zero terminated
QByteArray copy(*this);
QByteArray &QByteArray::prepend(const QByteArray &ba)
{
- if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
+ if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
*this = ba;
- } else if (ba.d != &shared_null) {
+ } else if (ba.d != &shared_null.ba) {
QByteArray tmp = *this;
*this = ba;
append(tmp);
if (str) {
if (d->ref != 1 || d->size + len > d->alloc)
realloc(qAllocMore(d->size + len, sizeof(Data)));
- memmove(d->data+len, d->data, d->size);
- memcpy(d->data, str, len);
+ memmove(d->data()+len, d->data(), d->size);
+ memcpy(d->data(), str, len);
d->size += len;
- d->data[d->size] = '\0';
+ d->data()[d->size] = '\0';
}
return *this;
}
{
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(qAllocMore(d->size + 1, sizeof(Data)));
- memmove(d->data+1, d->data, d->size);
- d->data[0] = ch;
+ memmove(d->data()+1, d->data(), d->size);
+ d->data()[0] = ch;
++d->size;
- d->data[d->size] = '\0';
+ d->data()[d->size] = '\0';
return *this;
}
QByteArray &QByteArray::append(const QByteArray &ba)
{
- if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
+ if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
*this = ba;
- } else if (ba.d != &shared_null) {
+ } else if (ba.d != &shared_null.ba) {
if (d->ref != 1 || d->size + ba.d->size > d->alloc)
realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
- memcpy(d->data + d->size, ba.d->data, ba.d->size);
+ memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
d->size += ba.d->size;
- d->data[d->size] = '\0';
+ d->data()[d->size] = '\0';
}
return *this;
}
int len = qstrlen(str);
if (d->ref != 1 || d->size + len > d->alloc)
realloc(qAllocMore(d->size + len, sizeof(Data)));
- memcpy(d->data + d->size, str, len + 1); // include null terminator
+ memcpy(d->data() + d->size, str, len + 1); // include null terminator
d->size += len;
}
return *this;
if (str && len) {
if (d->ref != 1 || d->size + len > d->alloc)
realloc(qAllocMore(d->size + len, sizeof(Data)));
- memcpy(d->data + d->size, str, len); // include null terminator
+ memcpy(d->data() + d->size, str, len); // include null terminator
d->size += len;
- d->data[d->size] = '\0';
+ d->data()[d->size] = '\0';
}
return *this;
}
{
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(qAllocMore(d->size + 1, sizeof(Data)));
- d->data[d->size++] = ch;
- d->data[d->size] = '\0';
+ d->data()[d->size++] = ch;
+ d->data()[d->size] = '\0';
return *this;
}
QByteArray &QByteArray::insert(int i, const QByteArray &ba)
{
QByteArray copy(ba);
- return qbytearray_insert(this, i, copy.d->data, copy.d->size);
+ return qbytearray_insert(this, i, copy.d->data(), copy.d->size);
}
/*!
if (pos + len >= d->size) {
resize(pos);
} else {
- memmove(d->data + pos, d->data + pos + len, d->size - pos - len);
+ memmove(d->data() + pos, d->data() + pos + len, d->size - pos - len);
resize(d->size - len);
}
return *this;
{
if (len == after.d->size && (pos + len <= d->size)) {
detach();
- memmove(d->data + pos, after.d->data, len*sizeof(char));
+ memmove(d->data() + pos, after.d->data(), len*sizeof(char));
return *this;
} else {
QByteArray copy(after);
{
if (len == alen && (pos + len <= d->size)) {
detach();
- memcpy(d->data + pos, after, len*sizeof(char));
+ memcpy(d->data() + pos, after, len*sizeof(char));
return *this;
} else {
remove(pos, len);
// protect against before or after being part of this
const char *a = after;
const char *b = before;
- if (after >= d->data && after < d->data + d->size) {
+ if (after >= d->data() && after < d->data() + d->size) {
char *copy = (char *)malloc(asize);
Q_CHECK_PTR(copy);
memcpy(copy, after, asize);
a = copy;
}
- if (before >= d->data && before < d->data + d->size) {
+ if (before >= d->data() && before < d->data() + d->size) {
char *copy = (char *)malloc(bsize);
Q_CHECK_PTR(copy);
memcpy(copy, before, bsize);
resize(newlen);
len = newlen;
}
- d = this->d->data;
+ d = this->d->data();
while(pos) {
pos--;
if (result.d->alloc != resultSize)
return QByteArray(); // not enough memory
- memcpy(result.d->data, d->data, d->size);
+ memcpy(result.d->data(), d->data(), d->size);
int sizeSoFar = d->size;
- char *end = result.d->data + sizeSoFar;
+ char *end = result.d->data() + sizeSoFar;
const int halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
- memcpy(end, result.d->data, sizeSoFar);
+ memcpy(end, result.d->data(), sizeSoFar);
end += sizeSoFar;
sizeSoFar <<= 1;
}
- memcpy(end, result.d->data, resultSize - sizeSoFar);
- result.d->data[resultSize] = '\0';
+ memcpy(end, result.d->data(), resultSize - sizeSoFar);
+ result.d->data()[resultSize] = '\0';
result.d->size = resultSize;
return result;
}
if (ol == 0)
return from;
if (ol == 1)
- return indexOf(*ba.d->data, from);
+ return indexOf(*ba.d->data(), from);
const int l = d->size;
if (from > d->size || ol + from > l)
return -1;
- return qFindByteArray(d->data, d->size, from, ba.d->data, ol);
+ return qFindByteArray(d->data(), d->size, from, ba.d->data(), ol);
}
/*! \fn int QByteArray::indexOf(const QString &str, int from) const
if (ol == 0)
return from;
- return qFindByteArray(d->data, d->size, from, c, ol);
+ return qFindByteArray(d->data(), d->size, from, c, ol);
}
/*!
if (from < 0)
from = qMax(from + d->size, 0);
if (from < d->size) {
- const char *n = d->data + from - 1;
- const char *e = d->data + d->size;
+ const char *n = d->data() + from - 1;
+ const char *e = d->data() + d->size;
while (++n != e)
if (*n == ch)
- return n - d->data;
+ return n - d->data();
}
return -1;
}
{
const int ol = ba.d->size;
if (ol == 1)
- return lastIndexOf(*ba.d->data, from);
+ return lastIndexOf(*ba.d->data(), from);
- return lastIndexOfHelper(d->data, d->size, ba.d->data, ol, from);
+ return lastIndexOfHelper(d->data(), d->size, ba.d->data(), ol, from);
}
/*! \fn int QByteArray::lastIndexOf(const QString &str, int from) const
if (ol == 1)
return lastIndexOf(*str, from);
- return lastIndexOfHelper(d->data, d->size, str, ol, from);
+ return lastIndexOfHelper(d->data(), d->size, str, ol, from);
}
/*!
else if (from > d->size)
from = d->size-1;
if (from >= 0) {
- const char *b = d->data;
- const char *n = d->data + from + 1;
+ const char *b = d->data();
+ const char *n = d->data() + from + 1;
while (n-- != b)
if (*n == ch)
return n - b;
int QByteArray::count(char ch) const
{
int num = 0;
- const char *i = d->data + d->size;
- const char *b = d->data;
+ const char *i = d->data() + d->size;
+ const char *b = d->data();
while (i != b)
if (*--i == ch)
++num;
return true;
if (d->size < ba.d->size)
return false;
- return memcmp(d->data, ba.d->data, ba.d->size) == 0;
+ return memcmp(d->data(), ba.d->data(), ba.d->size) == 0;
}
/*! \overload
int len = qstrlen(str);
if (d->size < len)
return false;
- return qstrncmp(d->data, str, len) == 0;
+ return qstrncmp(d->data(), str, len) == 0;
}
/*! \overload
{
if (d->size == 0)
return false;
- return d->data[0] == ch;
+ return d->data()[0] == ch;
}
/*!
return true;
if (d->size < ba.d->size)
return false;
- return memcmp(d->data + d->size - ba.d->size, ba.d->data, ba.d->size) == 0;
+ return memcmp(d->data() + d->size - ba.d->size, ba.d->data(), ba.d->size) == 0;
}
/*! \overload
int len = qstrlen(str);
if (d->size < len)
return false;
- return qstrncmp(d->data + d->size - len, str, len) == 0;
+ return qstrncmp(d->data() + d->size - len, str, len) == 0;
}
/*! \overload
{
if (d->size == 0)
return false;
- return d->data[d->size - 1] == ch;
+ return d->data()[d->size - 1] == ch;
}
/*!
return *this;
if (len < 0)
len = 0;
- return QByteArray(d->data, len);
+ return QByteArray(d->data(), len);
}
/*!
return *this;
if (len < 0)
len = 0;
- return QByteArray(d->data + d->size - len, len);
+ return QByteArray(d->data() + d->size - len, len);
}
/*!
QByteArray QByteArray::mid(int pos, int len) const
{
- if (d == &shared_null || d == &shared_empty || pos >= d->size)
+ if (d == &shared_null.ba || d == &shared_empty.ba || pos >= d->size)
return QByteArray();
if (len < 0)
len = d->size - pos;
len = d->size - pos;
if (pos == 0 && len == d->size)
return *this;
- return QByteArray(d->data + pos, len);
+ return QByteArray(d->data() + pos, len);
}
/*!
{
if (!d->ref.deref())
qFree(d);
- d = &shared_null;
+ d = const_cast<Data *>(&shared_null.ba);
d->ref.ref();
}
if (d->size == 0)
return *this;
QByteArray result(d->size, Qt::Uninitialized);
- const char *from = d->data;
+ const char *from = d->data();
const char *fromend = from + d->size;
int outc=0;
- char *to = result.d->data;
+ char *to = result.d->data();
for (;;) {
while (from!=fromend && isspace(uchar(*from)))
from++;
{
if (d->size == 0)
return *this;
- const char *s = d->data;
+ const char *s = d->data();
if (!isspace(uchar(*s)) && !isspace(uchar(s[d->size-1])))
return *this;
int start = 0;
}
int l = end - start + 1;
if (l <= 0) {
- shared_empty.ref.ref();
- return QByteArray(&shared_empty, 0, 0);
+ return QByteArray(const_cast<Data *>(&shared_empty.ba), 0, 0);
}
return QByteArray(s+start, l);
}
if (padlen > 0) {
result.resize(len+padlen);
if (len)
- memcpy(result.d->data, d->data, len);
- memset(result.d->data+len, fill, padlen);
+ memcpy(result.d->data(), d->data(), len);
+ memset(result.d->data()+len, fill, padlen);
} else {
if (truncate)
result = left(width);
if (padlen > 0) {
result.resize(len+padlen);
if (len)
- memcpy(result.d->data+padlen, data(), len);
- memset(result.d->data, fill, padlen);
+ memcpy(result.d->data()+padlen, data(), len);
+ memset(result.d->data(), fill, padlen);
} else {
if (truncate)
result = left(width);
return result;
}
-bool QByteArray::isNull() const { return d == &shared_null; }
+bool QByteArray::isNull() const { return d == &shared_null.ba; }
/*!
char *out = tmp.data();
while (i < d->size) {
int chunk = 0;
- chunk |= int(uchar(d->data[i++])) << 16;
+ chunk |= int(uchar(d->data()[i++])) << 16;
if (i == d->size) {
padlen = 2;
} else {
- chunk |= int(uchar(d->data[i++])) << 8;
+ chunk |= int(uchar(d->data()[i++])) << 8;
if (i == d->size) padlen = 1;
- else chunk |= int(uchar(d->data[i++]));
+ else chunk |= int(uchar(d->data()[i++]));
}
int j = (chunk & 0x00fc0000) >> 18;
QByteArray QByteArray::fromRawData(const char *data, int size)
{
- Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
- Q_CHECK_PTR(x);
- if (data) {
- x->data = const_cast<char *>(data);
+ Data *x;
+ if (!data) {
+ x = const_cast<Data *>(&shared_null.ba);
+ } else if (!size) {
+ x = const_cast<Data *>(&shared_empty.ba);
} else {
- x->data = x->array;
- size = 0;
+ x = static_cast<Data *>(qMalloc(sizeof(Data) + 1));
+ Q_CHECK_PTR(x);
+ x->ref = 1;
+ x->size = size;
+ x->alloc = 0;
+ x->capacityReserved = false;
+ x->offset = data - (x->d + sizeof(qptrdiff));
}
- x->ref = 1;
- x->alloc = x->size = size;
- *x->array = '\0';
return QByteArray(x, 0, 0);
}
*this = fromRawData(data, size);
} else {
if (data) {
- d->data = const_cast<char *>(data);
+ d->size = size;
+ d->offset = data - (d->d + sizeof(qptrdiff));
} else {
- d->data = d->array;
- size = 0;
+ d->offset = 0;
+ d->size = 0;
+ *d->data() = 0;
}
- d->alloc = d->size = size;
- *d->array = '\0';
}
return *this;
}
{
QByteArray hex(d->size * 2, Qt::Uninitialized);
char *hexData = hex.data();
- const uchar *data = (const uchar *)d->data;
+ const uchar *data = (const uchar *)d->data();
for (int i = 0; i < d->size; ++i) {
int j = (data[i] >> 4) & 0xf;
if (j <= 9)
#ifndef QBYTEARRAY_H
#define QBYTEARRAY_H
-#include <QtCore/qatomic.h>
+#include <QtCore/qrefcount.h>
#include <QtCore/qnamespace.h>
#include <string.h>
class QDataStream;
template <typename T> class QList;
+struct QByteArrayData
+{
+ QtPrivate::RefCount ref;
+ int size;
+ uint alloc : 31;
+ uint capacityReserved : 1;
+ union {
+ qptrdiff offset; // will always work as we add/subtract from a ushort ptr
+ char d[sizeof(qptrdiff)];
+ };
+ inline char *data() { return d + sizeof(qptrdiff) + offset; }
+ inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
+};
+
+template<int n> struct QConstByteArrayData
+{
+ const QByteArrayData ba;
+ const char data[n];
+};
+
+template<int N> struct QConstByteArrayDataPtr
+{
+ const QConstByteArrayData<N> *ptr;
+};
+
+
+#if defined(Q_COMPILER_LAMBDA)
+# define QByteArrayLiteral(str) ([]() { \
+ enum { Size = sizeof(str) }; \
+ static const QConstByteArrayData<Size> qbytearray_literal = \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
+ QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
+ return holder; }())
+
+#elif defined(Q_CC_GNU)
+// We need to create a QByteArrayData in the .rodata section of memory
+// and the only way to do that is to create a "static const" variable.
+// To do that, we need the __extension__ {( )} trick which only GCC supports
+
+# define QByteArrayLiteral(str) \
+ __extension__ ({ \
+ enum { Size = sizeof(str) }; \
+ static const QConstByteArrayData<Size> qbytearray_literal = \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
+ QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
+ holder; })
+#endif
+
+#ifndef QByteArrayLiteral
+// no lambdas, not GCC, use const char * instead
+
+# define QByteArrayLiteral(str) (str)
+#endif
+
+
class Q_CORE_EXPORT QByteArray
{
private:
- struct Data {
- QBasicAtomicInt ref;
- int alloc, size;
- // ### Qt 5.0: We need to add the missing capacity bit
- // (like other tool classes have), to maintain the
- // reserved memory on resize.
- char *data;
- char array[1];
- };
+ typedef QByteArrayData Data;
public:
inline QByteArray();
int length() const { return d->size; }
bool isNull() const;
+ template <int n>
+ inline QByteArray(const QConstByteArrayData<n> &dd)
+ : d(const_cast<QByteArrayData *>(&dd.str)) {}
+ template <int N>
+ Q_DECL_CONSTEXPR inline QByteArray(QConstByteArrayDataPtr<N> dd)
+ : d(const_cast<QByteArrayData *>(&dd.ptr->ba)) {}
+
private:
operator QNoImplicitBoolCast() const;
- static Data shared_null;
- static Data shared_empty;
+ static QConstByteArrayData<1> shared_null;
+ static QConstByteArrayData<1> shared_empty;
Data *d;
QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
void realloc(int alloc);
inline DataPtr &data_ptr() { return d; }
};
-inline QByteArray::QByteArray(): d(&shared_null) { d->ref.ref(); }
+inline QByteArray::QByteArray(): d(const_cast<Data *>(&shared_null.ba)) { d->ref.ref(); }
inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); }
inline int QByteArray::size() const
{ return d->size; }
inline char QByteArray::at(int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+{ Q_ASSERT(i >= 0 && i < size()); return d->data()[i]; }
inline char QByteArray::operator[](int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+{ Q_ASSERT(i >= 0 && i < size()); return d->data()[i]; }
inline char QByteArray::operator[](uint i) const
-{ Q_ASSERT(i < uint(size())); return d->data[i]; }
+{ Q_ASSERT(i < uint(size())); return d->data()[i]; }
inline bool QByteArray::isEmpty() const
{ return d->size == 0; }
#ifndef QT_NO_CAST_FROM_BYTEARRAY
inline QByteArray::operator const char *() const
-{ return d->data; }
+{ return d->data(); }
inline QByteArray::operator const void *() const
-{ return d->data; }
+{ return d->data(); }
#endif
inline char *QByteArray::data()
-{ detach(); return d->data; }
+{ detach(); return d->data(); }
inline const char *QByteArray::data() const
-{ return d->data; }
+{ return d->data(); }
inline const char *QByteArray::constData() const
-{ return d->data; }
+{ return d->data(); }
inline void QByteArray::detach()
-{ if (d->ref != 1 || d->data != d->array) realloc(d->size); }
+{ if (d->ref != 1 || d->offset) realloc(d->size); }
inline bool QByteArray::isDetached() const
{ return d->ref == 1; }
inline QByteArray::QByteArray(const QByteArray &a) : d(a.d)
{ return d->alloc; }
inline void QByteArray::reserve(int asize)
-{ if (d->ref != 1 || asize > d->alloc) realloc(asize); }
+{ if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true; }
inline void QByteArray::squeeze()
-{ if (d->size < d->alloc) realloc(d->size); }
+{ if (d->size < d->alloc) realloc(d->size); d->capacityReserved = false; }
class Q_CORE_EXPORT QByteRef {
QByteArray &a;
friend class QByteArray;
public:
inline operator char() const
- { return i < a.d->size ? a.d->data[i] : char(0); }
+ { return i < a.d->size ? a.d->data()[i] : char(0); }
inline QByteRef &operator=(char c)
{ if (i >= a.d->size) a.expand(i); else a.detach();
- a.d->data[i] = c; return *this; }
+ a.d->data()[i] = c; return *this; }
inline QByteRef &operator=(const QByteRef &c)
{ if (i >= a.d->size) a.expand(i); else a.detach();
- a.d->data[i] = c.a.d->data[c.i]; return *this; }
+ a.d->data()[i] = c.a.d->data()[c.i]; return *this; }
inline bool operator==(char c) const
- { return a.d->data[i] == c; }
+ { return a.d->data()[i] == c; }
inline bool operator!=(char c) const
- { return a.d->data[i] != c; }
+ { return a.d->data()[i] != c; }
inline bool operator>(char c) const
- { return a.d->data[i] > c; }
+ { return a.d->data()[i] > c; }
inline bool operator>=(char c) const
- { return a.d->data[i] >= c; }
+ { return a.d->data()[i] >= c; }
inline bool operator<(char c) const
- { return a.d->data[i] < c; }
+ { return a.d->data()[i] < c; }
inline bool operator<=(char c) const
- { return a.d->data[i] <= c; }
+ { return a.d->data()[i] <= c; }
};
inline QByteRef QByteArray::operator[](int i)
inline QByteRef QByteArray::operator[](uint i)
{ return QByteRef(*this, i); }
inline QByteArray::iterator QByteArray::begin()
-{ detach(); return d->data; }
+{ detach(); return d->data(); }
inline QByteArray::const_iterator QByteArray::begin() const
-{ return d->data; }
+{ return d->data(); }
inline QByteArray::const_iterator QByteArray::constBegin() const
-{ return d->data; }
+{ return d->data(); }
inline QByteArray::iterator QByteArray::end()
-{ detach(); return d->data + d->size; }
+{ detach(); return d->data() + d->size; }
inline QByteArray::const_iterator QByteArray::end() const
-{ return d->data + d->size; }
+{ return d->data() + d->size; }
inline QByteArray::const_iterator QByteArray::constEnd() const
-{ return d->data + d->size; }
+{ return d->data() + d->size; }
inline QByteArray &QByteArray::operator+=(char c)
{ return append(c); }
inline QByteArray &QByteArray::operator+=(const char *s)