summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/serialization')
-rw-r--r--src/corelib/serialization/qbinaryjson_p.h8
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue.cpp18
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue_p.h4
-rw-r--r--src/corelib/serialization/qcborarray.cpp2
-rw-r--r--src/corelib/serialization/qcborarray.h2
-rw-r--r--src/corelib/serialization/qcborcommon.h4
-rw-r--r--src/corelib/serialization/qcbordiagnostic.cpp15
-rw-r--r--src/corelib/serialization/qcbormap.cpp2
-rw-r--r--src/corelib/serialization/qcbormap.h2
-rw-r--r--src/corelib/serialization/qcborstreamreader.cpp4
-rw-r--r--src/corelib/serialization/qcborstreamwriter.cpp4
-rw-r--r--src/corelib/serialization/qcborvalue.cpp11
-rw-r--r--src/corelib/serialization/qcborvalue.h6
-rw-r--r--src/corelib/serialization/qcborvalue_p.h19
-rw-r--r--src/corelib/serialization/qdatastream.cpp51
-rw-r--r--src/corelib/serialization/qdatastream.h91
-rw-r--r--src/corelib/serialization/qjsonarray.cpp2
-rw-r--r--src/corelib/serialization/qjsonarray.h3
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp24
-rw-r--r--src/corelib/serialization/qjsondocument.h4
-rw-r--r--src/corelib/serialization/qjsonobject.cpp2
-rw-r--r--src/corelib/serialization/qjsonobject.h2
-rw-r--r--src/corelib/serialization/qjsonparser.cpp21
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp96
-rw-r--r--src/corelib/serialization/qjsonvalue.h3
-rw-r--r--src/corelib/serialization/qjsonwriter.cpp16
-rw-r--r--src/corelib/serialization/qtextstream.cpp240
-rw-r--r--src/corelib/serialization/qtextstream.h12
-rw-r--r--src/corelib/serialization/qtextstream_p.h18
-rw-r--r--src/corelib/serialization/qxmlstream.cpp398
-rw-r--r--src/corelib/serialization/qxmlstream.g65
-rw-r--r--src/corelib/serialization/qxmlstream.h6
-rw-r--r--src/corelib/serialization/qxmlstream_p.h61
33 files changed, 520 insertions, 696 deletions
diff --git a/src/corelib/serialization/qbinaryjson_p.h b/src/corelib/serialization/qbinaryjson_p.h
index 132c36f227..3eca794a58 100644
--- a/src/corelib/serialization/qbinaryjson_p.h
+++ b/src/corelib/serialization/qbinaryjson_p.h
@@ -64,8 +64,7 @@ QT_REQUIRE_CONFIG(binaryjson);
QT_BEGIN_NAMESPACE
// in qstring.cpp
-void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len);
-void qt_from_latin1(ushort *dst, const char *str, size_t size) noexcept;
+void qt_to_latin1_unchecked(uchar *dst, const char16_t *uc, qsizetype len);
/*
This defines a binary data structure for Json data. The data structure is optimised for fast reading
@@ -282,10 +281,9 @@ public:
static void copy(char *dest, QStringView src)
{
Data *data = reinterpret_cast<Data *>(dest);
- data->length = src.length();
+ data->length = src.length(); // ### narrows from int to ushort
auto *l = reinterpret_cast<uchar *>(data->latin1);
- const auto *uc = reinterpret_cast<const ushort *>(src.utf16());
- qt_to_latin1_unchecked(l, uc, data->length);
+ qt_to_latin1_unchecked(l, src.utf16(), data->length);
for (uint len = data->length; quintptr(l + len) & 0x3; ++len)
l[len] = 0;
diff --git a/src/corelib/serialization/qbinaryjsonvalue.cpp b/src/corelib/serialization/qbinaryjsonvalue.cpp
index 5e3a01ad38..7d0bc3d366 100644
--- a/src/corelib/serialization/qbinaryjsonvalue.cpp
+++ b/src/corelib/serialization/qbinaryjsonvalue.cpp
@@ -63,12 +63,9 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
case QJsonValue::Double:
dbl = v.toDouble(parent);
break;
- case QJsonValue::String: {
- QString s = v.toString(parent);
- stringData = s.data_ptr();
- stringData->ref.ref();
+ case QJsonValue::String:
+ stringData = v.toString(parent);
break;
- }
case QJsonValue::Array:
case QJsonValue::Object:
d = data;
@@ -80,9 +77,9 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
}
QBinaryJsonValue::QBinaryJsonValue(QString string)
- : stringData(*reinterpret_cast<QStringData **>(&string)), t(QJsonValue::String)
+ : d(nullptr), t(QJsonValue::String)
{
- stringData->ref.ref();
+ stringData = std::move(string);
}
QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonArray &a)
@@ -101,9 +98,6 @@ QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonObject &o)
QBinaryJsonValue::~QBinaryJsonValue()
{
- if (t == QJsonValue::String && stringData && !stringData->ref.deref())
- free(stringData);
-
if (d && !d->ref.deref())
delete d;
}
@@ -134,9 +128,7 @@ QString QBinaryJsonValue::toString() const
{
if (t != QJsonValue::String)
return QString();
- stringData->ref.ref(); // the constructor below doesn't add a ref.
- QStringDataPtr holder = { stringData };
- return QString(holder);
+ return stringData;
}
void QBinaryJsonValue::detach()
diff --git a/src/corelib/serialization/qbinaryjsonvalue_p.h b/src/corelib/serialization/qbinaryjsonvalue_p.h
index 498fc62ecd..c3b943250c 100644
--- a/src/corelib/serialization/qbinaryjsonvalue_p.h
+++ b/src/corelib/serialization/qbinaryjsonvalue_p.h
@@ -86,6 +86,7 @@ public:
QBinaryJsonValue(QBinaryJsonValue &&other) noexcept
: ui(other.ui),
+ stringData(std::move(other.stringData)),
d(other.d),
t(other.t)
{
@@ -96,6 +97,7 @@ public:
QBinaryJsonValue &operator =(QBinaryJsonValue &&other) noexcept
{
+ qSwap(stringData, other.stringData);
qSwap(ui, other.ui);
qSwap(d, other.d);
qSwap(t, other.t);
@@ -122,9 +124,9 @@ private:
quint64 ui;
bool b;
double dbl;
- QStringData *stringData;
const QBinaryJsonPrivate::Base *base;
};
+ QString stringData;
QBinaryJsonPrivate::MutableData *d = nullptr; // needed for Objects and Arrays
QJsonValue::Type t = QJsonValue::Null;
};
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
index ca0156e07d..3bb99176af 100644
--- a/src/corelib/serialization/qcborarray.cpp
+++ b/src/corelib/serialization/qcborarray.cpp
@@ -1200,7 +1200,7 @@ void QCborArray::detach(qsizetype reserved)
Returns the offset of this iterator relative to \a other.
*/
-uint qHash(const QCborArray &array, uint seed)
+size_t qHash(const QCborArray &array, size_t seed)
{
return qHashRange(array.begin(), array.end(), seed);
}
diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h
index fe06b8630f..0438b920ab 100644
--- a/src/corelib/serialization/qcborarray.h
+++ b/src/corelib/serialization/qcborarray.h
@@ -294,7 +294,7 @@ inline QCborArray QCborValueRef::toArray(const QCborArray &a) const
return concrete().toArray(a);
}
-Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0);
+Q_CORE_EXPORT size_t qHash(const QCborArray &array, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a);
diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h
index bec46399ce..1497da3d2e 100644
--- a/src/corelib/serialization/qcborcommon.h
+++ b/src/corelib/serialization/qcborcommon.h
@@ -138,12 +138,12 @@ QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
#endif
-inline uint qHash(QCborSimpleType tag, uint seed = 0)
+inline size_t qHash(QCborSimpleType tag, size_t seed = 0)
{
return qHash(quint8(tag), seed);
}
-inline uint qHash(QCborTag tag, uint seed = 0)
+inline size_t qHash(QCborTag tag, size_t seed = 0)
{
return qHash(quint64(tag), seed);
}
diff --git a/src/corelib/serialization/qcbordiagnostic.cpp b/src/corelib/serialization/qcbordiagnostic.cpp
index 75feaded17..2e92dab0a4 100644
--- a/src/corelib/serialization/qcbordiagnostic.cpp
+++ b/src/corelib/serialization/qcbordiagnostic.cpp
@@ -112,7 +112,7 @@ static QString makeFpString(double d)
s.prepend(QLatin1Char('-'));
} else {
s = QString::number(d, 'g', QLocale::FloatingPointShortest);
- if (!s.contains(QLatin1Char('.')) && !s.contains('e'))
+ if (!s.contains(u'.') && !s.contains(u'e'))
s += QLatin1Char('.');
}
return s;
@@ -171,14 +171,17 @@ void DiagnosticNotation::appendString(const QString &s)
buf[1] = QChar(uc);
if (buf[1] == QChar::Null) {
- using QtMiscUtils::toHexUpper;
+ const auto toHexUpper = [](char32_t value) -> QChar {
+ // QtMiscUtils::toHexUpper() returns char, we need QChar, so wrap
+ return char16_t(QtMiscUtils::toHexUpper(value));
+ };
if (ptr->isHighSurrogate() && (ptr + 1) != end && ptr[1].isLowSurrogate()) {
// properly-paired surrogates
++ptr;
char32_t ucs4 = QChar::surrogateToUcs4(uc, ptr->unicode());
- buf[1] = 'U';
- buf[2] = '0'; // toHexUpper(ucs4 >> 28);
- buf[3] = '0'; // toHexUpper(ucs4 >> 24);
+ buf[1] = u'U';
+ buf[2] = u'0'; // toHexUpper(ucs4 >> 28);
+ buf[3] = u'0'; // toHexUpper(ucs4 >> 24);
buf[4] = toHexUpper(ucs4 >> 20);
buf[5] = toHexUpper(ucs4 >> 16);
buf[6] = toHexUpper(ucs4 >> 12);
@@ -187,7 +190,7 @@ void DiagnosticNotation::appendString(const QString &s)
buf[9] = toHexUpper(ucs4);
buflen = 10;
} else {
- buf[1] = 'u';
+ buf[1] = u'u';
buf[2] = toHexUpper(uc >> 12);
buf[3] = toHexUpper(uc >> 8);
buf[4] = toHexUpper(uc >> 4);
diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp
index 4b28ca4a2e..9a8a2c4417 100644
--- a/src/corelib/serialization/qcbormap.cpp
+++ b/src/corelib/serialization/qcbormap.cpp
@@ -1744,7 +1744,7 @@ void QCborMap::detach(qsizetype reserved)
\sa operator+=(), operator-()
*/
-uint qHash(const QCborMap &map, uint seed)
+size_t qHash(const QCborMap &map, size_t seed)
{
return qHashRange(map.begin(), map.end(), seed);
}
diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h
index 6636ce776a..0609c0a39e 100644
--- a/src/corelib/serialization/qcbormap.h
+++ b/src/corelib/serialization/qcbormap.h
@@ -350,7 +350,7 @@ inline QCborMap QCborValueRef::toMap(const QCborMap &m) const
return concrete().toMap(m);
}
-Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0);
+Q_CORE_EXPORT size_t qHash(const QCborMap &map, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m);
diff --git a/src/corelib/serialization/qcborstreamreader.cpp b/src/corelib/serialization/qcborstreamreader.cpp
index ec385e0629..5eb2086447 100644
--- a/src/corelib/serialization/qcborstreamreader.cpp
+++ b/src/corelib/serialization/qcborstreamreader.cpp
@@ -44,7 +44,7 @@
#include <private/qbytearray_p.h>
#include <private/qnumeric_p.h>
-#include <private/qutfcodec_p.h>
+#include <private/qstringconverter_p.h>
#include <qdebug.h>
#include <qstack.h>
@@ -1348,7 +1348,7 @@ QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
if (r.data.size() > MaxStringSize) {
err = CborErrorDataTooLarge;
} else {
- QTextCodec::ConverterState cs;
+ QStringConverter::State cs(QStringConverter::Flag::Stateless);
result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
if (cs.invalidChars != 0 || cs.remainingChars != 0)
err = CborErrorInvalidUtf8TextString;
diff --git a/src/corelib/serialization/qcborstreamwriter.cpp b/src/corelib/serialization/qcborstreamwriter.cpp
index 9d78785416..c73c17aed1 100644
--- a/src/corelib/serialization/qcborstreamwriter.cpp
+++ b/src/corelib/serialization/qcborstreamwriter.cpp
@@ -729,7 +729,7 @@ void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
length is implied by the elements contained in it. Note, however, that use
of indeterminate-length arrays is not compliant with canonical CBOR encoding.
- The following example appends elements from the linked list of strings
+ The following example appends elements from the vector of strings
passed as input:
\snippet code/src_corelib_serialization_qcborstream.cpp 20
@@ -802,7 +802,7 @@ bool QCborStreamWriter::endArray()
indeterminate-length maps is not compliant with canonical CBOR encoding
(canonical encoding also requires keys to be unique and in sorted order).
- The following example appends elements from the linked list of int and
+ The following example appends elements from the vector of int and
string pairs passed as input:
\snippet code/src_corelib_serialization_qcborstream.cpp 22
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 89a928d348..0b95bf5b8e 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -1026,7 +1026,7 @@ void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &valu
}
// in qstring.cpp
-void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len);
+void qt_to_latin1_unchecked(uchar *dst, const char16_t *uc, qsizetype len);
Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(QStringView s)
{
@@ -1039,8 +1039,7 @@ Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(QStringView s)
char *ptr = data.data() + e.value + sizeof(ByteData);
uchar *l = reinterpret_cast<uchar *>(ptr);
- const ushort *uc = (const ushort *)s.utf16();
- qt_to_latin1_unchecked(l, uc, len);
+ qt_to_latin1_unchecked(l, s.utf16(), len);
}
QCborValue QCborContainerPrivate::extractAt_complex(Element e)
@@ -2559,7 +2558,7 @@ QCborValue QCborValue::fromCbor(const QByteArray &ba, QCborParserError *error)
\sa fromCbor(), fromVariant(), fromJsonValue()
*/
-QByteArray QCborValue::toCbor(EncodingOptions opt)
+QByteArray QCborValue::toCbor(EncodingOptions opt) const
{
QByteArray result;
QCborStreamWriter writer(&result);
@@ -2596,7 +2595,7 @@ QByteArray QCborValue::toCbor(EncodingOptions opt)
\sa fromCbor(), fromVariant(), fromJsonValue()
*/
-Q_NEVER_INLINE void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt)
+Q_NEVER_INLINE void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt) const
{
if (isContainer() || isTag())
return encodeToCbor(writer, container, -type(), opt);
@@ -2942,7 +2941,7 @@ inline QCborMap::QCborMap(QCborContainerPrivate &dd) noexcept
{
}
-uint qHash(const QCborValue &value, uint seed)
+size_t qHash(const QCborValue &value, size_t seed)
{
switch (value.type()) {
case QCborValue::Integer:
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
index aa51e5da81..3fd03301a1 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -297,8 +297,8 @@ public:
{ return fromCbor(QByteArray(reinterpret_cast<const char *>(data), int(len)), error); }
#endif // QT_CONFIG(cborstreamreader)
#if QT_CONFIG(cborstreamwriter)
- QByteArray toCbor(EncodingOptions opt = NoTransformation);
- void toCbor(QCborStreamWriter &writer, EncodingOptions opt = NoTransformation);
+ QByteArray toCbor(EncodingOptions opt = NoTransformation) const;
+ void toCbor(QCborStreamWriter &writer, EncodingOptions opt = NoTransformation) const;
#endif
QString toDiagnosticNotation(DiagnosticNotationOptions opts = Compact) const;
@@ -480,7 +480,7 @@ private:
qsizetype i;
};
-Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0);
+Q_CORE_EXPORT size_t qHash(const QCborValue &value, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v);
diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h
index 041a20e746..38383c7522 100644
--- a/src/corelib/serialization/qcborvalue_p.h
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -54,7 +54,7 @@
#include "qcborvalue.h"
#include <private/qglobal_p.h>
-#include <private/qutfcodec_p.h>
+#include <private/qstringconverter_p.h>
#include <math.h>
@@ -148,8 +148,8 @@ public:
qptrdiff offset = data.size();
// align offset
- offset += Q_ALIGNOF(QtCbor::ByteData) - 1;
- offset &= ~(Q_ALIGNOF(QtCbor::ByteData) - 1);
+ offset += alignof(QtCbor::ByteData) - 1;
+ offset &= ~(alignof(QtCbor::ByteData) - 1);
qptrdiff increment = qptrdiff(sizeof(QtCbor::ByteData)) + len;
@@ -171,7 +171,7 @@ public:
return nullptr;
size_t offset = size_t(e.value);
- Q_ASSERT((offset % Q_ALIGNOF(QtCbor::ByteData)) == 0);
+ Q_ASSERT((offset % alignof(QtCbor::ByteData)) == 0);
Q_ASSERT(offset + sizeof(QtCbor::ByteData) <= size_t(data.size()));
auto b = reinterpret_cast<const QtCbor::ByteData *>(data.constData() + offset);
@@ -215,7 +215,7 @@ public:
}
void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
{
- replaceAt_internal(*elements.insert(elements.begin() + idx, {}), value, disp);
+ replaceAt_internal(*elements.insert(elements.begin() + int(idx), {}), value, disp);
}
void append(QtCbor::Undefined)
@@ -236,6 +236,15 @@ public:
elements.append(QtCbor::Element(addByteData(data, len), type,
QtCbor::Element::HasByteData | extraFlags));
}
+ void appendAsciiString(const QString &s);
+ void appendAsciiString(const char *str, qsizetype len)
+ {
+ appendByteData(str, len, QCborValue::String, QtCbor::Element::StringIsAscii);
+ }
+ void appendUtf8String(const char *str, qsizetype len)
+ {
+ appendByteData(str, len, QCborValue::String);
+ }
void append(QLatin1String s)
{
if (!QtPrivate::isAscii(s))
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 5082a8cb0d..3026e554bf 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -163,7 +163,7 @@ QT_BEGIN_NAMESPACE
\section1 Reading and Writing Qt Collection Classes
The Qt container classes can also be serialized to a QDataStream.
- These include QList, QLinkedList, QVector, QSet, QHash, and QMap.
+ These include QList, QVector, QSet, QHash, and QMap.
The stream operators are declared as non-members of the classes.
\target Serializing Qt Classes
@@ -1025,6 +1025,31 @@ QDataStream &QDataStream::operator>>(char *&s)
return readBytes(s, len);
}
+/*!
+ \overload
+
+ Reads a char from the stream into char \a chr.
+*/
+QDataStream &QDataStream::operator>>(char16_t &c)
+{
+ quint16 u;
+ *this >> u;
+ c = char16_t(u);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Reads a char from the stream into char \a chr.
+*/
+QDataStream &QDataStream::operator>>(char32_t &c)
+{
+ quint32 u;
+ *this >> u;
+ c = char32_t(u);
+ return *this;
+}
/*!
Reads the buffer \a s from the stream and returns a reference to
@@ -1338,6 +1363,30 @@ QDataStream &QDataStream::operator<<(const char *s)
}
/*!
+ \overload
+ \since 6.0
+
+ Writes a character, \a c, to the stream. Returns a reference to
+ the stream
+*/
+QDataStream &QDataStream::operator<<(char16_t c)
+{
+ return *this << qint16(c);
+}
+
+/*!
+ \overload
+ \since 6.0
+
+ Writes a character, \a c, to the stream. Returns a reference to
+ the stream
+*/
+QDataStream &QDataStream::operator<<(char32_t c)
+{
+ return *this << qint32(c);
+}
+
+/*!
Writes the length specifier \a len and the buffer \a s to the
stream and returns a reference to the stream.
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index bc05841b52..4568ba3a84 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -43,6 +43,7 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qpair.h>
+#include <QtCore/qcontainerfwd.h>
#ifdef Status
#error qdatastream.h must be included before any header file that defines Status
@@ -54,12 +55,6 @@ class qfloat16;
class QByteArray;
class QIODevice;
-template <typename T> class QList;
-template <typename T> class QVector;
-template <typename T> class QSet;
-template <class Key, class T> class QHash;
-template <class Key, class T> class QMap;
-
#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
class QDataStreamPrivate;
namespace QtPrivate {
@@ -100,15 +95,9 @@ public:
Qt_5_12 = 18,
Qt_5_13 = 19,
Qt_5_14 = Qt_5_13,
-#if QT_VERSION >= 0x050f00
Qt_5_15 = Qt_5_14,
- Qt_DefaultCompiledVersion = Qt_5_15
-#elif QT_VERSION >= 0x060000
- Qt_6_0 = Qt_5_15,
+ Qt_6_0 = 20,
Qt_DefaultCompiledVersion = Qt_6_0
-#else
- Qt_DefaultCompiledVersion = Qt_5_14
-#endif
#if QT_VERSION >= 0x060100
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
@@ -174,6 +163,8 @@ public:
QDataStream &operator>>(float &f);
QDataStream &operator>>(double &f);
QDataStream &operator>>(char *&str);
+ QDataStream &operator>>(char16_t &c);
+ QDataStream &operator>>(char32_t &c);
QDataStream &operator<<(qint8 i);
QDataStream &operator<<(quint8 i);
@@ -189,6 +180,9 @@ public:
QDataStream &operator<<(float f);
QDataStream &operator<<(double f);
QDataStream &operator<<(const char *str);
+ QDataStream &operator<<(char16_t c);
+ QDataStream &operator<<(char32_t c);
+
QDataStream &readBytes(char *&, uint &len);
int readRawData(char *, int len);
@@ -285,13 +279,6 @@ QDataStream &readListBasedContainer(QDataStream &s, Container &c)
return s;
}
-template <typename T>
-struct MultiContainer { using type = T; };
-template <typename K, typename V>
-struct MultiContainer<QMap<K, V>> { using type = QMultiMap<K, V>; };
-template <typename K, typename V>
-struct MultiContainer<QHash<K, V>> { using type = QMultiHash<K, V>; };
-
template <typename Container>
QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
{
@@ -308,7 +295,7 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
c.clear();
break;
}
- static_cast<typename MultiContainer<Container>::type &>(c).insert(k, t);
+ c.insert(k, t);
}
return s;
@@ -328,20 +315,20 @@ template <typename Container>
QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
{
s << quint32(c.size());
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && QT_DEPRECATED_SINCE(5, 15)
- // Deserialization should occur in the reverse order.
- // Otherwise, value() will return the least recently inserted
- // value instead of the most recently inserted one.
- auto it = c.constEnd();
- auto begin = c.constBegin();
- while (it != begin) {
- QT_WARNING_PUSH
- QT_WARNING_DISABLE_DEPRECATED
- --it;
- QT_WARNING_POP
+ auto it = c.constBegin();
+ auto end = c.constEnd();
+ while (it != end) {
s << it.key() << it.value();
+ ++it;
}
-#else
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
+{
+ s << quint32(c.size());
auto it = c.constBegin();
auto end = c.constEnd();
while (it != end) {
@@ -354,7 +341,6 @@ QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
s << next.key() << next.value();
}
}
-#endif
return s;
}
@@ -419,18 +405,6 @@ typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator>>(QDataStream &s, T &t)
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
-template <typename T>
-inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
-{
- return QtPrivate::readArrayBasedContainer(s, l);
-}
-
-template <typename T>
-inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
-{
- return QtPrivate::writeSequentialContainer(s, l);
-}
-
template<typename T>
inline QDataStream &operator>>(QDataStream &s, QVector<T> &v)
{
@@ -462,12 +436,25 @@ inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
}
template <class Key, class T>
+
inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
{
return QtPrivate::writeAssociativeContainer(s, hash);
}
template <class Key, class T>
+inline QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
+{
+ return QtPrivate::readAssociativeContainer(s, hash);
+}
+
+template <class Key, class T>
+inline QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
+{
+ return QtPrivate::writeAssociativeMultiContainer(s, hash);
+}
+
+template <class Key, class T>
inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
{
return QtPrivate::readAssociativeContainer(s, map);
@@ -479,6 +466,18 @@ inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
return QtPrivate::writeAssociativeContainer(s, map);
}
+template <class Key, class T>
+inline QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map)
+{
+ return QtPrivate::readAssociativeContainer(s, map);
+}
+
+template <class Key, class T>
+inline QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
+{
+ return QtPrivate::writeAssociativeMultiContainer(s, map);
+}
+
#ifndef QT_NO_DATASTREAM
template <class T1, class T2>
inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p)
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index 05138ad610..98ace021fc 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -1133,7 +1133,7 @@ void QJsonArray::compact()
a->compact(a->elements.size());
}
-uint qHash(const QJsonArray &array, uint seed)
+size_t qHash(const QJsonArray &array, size_t seed)
{
return qHashRange(array.begin(), array.end(), seed);
}
diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 22aa996a3e..d39522bd2f 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
class QDebug;
class QStringList;
-template <typename T> class QList;
typedef QList<QVariant> QVariantList;
class Q_CORE_EXPORT QJsonArray
@@ -253,7 +252,7 @@ private:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonArray)
-Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0);
+Q_CORE_EXPORT size_t qHash(const QJsonArray &array, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
index ee4dd90416..000008db50 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 Intel Corporation.
+** Copyright (C) 2020 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -262,8 +262,7 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
const auto &e = d->elements.at(idx);
switch (e.type) {
case QCborValue::Integer:
- return QJsonPrivate::Value::fromTrustedCbor(e.value);
-
+ return QJsonValue(e.value);
case QCborValue::ByteArray:
case QCborValue::String:
case QCborValue::SimpleType:
@@ -370,7 +369,7 @@ QJsonValue QCborValue::toJsonValue() const
return false;
case Integer:
- return QJsonPrivate::Value::fromTrustedCbor(n);
+ return QJsonPrivate::Value::fromTrustedCbor(*this);
case True:
return true;
@@ -615,11 +614,9 @@ QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
case QJsonValue::Bool:
return v.toBool();
case QJsonValue::Double: {
- qint64 i;
- const double dbl = v.toDouble();
- if (convertDoubleTo(dbl, &i))
- return i;
- return dbl;
+ if (v.t == Integer)
+ return v.toInteger();
+ return v.toDouble();
}
case QJsonValue::String:
return v.toString();
@@ -667,9 +664,7 @@ static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
\row \li \c bool \li Bool
\row \li \c std::nullptr_t \li Null
\row \li \c short, \c ushort, \c int, \c uint, \l qint64 \li Integer
- \row \li \l quint64 \li Integer, but they are cast to \c qint64 first so
- values higher than 2\sup{63}-1 (\c INT64_MAX) will
- be wrapped to negative
+ \row \li \l quint64 \li Integer, or Double if outside the range of qint64
\row \li \c float, \c double \li Double
\row \li \l QByteArray \li ByteArray
\row \li \l QDateTime \li DateTime
@@ -713,9 +708,12 @@ QCborValue QCborValue::fromVariant(const QVariant &variant)
case QMetaType::UShort:
case QMetaType::Int:
case QMetaType::LongLong:
- case QMetaType::ULongLong:
case QMetaType::UInt:
return variant.toLongLong();
+ case QMetaType::ULongLong:
+ if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
+ return variant.toLongLong();
+ Q_FALLTHROUGH();
case QMetaType::Float:
case QMetaType::Double:
return variant.toDouble();
diff --git a/src/corelib/serialization/qjsondocument.h b/src/corelib/serialization/qjsondocument.h
index 758bbfd9dd..fd3a3ac61d 100644
--- a/src/corelib/serialization/qjsondocument.h
+++ b/src/corelib/serialization/qjsondocument.h
@@ -74,8 +74,8 @@ struct Q_CORE_EXPORT QJsonParseError
QString errorString() const;
- int offset;
- ParseError error;
+ int offset = -1;
+ ParseError error = NoError;
};
class QJsonDocumentPrivate;
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index 36429662fc..bf2bdb957d 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -1490,7 +1490,7 @@ void QJsonObject::removeAt(int index)
o->removeAt(2 * index);
}
-uint qHash(const QJsonObject &object, uint seed)
+size_t qHash(const QJsonObject &object, size_t seed)
{
QtPrivate::QHashCombine hash;
for (auto it = object.begin(), end = object.end(); it != end; ++it) {
diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index c31be0353d..dc449eecf4 100644
--- a/src/corelib/serialization/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
@@ -302,7 +302,7 @@ private:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonObject)
-Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0);
+Q_CORE_EXPORT size_t qHash(const QJsonObject &object, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index 6d0a92e094..116e7f6995 100644
--- a/src/corelib/serialization/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
@@ -44,7 +44,7 @@
#include <qdebug.h>
#include "qjsonparser_p.h"
#include "qjson_p.h"
-#include "private/qutfcodec_p.h"
+#include "private/qstringconverter_p.h"
#include "private/qcborvalue_p.h"
#include "private/qnumeric_p.h"
@@ -709,10 +709,11 @@ bool Parser::parseNumber()
// frac = decimal-point 1*DIGIT
if (json < end && *json == '.') {
- isInt = false;
++json;
- while (json < end && *json >= '0' && *json <= '9')
+ while (json < end && *json >= '0' && *json <= '9') {
+ isInt = isInt && *json == '0';
++json;
+ }
}
// exp = e [ minus / plus ] 1*DIGIT
@@ -893,9 +894,10 @@ bool Parser::parseString()
// no escape sequences, we are done
if (isUtf8) {
- container->appendByteData(start, json - start - 1, QCborValue::String,
- isAscii ? QtCbor::Element::StringIsAscii
- : QtCbor::Element::ValueFlags {});
+ if (isAscii)
+ container->appendAsciiString(start, json - start - 1);
+ else
+ container->appendUtf8String(start, json - start - 1);
END;
return true;
}
@@ -920,12 +922,7 @@ bool Parser::parseString()
return false;
}
}
- if (QChar::requiresSurrogates(ch)) {
- ucs4.append(QChar::highSurrogate(ch));
- ucs4.append(QChar::lowSurrogate(ch));
- } else {
- ucs4.append(QChar(ushort(ch)));
- }
+ ucs4.append(QChar::fromUcs4(ch));
}
++json;
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index caf81c79ef..5eb33bd2a3 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -154,7 +154,9 @@ QJsonValue::QJsonValue(bool b)
QJsonValue::QJsonValue(double v)
: d(nullptr)
{
- if (convertDoubleTo(v, &n)) {
+ // Convert to integer if the number is an integer and changing wouldn't
+ // introduce additional digit precision not present in the double.
+ if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */)) {
t = QCborValue::Integer;
} else {
memcpy(&n, &v, sizeof(n));
@@ -449,12 +451,18 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
return QJsonValue(Null);
case QMetaType::Bool:
return QJsonValue(variant.toBool());
+ case QMetaType::Short:
+ case QMetaType::UShort:
case QMetaType::Int:
- case QMetaType::Float:
- case QMetaType::Double:
+ case QMetaType::UInt:
case QMetaType::LongLong:
+ return QJsonValue(variant.toLongLong());
case QMetaType::ULongLong:
- case QMetaType::UInt:
+ if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
+ return QJsonValue(variant.toLongLong());
+ Q_FALLTHROUGH();
+ case QMetaType::Float:
+ case QMetaType::Double:
return QJsonValue(variant.toDouble());
case QMetaType::QString:
return QJsonValue(variant.toString());
@@ -504,7 +512,7 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
\value Null QMetaType::Nullptr
\value Bool QMetaType::Bool
- \value Double QMetaType::Double
+ \value Double QMetaType::Double or QMetaType::LongLong
\value String QString
\value Array QVariantList
\value Object QVariantMap
@@ -520,6 +528,7 @@ QVariant QJsonValue::toVariant() const
case QCborValue::False:
return false;
case QCborValue::Integer:
+ return toInteger();
case QCborValue::Double:
return toDouble();
case QCborValue::String:
@@ -548,7 +557,8 @@ QVariant QJsonValue::toVariant() const
\value Null A Null value
\value Bool A boolean value. Use toBool() to convert to a bool.
- \value Double A double. Use toDouble() to convert to a double.
+ \value Double A number value. Use toDouble() to convert to a double,
+ or toInteger() to convert to a qint64.
\value String A string. Use toString() to convert to a QString.
\value Array An array. Use toArray() to convert to a QJsonArray.
\value Object An object. Use toObject() to convert to a QJsonObject.
@@ -613,18 +623,43 @@ int QJsonValue::toInt(int defaultValue) const
{
switch (t) {
case QCborValue::Double: {
- const double dbl = toDouble();
int dblInt;
- convertDoubleTo<int>(dbl, &dblInt);
- return dbl == dblInt ? dblInt : defaultValue;
+ if (convertDoubleTo<int>(toDouble(), &dblInt))
+ return dblInt;
+ break;
}
case QCborValue::Integer:
- return (n <= qint64(std::numeric_limits<int>::max())
- && n >= qint64(std::numeric_limits<int>::min()))
- ? n : defaultValue;
+ if (qint64(int(n)) == n)
+ return int(n);
+ break;
default:
- return defaultValue;
+ break;
}
+ return defaultValue;
+}
+
+/*!
+ \since 6.0
+ Converts the value to an integer and returns it.
+
+ If type() is not Double or the value is not a whole number
+ representable as qint64, the \a defaultValue will be returned.
+ */
+qint64 QJsonValue::toInteger(qint64 defaultValue) const
+{
+ switch (t) {
+ case QCborValue::Integer:
+ return n;
+ case QCborValue::Double: {
+ qint64 dblInt;
+ if (convertDoubleTo<qint64>(toDouble(), &dblInt))
+ return dblInt;
+ break;
+ }
+ default:
+ break;
+ }
+ return defaultValue;
}
/*!
@@ -641,7 +676,7 @@ double QJsonValue::toDouble(double defaultValue) const
return d;
}
case QCborValue::Integer:
- return n;
+ return double(n);
default:
return defaultValue;
}
@@ -787,8 +822,13 @@ const QJsonValue QJsonValue::operator[](int i) const
*/
bool QJsonValue::operator==(const QJsonValue &other) const
{
- if (t != other.t)
+ if (t != other.t) {
+ if (isDouble() && other.isDouble()) {
+ // One value Cbor integer, one Cbor double, should interact as doubles.
+ return toDouble() == other.toDouble();
+ }
return false;
+ }
switch (t) {
case QCborValue::Undefined:
@@ -903,7 +943,7 @@ QJsonValue QJsonValueRef::toValue() const
return o->valueAt(index);
}
-uint qHash(const QJsonValue &value, uint seed)
+size_t qHash(const QJsonValue &value, size_t seed)
{
switch (value.type()) {
case QJsonValue::Null:
@@ -929,32 +969,38 @@ uint qHash(const QJsonValue &value, uint seed)
QDebug operator<<(QDebug dbg, const QJsonValue &o)
{
QDebugStateSaver saver(dbg);
- switch (o.type()) {
- case QJsonValue::Undefined:
+ switch (o.t) {
+ case QCborValue::Undefined:
dbg << "QJsonValue(undefined)";
break;
- case QJsonValue::Null:
+ case QCborValue::Null:
dbg << "QJsonValue(null)";
break;
- case QJsonValue::Bool:
+ case QCborValue::True:
+ case QCborValue::False:
dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')';
break;
- case QJsonValue::Double:
+ case QCborValue::Integer:
+ dbg.nospace() << "QJsonValue(double, " << o.toInteger() << ')';
+ break;
+ case QCborValue::Double:
dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')';
break;
- case QJsonValue::String:
+ case QCborValue::String:
dbg.nospace() << "QJsonValue(string, " << o.toString() << ')';
break;
- case QJsonValue::Array:
+ case QCborValue::Array:
dbg.nospace() << "QJsonValue(array, ";
dbg << o.toArray();
dbg << ')';
break;
- case QJsonValue::Object:
+ case QCborValue::Map:
dbg.nospace() << "QJsonValue(object, ";
dbg << o.toObject();
dbg << ')';
break;
+ default:
+ Q_UNREACHABLE();
}
return dbg;
}
diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index 5adcd64176..fa877ff7ee 100644
--- a/src/corelib/serialization/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
@@ -112,6 +112,7 @@ public:
bool toBool(bool defaultValue = false) const;
int toInt(int defaultValue = 0) const;
+ qint64 toInteger(qint64 defaultValue = 0) const;
double toDouble(double defaultValue = 0) const;
QString toString() const;
QString toString(const QString &defaultValue) const;
@@ -231,7 +232,7 @@ public:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue)
-Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0);
+Q_CORE_EXPORT size_t qHash(const QJsonValue &value, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
diff --git a/src/corelib/serialization/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp
index 627d1bbd62..8610cdff7e 100644
--- a/src/corelib/serialization/qjsonwriter.cpp
+++ b/src/corelib/serialization/qjsonwriter.cpp
@@ -42,7 +42,7 @@
#include <qlocale.h>
#include "qjsonwriter_p.h"
#include "qjson_p.h"
-#include "private/qutfcodec_p.h"
+#include "private/qstringconverter_p.h"
#include <private/qnumeric_p.h>
#include <private/qcborvalue_p.h>
@@ -60,7 +60,8 @@ static inline uchar hexdig(uint u)
static QByteArray escapedString(const QString &s)
{
- QByteArray ba(s.length(), Qt::Uninitialized);
+ // give it a minimum size to ensure the resize() below always adds enough space
+ QByteArray ba(qMax(s.length(), 16), Qt::Uninitialized);
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
const uchar *ba_end = cursor + ba.length();
@@ -138,15 +139,14 @@ static void valueToJson(const QCborValue &v, QByteArray &json, int indent, bool
json += "false";
break;
case QCborValue::Integer:
+ json += QByteArray::number(v.toInteger());
+ break;
case QCborValue::Double: {
const double d = v.toDouble();
- if (qIsFinite(d)) {
- quint64 absInt;
- json += QByteArray::number(d, convertDoubleTo(std::abs(d), &absInt) ? 'f' : 'g',
- QLocale::FloatingPointShortest);
- } else {
+ if (qIsFinite(d))
+ json += QByteArray::number(d, 'g', QLocale::FloatingPointShortest);
+ else
json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
- }
break;
}
case QCborValue::String:
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index 9325cd9163..344eff56b2 100644
--- a/src/corelib/serialization/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
@@ -62,7 +62,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
It's also common to use QTextStream to read console input and write
console output. QTextStream is locale aware, and will automatically decode
- standard input using the correct codec. Example:
+ standard input using the correct encoding. Example:
\snippet code/src_corelib_io_qtextstream.cpp 1
@@ -74,16 +74,16 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
buffer into the device and call flush() on the device.
Internally, QTextStream uses a Unicode based buffer, and
- QTextCodec is used by QTextStream to automatically support
- different character sets. By default, QTextCodec::codecForLocale()
- is used for reading and writing, but you can also set the codec by
- calling setCodec(). Automatic Unicode detection is also
+ QStringConverter is used by QTextStream to automatically support
+ different encodings. By default, UTF-8
+ is used for reading and writing, but you can also set the encoding by
+ calling setEncoding(). Automatic Unicode detection is also
supported. When this feature is enabled (the default behavior),
- QTextStream will detect the UTF-16 or the UTF-32 BOM (Byte Order Mark) and
- switch to the appropriate UTF codec when reading. QTextStream
+ QTextStream will detect the UTF-8, UTF-16 or the UTF-32 BOM (Byte Order Mark) and
+ switch to the appropriate UTF encoding when reading. QTextStream
does not write a BOM by default, but you can enable this by calling
setGenerateByteOrderMark(true). When QTextStream operates on a QString
- directly, the codec is disabled.
+ directly, the encoding is disabled.
There are three general ways to use QTextStream when reading text
files:
@@ -165,7 +165,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
parameter: qSetFieldWidth(), qSetPadChar(), and
qSetRealNumberPrecision().
- \sa QDataStream, QIODevice, QFile, QBuffer, QTcpSocket, {Text Codecs Example}
+ \sa QDataStream, QIODevice, QFile, QBuffer, QTcpSocket
*/
/*! \enum QTextStream::RealNumberNotation
@@ -233,6 +233,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
#include <locale.h>
#include "private/qlocale_p.h"
+#include "private/qstringconverter_p.h"
#include <stdlib.h>
#include <limits.h>
@@ -325,12 +326,8 @@ QT_BEGIN_NAMESPACE
\internal
*/
QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr)
- :
-#if QT_CONFIG(textcodec)
- readConverterSavedState(nullptr),
-#endif
- readConverterSavedStateOffset(0),
- locale(QLocale::c())
+ : readConverterSavedStateOffset(0),
+ locale(QLocale::c())
{
this->q_ptr = q_ptr;
reset();
@@ -347,32 +344,8 @@ QTextStreamPrivate::~QTextStreamPrivate()
#endif
delete device;
}
-#if QT_CONFIG(textcodec)
- delete readConverterSavedState;
-#endif
}
-#if QT_CONFIG(textcodec)
-static void resetCodecConverterStateHelper(QTextCodec::ConverterState *state)
-{
- state->~ConverterState();
- new (state) QTextCodec::ConverterState;
-}
-
-static void copyConverterStateHelper(QTextCodec::ConverterState *dest,
- const QTextCodec::ConverterState *src)
-{
- // ### QTextCodec::ConverterState's copy constructors and assignments are
- // private. This function copies the structure manually.
- Q_ASSERT(!src->d);
- dest->flags = src->flags;
- dest->invalidChars = src->invalidChars;
- dest->state_data[0] = src->state_data[0];
- dest->state_data[1] = src->state_data[1];
- dest->state_data[2] = src->state_data[2];
-}
-#endif
-
void QTextStreamPrivate::Params::reset()
{
realNumberPrecision = 6;
@@ -401,15 +374,12 @@ void QTextStreamPrivate::reset()
readBufferStartDevicePos = 0;
lastTokenSize = 0;
-#if QT_CONFIG(textcodec)
- codec = QTextCodec::codecForLocale();
- resetCodecConverterStateHelper(&readConverterState);
- resetCodecConverterStateHelper(&writeConverterState);
- delete readConverterSavedState;
- readConverterSavedState = nullptr;
- writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ hasWrittenData = false;
+ generateBOM = false;
+ encoding = QStringConverter::Utf8;
+ toUtf16 = QStringDecoder(encoding);
+ fromUtf16 = QStringEncoder(encoding);
autoDetectUnicode = true;
-#endif
}
/*!
@@ -461,22 +431,19 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
if (bytesRead <= 0)
return false;
-#if QT_CONFIG(textcodec)
- // codec auto detection, explicitly defaults to locale encoding if the
- // codec has been set to 0.
- if (!codec || autoDetectUnicode) {
+ if (autoDetectUnicode) {
autoDetectUnicode = false;
- codec = QTextCodec::codecForUtfText(QByteArray::fromRawData(buf, bytesRead), codec);
- if (!codec) {
- codec = QTextCodec::codecForLocale();
- writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ auto e = QStringConverter::encodingForData(buf, bytesRead);
+ // QStringConverter::Locale implies unknown, so keep the current encoding
+ if (e) {
+ encoding = *e;
+ toUtf16 = QStringDecoder(encoding);
+ fromUtf16 = QStringEncoder(encoding);
}
}
#if defined (QTEXTSTREAM_DEBUG)
- qDebug("QTextStreamPrivate::fillReadBuffer(), using %s codec",
- codec ? codec->name().constData() : "no");
-#endif
+ qDebug("QTextStreamPrivate::fillReadBuffer(), using %s encoding", QStringConverter::nameForEncoding(encoding));
#endif
#if defined (QTEXTSTREAM_DEBUG)
@@ -485,13 +452,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
#endif
int oldReadBufferSize = readBuffer.size();
-#if QT_CONFIG(textcodec)
- // convert to unicode
- readBuffer += Q_LIKELY(codec) ? codec->toUnicode(buf, bytesRead, &readConverterState)
- : QString::fromLatin1(buf, bytesRead);
-#else
- readBuffer += QString::fromLatin1(buf, bytesRead);
-#endif
+ readBuffer += toUtf16(buf, bytesRead);
// remove all '\r\n' in the string.
if (readBuffer.size() > oldReadBufferSize && textModeEnabled) {
@@ -567,23 +528,9 @@ void QTextStreamPrivate::flushWriteBuffer()
}
#endif
-#if QT_CONFIG(textcodec)
- if (!codec)
- codec = QTextCodec::codecForLocale();
-#if defined (QTEXTSTREAM_DEBUG)
- qDebug("QTextStreamPrivate::flushWriteBuffer(), using %s codec (%s generating BOM)",
- codec ? codec->name().constData() : "no",
- !codec || (writeConverterState.flags & QTextCodec::IgnoreHeader) ? "not" : "");
-#endif
-
- // convert from unicode to raw data
- // codec might be null if we're already inside global destructors (QTestCodec::codecForLocale returned null)
- QByteArray data = Q_LIKELY(codec) ? codec->fromUnicode(writeBuffer.data(), writeBuffer.size(), &writeConverterState)
- : writeBuffer.toLatin1();
-#else
- QByteArray data = writeBuffer.toLatin1();
-#endif
+ QByteArray data = fromUtf16(writeBuffer);
writeBuffer.clear();
+ hasWrittenData = true;
// write raw data to the device
qint64 bytesWritten = device->write(data);
@@ -786,18 +733,8 @@ inline void QTextStreamPrivate::consume(int size)
*/
inline void QTextStreamPrivate::saveConverterState(qint64 newPos)
{
-#if QT_CONFIG(textcodec)
- if (readConverterState.d) {
- // converter cannot be copied, so don't save anything
- // don't update readBufferStartDevicePos either
- return;
- }
-
- if (!readConverterSavedState)
- readConverterSavedState = new QTextCodec::ConverterState;
- copyConverterStateHelper(readConverterSavedState, &readConverterState);
-#endif
-
+ // ### Hack, FIXME
+ memcpy((void *)&savedToUtf16, (void *)&toUtf16, sizeof(QStringDecoder));
readBufferStartDevicePos = newPos;
readConverterSavedStateOffset = 0;
}
@@ -807,17 +744,11 @@ inline void QTextStreamPrivate::saveConverterState(qint64 newPos)
*/
inline void QTextStreamPrivate::restoreToSavedConverterState()
{
-#if QT_CONFIG(textcodec)
- if (readConverterSavedState) {
- // we have a saved state
- // that means the converter can be copied
- copyConverterStateHelper(&readConverterState, readConverterSavedState);
- } else {
- // the only state we could save was the initial
- // so reset to that
- resetCodecConverterStateHelper(&readConverterState);
- }
-#endif
+ if (savedToUtf16.isValid())
+ memcpy((void *)&toUtf16, (void *)&savedToUtf16, sizeof(QStringDecoder));
+ else
+ toUtf16.resetState();
+ savedToUtf16 = QStringDecoder();
}
/*!
@@ -1202,14 +1133,8 @@ bool QTextStream::seek(qint64 pos)
return false;
d->resetReadBuffer();
-#if QT_CONFIG(textcodec)
- // Reset the codec converter states.
- resetCodecConverterStateHelper(&d->readConverterState);
- resetCodecConverterStateHelper(&d->writeConverterState);
- delete d->readConverterSavedState;
- d->readConverterSavedState = nullptr;
- d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
-#endif
+ d->toUtf16.resetState();
+ d->fromUtf16.resetState();
return true;
}
@@ -1253,11 +1178,9 @@ qint64 QTextStream::pos() const
QTextStreamPrivate *thatd = const_cast<QTextStreamPrivate *>(d);
thatd->readBuffer.clear();
-#if QT_CONFIG(textcodec)
thatd->restoreToSavedConverterState();
if (d->readBufferStartDevicePos == 0)
thatd->autoDetectUnicode = true;
-#endif
// Rewind the device to get to the current position Ensure that
// readBufferOffset is unaffected by fillReadBuffer()
@@ -1305,7 +1228,7 @@ void QTextStream::skipWhiteSpace()
replaced.
\note This function resets locale to the default locale ('C')
- and codec to the default codec, QTextCodec::codecForLocale().
+ and encoding to the default encoding, UTF-8.
\sa device(), setString()
*/
@@ -2577,10 +2500,9 @@ QTextStream &QTextStream::operator<<(double f)
/*!
Writes the string \a string to the stream, and returns a reference
to the QTextStream. The string is first encoded using the assigned
- codec (the default codec is QTextCodec::codecForLocale()) before
- it is written to the stream.
+ encoding (the default is UTF-8) before it is written to the stream.
- \sa setFieldWidth(), setCodec()
+ \sa setFieldWidth(), setEncoding()
*/
QTextStream &QTextStream::operator<<(const QString &string)
{
@@ -3132,7 +3054,6 @@ QTextStream &ws(QTextStream &stream)
Equivalent to QTextStream::setRealNumberPrecision(\a precision).
*/
-#if QT_CONFIG(textcodec)
namespace Qt {
/*!
@@ -3143,7 +3064,7 @@ namespace Qt {
/*!
Toggles insertion of the Byte Order Mark on \a stream when QTextStream is
- used with a UTF codec.
+ used with a UTF encoding.
\sa QTextStream::setGenerateByteOrderMark(), {QTextStream manipulators}
*/
@@ -3155,75 +3076,66 @@ QTextStream &bom(QTextStream &stream)
} // namespace Qt
+
/*!
- Sets the codec for this stream to \a codec. The codec is used for
+ Sets the encoding for this stream to \a encoding. The encoding is used for
decoding any data that is read from the assigned device, and for
encoding any data that is written. By default,
- QTextCodec::codecForLocale() is used, and automatic unicode
+ QStringConverter::Utf8 is used, and automatic unicode
detection is enabled.
If QTextStream operates on a string, this function does nothing.
\warning If you call this function while the text stream is reading
from an open sequential socket, the internal buffer may still contain
- text decoded using the old codec.
+ text decoded using the old encoding.
- \sa codec(), setAutoDetectUnicode(), setLocale()
+ \sa encoding(), setAutoDetectUnicode(), setLocale()
*/
-void QTextStream::setCodec(QTextCodec *codec)
+void QTextStream::setEncoding(QStringConverter::Encoding encoding)
{
Q_D(QTextStream);
+ if (d->encoding == encoding)
+ return;
+
qint64 seekPos = -1;
if (!d->readBuffer.isEmpty()) {
if (!d->device->isSequential()) {
seekPos = pos();
}
}
- d->codec = codec;
- if (seekPos >=0 && !d->readBuffer.isEmpty())
- seek(seekPos);
-}
-/*!
- Sets the codec for this stream to the QTextCodec for the encoding
- specified by \a codecName. Common values for \c codecName include
- "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
- recognized, nothing happens.
-
- Example:
+ d->encoding = encoding;
+ d->toUtf16 = QStringDecoder(d->encoding);
+ bool generateBOM = d->hasWrittenData && d->generateBOM;
+ d->fromUtf16 = QStringEncoder(d->encoding,
+ generateBOM ? QStringEncoder::Flag::WriteBom : QStringEncoder::Flag::Default);
- \snippet code/src_corelib_io_qtextstream.cpp 10
-
- \sa QTextCodec::codecForName(), setLocale()
-*/
-void QTextStream::setCodec(const char *codecName)
-{
- QTextCodec *codec = QTextCodec::codecForName(codecName);
- if (codec)
- setCodec(codec);
+ if (seekPos >=0 && !d->readBuffer.isEmpty())
+ seek(seekPos);
}
/*!
- Returns the codec that is current assigned to the stream.
+ Returns the encoding that is current assigned to the stream.
- \sa setCodec(), setAutoDetectUnicode(), locale()
+ \sa setEncoding(), setAutoDetectUnicode(), locale()
*/
-QTextCodec *QTextStream::codec() const
+QStringConverter::Encoding QTextStream::encoding() const
{
Q_D(const QTextStream);
- return d->codec;
+ return d->encoding;
}
/*!
If \a enabled is true, QTextStream will attempt to detect Unicode encoding
by peeking into the stream data to see if it can find the UTF-8, UTF-16, or
UTF-32 Byte Order Mark (BOM). If this mark is found, QTextStream will
- replace the current codec with the UTF codec.
+ replace the current encoding with the UTF encoding.
- This function can be used together with setCodec(). It is common
- to set the codec to UTF-8, and then enable UTF-16 detection.
+ This function can be used together with setEncoding(). It is common
+ to set the encoding to UTF-8, and then enable UTF-16 detection.
- \sa autoDetectUnicode(), setCodec(), QTextCodec::codecForUtfText()
+ \sa autoDetectUnicode(), setEncoding()
*/
void QTextStream::setAutoDetectUnicode(bool enabled)
{
@@ -3235,7 +3147,7 @@ void QTextStream::setAutoDetectUnicode(bool enabled)
Returns \c true if automatic Unicode detection is enabled, otherwise
returns \c false. Automatic Unicode detection is enabled by default.
- \sa setAutoDetectUnicode(), setCodec(), QTextCodec::codecForUtfText()
+ \sa setAutoDetectUnicode(), setEncoding()
*/
bool QTextStream::autoDetectUnicode() const
{
@@ -3244,7 +3156,7 @@ bool QTextStream::autoDetectUnicode() const
}
/*!
- If \a generate is true and a UTF codec is used, QTextStream will insert
+ If \a generate is true and a UTF encoding is used, QTextStream will insert
the BOM (Byte Order Mark) before any data has been written to the
device. If \a generate is false, no BOM will be inserted. This function
must be called before any data is written. Otherwise, it does nothing.
@@ -3254,14 +3166,16 @@ bool QTextStream::autoDetectUnicode() const
void QTextStream::setGenerateByteOrderMark(bool generate)
{
Q_D(QTextStream);
- if (d->writeBuffer.isEmpty()) {
- d->writeConverterState.flags.setFlag(QTextCodec::IgnoreHeader, !generate);
- }
+ if (d->hasWrittenData || d->generateBOM == generate)
+ return;
+
+ d->generateBOM = generate;
+ d->fromUtf16 = QStringEncoder(d->encoding, generate ? QStringConverter::Flag::WriteBom : QStringConverter::Flag::Default);
}
/*!
Returns \c true if QTextStream is set to generate the UTF BOM (Byte Order
- Mark) when using a UTF codec; otherwise returns \c false. UTF BOM generation is
+ Mark) when using a UTF encoding; otherwise returns \c false. UTF BOM generation is
set to false by default.
\sa setGenerateByteOrderMark()
@@ -3269,11 +3183,9 @@ void QTextStream::setGenerateByteOrderMark(bool generate)
bool QTextStream::generateByteOrderMark() const
{
Q_D(const QTextStream);
- return (d->writeConverterState.flags & QTextCodec::IgnoreHeader) == 0;
+ return d->generateBOM;
}
-#endif
-
/*!
\since 4.5
@@ -3337,9 +3249,7 @@ QTextStream &reset(QTextStream &s) { return Qt::reset(s); }
QTextStream &ws(QTextStream &s) { return Qt::ws(s); }
-#if QT_CONFIG(textcodec)
QTextStream &bom(QTextStream &s) { return Qt::bom(s); }
-#endif
} // namespace QTextStreamFunctions
#endif
@@ -3375,10 +3285,8 @@ Q_CORE_EXPORT QTextStream &reset(QTextStream &s) { return Qt::reset(s); }
Q_CORE_EXPORT QTextStream &ws(QTextStream &s) { return Qt::ws(s); }
-#if QT_CONFIG(textcodec)
Q_CORE_EXPORT QTextStream &bom(QTextStream &s) { return Qt::bom(s); }
#endif
-#endif
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h
index 97d596137e..2b164ce9b3 100644
--- a/src/corelib/serialization/qtextstream.h
+++ b/src/corelib/serialization/qtextstream.h
@@ -45,6 +45,7 @@
#include <QtCore/qchar.h>
#include <QtCore/qlocale.h>
#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstringconverter.h>
#include <stdio.h>
@@ -54,10 +55,6 @@
QT_BEGIN_NAMESPACE
-
-class QTextCodec;
-class QTextDecoder;
-
class QTextStreamPrivate;
class Q_CORE_EXPORT QTextStream // text stream class
{
@@ -98,15 +95,12 @@ public:
explicit QTextStream(const QByteArray &array, QIODevice::OpenMode openMode = QIODevice::ReadOnly);
virtual ~QTextStream();
-#if QT_CONFIG(textcodec)
- void setCodec(QTextCodec *codec);
- void setCodec(const char *codecName);
- QTextCodec *codec() const;
+ void setEncoding(QStringConverter::Encoding encoding);
+ QStringConverter::Encoding encoding() const;
void setAutoDetectUnicode(bool enabled);
bool autoDetectUnicode() const;
void setGenerateByteOrderMark(bool generate);
bool generateByteOrderMark() const;
-#endif
void setLocale(const QLocale &locale);
QLocale locale() const;
diff --git a/src/corelib/serialization/qtextstream_p.h b/src/corelib/serialization/qtextstream_p.h
index 172824d27d..cee79a7ecf 100644
--- a/src/corelib/serialization/qtextstream_p.h
+++ b/src/corelib/serialization/qtextstream_p.h
@@ -54,9 +54,6 @@
#include <QtCore/private/qglobal_p.h>
#include "qtextstream.h"
-#if QT_CONFIG(textcodec)
-#include "qtextcodec.h"
-#endif
QT_BEGIN_NAMESPACE
@@ -118,13 +115,10 @@ public:
int stringOffset;
QIODevice::OpenMode stringOpenMode;
-#if QT_CONFIG(textcodec)
- // codec
- QTextCodec *codec;
- QTextCodec::ConverterState readConverterState;
- QTextCodec::ConverterState writeConverterState;
- QTextCodec::ConverterState *readConverterSavedState;
-#endif
+ QStringConverter::Encoding encoding = QStringConverter::Utf8;
+ QStringEncoder fromUtf16;
+ QStringDecoder toUtf16;
+ QStringDecoder savedToUtf16;
QString writeBuffer;
QString readBuffer;
@@ -141,9 +135,9 @@ public:
int lastTokenSize;
bool deleteDevice;
-#if QT_CONFIG(textcodec)
bool autoDetectUnicode;
-#endif
+ bool hasWrittenData = false;
+ bool generateBOM = false;
// i/o
enum TokenDelimiter {
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index d7fb0d0d41..c26b0d11d2 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -45,9 +45,7 @@
#include <qdebug.h>
#include <qfile.h>
#include <stdio.h>
-#if QT_CONFIG(textcodec)
-#include <qtextcodec.h>
-#endif
+#include <qstringconverter.h>
#include <qstack.h>
#include <qbuffer.h>
#include <qscopeguard.h>
@@ -60,23 +58,42 @@
#define Q_DECLARE_TR_FUNCTIONS(context) \
public: \
static inline QString tr(const char *sourceText, const char *comment = nullptr) \
- { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
+ { Q_UNUSED(comment); return QString::fromUtf8(sourceText); } \
static inline QString trUtf8(const char *sourceText, const char *comment = nullptr) \
- { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
+ { Q_UNUSED(comment); return QString::fromUtf8(sourceText); } \
static inline QString tr(const char *sourceText, const char*, int) \
- { return QString::fromLatin1(sourceText); } \
+ { return QString::fromUtf8(sourceText); } \
static inline QString trUtf8(const char *sourceText, const char*, int) \
- { return QString::fromLatin1(sourceText); } \
+ { return QString::fromUtf8(sourceText); } \
private:
#endif
#include <private/qmemory_p.h>
+#include <iterator>
+
QT_BEGIN_NAMESPACE
#include "qxmlstream_p.h"
enum { StreamEOF = ~0U };
+namespace {
+template <typename Range>
+auto reversed(Range &r)
+{
+ struct R {
+ Range *r;
+ auto begin() { return std::make_reverse_iterator(std::end(*r)); }
+ auto end() { return std::make_reverse_iterator(std::begin(*r)); }
+ };
+
+ return R{&r};
+}
+
+template <typename Range>
+void reversed(const Range &&) = delete;
+}
+
/*!
\enum QXmlStreamReader::TokenType
@@ -263,12 +280,10 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
\ingroup xml-tools
- QXmlStreamReader is a faster and more convenient replacement for
- Qt's own SAX parser (see QXmlSimpleReader). In some cases it might
- also be a faster and more convenient alternative for use in
- applications that would otherwise use a DOM tree (see QDomDocument).
- QXmlStreamReader reads data either from a QIODevice (see
- setDevice()), or from a raw QByteArray (see addData()).
+ QXmlStreamReader provides a simple streaming API to parse well-formed
+ XML. It is an alternative to first loading the complete XML into a
+ DOM tree (see \l QDomDocument). QXmlStreamReader reads data either
+ from a QIODevice (see setDevice()), or from a raw QByteArray (see addData()).
Qt provides QXmlStreamWriter for writing XML.
@@ -414,25 +429,15 @@ QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
/*!
Creates a new stream reader that reads from \a data.
- This function should only be used if the XML header either says the encoding
- is "UTF-8" or lacks any encoding information (the latter is the case of
- QXmlStreamWriter writing to a QString). Any other encoding is likely going to
- cause data corruption ("mojibake").
-
\sa addData(), clear(), setDevice()
*/
QXmlStreamReader::QXmlStreamReader(const QString &data)
: d_ptr(new QXmlStreamReaderPrivate(this))
{
Q_D(QXmlStreamReader);
-#if !QT_CONFIG(textcodec)
- d->dataBuffer = data.toLatin1();
-#else
- d->dataBuffer = d->codec->fromUnicode(data);
- d->decoder = d->codec->makeDecoder();
-#endif
+ d->dataBuffer = data.toUtf8();
+ d->decoder = QStringDecoder(QStringDecoder::Utf8);
d->lockEncoding = true;
-
}
/*!
@@ -520,11 +525,9 @@ void QXmlStreamReader::addData(const QString &data)
{
Q_D(QXmlStreamReader);
d->lockEncoding = true;
-#if !QT_CONFIG(textcodec)
- addData(data.toLatin1());
-#else
- addData(d->codec->fromUnicode(data));
-#endif
+ if (!d->decoder.isValid())
+ d->decoder = QStringDecoder(QStringDecoder::Utf8);
+ addData(data.toUtf8());
}
/*!
@@ -797,9 +800,6 @@ QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
{
device = nullptr;
deleteDevice = false;
-#if QT_CONFIG(textcodec)
- decoder = nullptr;
-#endif
stack_size = 64;
sym_stack = nullptr;
state_stack = nullptr;
@@ -843,11 +843,7 @@ void QXmlStreamReaderPrivate::init()
lineNumber = lastLineStart = characterOffset = 0;
readBufferPos = 0;
nbytesread = 0;
-#if QT_CONFIG(textcodec)
- codec = QTextCodec::codecForMib(106); // utf8
- delete decoder;
- decoder = nullptr;
-#endif
+ decoder = QStringDecoder();
attributeStack.clear();
attributeStack.reserve(16);
entityParser.reset();
@@ -908,9 +904,6 @@ inline void QXmlStreamReaderPrivate::reallocateStack()
QXmlStreamReaderPrivate::~QXmlStreamReaderPrivate()
{
-#if QT_CONFIG(textcodec)
- delete decoder;
-#endif
free(sym_stack);
free(state_stack);
}
@@ -1441,36 +1434,40 @@ inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
return n;
}
-void QXmlStreamReaderPrivate::putString(const QString &s, int from)
+void QXmlStreamReaderPrivate::putString(QStringView s, qsizetype from)
{
+ if (from != 0) {
+ putString(s.mid(from));
+ return;
+ }
putStack.reserve(s.size());
- for (int i = s.size()-1; i >= from; --i)
- putStack.rawPush() = s.at(i).unicode();
+ for (auto it = s.rbegin(), end = s.rend(); it != end; ++it)
+ putStack.rawPush() = it->unicode();
}
-void QXmlStreamReaderPrivate::putStringLiteral(const QString &s)
+void QXmlStreamReaderPrivate::putStringLiteral(QStringView s)
{
putStack.reserve(s.size());
- for (int i = s.size()-1; i >= 0; --i)
- putStack.rawPush() = ((LETTER << 16) | s.at(i).unicode());
+ for (auto it = s.rbegin(), end = s.rend(); it != end; ++it)
+ putStack.rawPush() = ((LETTER << 16) | it->unicode());
}
-void QXmlStreamReaderPrivate::putReplacement(const QString &s)
+void QXmlStreamReaderPrivate::putReplacement(QStringView s)
{
putStack.reserve(s.size());
- for (int i = s.size()-1; i >= 0; --i) {
- ushort c = s.at(i).unicode();
+ for (auto it = s.rbegin(), end = s.rend(); it != end; ++it) {
+ char16_t c = it->unicode();
if (c == '\n' || c == '\r')
putStack.rawPush() = ((LETTER << 16) | c);
else
putStack.rawPush() = c;
}
}
-void QXmlStreamReaderPrivate::putReplacementInAttributeValue(const QString &s)
+void QXmlStreamReaderPrivate::putReplacementInAttributeValue(QStringView s)
{
putStack.reserve(s.size());
- for (int i = s.size()-1; i >= 0; --i) {
- ushort c = s.at(i).unicode();
+ for (auto it = s.rbegin(), end = s.rend(); it != end; ++it) {
+ char16_t c = it->unicode();
if (c == '&' || c == ';')
putStack.rawPush() = c;
else if (c == '\n' || c == '\r')
@@ -1486,14 +1483,12 @@ uint QXmlStreamReaderPrivate::getChar_helper()
characterOffset += readBufferPos;
readBufferPos = 0;
readBuffer.resize(0);
-#if QT_CONFIG(textcodec)
- if (decoder)
-#endif
+ if (decoder.isValid())
nbytesread = 0;
if (device) {
rawReadBuffer.resize(BUFFER_SIZE);
- int nbytesreadOrMinus1 = device->read(rawReadBuffer.data() + nbytesread, BUFFER_SIZE - nbytesread);
- nbytesread += qMax(nbytesreadOrMinus1, 0);
+ qint64 nbytesreadOrMinus1 = device->read(rawReadBuffer.data() + nbytesread, BUFFER_SIZE - nbytesread);
+ nbytesread += qMax(nbytesreadOrMinus1, qint64{0});
} else {
if (nbytesread)
rawReadBuffer += dataBuffer;
@@ -1507,49 +1502,26 @@ uint QXmlStreamReaderPrivate::getChar_helper()
return StreamEOF;
}
-#if QT_CONFIG(textcodec)
- if (!decoder) {
+ if (!decoder.isValid()) {
if (nbytesread < 4) { // the 4 is to cover 0xef 0xbb 0xbf plus
// one extra for the utf8 codec
atEnd = true;
return StreamEOF;
}
- int mib = 106; // UTF-8
-
- // look for byte order mark
- uchar ch1 = rawReadBuffer.at(0);
- uchar ch2 = rawReadBuffer.at(1);
- uchar ch3 = rawReadBuffer.at(2);
- uchar ch4 = rawReadBuffer.at(3);
-
- if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
- (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
- mib = 1017; // UTF-32 with byte order mark
- else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
- mib = 1019; // UTF-32LE
- else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
- mib = 1018; // UTF-32BE
- else if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
- mib = 1015; // UTF-16 with byte order mark
- else if (ch1 == 0x3c && ch2 == 0x00)
- mib = 1014; // UTF-16LE
- else if (ch1 == 0x00 && ch2 == 0x3c)
- mib = 1013; // UTF-16BE
- codec = QTextCodec::codecForMib(mib);
- Q_ASSERT(codec);
- decoder = codec->makeDecoder();
- }
-
- decoder->toUnicode(&readBuffer, rawReadBuffer.constData(), nbytesread);
-
- if(lockEncoding && decoder->hasFailure()) {
+ auto encoding = QStringDecoder::encodingForData(rawReadBuffer.constData(), rawReadBuffer.size(), char16_t('<'));
+ if (!encoding)
+ // assume utf-8
+ encoding = QStringDecoder::Utf8;
+ decoder = QStringDecoder(*encoding);
+ }
+
+ readBuffer = decoder(rawReadBuffer.constData(), nbytesread);
+
+ if (lockEncoding && decoder.hasError()) {
raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
readBuffer.clear();
return StreamEOF;
}
-#else
- readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
-#endif // textcodec
readBuffer.reserve(1); // keep capacity when calling resize() next time
@@ -1564,8 +1536,7 @@ uint QXmlStreamReaderPrivate::getChar_helper()
QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
{
- for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
- const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(j);
+ for (const NamespaceDeclaration &namespaceDeclaration : reversed(namespaceDeclarations)) {
if (namespaceDeclaration.prefix == prefix) {
return namespaceDeclaration.namespaceUri;
}
@@ -1585,17 +1556,16 @@ QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
void QXmlStreamReaderPrivate::resolveTag()
{
const auto attributeStackCleaner = qScopeGuard([this](){ attributeStack.clear(); });
- int n = attributeStack.size();
+ const qsizetype n = attributeStack.size();
if (namespaceProcessing) {
- for (int a = 0; a < dtdAttributes.size(); ++a) {
- DtdAttribute &dtdAttribute = dtdAttributes[a];
+ for (DtdAttribute &dtdAttribute : dtdAttributes) {
if (!dtdAttribute.isNamespaceAttribute
|| dtdAttribute.defaultValue.isNull()
|| dtdAttribute.tagName != qualifiedName
|| dtdAttribute.attributeQualifiedName.isNull())
continue;
- int i = 0;
+ qsizetype i = 0;
while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
++i;
if (i != n)
@@ -1631,7 +1601,7 @@ void QXmlStreamReaderPrivate::resolveTag()
attributes.resize(n);
- for (int i = 0; i < n; ++i) {
+ for (qsizetype i = 0; i < n; ++i) {
QXmlStreamAttribute &attribute = attributes[i];
Attribute &attrib = attributeStack[i];
QStringRef prefix(symPrefix(attrib.key));
@@ -1648,7 +1618,7 @@ void QXmlStreamReaderPrivate::resolveTag()
attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
}
- for (int j = 0; j < i; ++j) {
+ for (qsizetype j = 0; j < i; ++j) {
if (attributes[j].name() == attribute.name()
&& attributes[j].namespaceUri() == attribute.namespaceUri()
&& (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
@@ -1659,14 +1629,13 @@ void QXmlStreamReaderPrivate::resolveTag()
}
}
- for (int a = 0; a < dtdAttributes.size(); ++a) {
- DtdAttribute &dtdAttribute = dtdAttributes[a];
+ for (DtdAttribute &dtdAttribute : dtdAttributes) {
if (dtdAttribute.isNamespaceAttribute
|| dtdAttribute.defaultValue.isNull()
|| dtdAttribute.tagName != qualifiedName
|| dtdAttribute.attributeQualifiedName.isNull())
continue;
- int i = 0;
+ qsizetype i = 0;
while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
++i;
if (i != n)
@@ -1684,16 +1653,16 @@ void QXmlStreamReaderPrivate::resolveTag()
attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
}
attribute.m_isDefault = true;
- attributes.append(attribute);
+ attributes.append(std::move(attribute));
}
}
void QXmlStreamReaderPrivate::resolvePublicNamespaces()
{
const Tag &tag = tagStack.top();
- int n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize;
+ qsizetype n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize;
publicNamespaceDeclarations.resize(n);
- for (int i = 0; i < n; ++i) {
+ for (qsizetype i = 0; i < n; ++i) {
const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i);
QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i];
publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix);
@@ -1704,7 +1673,7 @@ void QXmlStreamReaderPrivate::resolvePublicNamespaces()
void QXmlStreamReaderPrivate::resolveDtd()
{
publicNotationDeclarations.resize(notationDeclarations.size());
- for (int i = 0; i < notationDeclarations.size(); ++i) {
+ for (qsizetype i = 0; i < notationDeclarations.size(); ++i) {
const QXmlStreamReaderPrivate::NotationDeclaration &notationDeclaration = notationDeclarations.at(i);
QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i];
publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name);
@@ -1714,7 +1683,7 @@ void QXmlStreamReaderPrivate::resolveDtd()
}
notationDeclarations.clear();
publicEntityDeclarations.resize(entityDeclarations.size());
- for (int i = 0; i < entityDeclarations.size(); ++i) {
+ for (qsizetype i = 0; i < entityDeclarations.size(); ++i) {
const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i);
QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i];
publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name);
@@ -1800,7 +1769,7 @@ void QXmlStreamReaderPrivate::startDocument()
else
err = QXmlStream::tr("Unsupported XML version.");
}
- int n = attributeStack.size();
+ qsizetype n = attributeStack.size();
/* We use this bool to ensure that the pesudo attributes are in the
* proper order:
@@ -1808,7 +1777,7 @@ void QXmlStreamReaderPrivate::startDocument()
* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
bool hasStandalone = false;
- for (int i = 0; err.isNull() && i < n; ++i) {
+ for (qsizetype i = 0; err.isNull() && i < n; ++i) {
Attribute &attrib = attributeStack[i];
QStringRef prefix(symPrefix(attrib.key));
QStringRef key(symString(attrib.key));
@@ -1822,19 +1791,15 @@ void QXmlStreamReaderPrivate::startDocument()
if (!QXmlUtils::isEncName(value))
err = QXmlStream::tr("%1 is an invalid encoding name.").arg(value);
else {
-#if !QT_CONFIG(textcodec)
- readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
-#else
- QTextCodec *const newCodec = QTextCodec::codecForName(value.toLatin1());
- if (!newCodec)
- err = QXmlStream::tr("Encoding %1 is unsupported").arg(value);
- else if (newCodec != codec && !lockEncoding) {
- codec = newCodec;
- delete decoder;
- decoder = codec->makeDecoder();
- decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
+ QByteArray enc = value.toString().toUtf8();
+ if (!lockEncoding) {
+ decoder = QStringDecoder(enc.constData());
+ if (!decoder.isValid()) {
+ err = QXmlStream::tr("Encoding %1 is unsupported").arg(value);
+ } else {
+ readBuffer = decoder(rawReadBuffer.data(), nbytesread);
+ }
}
-#endif // textcodec
}
} else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
hasStandalone = true;
@@ -2122,8 +2087,8 @@ void QXmlStreamReader::addExtraNamespaceDeclaration(const QXmlStreamNamespaceDec
*/
void QXmlStreamReader::addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclarations)
{
- for (int i = 0; i < extraNamespaceDeclarations.size(); ++i)
- addExtraNamespaceDeclaration(extraNamespaceDeclarations.at(i));
+ for (const auto &extraNamespaceDeclaration : extraNamespaceDeclarations)
+ addExtraNamespaceDeclaration(extraNamespaceDeclaration);
}
@@ -2732,8 +2697,7 @@ Returns the entity's value.
*/
QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
{
- for (int i = 0; i < size(); ++i) {
- const QXmlStreamAttribute &attribute = at(i);
+ for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
return attribute.value();
}
@@ -2747,8 +2711,7 @@ QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QStrin
*/
QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, QLatin1String name) const
{
- for (int i = 0; i < size(); ++i) {
- const QXmlStreamAttribute &attribute = at(i);
+ for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
return attribute.value();
}
@@ -2762,8 +2725,7 @@ QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, QLatin1Strin
*/
QStringRef QXmlStreamAttributes::value(QLatin1String namespaceUri, QLatin1String name) const
{
- for (int i = 0; i < size(); ++i) {
- const QXmlStreamAttribute &attribute = at(i);
+ for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
return attribute.value();
}
@@ -2784,8 +2746,7 @@ QStringRef QXmlStreamAttributes::value(QLatin1String namespaceUri, QLatin1String
*/
QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
{
- for (int i = 0; i < size(); ++i) {
- const QXmlStreamAttribute &attribute = at(i);
+ for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.qualifiedName() == qualifiedName)
return attribute.value();
}
@@ -2806,8 +2767,7 @@ QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
*/
QStringRef QXmlStreamAttributes::value(QLatin1String qualifiedName) const
{
- for (int i = 0; i < size(); ++i) {
- const QXmlStreamAttribute &attribute = at(i);
+ for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.qualifiedName() == qualifiedName)
return attribute.value();
}
@@ -2996,8 +2956,7 @@ QStringRef QXmlStreamReader::documentEncoding() const
writeProcessingInstruction(), and writeDTD(). Chaining of XML
streams is supported with writeCurrentToken().
- By default, QXmlStreamWriter encodes XML in UTF-8. Different
- encodings can be enforced using setCodec().
+ QXmlStreamWriter always encodes XML in UTF-8.
If an error occurs while writing to the underlying device, hasError()
starts returning true and subsequent writes are ignored.
@@ -3018,9 +2977,6 @@ public:
~QXmlStreamWriterPrivate() {
if (deleteDevice)
delete device;
-#if QT_CONFIG(textcodec)
- delete encoder;
-#endif
}
void write(const QStringRef &);
@@ -3040,16 +2996,10 @@ public:
uint hasIoError :1;
uint hasEncodingError :1;
uint autoFormatting :1;
- uint isCodecASCIICompatible :1;
QByteArray autoFormattingIndent;
NamespaceDeclaration emptyNamespace;
- int lastNamespaceDeclaration;
-
-#if QT_CONFIG(textcodec)
- QTextCodec *codec;
- QTextEncoder *encoder;
-#endif
- void checkIfASCIICompatibleCodec();
+ qsizetype lastNamespaceDeclaration;
+ QStringEncoder toUtf8;
NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
@@ -3061,17 +3011,13 @@ public:
QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
- :autoFormattingIndent(4, ' ')
+ : autoFormattingIndent(4, ' '),
+ toUtf8(QStringEncoder::Utf8, QStringEncoder::Flag::Stateless)
{
q_ptr = q;
device = nullptr;
stringDevice = nullptr;
deleteDevice = false;
-#if QT_CONFIG(textcodec)
- codec = QTextCodec::codecForMib(106); // utf8
- encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
-#endif
- checkIfASCIICompatibleCodec();
inStartElement = inEmptyElement = false;
wroteSomething = false;
hasIoError = false;
@@ -3082,37 +3028,16 @@ QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
namespacePrefixCount = 0;
}
-void QXmlStreamWriterPrivate::checkIfASCIICompatibleCodec()
-{
-#if QT_CONFIG(textcodec)
- Q_ASSERT(encoder);
- // test ASCII-compatibility using the letter 'a'
- QChar letterA = QLatin1Char('a');
- const QByteArray bytesA = encoder->fromUnicode(&letterA, 1);
- const bool isCodecASCIICompatibleA = (bytesA.count() == 1) && (bytesA[0] == 0x61) ;
- QChar letterLess = QLatin1Char('<');
- const QByteArray bytesLess = encoder->fromUnicode(&letterLess, 1);
- const bool isCodecASCIICompatibleLess = (bytesLess.count() == 1) && (bytesLess[0] == 0x3C) ;
- isCodecASCIICompatible = isCodecASCIICompatibleA && isCodecASCIICompatibleLess ;
-#else
- isCodecASCIICompatible = true;
-#endif
-}
-
void QXmlStreamWriterPrivate::write(const QStringRef &s)
{
if (device) {
if (hasIoError)
return;
-#if !QT_CONFIG(textcodec)
- QByteArray bytes = s.toLatin1();
-#else
- QByteArray bytes = encoder->fromUnicode(s.constData(), s.size());
- if (encoder->hasFailure()) {
+ QByteArray bytes = toUtf8(s);
+ if (toUtf8.hasError()) {
hasEncodingError = true;
return;
}
-#endif
if (device->write(bytes) != bytes.size())
hasIoError = true;
}
@@ -3127,15 +3052,11 @@ void QXmlStreamWriterPrivate::write(const QString &s)
if (device) {
if (hasIoError)
return;
-#if !QT_CONFIG(textcodec)
- QByteArray bytes = s.toLatin1();
-#else
- QByteArray bytes = encoder->fromUnicode(s);
- if (encoder->hasFailure()) {
+ QByteArray bytes = toUtf8(s);
+ if (toUtf8.hasError()) {
hasEncodingError = true;
return;
}
-#endif
if (device->write(bytes) != bytes.size())
hasIoError = true;
}
@@ -3197,20 +3118,18 @@ void QXmlStreamWriterPrivate::writeEscaped(const QString &s, bool escapeWhitespa
write(escaped);
}
-// Converts from ASCII to output encoding
+// Writes utf8
void QXmlStreamWriterPrivate::write(const char *s, int len)
{
if (device) {
if (hasIoError)
return;
- if (isCodecASCIICompatible) {
- if (device->write(s, len) != len)
- hasIoError = true;
- return;
- }
+ if (device->write(s, len) != len)
+ hasIoError = true;
+ return;
}
- write(QString::fromLatin1(s, len));
+ write(QString::fromUtf8(s, len));
}
void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
@@ -3249,8 +3168,7 @@ bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(const QString &namespaceUri, bool writeDeclaration, bool noDefault)
{
- for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
- NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations[j];
+ for (NamespaceDeclaration &namespaceDeclaration : reversed(namespaceDeclarations)) {
if (namespaceDeclaration.namespaceUri == namespaceUri) {
if (!noDefault || !namespaceDeclaration.prefix.isEmpty())
return namespaceDeclaration;
@@ -3266,7 +3184,7 @@ QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNa
int n = ++namespacePrefixCount;
forever {
s = QLatin1Char('n') + QString::number(n++);
- int j = namespaceDeclarations.size() - 2;
+ qsizetype j = namespaceDeclarations.size() - 2;
while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
--j;
if (j < 0)
@@ -3326,8 +3244,6 @@ QXmlStreamWriter::QXmlStreamWriter(QByteArray *array)
/*! Constructs a stream writer that writes into \a string.
*
- * Note that when writing to QString, QXmlStreamWriter ignores the codec set
- * with setCodec(). See that function for more information.
*/
QXmlStreamWriter::QXmlStreamWriter(QString *string)
: d_ptr(new QXmlStreamWriterPrivate(this))
@@ -3375,67 +3291,6 @@ QIODevice *QXmlStreamWriter::device() const
return d->device;
}
-
-#if QT_CONFIG(textcodec)
-/*!
- Sets the codec for this stream to \a codec. The codec is used for
- encoding any data that is written. By default, QXmlStreamWriter
- uses UTF-8.
-
- The encoding information is stored in the initial xml tag which
- gets written when you call writeStartDocument(). Call this
- function before calling writeStartDocument().
-
- \note When writing the XML to a QString, the codec information is ignored
- and the XML header will not include any encoding information, since all
- QStrings are UTF-16. If you later convert the QString to an 8-bit format,
- you must arrange for the encoding information to be transmitted
- out-of-band.
-
- \sa codec()
-*/
-void QXmlStreamWriter::setCodec(QTextCodec *codec)
-{
- Q_D(QXmlStreamWriter);
- if (codec) {
- d->codec = codec;
- delete d->encoder;
- d->encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
- d->checkIfASCIICompatibleCodec();
- }
-}
-
-/*!
- Sets the codec for this stream to the QTextCodec for the encoding
- specified by \a codecName. Common values for \c codecName include
- "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
- recognized, nothing happens.
-
- \note When writing the XML to a QString, the codec information is ignored
- and the XML header will not include any encoding information, since all
- QStrings are UTF-16. If you later convert the QString to an 8-bit format,
- you must arrange for the encoding information to be transmitted
- out-of-band.
-
- \sa QTextCodec::codecForName()
-*/
-void QXmlStreamWriter::setCodec(const char *codecName)
-{
- setCodec(QTextCodec::codecForName(codecName));
-}
-
-/*!
- Returns the codec that is currently assigned to the stream.
-
- \sa setCodec()
-*/
-QTextCodec *QXmlStreamWriter::codec() const
-{
- Q_D(const QXmlStreamWriter);
- return d->codec;
-}
-#endif // textcodec
-
/*!
\property QXmlStreamWriter::autoFormatting
\since 4.4
@@ -3597,8 +3452,8 @@ void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes& attributes)
Q_D(QXmlStreamWriter);
Q_ASSERT(d->inStartElement);
Q_UNUSED(d);
- for (int i = 0; i < attributes.size(); ++i)
- writeAttribute(attributes.at(i));
+ for (const auto &attr : attributes)
+ writeAttribute(attr);
}
@@ -3874,10 +3729,9 @@ void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const Q
/*!\overload
- Writes a document start with XML version number "1.0". This also
- writes the encoding information.
+ Writes a document start with XML version number "1.0".
- \sa writeEndDocument(), setCodec()
+ \sa writeEndDocument()
\since 4.5
*/
void QXmlStreamWriter::writeStartDocument()
@@ -3897,15 +3751,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version)
d->finishStartElement(false);
d->write("<?xml version=\"");
d->write(version);
- if (d->device) { // stringDevice does not get any encoding
- d->write("\" encoding=\"");
-#if !QT_CONFIG(textcodec)
- d->write("iso-8859-1");
-#else
- const QByteArray name = d->codec->name();
- d->write(name.constData(), name.length());
-#endif
- }
+ if (d->device) // stringDevice does not get any encoding
+ d->write("\" encoding=\"UTF-8");
d->write("\"?>");
}
@@ -3921,15 +3768,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalon
d->finishStartElement(false);
d->write("<?xml version=\"");
d->write(version);
- if (d->device) { // stringDevice does not get any encoding
- d->write("\" encoding=\"");
-#if !QT_CONFIG(textcodec)
- d->write("iso-8859-1");
-#else
- const QByteArray name = d->codec->name();
- d->write(name.constData(), name.length());
-#endif
- }
+ if (d->device) // stringDevice does not get any encoding
+ d->write("\" encoding=\"UTF-8");
if (standalone)
d->write("\" standalone=\"yes\"?>");
else
@@ -3983,7 +3823,7 @@ void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, con
write(tag.name);
inStartElement = lastWasStartElement = true;
- for (int i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
+ for (qsizetype i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
writeNamespaceDeclaration(namespaceDeclarations[i]);
tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
}
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index b623de9505..876157a9e6 100644
--- a/src/corelib/serialization/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
@@ -151,15 +151,16 @@
/.
#include <QtCore/private/qglobal_p.h>
+#include <qstringconverter.h>
template <typename T> class QXmlStreamSimpleStack {
T *data;
- int tos, cap;
+ qsizetype tos, cap;
public:
- inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){}
+ inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
- inline void reserve(int extraCapacity) {
+ inline void reserve(qsizetype extraCapacity) {
if (tos + extraCapacity + 1 > cap) {
cap = qMax(tos + extraCapacity + 1, cap << 1 );
void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
@@ -173,12 +174,21 @@ public:
inline const T &top() const { return data[tos]; }
inline T &top() { return data[tos]; }
inline T &pop() { return data[tos--]; }
- inline T &operator[](int index) { return data[index]; }
- inline const T &at(int index) const { return data[index]; }
- inline int size() const { return tos + 1; }
- inline void resize(int s) { tos = s - 1; }
+ inline T &operator[](qsizetype index) { return data[index]; }
+ inline const T &at(qsizetype index) const { return data[index]; }
+ inline qsizetype size() const { return tos + 1; }
+ inline void resize(qsizetype s) { tos = s - 1; }
inline bool isEmpty() const { return tos < 0; }
inline void clear() { tos = -1; }
+
+ using const_iterator = const T*;
+ using iterator = T*;
+ T *begin() { return data; }
+ const T *begin() const { return data; }
+ const T *cbegin() const { return begin(); }
+ T *end() { return data + size(); }
+ const T *end() const { return data + size(); }
+ const T *cend() const { return end(); }
};
@@ -201,7 +211,7 @@ public:
QStringRef qualifiedName;
NamespaceDeclaration namespaceDeclaration;
int tagStackStringStorageSize;
- int namespaceDeclarationsSize;
+ qsizetype namespaceDeclarationsSize;
};
@@ -309,10 +319,7 @@ public:
QIODevice *device;
bool deleteDevice;
-#if QT_CONFIG(textcodec)
- QTextCodec *codec;
- QTextDecoder *decoder;
-#endif
+ QStringDecoder decoder;
bool atEnd;
/*!
@@ -488,10 +495,10 @@ public:
inline uint peekChar();
inline void putChar(uint c) { putStack.push() = c; }
inline void putChar(QChar c) { putStack.push() = c.unicode(); }
- void putString(const QString &s, int from = 0);
- void putStringLiteral(const QString &s);
- void putReplacement(const QString &s);
- void putReplacementInAttributeValue(const QString &s);
+ void putString(QStringView s, qsizetype from = 0);
+ void putStringLiteral(QStringView s);
+ void putReplacement(QStringView s);
+ void putReplacementInAttributeValue(QStringView s);
uint getChar_helper();
bool scanUntil(const char *str, short tokenToInject = -1);
@@ -502,7 +509,7 @@ public:
QString resolveUndeclaredEntity(const QString &name);
void parseEntity(const QString &value);
- QXmlStreamReaderPrivate *entityParser;
+ std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
bool scanAfterLangleBang();
bool scanPublicOrSystem();
@@ -602,13 +609,11 @@ bool QXmlStreamReaderPrivate::parse()
lockEncoding = true;
documentVersion.clear();
documentEncoding.clear();
-#if QT_CONFIG(textcodec)
- if (decoder && decoder->hasFailure()) {
+ if (decoder.isValid() && decoder.hasError()) {
raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
readBuffer.clear();
return false;
}
-#endif
Q_FALLTHROUGH();
default:
clearTextBuffer();
@@ -1642,8 +1647,8 @@ entity_ref ::= AMPERSAND name SEMICOLON;
case $rule_number: {
sym(1).len += sym(2).len + 1;
QStringView reference = symView(2);
- if (entityHash.contains(reference)) {
- Entity &entity = entityHash[reference];
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
if (entity.unparsed) {
raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
} else {
@@ -1684,9 +1689,9 @@ pereference ::= PERCENT name SEMICOLON;
case $rule_number: {
sym(1).len += sym(2).len + 1;
QStringView reference = symView(2);
- if (parameterEntityHash.contains(reference)) {
+ if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
referenceToParameterEntityDetected = true;
- Entity &entity = parameterEntityHash[reference];
+ Entity &entity = *it;
if (entity.unparsed || entity.external) {
referenceToUnparsedEntityDetected = true;
} else {
@@ -1715,8 +1720,8 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
case $rule_number: {
sym(1).len += sym(2).len + 1;
QStringView reference = symView(2);
- if (entityHash.contains(reference)) {
- Entity &entity = entityHash[reference];
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
if (entity.unparsed || entity.value.isNull()) {
raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
break;
@@ -1752,12 +1757,8 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
char_ref ::= AMPERSAND HASH char_ref_value SEMICOLON;
/.
case $rule_number: {
- if (uint s = resolveCharRef(3)) {
- if (s >= 0xffff)
- putStringLiteral(QString::fromUcs4(&s, 1));
- else
- putChar((LETTER << 16) | s);
-
+ if (char32_t s = resolveCharRef(3)) {
+ putStringLiteral(QChar::fromUcs4(s));
textBuffer.chop(3 + sym(3).len);
clearSym();
} else {
diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h
index c8647e0465..1b22dfa4c7 100644
--- a/src/corelib/serialization/qxmlstream.h
+++ b/src/corelib/serialization/qxmlstream.h
@@ -474,12 +474,6 @@ public:
void setDevice(QIODevice *device);
QIODevice *device() const;
-#if QT_CONFIG(textcodec)
- void setCodec(QTextCodec *codec);
- void setCodec(const char *codecName);
- QTextCodec *codec() const;
-#endif
-
void setAutoFormatting(bool);
bool autoFormatting() const;
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index 103b123b10..c9239eb410 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -49,6 +49,7 @@
//
#include <QtCore/private/qglobal_p.h>
+#include <qstringconverter.h>
// This file was generated by qlalr - DO NOT EDIT!
#ifndef QXMLSTREAM_P_H
@@ -643,12 +644,12 @@ const short QXmlStreamReader_Table::action_check [] = {
template <typename T> class QXmlStreamSimpleStack {
T *data;
- int tos, cap;
+ qsizetype tos, cap;
public:
inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
- inline void reserve(int extraCapacity) {
+ inline void reserve(qsizetype extraCapacity) {
if (tos + extraCapacity + 1 > cap) {
cap = qMax(tos + extraCapacity + 1, cap << 1 );
void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
@@ -662,12 +663,21 @@ public:
inline const T &top() const { return data[tos]; }
inline T &top() { return data[tos]; }
inline T &pop() { return data[tos--]; }
- inline T &operator[](int index) { return data[index]; }
- inline const T &at(int index) const { return data[index]; }
- inline int size() const { return tos + 1; }
- inline void resize(int s) { tos = s - 1; }
+ inline T &operator[](qsizetype index) { return data[index]; }
+ inline const T &at(qsizetype index) const { return data[index]; }
+ inline qsizetype size() const { return tos + 1; }
+ inline void resize(qsizetype s) { tos = s - 1; }
inline bool isEmpty() const { return tos < 0; }
inline void clear() { tos = -1; }
+
+ using const_iterator = const T*;
+ using iterator = T*;
+ T *begin() { return data; }
+ const T *begin() const { return data; }
+ const T *cbegin() const { return begin(); }
+ T *end() { return data + size(); }
+ const T *end() const { return data + size(); }
+ const T *cend() const { return end(); }
};
@@ -690,7 +700,7 @@ public:
QStringRef qualifiedName;
NamespaceDeclaration namespaceDeclaration;
int tagStackStringStorageSize;
- int namespaceDeclarationsSize;
+ qsizetype namespaceDeclarationsSize;
};
@@ -798,10 +808,7 @@ public:
QIODevice *device;
bool deleteDevice;
-#if QT_CONFIG(textcodec)
- QTextCodec *codec;
- QTextDecoder *decoder;
-#endif
+ QStringDecoder decoder;
bool atEnd;
/*!
@@ -977,10 +984,10 @@ public:
inline uint peekChar();
inline void putChar(uint c) { putStack.push() = c; }
inline void putChar(QChar c) { putStack.push() = c.unicode(); }
- void putString(const QString &s, int from = 0);
- void putStringLiteral(const QString &s);
- void putReplacement(const QString &s);
- void putReplacementInAttributeValue(const QString &s);
+ void putString(QStringView s, qsizetype from = 0);
+ void putStringLiteral(QStringView s);
+ void putReplacement(QStringView s);
+ void putReplacementInAttributeValue(QStringView s);
uint getChar_helper();
bool scanUntil(const char *str, short tokenToInject = -1);
@@ -1091,13 +1098,11 @@ bool QXmlStreamReaderPrivate::parse()
lockEncoding = true;
documentVersion.clear();
documentEncoding.clear();
-#if QT_CONFIG(textcodec)
- if (decoder && decoder->hasFailure()) {
+ if (decoder.isValid() && decoder.hasError()) {
raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
readBuffer.clear();
return false;
}
-#endif
Q_FALLTHROUGH();
default:
clearTextBuffer();
@@ -1814,8 +1819,8 @@ bool QXmlStreamReaderPrivate::parse()
case 240: {
sym(1).len += sym(2).len + 1;
QStringView reference = symView(2);
- if (entityHash.contains(reference)) {
- Entity &entity = entityHash[reference];
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
if (entity.unparsed) {
raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
} else {
@@ -1853,9 +1858,9 @@ bool QXmlStreamReaderPrivate::parse()
case 241: {
sym(1).len += sym(2).len + 1;
QStringView reference = symView(2);
- if (parameterEntityHash.contains(reference)) {
+ if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
referenceToParameterEntityDetected = true;
- Entity &entity = parameterEntityHash[reference];
+ Entity &entity = *it;
if (entity.unparsed || entity.external) {
referenceToUnparsedEntityDetected = true;
} else {
@@ -1876,8 +1881,8 @@ bool QXmlStreamReaderPrivate::parse()
case 243: {
sym(1).len += sym(2).len + 1;
QStringView reference = symView(2);
- if (entityHash.contains(reference)) {
- Entity &entity = entityHash[reference];
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
if (entity.unparsed || entity.value.isNull()) {
raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
break;
@@ -1910,12 +1915,8 @@ bool QXmlStreamReaderPrivate::parse()
} break;
case 244: {
- if (uint s = resolveCharRef(3)) {
- if (s >= 0xffff)
- putStringLiteral(QString::fromUcs4(&s, 1));
- else
- putChar((LETTER << 16) | s);
-
+ if (char32_t s = resolveCharRef(3)) {
+ putStringLiteral(QChar::fromUcs4(s));
textBuffer.chop(3 + sym(3).len);
clearSym();
} else {