diff options
Diffstat (limited to 'src/corelib/tools/qstring.h')
| -rw-r--r-- | src/corelib/tools/qstring.h | 130 |
1 files changed, 88 insertions, 42 deletions
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 154012d132c..81dff3d309e 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -44,7 +44,7 @@ #include <QtCore/qchar.h> #include <QtCore/qbytearray.h> -#include <QtCore/qatomic.h> +#include <QtCore/qrefcount.h> #include <QtCore/qnamespace.h> #ifndef QT_NO_STL @@ -77,9 +77,65 @@ class QLatin1String; class QStringRef; template <typename T> class QVector; +struct QStringData { + 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 + ushort d[sizeof(qptrdiff)/sizeof(ushort)]; + }; + inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } + inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } +}; + + +#if defined(Q_COMPILER_UNICODE_STRINGS) + +template<int n> struct QConstStringData +{ + const QStringData str; + const char16_t data[n]; + operator const QStringData &() const { return str; } +}; +#define QStringLiteral(str) (const QConstStringData<sizeof(u"" str)/2>) \ +{ { Q_REFCOUNT_INITIALIZER(-1), sizeof(u"" str)/2 -1, 0, 0, { 0 } }, u"" str } + +// wchar_t is 2 bytes +#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) + +template<int n> struct QConstStringData +{ + const QStringData str; + const wchar_t data[n]; + operator const QStringData &() const { return str; } +}; +#define QStringLiteral(str) (const QConstStringData<sizeof(L"" str)/2>) \ +{ { Q_REFCOUNT_INITIALIZER(-1), sizeof(L"" str)/2 -1, 0, 0, { 0 } }, L"" str } + +// fallback, uses QLatin1String as next best options +#else + +template<int n> struct QConstStringData +{ + const QStringData str; + const ushort data[n]; + operator const QStringData &() const { return str; } +}; +#define QStringLiteral(str) QLatin1String(str) + +#endif + +#ifndef QT_NO_KEYWORDS +#define qs(str) QStringLiteral(str) +#endif + class Q_CORE_EXPORT QString { public: + typedef QStringData Data; + inline QString(); QString(const QChar *unicode, int size); // Qt5: don't cap size < 0 explicit QString(const QChar *unicode); // Qt5: merge with the above @@ -108,7 +164,7 @@ public: int capacity() const; inline void reserve(int size); - inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacity = 0;} + inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacityReserved = false;} inline const QChar *unicode() const; inline QChar *data(); @@ -262,8 +318,8 @@ public: inline QString &operator+=(QChar c) { if (d->ref != 1 || d->size + 1 > d->alloc) realloc(grow(d->size + 1)); - d->data[d->size++] = c.unicode(); - d->data[d->size] = '\0'; + d->data()[d->size++] = c.unicode(); + d->data()[d->size] = '\0'; return *this; } @@ -491,15 +547,17 @@ public: // compatibility struct Null { }; static const Null null; - inline QString(const Null &): d(&shared_null) { d->ref.ref(); } + inline QString(const Null &): d(const_cast<Data *>(&shared_null.str)) {} inline QString &operator=(const Null &) { *this = QString(); return *this; } - inline bool isNull() const { return d == &shared_null; } + inline bool isNull() const { return d == &shared_null.str; } - bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; } + bool isSimpleText() const; bool isRightToLeft() const; QString(int size, Qt::Initialization); + template <int n> + inline QString(const QConstStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {} private: #if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED) @@ -511,22 +569,11 @@ private: QString &operator=(const QByteArray &a); #endif - struct Data { - QBasicAtomicInt ref; - int alloc, size; - ushort *data; // QT5: put that after the bit field to fill alignment gap; don't use sizeof any more then - ushort clean : 1; - ushort simpletext : 1; - ushort righttoleft : 1; - ushort capacity : 1; - ushort reserved : 11; - // ### Qt5: try to ensure that "array" is aligned to 16 bytes on both 32- and 64-bit - ushort array[1]; - }; - static Data shared_null; - static Data shared_empty; + static const QConstStringData<1> shared_null; + static const QConstStringData<1> shared_empty; Data *d; - QString(Data *dd, int /*dummy*/) : d(dd) {} + inline QString(Data *dd, int /*dummy*/) : d(dd) {} + #ifndef QT_NO_TEXTCODEC static QTextCodec *codecForCStrings; #endif @@ -605,23 +652,23 @@ inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLat inline int QString::length() const { return d->size; } inline const QChar QString::at(int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } inline const QChar QString::operator[](int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } inline const QChar QString::operator[](uint i) const -{ Q_ASSERT(i < uint(size())); return d->data[i]; } +{ Q_ASSERT(i < uint(size())); return d->data()[i]; } inline bool QString::isEmpty() const { return d->size == 0; } inline const QChar *QString::unicode() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline const QChar *QString::data() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline QChar *QString::data() -{ detach(); return reinterpret_cast<QChar*>(d->data); } +{ detach(); return reinterpret_cast<QChar*>(d->data()); } inline const QChar *QString::constData() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline void QString::detach() -{ if (d->ref != 1 || d->data != d->array) realloc(); } +{ if (d->ref != 1 || d->offset) realloc(); } inline bool QString::isDetached() const { return d->ref == 1; } inline QString &QString::operator=(const QLatin1String &s) @@ -703,10 +750,10 @@ public: // all this is not documented: We just say "like QChar" and let it be. inline operator QChar() const - { return i < s.d->size ? s.d->data[i] : 0; } + { return i < s.d->size ? s.d->data()[i] : 0; } inline QCharRef &operator=(const QChar &c) { if (i >= s.d->size) s.expand(i); else s.detach(); - s.d->data[i] = c.unicode(); return *this; } + s.d->data()[i] = c.unicode(); return *this; } // An operator= for each QChar cast constructors #ifndef QT_NO_CAST_FROM_ASCII @@ -773,9 +820,9 @@ inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); } inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); } -inline QString::QString() : d(&shared_null) { d->ref.ref(); } +inline QString::QString() : d(const_cast<Data *>(&shared_null.str)) {} inline QString::~QString() { if (!d->ref.deref()) free(d); } -inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacity = 1;} +inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true;} inline QString &QString::setUtf16(const ushort *autf16, int asize) { return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); } inline QCharRef QString::operator[](int i) @@ -783,17 +830,17 @@ inline QCharRef QString::operator[](int i) inline QCharRef QString::operator[](uint i) { return QCharRef(*this, i); } inline QString::iterator QString::begin() -{ detach(); return reinterpret_cast<QChar*>(d->data); } +{ detach(); return reinterpret_cast<QChar*>(d->data()); } inline QString::const_iterator QString::begin() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline QString::const_iterator QString::constBegin() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline QString::iterator QString::end() -{ detach(); return reinterpret_cast<QChar*>(d->data + d->size); } +{ detach(); return reinterpret_cast<QChar*>(d->data() + d->size); } inline QString::const_iterator QString::end() const -{ return reinterpret_cast<const QChar*>(d->data + d->size); } +{ return reinterpret_cast<const QChar*>(d->data() + d->size); } inline QString::const_iterator QString::constEnd() const -{ return reinterpret_cast<const QChar*>(d->data + d->size); } +{ return reinterpret_cast<const QChar*>(d->data() + d->size); } inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return QBool(indexOf(s, 0, cs) != -1); } inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const @@ -1024,7 +1071,7 @@ public: inline const QChar *unicode() const { if (!m_string) - return reinterpret_cast<const QChar *>(QString::shared_null.data); + return reinterpret_cast<const QChar *>(QString::shared_null.str.data()); return m_string->unicode() + m_position; } inline const QChar *data() const { return unicode(); } @@ -1154,7 +1201,6 @@ inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) c { return QBool(indexOf(s, 0, cs) != -1); } - QT_END_NAMESPACE QT_END_HEADER |
