summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/configure.json12
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp16
-rw-r--r--src/corelib/doc/src/qtcore-index.qdoc2
-rw-r--r--src/corelib/doc/src/resource-system.qdoc4
-rw-r--r--src/corelib/global/qcompilerdetection.h13
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h3
-rw-r--r--src/corelib/global/qendian.cpp6
-rw-r--r--src/corelib/global/qglobal.cpp30
-rw-r--r--src/corelib/global/qglobal.h12
-rw-r--r--src/corelib/global/qlibraryinfo.cpp36
-rw-r--r--src/corelib/global/qnamespace.h1
-rw-r--r--src/corelib/global/qnamespace.qdoc6
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp2
-rw-r--r--src/corelib/global/qrandom.cpp2
-rw-r--r--src/corelib/io/qprocess_win.cpp13
-rw-r--r--src/corelib/io/qresource.cpp6
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel.cpp24
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel.h2
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp17
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp23
-rw-r--r--src/corelib/kernel/qobject_p.h1
-rw-r--r--src/corelib/kernel/qtimer.cpp8
-rw-r--r--src/corelib/kernel/qvariant.cpp41
-rw-r--r--src/corelib/kernel/qvariant.h10
-rw-r--r--src/corelib/kernel/qvariant_p.h5
-rw-r--r--src/corelib/mimetypes/mime/generate.bat73
-rw-r--r--src/corelib/mimetypes/mime/generate.pl113
-rw-r--r--src/corelib/mimetypes/mime/hexdump.ps143
-rw-r--r--src/corelib/mimetypes/mimetypes.pri29
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp11
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp95
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h11
-rw-r--r--src/corelib/serialization/qcborcommon.cpp328
-rw-r--r--src/corelib/serialization/qcborcommon.h2
-rw-r--r--src/corelib/serialization/qcborcommon_p.h84
-rw-r--r--src/corelib/serialization/qcborstream.h226
-rw-r--r--src/corelib/serialization/qcborstreamreader.cpp (renamed from src/corelib/serialization/qcborstream.cpp)1142
-rw-r--r--src/corelib/serialization/qcborstreamreader.h210
-rw-r--r--src/corelib/serialization/qcborstreamwriter.cpp868
-rw-r--r--src/corelib/serialization/qcborstreamwriter.h130
-rw-r--r--src/corelib/serialization/qcborvalue.cpp34
-rw-r--r--src/corelib/serialization/qcborvalue.h8
-rw-r--r--src/corelib/serialization/qdatastream.h3
-rw-r--r--src/corelib/serialization/qjsonarray.cpp12
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp8
-rw-r--r--src/corelib/serialization/qjsonobject.cpp4
-rw-r--r--src/corelib/serialization/qjsonobject.h2
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp12
-rw-r--r--src/corelib/serialization/qtextstream.cpp52
-rw-r--r--src/corelib/serialization/qtextstream.h42
-rw-r--r--src/corelib/serialization/serialization.pri17
-rw-r--r--src/corelib/text/qbytearray.cpp13
-rw-r--r--src/corelib/text/qchar.cpp2
-rw-r--r--src/corelib/text/qlocale.cpp47
-rw-r--r--src/corelib/text/qlocale_p.h3
-rw-r--r--src/corelib/text/qlocale_unix.cpp4
-rw-r--r--src/corelib/text/qregexp.cpp8
-rw-r--r--src/corelib/text/qregularexpression.cpp97
-rw-r--r--src/corelib/text/qstring.cpp29
-rw-r--r--src/corelib/text/qstring.h2
-rw-r--r--src/corelib/text/qstringalgorithms.h1
-rw-r--r--src/corelib/text/qstringview.cpp15
-rw-r--r--src/corelib/text/qstringview.h2
-rw-r--r--src/corelib/thread/qatomic.cpp204
-rw-r--r--src/corelib/thread/qatomic.h6
-rw-r--r--src/corelib/thread/qwaitcondition.h9
-rw-r--r--src/corelib/thread/qwaitcondition.qdoc6
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp4
-rw-r--r--src/corelib/time/qcalendar.cpp4
-rw-r--r--src/corelib/time/qdatetime.cpp104
-rw-r--r--src/corelib/tools/qhash.cpp102
-rw-r--r--src/corelib/tools/qhash.h250
-rw-r--r--src/corelib/tools/qmap.cpp14
-rw-r--r--src/corelib/tools/qmap.h44
-rw-r--r--src/corelib/tools/qvector.h1
75 files changed, 2974 insertions, 1851 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index 5ee7888d4f..c8e650ca9f 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -1093,14 +1093,20 @@ Mozilla License) is included. The data is then also used in QNetworkCookieJar::v
"label": "Windows System Libraries",
"condition": "config.win32 && libs.advapi32 && libs.gdi32 && libs.kernel32 && libs.netapi32 && libs.ole32 && libs.shell32 && libs.uuid && libs.user32 && libs.winmm && libs.ws2_32"
},
- "cborstream": {
- "label": "CBOR stream I/O",
- "purpose": "Provides support for reading and writing the CBOR binary format.
+ "cborstreamreader": {
+ "label": "CBOR stream reading",
+ "purpose": "Provides support for reading the CBOR binary format.
Note that this is required for plugin loading. Qt GUI needs QPA plugins for basic operation.",
"section": "Utilities",
"output": [ "publicFeature" ]
},
+ "cborstreamwriter": {
+ "label": "CBOR stream writing",
+ "purpose": "Provides support for writing the CBOR binary format.",
+ "section": "Utilities",
+ "output": [ "publicFeature" ]
+ },
"binaryjson": {
"label": "Binary JSON (deprecated)",
"purpose": "Provides support for the deprecated binary JSON format.",
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index 9813cc98d5..a140175956 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -119,22 +119,6 @@ hash.insert("plenty", 2000);
//! [9]
-//! [10]
-QList<int> values = hash.values("plenty");
-for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << Qt::endl;
-//! [10]
-
-
-//! [11]
-QHash<QString, int>::iterator i = hash.find("plenty");
-while (i != hash.end() && i.key() == "plenty") {
- cout << i.value() << Qt::endl;
- ++i;
-}
-//! [11]
-
-
//! [12]
QHash<QString, int> hash;
...
diff --git a/src/corelib/doc/src/qtcore-index.qdoc b/src/corelib/doc/src/qtcore-index.qdoc
index 40a6584af0..29fc25f69d 100644
--- a/src/corelib/doc/src/qtcore-index.qdoc
+++ b/src/corelib/doc/src/qtcore-index.qdoc
@@ -56,7 +56,7 @@
\include module-use.qdocinc using qt module
\quotefile overview/using-qt-core.cmake
- See also the \l[QtDoc]{Building with CMake} overview.
+ See also the \l[QtDoc]{Build with CMake} overview.
\section2 Building with qmake
diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc
index 69ec5e556b..f9ef317799 100644
--- a/src/corelib/doc/src/resource-system.qdoc
+++ b/src/corelib/doc/src/resource-system.qdoc
@@ -189,13 +189,13 @@
XML file to indicate a file should be most compressed, regardless of
which algorithms \c rcc supports.
- \li \c{zstd}: use the \l{Zstandard}{https://zstd.net} library to compress
+ \li \c{zstd}: use the \l{https://zstd.net}{Zstandard} library to compress
contents. Valid compression levels range from 1 to 19, 1 is least
compression (least CPU time) and 19 is the most compression (most CPU
time). The default level is 14. A special value of 0 tells the \c{zstd}
library to choose an implementation-defined default.
- \li \c{zlib}: use the \l{zlib}{https://zlib.net} library to compress
+ \li \c{zlib}: use the \l{https://zlib.net}{zlib} library to compress
contents. Valid compression levels range from 1 to 9, with 1the least
compression (least CPU time) and 9 the most compression (most CPU time).
The special value 0 means "no compression" and should not be used. The
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index fedf08301f..e4c37451d2 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -815,13 +815,14 @@
# endif
# endif
-# if defined(__has_warning)
-# if __has_warning("-Wunused-private-field")
-# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
-# endif
-# endif
+#endif // Q_CC_CLANG && !Q_CC_INTEL && !Q_CC_MSVC
-#endif // Q_CC_CLANG
+#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
+# ifndef Q_DECL_UNUSED
+# define Q_DECL_UNUSED __attribute__((__unused__))
+# endif
+# define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED
+#endif
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
# define Q_COMPILER_RESTRICTED_VLA
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index 2e6c3fbb20..4a8a4598a0 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -75,7 +75,8 @@
# define QT_FEATURE_alloca_malloc_h -1
#endif
#define QT_FEATURE_binaryjson -1
-#define QT_FEATURE_cborstream -1
+#define QT_FEATURE_cborstreamreader -1
+#define QT_FEATURE_cborstreamwriter 1
#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1
#define QT_FEATURE_cxx11_random (__has_include(<random>) ? 1 : -1)
#define QT_NO_DATASTREAM
diff --git a/src/corelib/global/qendian.cpp b/src/corelib/global/qendian.cpp
index c56a7ffbf7..f1c39f3c62 100644
--- a/src/corelib/global/qendian.cpp
+++ b/src/corelib/global/qendian.cpp
@@ -137,7 +137,7 @@ QT_BEGIN_NAMESPACE
\sa qToLittleEndian()
*/
/*!
- \fn template <typename T> T qFromLittleEndian(const void *src)
+ \fn template <typename T> inline T qFromLittleEndian(const void *src)
\since 4.3
\relates <QtEndian>
@@ -159,7 +159,7 @@ QT_BEGIN_NAMESPACE
\sa qToLittleEndian()
*/
/*!
- \fn template <typename T> T qFromLittleEndian(T src)
+ \fn template <typename T> inline T qFromLittleEndian(T src)
\since 4.3
\relates <QtEndian>
\overload
@@ -171,7 +171,7 @@ QT_BEGIN_NAMESPACE
unmodified.
*/
/*!
- \fn template <typename T> T qFromLittleEndian(const void *src, qsizetype count, void *dest)
+ \fn template <typename T> inline T qFromLittleEndian(const void *src, qsizetype count, void *dest)
\since 5.12
\relates <QtEndian>
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index c2c91df756..f9f005a83f 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -4161,36 +4161,6 @@ bool qunsetenv(const char *varName)
*/
/*!
- \macro QABS(n)
- \relates <QtGlobal>
- \obsolete
-
- Use qAbs(\a n) instead.
-
- \sa QMIN(), QMAX()
-*/
-
-/*!
- \macro QMIN(x, y)
- \relates <QtGlobal>
- \obsolete
-
- Use qMin(\a x, \a y) instead.
-
- \sa QMAX(), QABS()
-*/
-
-/*!
- \macro QMAX(x, y)
- \relates <QtGlobal>
- \obsolete
-
- Use qMax(\a x, \a y) instead.
-
- \sa QMIN(), QABS()
-*/
-
-/*!
\macro const char *qPrintable(const QString &str)
\relates <QtGlobal>
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 80433ebeff..d508716024 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -892,6 +892,10 @@ QT_WARNING_POP
# define Q_DUMMY_COMPARISON_OPERATOR(C)
#endif
+QT_WARNING_PUSH
+// warning: noexcept-expression evaluates to ‘false’ because of a call to ‘void swap(..., ...)'
+QT_WARNING_DISABLE_GCC("-Wnoexcept")
+
namespace QtPrivate
{
namespace SwapExceptionTester { // insulate users from the "using std::swap" below
@@ -911,6 +915,8 @@ inline void qSwap(T &value1, T &value2)
swap(value1, value2);
}
+QT_WARNING_POP
+
#if QT_DEPRECATED_SINCE(5, 0)
Q_CORE_EXPORT QT_DEPRECATED void *qMalloc(size_t size) Q_ALLOC_SIZE(1);
Q_CORE_EXPORT QT_DEPRECATED void qFree(void *ptr);
@@ -1214,8 +1220,10 @@ inline int qIntCast(float f) { return int(f); }
/*
Reentrant versions of basic rand() functions for random number generation
*/
-Q_CORE_EXPORT void qsrand(uint seed);
-Q_CORE_EXPORT int qrand();
+#if QT_DEPRECATED_SINCE(5, 15)
+Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_5_15("use QRandomGenerator instead") void qsrand(uint seed);
+Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_5_15("use QRandomGenerator instead") int qrand();
+#endif
#define QT_MODULE(x)
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index aed224215c..9fab49a73e 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -561,9 +561,39 @@ static QString getRelocatablePrefix()
HMODULE hModule = getWindowsModuleHandle();
const int kBufferSize = 4096;
wchar_t buffer[kBufferSize];
- const int pathSize = GetModuleFileName(hModule, buffer, kBufferSize);
- if (pathSize > 0)
- prefixPath = prefixFromQtCoreLibraryHelper(QString::fromWCharArray(buffer, pathSize));
+ DWORD pathSize = GetModuleFileName(hModule, buffer, kBufferSize);
+ const QString qtCoreFilePath = QString::fromWCharArray(buffer, int(pathSize));
+ const QString qtCoreDirPath = QFileInfo(qtCoreFilePath).absolutePath();
+ pathSize = GetModuleFileName(NULL, buffer, kBufferSize);
+ const QString exeDirPath = QFileInfo(QString::fromWCharArray(buffer, int(pathSize))).absolutePath();
+ if (QFileInfo(exeDirPath) == QFileInfo(qtCoreDirPath)) {
+ // QtCore DLL is next to the executable. This is either a windeployqt'ed executable or an
+ // executable within the QT_HOST_BIN directory. We're detecting the latter case by checking
+ // whether there's an import library corresponding to our QtCore DLL in PREFIX/lib.
+ const QString libdir = QString::fromLatin1(
+ qt_configure_strs + qt_configure_str_offsets[QLibraryInfo::LibrariesPath - 1]);
+ const QLatin1Char slash('/');
+#if defined(Q_CC_MINGW)
+ const QString implibPrefix = QStringLiteral("lib");
+ const QString implibSuffix = QStringLiteral(".a");
+#else
+ const QString implibPrefix;
+ const QString implibSuffix = QStringLiteral(".lib");
+#endif
+ const QString qtCoreImpLibFileName = implibPrefix
+ + QFileInfo(qtCoreFilePath).completeBaseName() + implibSuffix;
+ const QString qtCoreImpLibPath = qtCoreDirPath
+ + slash + QLatin1String(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH)
+ + slash + libdir
+ + slash + qtCoreImpLibFileName;
+ if (!QFileInfo::exists(qtCoreImpLibPath)) {
+ // We did not find a corresponding import library and conclude that this is a
+ // windeployqt'ed executable.
+ return exeDirPath;
+ }
+ }
+ if (!qtCoreFilePath.isEmpty())
+ prefixPath = prefixFromQtCoreLibraryHelper(qtCoreFilePath);
#else
#error "The chosen platform / config does not support querying for a dynamic prefix."
#endif
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 6ae04f0c7b..b9e981b4a6 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -505,6 +505,7 @@ namespace Qt {
AA_DontUseNativeMenuBar = 6,
AA_MacDontSwapCtrlAndMeta = 7,
AA_Use96Dpi = 8,
+ AA_MSWindowsDisableVirtualKeyboard = 9,
#if QT_DEPRECATED_SINCE(5, 14)
AA_X11InitThreads Q_DECL_ENUMERATOR_DEPRECATED = 10,
#endif
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index ef5f345e9c..6149281904 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -293,6 +293,12 @@
This attribute must be set before QGuiApplication is constructed.
This value was added in 5.13
+ \value AA_MSWindowsDisableVirtualKeyboard When this attribute is set,
+ Windows' native on-screen virtual keyboard will not be shown
+ automatically when a text input widget gains focus on a system
+ without a physical keyboard.
+ This value was added in 5.15
+
The following values are deprecated or obsolete:
\value AA_ImmediateWidgetCreation This attribute is no longer fully
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
index 33793ca168..261f5c8795 100644
--- a/src/corelib/global/qoperatingsystemversion.cpp
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -299,6 +299,8 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
Returns the current OS type without constructing a QOperatingSystemVersion instance.
+ \since 5.10
+
\sa current()
*/
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 563e5eb7ed..3dc024e301 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -1295,7 +1295,7 @@ void qsrand(uint seed)
\note This function is deprecated. In new applications, use
QRandomGenerator instead.
- \sa qrand(), QRandomGenerator
+ \sa qsrand(), QRandomGenerator
*/
int qrand()
{
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 05af5a5aee..1527cf93ed 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -49,7 +49,6 @@
#include <qelapsedtimer.h>
#include <qfileinfo.h>
#include <qrandom.h>
-#include <qregexp.h>
#include <qwineventnotifier.h>
#include <private/qsystemlibrary_p.h>
#include <private/qthread_p.h>
@@ -398,7 +397,17 @@ static QString qt_create_commandline(const QString &program, const QStringList &
for (int i=0; i<arguments.size(); ++i) {
QString tmp = arguments.at(i);
// Quotes are escaped and their preceding backslashes are doubled.
- tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\""));
+ int index = tmp.indexOf(QLatin1Char('"'));
+ while (index >= 0) {
+ // Escape quote
+ tmp.insert(index++, QLatin1Char('\\'));
+ // Double preceding backslashes (ignoring the one we just inserted)
+ for (int i = index - 2 ; i >= 0 && tmp.at(i) == QLatin1Char('\\') ; --i) {
+ tmp.insert(i, QLatin1Char('\\'));
+ index++;
+ }
+ index = tmp.indexOf(QLatin1Char('"'), index + 1);
+ }
if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
// The argument must not end with a \ since this would be interpreted
// as escaping the quote -- rather put the \ behind the quote: e.g.
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 6bdb99f97a..0d75faa234 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -280,9 +280,9 @@ static inline QStringList *resourceSearchPaths()
RCC tool used to compress the payload.
\value NoCompression Contents are not compressed
- \value ZlibCompression Contents are compressed using \l{zlib}{https://zlib.net} and can
+ \value ZlibCompression Contents are compressed using \l{https://zlib.net}{zlib} and can
be decompressed using the qUncompress() function.
- \value ZstdCompression Contents are compressed using \l{zstd}{https://zstd.net}. To
+ \value ZstdCompression Contents are compressed using \l{https://zstd.net}{zstd}. To
decompress, use the \c{ZSTD_decompress} function from the zstd
library.
@@ -629,6 +629,8 @@ const uchar *QResource::data() const
}
/*!
+ \since 5.8
+
Returns the date and time when the file was last modified before
packaging into a resource.
*/
diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp
index 39992eccd3..f5684c6eda 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.cpp
+++ b/src/corelib/itemmodels/qidentityproxymodel.cpp
@@ -313,6 +313,30 @@ bool QIdentityProxyModel::removeRows(int row, int count, const QModelIndex& pare
/*!
\reimp
+ \since 5.15
+ */
+bool QIdentityProxyModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == this : true);
+ Q_ASSERT(destinationParent.isValid() ? destinationParent.model() == this : true);
+ Q_D(QIdentityProxyModel);
+ return d->model->moveRows(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild);
+}
+
+/*!
+ \reimp
+ \since 5.15
+ */
+bool QIdentityProxyModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == this : true);
+ Q_ASSERT(destinationParent.isValid() ? destinationParent.model() == this : true);
+ Q_D(QIdentityProxyModel);
+ return d->model->moveColumns(mapToSource(sourceParent), sourceColumn, count, mapToSource(destinationParent), destinationChild);
+}
+
+/*!
+ \reimp
*/
int QIdentityProxyModel::rowCount(const QModelIndex& parent) const
{
diff --git a/src/corelib/itemmodels/qidentityproxymodel.h b/src/corelib/itemmodels/qidentityproxymodel.h
index 89ac89cdba..4c14e6176a 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.h
+++ b/src/corelib/itemmodels/qidentityproxymodel.h
@@ -77,6 +77,8 @@ public:
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
+ bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
+ bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override;
protected:
QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent);
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index f4402c88dc..e4ac5da299 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -1627,10 +1627,9 @@ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &par
QItemSelection sel = d->ranges;
sel.merge(d->currentSelection, d->currentCommand);
- for (int i = 0; i < sel.count(); ++i) {
- QItemSelectionRange range = sel.at(i);
+ for (const QItemSelectionRange &range : qAsConst(sel)) {
if (range.parent() != parent)
- return false;
+ return false;
int top = range.top();
int bottom = range.bottom();
int left = range.left();
@@ -1661,11 +1660,13 @@ bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelInde
QItemSelection sel = d->ranges;
sel.merge(d->currentSelection, d->currentCommand);
- for (int i = 0; i < sel.count(); ++i) {
- int left = sel.at(i).left();
- int right = sel.at(i).right();
- int top = sel.at(i).top();
- int bottom = sel.at(i).bottom();
+ for (const QItemSelectionRange &range : qAsConst(sel)) {
+ if (range.parent() != parent)
+ return false;
+ int top = range.top();
+ int bottom = range.bottom();
+ int left = range.left();
+ int right = range.right();
if (left <= column && right >= column) {
for (int j = top; j <= bottom; j++) {
const Qt::ItemFlags flags = d->model->index(j, column, parent).flags();
diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp
index a248cdcd38..9c87ff853a 100644
--- a/src/corelib/itemmodels/qstringlistmodel.cpp
+++ b/src/corelib/itemmodels/qstringlistmodel.cpp
@@ -301,24 +301,23 @@ bool QStringListModel::moveRows(const QModelIndex &sourceParent, int sourceRow,
{
if (sourceRow < 0
|| sourceRow + count - 1 >= rowCount(sourceParent)
- || destinationChild <= 0
+ || destinationChild < 0
|| destinationChild > rowCount(destinationParent)
+ || sourceRow == destinationChild
|| sourceRow == destinationChild - 1
- || count <= 0) {
+ || count <= 0
+ || sourceParent.isValid()
+ || destinationParent.isValid()) {
return false;
}
if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), destinationChild))
return false;
- /*
- QList::move assumes that the second argument is the index where the item will end up to
- i.e. the valid range for that argument is from 0 to QList::size()-1
- QAbstractItemModel::moveRows when source and destinations have the same parent assumes that
- the item will end up being in the row BEFORE the one indicated by destinationChild
- i.e. the valid range for that argument is from 1 to QList::size()
- For this reason we remove 1 from destinationChild when using it inside QList
- */
- destinationChild--;
- const int fromRow = destinationChild < sourceRow ? (sourceRow + count - 1) : sourceRow;
+
+ int fromRow = sourceRow;
+ if (destinationChild < sourceRow)
+ fromRow += count - 1;
+ else
+ destinationChild--;
while (count--)
lst.move(fromRow, destinationChild);
endMoveRows();
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index a421b55764..d6e73fbefc 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -362,7 +362,6 @@ public:
}
public:
ExtraData *extraData; // extra data set by the user
- QThreadData *getThreadData() const { return threadData.loadAcquire(); }
// This atomic requires acquire/release semantics in a few places,
// e.g. QObject::moveToThread must synchronize with QCoreApplication::postEvent,
// because postEvent is thread-safe.
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index f843fc4236..25ce0c032f 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -84,10 +84,10 @@ QT_BEGIN_NAMESPACE
must start and stop the timer in its thread; it is not possible to
start a timer from another thread.
- As a special case, a QTimer with a timeout of 0 will time out as
- soon as all the events in the window system's event queue have
- been processed. This can be used to do heavy work while providing
- a snappy user interface:
+ As a special case, a QTimer with a timeout of 0 will time out as soon as
+ possible, though the ordering between zero timers and other sources of
+ events is unspecified. Zero timers can be used to do some work while still
+ providing a snappy user interface:
\snippet timers/timers.cpp 4
\snippet timers/timers.cpp 5
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index fee1e3842d..888da17a98 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -944,7 +944,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
const QVariantHash *hash = v_cast<QVariantHash>(d);
const auto end = hash->end();
for (auto it = hash->begin(); it != end; ++it)
- map->insertMulti(it.key(), it.value());
+ static_cast<QMultiMap<QString, QVariant> *>(map)->insert(it.key(), it.value());
#ifndef QT_BOOTSTRAPPED
} else if (d->type == QMetaType::QCborValue) {
if (!v_cast<QCborValue>(d)->isMap())
@@ -972,7 +972,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
const QVariantMap *map = v_cast<QVariantMap>(d);
const auto end = map->end();
for (auto it = map->begin(); it != end; ++it)
- hash->insertMulti(it.key(), it.value());
+ static_cast<QMultiHash<QString, QVariant> *>(hash)->insert(it.key(), it.value());
#ifndef QT_BOOTSTRAPPED
} else if (d->type == QMetaType::QCborValue) {
if (!v_cast<QCborValue>(d)->isMap())
@@ -1544,7 +1544,7 @@ static void customStreamDebug(QDebug dbg, const QVariant &variant) {
#ifndef QT_BOOTSTRAPPED
QMetaType::TypeFlags flags = QMetaType::typeFlags(variant.userType());
if (flags & QMetaType::PointerToQObject)
- dbg.nospace() << variant.value<QObject*>();
+ dbg.nospace() << qvariant_cast<QObject*>(variant);
#else
Q_UNUSED(dbg);
Q_UNUSED(variant);
@@ -4414,15 +4414,24 @@ QSequentialIterable::const_iterator QSequentialIterable::end() const
return it;
}
+static const QVariant variantFromVariantDataHelper(const QtMetaTypePrivate::VariantData &d) {
+ QVariant v;
+ if (d.metaTypeId == qMetaTypeId<QVariant>())
+ v = *reinterpret_cast<const QVariant*>(d.data);
+ else
+ v = QVariant(d.metaTypeId, d.data, d.flags & ~QVariantConstructionFlags::ShouldDeleteVariantData);
+ if (d.flags & QVariantConstructionFlags::ShouldDeleteVariantData)
+ QMetaType::destroy(d.metaTypeId, const_cast<void *>(d.data));
+ return v;
+}
+
/*!
Returns the element at position \a idx in the container.
*/
QVariant QSequentialIterable::at(int idx) const
{
const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- return *reinterpret_cast<const QVariant*>(d.data);
- return QVariant(d.metaTypeId, d.data, d.flags);
+ return variantFromVariantDataHelper(d);
}
/*!
@@ -4499,9 +4508,7 @@ QSequentialIterable::const_iterator::operator=(const const_iterator &other)
const QVariant QSequentialIterable::const_iterator::operator*() const
{
const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- return *reinterpret_cast<const QVariant*>(d.data);
- return QVariant(d.metaTypeId, d.data, d.flags);
+ return variantFromVariantDataHelper(d);
}
/*!
@@ -4833,10 +4840,7 @@ QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
const QVariant QAssociativeIterable::const_iterator::operator*() const
{
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
- QVariant v(d.metaTypeId, d.data, d.flags);
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- return *reinterpret_cast<const QVariant*>(d.data);
- return v;
+ return variantFromVariantDataHelper(d);
}
/*!
@@ -4845,10 +4849,7 @@ const QVariant QAssociativeIterable::const_iterator::operator*() const
const QVariant QAssociativeIterable::const_iterator::key() const
{
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
- QVariant v(d.metaTypeId, d.data, d.flags);
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- return *reinterpret_cast<const QVariant*>(d.data);
- return v;
+ return variantFromVariantDataHelper(d);
}
/*!
@@ -4856,11 +4857,7 @@ const QVariant QAssociativeIterable::const_iterator::key() const
*/
const QVariant QAssociativeIterable::const_iterator::value() const
{
- const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
- QVariant v(d.metaTypeId, d.data, d.flags);
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- return *reinterpret_cast<const QVariant*>(d.data);
- return v;
+ return operator*();
}
/*!
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 24c7bd44dd..66bf8ce7b5 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -771,7 +771,7 @@ namespace QtPrivate {
return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QByteArrayList*>(v.constData())));
}
#endif
- return QSequentialIterable(v.value<QtMetaTypePrivate::QSequentialIterableImpl>());
+ return QSequentialIterable(qvariant_cast<QtMetaTypePrivate::QSequentialIterableImpl>(v));
}
};
template<>
@@ -786,7 +786,7 @@ namespace QtPrivate {
if (typeId == qMetaTypeId<QVariantHash>()) {
return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantHash*>(v.constData())));
}
- return QAssociativeIterable(v.value<QtMetaTypePrivate::QAssociativeIterableImpl>());
+ return QAssociativeIterable(qvariant_cast<QtMetaTypePrivate::QAssociativeIterableImpl>(v));
}
};
template<>
@@ -817,7 +817,7 @@ namespace QtPrivate {
QVariantHash l;
l.reserve(iter.size());
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insertMulti(it.key().toString(), it.value());
+ static_cast<QMultiHash<QString, QVariant> &>(l).insert(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantHash>::invoke(v);
@@ -833,7 +833,7 @@ namespace QtPrivate {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insertMulti(it.key().toString(), it.value());
+ static_cast<QMultiMap<QString, QVariant> &>(l).insert(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantMap>::invoke(v);
@@ -849,7 +849,7 @@ namespace QtPrivate {
return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
- QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+ QtMetaTypePrivate::QPairVariantInterfaceImpl pi = qvariant_cast<QtMetaTypePrivate::QPairVariantInterfaceImpl>(v);
const QtMetaTypePrivate::VariantData d1 = pi.first();
QVariant v1(d1.metaTypeId, d1.data, d1.flags);
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 3d87beac83..b8b63b5e6f 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -105,6 +105,11 @@ inline T *v_cast(QVariant::Private *d, T * = nullptr)
#endif
+enum QVariantConstructionFlags : uint {
+ Default = 0x0,
+ PointerType = 0x1,
+ ShouldDeleteVariantData = 0x2 // only used in Q*Iterable
+};
//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
diff --git a/src/corelib/mimetypes/mime/generate.bat b/src/corelib/mimetypes/mime/generate.bat
new file mode 100644
index 0000000000..f63fc63693
--- /dev/null
+++ b/src/corelib/mimetypes/mime/generate.bat
@@ -0,0 +1,73 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2019 Intel Corporation.
+:: Contact: https://www.qt.io/licensing/
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:GPL-EXCEPT$
+:: Commercial License Usage
+:: Licensees holding valid commercial Qt licenses may use this file in
+:: accordance with the commercial license agreement provided with the
+:: Software or, alternatively, in accordance with the terms contained in
+:: a written agreement between you and The Qt Company. For licensing terms
+:: and conditions see https://www.qt.io/terms-conditions. For further
+:: information use the contact form at https://www.qt.io/contact-us.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3 as published by the Free Software
+:: Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+:: included in the packaging of this file. Please review the following
+:: information to ensure the GNU General Public License requirements will
+:: be met: https://www.gnu.org/licenses/gpl-3.0.html.
+::
+:: $QT_END_LICENSE$
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+@echo off
+setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
+set me=%~dp0
+
+:: Check if certain tools are in PATH
+for %%C in (gzip.exe zstd.exe perl.exe) do set %%C=%%~$PATH:C
+
+:: If perl is in PATH, just let it do everything
+if not "%perl.exe%" == "" goto PuntToPerl
+
+set COMPRESS=
+set MACRO=MIME_DATABASE_IS_UNCOMPRESSED
+if not "%gzip.exe%" == "" (
+ set COMPRESS=gzip -9
+ set MACRO=MIME_DATABASE_IS_GZIP
+)
+
+:: Check if zstd support was enabled
+if /i "%~1" == "--zstd" (
+ shift
+ if not "%zstd.exe%" == "" (
+ set COMPRESS=zstd -19
+ set MACRO=MIME_DATABASE_IS_ZSTD
+ )
+)
+
+if not "%COMPRESS%" == "" goto CompressedCommon
+
+:: No Compression and no Perl
+:: Just hex-dump with Powershell
+powershell -ExecutionPolicy Bypass %me%hexdump.ps1 %1 %1
+exit /b %errorlevel%
+
+:CompressedCommon
+:: Compress to a temporary file, then hex-dump using Powershell
+echo #define %MACRO%
+set tempfile=generate%RANDOM%.tmp
+%COMPRESS% < %1 > %tempfile%
+powershell -ExecutionPolicy Bypass %me%hexdump.ps1 %tempfile% %1
+del %tempfile%
+exit /b %errorlevel%
+
+:PuntToPerl
+perl %me%generate.pl %*
+exit /b %errorlevel%
diff --git a/src/corelib/mimetypes/mime/generate.pl b/src/corelib/mimetypes/mime/generate.pl
new file mode 100644
index 0000000000..0f87d61f8e
--- /dev/null
+++ b/src/corelib/mimetypes/mime/generate.pl
@@ -0,0 +1,113 @@
+#!/usr/bin/perl
+#############################################################################
+##
+## Copyright (C) 2019 Intel Corporation.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+use strict;
+use warnings;
+use Config;
+local $/; # Enable "slurp" mode
+
+sub checkCommand($) {
+ use File::Spec::Functions;
+ my $cmd = $_[0] . $Config{_exe};
+ for my $path (path()) {
+ return 1 if -x catfile($path, $cmd);
+ }
+ return 0;
+}
+
+my $data;
+my $compress;
+my $macro;
+my $zlib = eval 'use Compress::Zlib; use IO::Compress::Gzip; return 1;';
+my $fname = shift @ARGV;
+
+if ($zlib) {
+ # Prefer internal zlib support (useful on Windows where gzip.exe isn't
+ # always presnet)
+ $macro = "MIME_DATABASE_IS_GZIP";
+} elsif (checkCommand("gzip")) {
+ # No builtin support for compression (old Perl?)
+ $compress = "gzip -c9";
+ $macro = "MIME_DATABASE_IS_GZIP";
+}
+
+# Check if Qt is being built with zstd support
+if ($fname eq "--zstd") {
+ $fname = shift @ARGV;
+ if (checkCommand("zstd")) {
+ $compress = "zstd -cq19 --single-thread";
+ $macro = "MIME_DATABASE_IS_ZSTD";
+ }
+}
+
+# Check if xml (from xmlstarlet) is in $PATH
+my $cmd;
+if (checkCommand("xml")) {
+ # Minify the data before compressing
+ $cmd = "xml sel -D -B -t -c / $fname";
+ $cmd .= "| $compress" if $compress;
+} elsif ($compress) {
+ $cmd = "$compress < $fname"
+}
+if ($cmd) {
+ # Run the command and read everything
+ open CMD, "$cmd |";
+ $data = <CMD>;
+ close CMD;
+ die("Failed to run $cmd") if ($? >> 8);
+} else {
+ # No command, just read the file
+ open F, "<$fname";
+ $data = <F>;
+ close F;
+}
+
+# Do we need to compress with zlib?
+if (!$compress && $zlib) {
+ $data = eval q{
+ use Compress::Zlib;
+ use IO::Compress::Gzip qw(gzip);
+ my $compressed;
+ gzip \$data => \$compressed,
+ Minimal => 1,
+ Level => Z_BEST_COMPRESSION;
+ return $compressed;
+ };
+}
+
+# Now print as hex
+printf "#define %s\n", $macro if $macro;
+printf "static const unsigned char mimetype_database[] = {";
+my $i = 0;
+map {
+ printf "\n " if $i++ % 12 == 0;
+ printf "0x%02x, ", ord $_
+} split //, $data;
+printf "\n};\n";
+printf "static constexpr size_t MimeTypeDatabaseOriginalSize = %d;\n",
+ (stat $fname)[7];
diff --git a/src/corelib/mimetypes/mime/hexdump.ps1 b/src/corelib/mimetypes/mime/hexdump.ps1
new file mode 100644
index 0000000000..25ce8138fa
--- /dev/null
+++ b/src/corelib/mimetypes/mime/hexdump.ps1
@@ -0,0 +1,43 @@
+#############################################################################
+##
+## Copyright (C) 2019 Intel Corporation.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+param([String]$path, [String]$orig)
+
+"static const unsigned char mimetype_database[] = {"
+ForEach ($byte in Get-Content -Encoding byte -ReadCount 16 -path $path) {
+# if (($byte -eq 0).count -ne 16) {
+ $hex = $byte | Foreach-Object {
+ " 0x" + ("{0:x}" -f $_).PadLeft( 2, "0" ) + ","
+ }
+ " $hex"
+# }
+}
+"};"
+
+$file = Get-Childitem -file $orig
+"static constexpr size_t MimeTypeDatabaseOriginalSize = " + $file.length + ";"
diff --git a/src/corelib/mimetypes/mimetypes.pri b/src/corelib/mimetypes/mimetypes.pri
index 62bbe348e4..8cbe7b69ae 100644
--- a/src/corelib/mimetypes/mimetypes.pri
+++ b/src/corelib/mimetypes/mimetypes.pri
@@ -21,5 +21,32 @@ qtConfig(mimetype) {
mimetypes/qmimeglobpattern.cpp \
mimetypes/qmimeprovider.cpp
- qtConfig(mimetype-database): RESOURCES += mimetypes/mimetypes.qrc
+ MIME_DATABASE = mimetypes/mime/packages/freedesktop.org.xml
+ OTHER_FILES += $$MIME_DATABASE
+
+ qtConfig(mimetype-database) {
+ outpath = .rcc
+ debug_and_release {
+ CONFIG(debug, debug|release): outpath = .rcc/debug
+ else: outpath = .rcc/release
+ }
+
+ mimedb.depends = $$PWD/mime/generate.pl
+ equals(MAKEFILE_GENERATOR, MSVC.NET)|equals(MAKEFILE_GENERATOR, MSBUILD)|isEmpty(QMAKE_SH) {
+ mimedb.commands = cmd /c $$shell_path($$PWD/mime/generate.bat)
+ mimedb.depends += $$PWD/mime/generate.bat $$PWD/mime/hexdump.ps1
+ } else {
+ mimedb.commands = perl $${mimedb.depends}
+ }
+
+ qtConfig(zstd): mimedb.commands += --zstd
+ mimedb.commands += ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
+
+ mimedb.output = $$outpath/qmimeprovider_database.cpp
+ mimedb.input = MIME_DATABASE
+ mimedb.variable_out = INCLUDED_SOURCES
+ QMAKE_EXTRA_COMPILERS += mimedb
+ INCLUDEPATH += $$outpath
+ unset(outpath)
+ }
}
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index 4d4f3eadeb..f1d0dc859e 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -102,13 +102,18 @@ void QMimeDatabasePrivate::loadProviders()
const auto fdoIterator = std::find_if(mimeDirs.constBegin(), mimeDirs.constEnd(), [](const QString &mimeDir) -> bool {
return QFileInfo::exists(mimeDir + QStringLiteral("/packages/freedesktop.org.xml")); }
);
- if (fdoIterator == mimeDirs.constEnd())
- mimeDirs.prepend(QLatin1String(":/qt-project.org/qmime"));
//qDebug() << "mime dirs:" << mimeDirs;
Providers currentProviders;
std::swap(m_providers, currentProviders);
- m_providers.reserve(mimeDirs.size());
+
+ if (QMimeXMLProvider::InternalDatabaseAvailable && fdoIterator == mimeDirs.constEnd()) {
+ m_providers.reserve(mimeDirs.size() + 1);
+ m_providers.push_back(Providers::value_type(new QMimeXMLProvider(this, QMimeXMLProvider::InternalDatabase)));
+ } else {
+ m_providers.reserve(mimeDirs.size());
+ }
+
for (const QString &mimeDir : qAsConst(mimeDirs)) {
const QString cacheFile = mimeDir + QStringLiteral("/mime.cache");
QFileInfo fileInfo(cacheFile);
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index c61759025c..4aee772366 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -1,7 +1,8 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Copyright (C) 2019 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -45,6 +46,7 @@
#include "qmimemagicrulematcher_p.h"
#include <QXmlStreamReader>
+#include <QBuffer>
#include <QDir>
#include <QFile>
#include <QByteArrayMatcher>
@@ -52,12 +54,33 @@
#include <QDateTime>
#include <QtEndian>
-static void initResources()
-{
#if QT_CONFIG(mimetype_database)
- Q_INIT_RESOURCE(mimetypes);
+# if defined(Q_CC_MSVC)
+# pragma section(".qtmimedatabase", read, shared)
+__declspec(allocate(".qtmimedatabase")) __declspec(align(4096))
+# elif defined(Q_OS_DARWIN)
+__attribute__((section("__TEXT,.qtmimedatabase"), aligned(4096)))
+# elif (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && defined(Q_CC_GNU)
+__attribute__((section(".qtmimedatabase"), aligned(4096)))
+# endif
+
+# include "qmimeprovider_database.cpp"
+
+# ifdef MIME_DATABASE_IS_ZSTD
+# if !QT_CONFIG(zstd)
+# error "MIME database is zstd but no support compiled in!"
+# endif
+# include <zstd.h>
+# endif
+# ifdef MIME_DATABASE_IS_GZIP
+# ifdef QT_NO_COMPRESS
+# error "MIME database is zlib but no support compiled in!"
+# endif
+# define ZLIB_CONST
+# include <zconf.h>
+# include <zlib.h>
+# endif
#endif
-}
QT_BEGIN_NAMESPACE
@@ -597,10 +620,55 @@ void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
////
+#if QT_CONFIG(mimetype_database)
+static QString internalMimeFileName()
+{
+ return QStringLiteral("<internal MIME data>");
+}
+
+QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
+ : QMimeProviderBase(db, internalMimeFileName())
+{
+ Q_STATIC_ASSERT_X(sizeof(mimetype_database), "Bundled MIME database is empty");
+ Q_STATIC_ASSERT_X(sizeof(mimetype_database) <= MimeTypeDatabaseOriginalSize,
+ "Compressed MIME database is larger than the original size");
+ Q_STATIC_ASSERT_X(MimeTypeDatabaseOriginalSize <= 16*1024*1024,
+ "Bundled MIME database is too big");
+ const char *data = reinterpret_cast<const char *>(mimetype_database);
+ qsizetype size = MimeTypeDatabaseOriginalSize;
+
+#ifdef MIME_DATABASE_IS_ZSTD
+ // uncompress with libzstd
+ std::unique_ptr<char []> uncompressed(new char[size]);
+ size = ZSTD_decompress(uncompressed.get(), size, mimetype_database, sizeof(mimetype_database));
+ Q_ASSERT(!ZSTD_isError(size));
+ data = uncompressed.get();
+#elif defined(MIME_DATABASE_IS_GZIP)
+ std::unique_ptr<char []> uncompressed(new char[size]);
+ z_stream zs = {};
+ zs.next_in = mimetype_database;
+ zs.avail_in = sizeof(mimetype_database);
+ zs.next_out = reinterpret_cast<Bytef *>(uncompressed.get());
+ zs.avail_out = size;
+
+ int res = inflateInit2(&zs, MAX_WBITS | 32);
+ Q_ASSERT(res == Z_OK);
+ res = inflate(&zs, Z_FINISH);
+ Q_ASSERT(res == Z_STREAM_END);
+ res = inflateEnd(&zs);
+ Q_ASSERT(res == Z_OK);
+
+ data = uncompressed.get();
+ size = zs.total_out;
+#endif
+
+ load(data, size);
+}
+#endif
+
QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
: QMimeProviderBase(db, directory)
{
- initResources();
ensureLoaded();
}
@@ -692,6 +760,19 @@ bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage)
return parser.parse(&file, fileName, errorMessage);
}
+#if QT_CONFIG(mimetype_database)
+void QMimeXMLProvider::load(const char *data, qsizetype len)
+{
+ QBuffer buffer;
+ buffer.setData(QByteArray::fromRawData(data, len));
+ buffer.open(QIODevice::ReadOnly);
+ QString errorMessage;
+ QMimeTypeParser parser(*this);
+ if (!parser.parse(&buffer, internalMimeFileName(), &errorMessage))
+ qWarning("QMimeDatabase: Error loading internal MIME data\n%s", qPrintable(errorMessage));
+}
+#endif
+
void QMimeXMLProvider::addGlobPattern(const QMimeGlobPattern &glob)
{
m_mimeTypeGlobs.addGlob(glob);
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index b6268210c0..0629df8a95 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -132,6 +132,16 @@ private:
class QMimeXMLProvider : public QMimeProviderBase
{
public:
+ enum InternalDatabaseEnum { InternalDatabase };
+#if QT_CONFIG(mimetype_database)
+ enum : bool { InternalDatabaseAvailable = true };
+ QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum);
+#else
+ enum : bool { InternalDatabaseAvailable = false };
+ QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
+ : QMimeProviderBase(db, QString())
+ { Q_UNREACHABLE() };
+#endif
QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory);
~QMimeXMLProvider();
@@ -156,6 +166,7 @@ public:
private:
void load(const QString &fileName);
+ void load(const char *data, qsizetype len);
typedef QHash<QString, QMimeType> NameMimeTypeMap;
NameMimeTypeMap m_nameMimeTypeMap;
diff --git a/src/corelib/serialization/qcborcommon.cpp b/src/corelib/serialization/qcborcommon.cpp
new file mode 100644
index 0000000000..37fb198744
--- /dev/null
+++ b/src/corelib/serialization/qcborcommon.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define CBOR_NO_ENCODER_API
+#define CBOR_NO_PARSER_API
+#include "qcborcommon_p.h"
+
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+
+#include <cborerrorstrings.c>
+
+/*!
+ \headerfile <QtCborCommon>
+
+ \brief The <QtCborCommon> header contains definitions common to both the
+ streaming classes (QCborStreamReader and QCborStreamWriter) and to
+ QCborValue.
+ */
+
+/*!
+ \enum QCborSimpleType
+ \relates <QtCborCommon>
+
+ This enum contains the possible "Simple Types" for CBOR. Simple Types range
+ from 0 to 255 and are types that carry no further value.
+
+ The following values are currently known:
+
+ \value False A "false" boolean.
+ \value True A "true" boolean.
+ \value Null Absence of value (null).
+ \value Undefined Missing or deleted value, usually an error.
+
+ Qt CBOR API supports encoding and decoding any Simple Type, whether one of
+ those above or any other value.
+
+ Applications should only use further values if a corresponding specification
+ has been published, otherwise interpretation and validation by the remote
+ may fail. Values 24 to 31 are reserved and must not be used.
+
+ The current authoritative list is maintained by IANA in the
+ \l{https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xml}{Simple
+ Values registry}.
+
+ \sa QCborStreamWriter::append(QCborSimpleType), QCborStreamReader::isSimpleType(),
+ QCborStreamReader::toSimpleType(), QCborValue::isSimpleType(), QCborValue::toSimpleType()
+ */
+
+#if !defined(QT_NO_DATASTREAM)
+QDataStream &operator<<(QDataStream &ds, QCborSimpleType st)
+{
+ return ds << quint8(st);
+}
+
+QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
+{
+ quint8 v;
+ ds >> v;
+ st = QCborSimpleType(v);
+ return ds;
+}
+#endif
+
+/*!
+ \enum QCborTag
+ \relates <QtCborCommon>
+
+ This enum contains no enumeration and is used only to provide type-safe
+ access to a CBOR tag.
+
+ CBOR tags are 64-bit numbers that are attached to generic CBOR types to
+ provide further semantic meaning. QCborTag may be constructed from an
+ enumeration found in QCborKnownTags or directly by providing the numeric
+ representation.
+
+ For example, the following creates a QCborValue containing a byte array
+ tagged with a tag 2.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 0
+
+ \sa QCborKnownTags, QCborStreamWriter::append(QCborTag),
+ QCborStreamReader::isTag(), QCborStreamReader::toTag(),
+ QCborValue::isTag(), QCborValue::tag()
+ */
+
+/*!
+ \enum QCborKnownTags
+ \relates <QtCborCommon>
+
+ This enum contains a list of CBOR tags, known at the time of the Qt
+ implementation. This list is not meant to be complete and contains only
+ tags that are either backed by an RFC or specifically used by the Qt
+ implementation.
+
+ The authoritative list is maintained by IANA in the
+ \l{https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml}{CBOR tag
+ registry}.
+
+ \value DateTimeString A date and time string, formatted according to RFC 3339, as refined
+ by RFC 4287. It is the same format as Qt::ISODate and
+ Qt::ISODateWithMs.
+ \value UnixTime_t A numerical representation of seconds elapsed since
+ 1970-01-01T00:00Z.
+ \value PositiveBignum A positive number of arbitrary length, encoded as a byte array in
+ network byte order. For example, the number 2\sup{64} is represented by
+ a byte array containing the byte value 0x01 followed by 8 zero bytes.
+ \value NegativeBignum A negative number of arbirary length, encoded as the absolute value
+ of that number, minus one. For example, a byte array containing
+ byte value 0x02 followed by 8 zero bytes represents the number
+ -2\sup{65} - 1.
+ \value Decimal A decimal fraction, encoded as an array of two integers: the first
+ is the exponent of the power of 10, the second the integral
+ mantissa. The value 273.15 would be encoded as array \c{[-2, 27315]}.
+ \value Bigfloat Similar to Decimal, but the exponent is a power of 2 instead.
+ \value COSE_Encrypt0 An \c Encrypt0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Mac0 A \c Mac0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Sign1 A \c Sign1 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value ExpectedBase64url Indicates that the byte array should be encoded using Base64url
+ if the stream is converted to JSON.
+ \value ExpectedBase64 Indicates that the byte array should be encoded using Base64
+ if the stream is converted to JSON.
+ \value ExpectedBase16 Indicates that the byte array should be encoded using Base16 (hex)
+ if the stream is converted to JSON.
+ \value EncodedCbor Indicates that the byte array contains a CBOR stream.
+ \value Url Indicates that the string contains a URL.
+ \value Base64url Indicates that the string contains data encoded using Base64url.
+ \value Base64 Indicates that the string contains data encoded using Base64.
+ \value RegularExpression Indicates that the string contains a Perl-Compatible Regular
+ Expression pattern.
+ \value MimeMessage Indicates that the string contains a MIME message (according to
+ \l{https://tools.ietf.org/html/rfc2045}){RFC 2045}.
+ \value Uuid Indicates that the byte array contains a UUID.
+ \value COSE_Encrypt An \c Encrypt map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Mac A \c Mac map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Sign A \c Sign map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value Signature No change in interpretation; this tag can be used as the outermost
+ tag in a CBOR stream as the file header.
+
+ The following tags are interpreted by QCborValue during decoding and will
+ produce objects with extended Qt types, and it will use those tags when
+ encoding the same extended types.
+
+ \value DateTimeString \l QDateTime
+ \value UnixTime_t \l QDateTime (only in decoding)
+ \value Url \l QUrl
+ \value Uuid \l QUuid
+
+ Additionally, if a QCborValue containing a QByteArray is tagged using one of
+ \c ExpectedBase64url, \c ExpectedBase64 or \c ExpectedBase16, QCborValue
+ will use the expected encoding when converting to JSON (see
+ QCborValue::toJsonValue).
+
+ \sa QCborTag, QCborStreamWriter::append(QCborTag),
+ QCborStreamReader::isTag(), QCborStreamReader::toTag(),
+ QCborValue::isTag(), QCborValue::tag()
+ */
+
+/*!
+ \class QCborError
+ \inmodule QtCore
+ \relates <QtCborCommon>
+ \reentrant
+ \since 5.12
+
+ \brief The QCborError class holds the error condition found while parsing or
+ validating a CBOR stream.
+
+ \sa QCborStreamReader, QCborValue, QCborParserError
+ */
+
+/*!
+ \enum QCborError::Code
+
+ This enum contains the possible error condition codes.
+
+ \value NoError No error was detected.
+ \value UnknownError An unknown error occurred and no further details are available.
+ \value AdvancePastEnd QCborStreamReader::next() was called but there are no more elements in
+ the current context.
+ \value InputOutputError An I/O error with the QIODevice occurred.
+ \value GarbageAtEnd Data was found in the input stream after the last element.
+ \value EndOfFile The end of the input stream was unexpectedly reached while processing an
+ element.
+ \value UnexpectedBreak The CBOR stream contains a Break where it is not allowed (data is
+ corrupt and the error is not recoverable).
+ \value UnknownType The CBOR stream contains an unknown/unparseable Type (data is corrupt
+ and the and the error is not recoverable).
+ \value IllegalType The CBOR stream contains a known type in a position it is not allowed
+ to exist (data is corrupt and the error is not recoverable).
+ \value IllegalNumber The CBOR stream appears to be encoding a number larger than 64-bit
+ (data is corrupt and the error is not recoverable).
+ \value IllegalSimpleType The CBOR stream contains a Simple Type encoded incorrectly (data is
+ corrupt and the error is not recoverable).
+ \value InvalidUtf8String The CBOR stream contains a text string that does not decode properly
+ as UTF-8 (data is corrupt and the error is not recoverable).
+ \value DataTooLarge CBOR string, map or array is too big and cannot be parsed by Qt
+ (internal limitation, but the error is not recoverable).
+ \value NestingTooDeep Too many levels of arrays or maps encountered while processing the
+ input (internal limitation, but the error is not recoverable).
+ \value UnsupportedType The CBOR stream contains a known type that the implementation does not
+ support (internal limitation, but the error is not recoverable).
+ */
+
+/*!
+ \variable QCborError::c
+ \internal
+ */
+
+/*!
+ \fn QCborError::operator Code() const
+
+ Returns the error code that this QCborError object stores.
+ */
+
+/*!
+ Returns a text string that matches the error code in this QCborError object.
+
+ Note: the string is not translated. Applications whose interface allow users
+ to parse CBOR streams need to provide their own, translated strings.
+
+ \sa QCborError::Code
+ */
+QString QCborError::toString() const
+{
+ switch (c) {
+ case NoError:
+ Q_STATIC_ASSERT(int(NoError) == int(CborNoError));
+ return QString();
+
+ case UnknownError:
+ Q_STATIC_ASSERT(int(UnknownError) == int(CborUnknownError));
+ return QStringLiteral("Unknown error");
+ case AdvancePastEnd:
+ Q_STATIC_ASSERT(int(AdvancePastEnd) == int(CborErrorAdvancePastEOF));
+ return QStringLiteral("Read past end of buffer (more bytes needed)");
+ case InputOutputError:
+ Q_STATIC_ASSERT(int(InputOutputError) == int(CborErrorIO));
+ return QStringLiteral("Input/Output error");
+ case GarbageAtEnd:
+ Q_STATIC_ASSERT(int(GarbageAtEnd) == int(CborErrorGarbageAtEnd));
+ return QStringLiteral("Data found after the end of the stream");
+ case EndOfFile:
+ Q_STATIC_ASSERT(int(EndOfFile) == int(CborErrorUnexpectedEOF));
+ return QStringLiteral("Unexpected end of input data (more bytes needed)");
+ case UnexpectedBreak:
+ Q_STATIC_ASSERT(int(UnexpectedBreak) == int(CborErrorUnexpectedBreak));
+ return QStringLiteral("Invalid CBOR stream: unexpected 'break' byte");
+ case UnknownType:
+ Q_STATIC_ASSERT(int(UnknownType) == int(CborErrorUnknownType));
+ return QStringLiteral("Invalid CBOR stream: unknown type");
+ case IllegalType:
+ Q_STATIC_ASSERT(int(IllegalType) == int(CborErrorIllegalType));
+ return QStringLiteral("Invalid CBOR stream: illegal type found");
+ case IllegalNumber:
+ Q_STATIC_ASSERT(int(IllegalNumber) == int(CborErrorIllegalNumber));
+ return QStringLiteral("Invalid CBOR stream: illegal number encoding (future extension)");
+ case IllegalSimpleType:
+ Q_STATIC_ASSERT(int(IllegalSimpleType) == int(CborErrorIllegalSimpleType));
+ return QStringLiteral("Invalid CBOR stream: illegal simple type");
+ case InvalidUtf8String:
+ Q_STATIC_ASSERT(int(InvalidUtf8String) == int(CborErrorInvalidUtf8TextString));
+ return QStringLiteral("Invalid CBOR stream: invalid UTF-8 text string");
+ case DataTooLarge:
+ Q_STATIC_ASSERT(int(DataTooLarge) == int(CborErrorDataTooLarge));
+ return QStringLiteral("Internal limitation: data set too large");
+ case NestingTooDeep:
+ Q_STATIC_ASSERT(int(NestingTooDeep) == int(CborErrorNestingTooDeep));
+ return QStringLiteral("Internal limitation: data nesting too deep");
+ case UnsupportedType:
+ Q_STATIC_ASSERT(int(UnsupportedType) == int(CborErrorUnsupportedType));
+ return QStringLiteral("Internal limitation: unsupported type");
+ }
+
+ // get the error string from TinyCBOR
+ CborError err = CborError(int(c));
+ return QString::fromLatin1(cbor_error_string(err));
+}
+
+QT_END_NAMESPACE
+
+#ifndef QT_BOOTSTRAPPED
+#include "moc_qcborcommon.cpp"
+#endif
diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h
index 3dfe50cd09..bec46399ce 100644
--- a/src/corelib/serialization/qcborcommon.h
+++ b/src/corelib/serialization/qcborcommon.h
@@ -148,6 +148,8 @@ inline uint qHash(QCborTag tag, uint seed = 0)
return qHash(quint64(tag), seed);
}
+enum class QCborNegativeInteger : quint64 {};
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCborTag)
diff --git a/src/corelib/serialization/qcborcommon_p.h b/src/corelib/serialization/qcborcommon_p.h
new file mode 100644
index 0000000000..9b7f4b7099
--- /dev/null
+++ b/src/corelib/serialization/qcborcommon_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCBORCOMMON_P_H
+#define QCBORCOMMON_P_H
+
+#include "qcborcommon.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_NO_DEBUG
+# define NDEBUG 1
+#endif
+#undef assert
+#define assert Q_ASSERT
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wunused-function")
+QT_WARNING_DISABLE_CLANG("-Wunused-function")
+QT_WARNING_DISABLE_CLANG("-Wundefined-internal")
+
+#define CBOR_NO_VALIDATION_API 1
+#define CBOR_NO_PRETTY_API 1
+#define CBOR_API static inline
+#define CBOR_PRIVATE_API static inline
+#define CBOR_INLINE_API static inline
+
+#include <cbor.h>
+
+QT_WARNING_POP
+
+Q_DECLARE_TYPEINFO(CborValue, Q_PRIMITIVE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QCBORCOMMON_P_H
diff --git a/src/corelib/serialization/qcborstream.h b/src/corelib/serialization/qcborstream.h
index 08bf680cca..f2b88820cd 100644
--- a/src/corelib/serialization/qcborstream.h
+++ b/src/corelib/serialization/qcborstream.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -40,230 +41,17 @@
#ifndef QCBORSTREAM_H
#define QCBORSTREAM_H
-#include <QtCore/qbytearray.h>
-#include <QtCore/qcborcommon.h>
-#include <QtCore/qfloat16.h>
-#include <QtCore/qscopedpointer.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qstringview.h>
+#include <QtCore/qglobal.h>
-QT_REQUIRE_CONFIG(cborstream);
-
-// See qcborcommon.h for why we check
-#if defined(QT_X11_DEFINES_FOUND)
-# undef True
-# undef False
+#if QT_CONFIG(cborstreamreader)
+#include <QtCore/qcborstreamreader.h>
#endif
-QT_BEGIN_NAMESPACE
-
-class QIODevice;
-
-enum class QCborNegativeInteger : quint64 {};
-
-class QCborStreamWriterPrivate;
-class Q_CORE_EXPORT QCborStreamWriter
-{
-public:
- explicit QCborStreamWriter(QIODevice *device);
- explicit QCborStreamWriter(QByteArray *data);
- ~QCborStreamWriter();
- Q_DISABLE_COPY(QCborStreamWriter)
-
- void setDevice(QIODevice *device);
- QIODevice *device() const;
-
- void append(quint64 u);
- void append(qint64 i);
- void append(QCborNegativeInteger n);
- void append(const QByteArray &ba) { appendByteString(ba.constData(), ba.size()); }
- void append(QLatin1String str);
- void append(QStringView str);
- void append(QCborTag tag);
- void append(QCborKnownTags tag) { append(QCborTag(tag)); }
- void append(QCborSimpleType st);
- void append(std::nullptr_t) { append(QCborSimpleType::Null); }
- void append(qfloat16 f);
- void append(float f);
- void append(double d);
-
- void appendByteString(const char *data, qsizetype len);
- void appendTextString(const char *utf8, qsizetype len);
-
- // convenience
- void append(bool b) { append(b ? QCborSimpleType::True : QCborSimpleType::False); }
- void appendNull() { append(QCborSimpleType::Null); }
- void appendUndefined() { append(QCborSimpleType::Undefined); }
-
-#ifndef Q_QDOC
- // overloads to make normal code not complain
- void append(int i) { append(qint64(i)); }
- void append(uint u) { append(quint64(u)); }
-#endif
-#ifndef QT_NO_CAST_FROM_ASCII
- void append(const char *str, qsizetype size = -1)
- { appendTextString(str, (str && size == -1) ? int(strlen(str)) : size); }
+#if QT_CONFIG(cborstreamwriter)
+#include <QtCore/qcborstreamwriter.h>
#endif
- void startArray();
- void startArray(quint64 count);
- bool endArray();
- void startMap();
- void startMap(quint64 count);
- bool endMap();
-
- // no API for encoding chunked strings
-
-private:
- QScopedPointer<QCborStreamWriterPrivate> d;
-};
-
-class QCborStreamReaderPrivate;
-class Q_CORE_EXPORT QCborStreamReader
-{
- Q_GADGET
-public:
- enum Type : quint8 {
- UnsignedInteger = 0x00,
- NegativeInteger = 0x20,
- ByteString = 0x40,
- ByteArray = ByteString,
- TextString = 0x60,
- String = TextString,
- Array = 0x80,
- Map = 0xa0,
- Tag = 0xc0,
- SimpleType = 0xe0,
- HalfFloat = 0xf9,
- Float16 = HalfFloat,
- Float = 0xfa,
- Double = 0xfb,
-
- Invalid = 0xff
- };
- Q_ENUM(Type)
-
- enum StringResultCode {
- EndOfString = 0,
- Ok = 1,
- Error = -1
- };
- template <typename Container> struct StringResult {
- Container data;
- StringResultCode status = Error;
- };
- Q_ENUM(StringResultCode)
-
- QCborStreamReader();
- QCborStreamReader(const char *data, qsizetype len);
- QCborStreamReader(const quint8 *data, qsizetype len);
- explicit QCborStreamReader(const QByteArray &data);
- explicit QCborStreamReader(QIODevice *device);
- ~QCborStreamReader();
- Q_DISABLE_COPY(QCborStreamReader)
-
- void setDevice(QIODevice *device);
- QIODevice *device() const;
- void addData(const QByteArray &data);
- void addData(const char *data, qsizetype len);
- void addData(const quint8 *data, qsizetype len)
- { addData(reinterpret_cast<const char *>(data), len); }
- void reparse();
- void clear();
- void reset();
-
- QCborError lastError();
-
- qint64 currentOffset() const;
-
- bool isValid() const { return !isInvalid(); }
-
- int containerDepth() const;
- QCborStreamReader::Type parentContainerType() const;
- bool hasNext() const noexcept Q_DECL_PURE_FUNCTION;
- bool next(int maxRecursion = 10000);
-
- Type type() const { return QCborStreamReader::Type(type_); }
- bool isUnsignedInteger() const { return type() == UnsignedInteger; }
- bool isNegativeInteger() const { return type() == NegativeInteger; }
- bool isInteger() const { return quint8(type()) <= quint8(NegativeInteger); }
- bool isByteArray() const { return type() == ByteArray; }
- bool isString() const { return type() == String; }
- bool isArray() const { return type() == Array; }
- bool isMap() const { return type() == Map; }
- bool isTag() const { return type() == Tag; }
- bool isSimpleType() const { return type() == SimpleType; }
- bool isFloat16() const { return type() == Float16; }
- bool isFloat() const { return type() == Float; }
- bool isDouble() const { return type() == Double; }
- bool isInvalid() const { return type() == Invalid; }
-
- bool isSimpleType(QCborSimpleType st) const { return isSimpleType() && toSimpleType() == st; }
- bool isFalse() const { return isSimpleType(QCborSimpleType::False); }
- bool isTrue() const { return isSimpleType(QCborSimpleType::True); }
- bool isBool() const { return isFalse() || isTrue(); }
- bool isNull() const { return isSimpleType(QCborSimpleType::Null); }
- bool isUndefined() const { return isSimpleType(QCborSimpleType::Undefined); }
-
- bool isLengthKnown() const noexcept Q_DECL_PURE_FUNCTION;
- quint64 length() const;
-
- bool isContainer() const { return isMap() || isArray(); }
- bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
- bool leaveContainer();
-
- StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
- StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
- qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
- StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
-
- bool toBool() const { Q_ASSERT(isBool()); return value64 - int(QCborSimpleType::False); }
- QCborTag toTag() const { Q_ASSERT(isTag()); return QCborTag(value64); }
- quint64 toUnsignedInteger() const { Q_ASSERT(isUnsignedInteger()); return value64; }
- QCborNegativeInteger toNegativeInteger() const { Q_ASSERT(isNegativeInteger()); return QCborNegativeInteger(value64 + 1); }
- QCborSimpleType toSimpleType() const{ Q_ASSERT(isSimpleType()); return QCborSimpleType(value64); }
- qfloat16 toFloat16() const { Q_ASSERT(isFloat16()); return _toFloatingPoint<qfloat16>(); }
- float toFloat() const { Q_ASSERT(isFloat()); return _toFloatingPoint<float>(); }
- double toDouble() const { Q_ASSERT(isDouble()); return _toFloatingPoint<double>(); }
-
- qint64 toInteger() const
- {
- Q_ASSERT(isInteger());
- qint64 v = qint64(value64);
- if (isNegativeInteger())
- return -v - 1;
- return v;
- }
-
-private:
- void preparse();
- bool _enterContainer_helper();
- StringResult<QString> _readString_helper();
- StringResult<QByteArray> _readByteArray_helper();
- qsizetype _currentStringChunkSize() const;
-
- template <typename FP> FP _toFloatingPoint() const noexcept
- {
- using UIntFP = typename QIntegerForSizeof<FP>::Unsigned;
- UIntFP u = UIntFP(value64);
- FP f;
- memcpy(static_cast<void *>(&f), &u, sizeof(f));
- return f;
- }
-
- friend QCborStreamReaderPrivate;
- friend class QCborContainerPrivate;
- quint64 value64;
- QScopedPointer<QCborStreamReaderPrivate> d;
- quint8 type_;
- quint8 reserved[3] = {};
-};
-
+QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-#if defined(QT_X11_DEFINES_FOUND)
-# define True 1
-# define False 0
-#endif
-
#endif // QCBORSTREAM_H
diff --git a/src/corelib/serialization/qcborstream.cpp b/src/corelib/serialization/qcborstreamreader.cpp
index a232f7eef7..c983436606 100644
--- a/src/corelib/serialization/qcborstream.cpp
+++ b/src/corelib/serialization/qcborstreamreader.cpp
@@ -37,84 +37,46 @@
**
****************************************************************************/
-#include "qcborstream.h"
+#include "qcborstreamreader.h"
+
+#define CBOR_NO_ENCODER_API
+#include <private/qcborcommon_p.h>
#include <private/qnumeric_p.h>
#include <private/qutfcodec_p.h>
-#include <qbuffer.h>
#include <qdebug.h>
#include <qstack.h>
-#include <qdatastream.h>
QT_BEGIN_NAMESPACE
-#ifdef QT_NO_DEBUG
-# define NDEBUG 1
-#endif
-#undef assert
-#define assert Q_ASSERT
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_GCC("-Wunused-function")
-QT_WARNING_DISABLE_CLANG("-Wunused-function")
-QT_WARNING_DISABLE_CLANG("-Wundefined-internal")
-QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
-
-#define CBOR_ENCODER_NO_CHECK_USER
-
-#define CBOR_NO_VALIDATION_API 1
-#define CBOR_NO_PRETTY_API 1
-#define CBOR_API static inline
-#define CBOR_PRIVATE_API static inline
-#define CBOR_INLINE_API static inline
-
-#include <cbor.h>
-
-static CborError qt_cbor_encoder_write_callback(void *token, const void *data, size_t len, CborEncoderAppendType);
static bool qt_cbor_decoder_can_read(void *token, size_t len);
static void qt_cbor_decoder_advance(void *token, size_t len);
static void *qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len);
static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len);
-#define CBOR_ENCODER_WRITER_CONTROL 1
-#define CBOR_ENCODER_WRITE_FUNCTION qt_cbor_encoder_write_callback
-
#define CBOR_PARSER_READER_CONTROL 1
#define CBOR_PARSER_CAN_READ_BYTES_FUNCTION qt_cbor_decoder_can_read
#define CBOR_PARSER_ADVANCE_BYTES_FUNCTION qt_cbor_decoder_advance
#define CBOR_PARSER_TRANSFER_STRING_FUNCTION qt_cbor_decoder_transfer_string
#define CBOR_PARSER_READ_BYTES_FUNCTION qt_cbor_decoder_read
-#include "../3rdparty/tinycbor/src/cborencoder.c"
-#include "../3rdparty/tinycbor/src/cborerrorstrings.c"
-#include "../3rdparty/tinycbor/src/cborparser.c"
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
+
+#include <cborparser.c>
+
+QT_WARNING_POP
-// silence compilers that complain about this being a static function declared
-// but never defined
-static CborError cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
-{
- Q_UNREACHABLE();
- return CborErrorInternalError;
-}
static CborError _cbor_value_dup_string(const CborValue *, void **, size_t *, CborValue *)
{
Q_UNREACHABLE();
return CborErrorInternalError;
}
-static CborError cbor_value_get_half_float_as_float(const CborValue *, float *)
+static CborError Q_DECL_UNUSED cbor_value_get_half_float_as_float(const CborValue *, float *)
{
Q_UNREACHABLE();
return CborErrorInternalError;
}
-static CborError cbor_encode_float_as_half_float(CborEncoder *, float)
-{
- Q_UNREACHABLE();
- return CborErrorInternalError;
-}
-QT_WARNING_POP
-
-Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(CborValue, Q_PRIMITIVE_TYPE);
// confirm our constants match TinyCBOR's
Q_STATIC_ASSERT(int(QCborStreamReader::UnsignedInteger) == CborIntegerType);
@@ -130,1083 +92,6 @@ Q_STATIC_ASSERT(int(QCborStreamReader::Double) == CborDoubleType);
Q_STATIC_ASSERT(int(QCborStreamReader::Invalid) == CborInvalidType);
/*!
- \headerfile <QtCborCommon>
-
- \brief The <QtCborCommon> header contains definitions common to both the
- streaming classes (QCborStreamReader and QCborStreamWriter) and to
- QCborValue.
- */
-
-/*!
- \enum QCborSimpleType
- \relates <QtCborCommon>
-
- This enum contains the possible "Simple Types" for CBOR. Simple Types range
- from 0 to 255 and are types that carry no further value.
-
- The following values are currently known:
-
- \value False A "false" boolean.
- \value True A "true" boolean.
- \value Null Absence of value (null).
- \value Undefined Missing or deleted value, usually an error.
-
- Qt CBOR API supports encoding and decoding any Simple Type, whether one of
- those above or any other value.
-
- Applications should only use further values if a corresponding specification
- has been published, otherwise interpretation and validation by the remote
- may fail. Values 24 to 31 are reserved and must not be used.
-
- The current authoritative list is maintained by IANA in the
- \l{https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xml}{Simple
- Values registry}.
-
- \sa QCborStreamWriter::append(QCborSimpleType), QCborStreamReader::isSimpleType(),
- QCborStreamReader::toSimpleType(), QCborValue::isSimpleType(), QCborValue::toSimpleType()
- */
-
-#if !defined(QT_NO_DATASTREAM)
-QDataStream &operator<<(QDataStream &ds, QCborSimpleType st)
-{
- return ds << quint8(st);
-}
-
-QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
-{
- quint8 v;
- ds >> v;
- st = QCborSimpleType(v);
- return ds;
-}
-#endif
-
-/*!
- \enum QCborTag
- \relates <QtCborCommon>
-
- This enum contains no enumeration and is used only to provide type-safe
- access to a CBOR tag.
-
- CBOR tags are 64-bit numbers that are attached to generic CBOR types to
- provide further semantic meaning. QCborTag may be constructed from an
- enumeration found in QCborKnownTags or directly by providing the numeric
- representation.
-
- For example, the following creates a QCborValue containing a byte array
- tagged with a tag 2.
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 0
-
- \sa QCborKnownTags, QCborStreamWriter::append(QCborTag),
- QCborStreamReader::isTag(), QCborStreamReader::toTag(),
- QCborValue::isTag(), QCborValue::tag()
- */
-
-/*!
- \enum QCborKnownTags
- \relates <QtCborCommon>
-
- This enum contains a list of CBOR tags, known at the time of the Qt
- implementation. This list is not meant to be complete and contains only
- tags that are either backed by an RFC or specifically used by the Qt
- implementation.
-
- The authoritative list is maintained by IANA in the
- \l{https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml}{CBOR tag
- registry}.
-
- \value DateTimeString A date and time string, formatted according to RFC 3339, as refined
- by RFC 4287. It is the same format as Qt::ISODate and
- Qt::ISODateWithMs.
- \value UnixTime_t A numerical representation of seconds elapsed since
- 1970-01-01T00:00Z.
- \value PositiveBignum A positive number of arbitrary length, encoded as a byte array in
- network byte order. For example, the number 2\sup{64} is represented by
- a byte array containing the byte value 0x01 followed by 8 zero bytes.
- \value NegativeBignum A negative number of arbirary length, encoded as the absolute value
- of that number, minus one. For example, a byte array containing
- byte value 0x02 followed by 8 zero bytes represents the number
- -2\sup{65} - 1.
- \value Decimal A decimal fraction, encoded as an array of two integers: the first
- is the exponent of the power of 10, the second the integral
- mantissa. The value 273.15 would be encoded as array \c{[-2, 27315]}.
- \value Bigfloat Similar to Decimal, but the exponent is a power of 2 instead.
- \value COSE_Encrypt0 An \c Encrypt0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
- (CBOR Object Signing and Encryption).
- \value COSE_Mac0 A \c Mac0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
- (CBOR Object Signing and Encryption).
- \value COSE_Sign1 A \c Sign1 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
- (CBOR Object Signing and Encryption).
- \value ExpectedBase64url Indicates that the byte array should be encoded using Base64url
- if the stream is converted to JSON.
- \value ExpectedBase64 Indicates that the byte array should be encoded using Base64
- if the stream is converted to JSON.
- \value ExpectedBase16 Indicates that the byte array should be encoded using Base16 (hex)
- if the stream is converted to JSON.
- \value EncodedCbor Indicates that the byte array contains a CBOR stream.
- \value Url Indicates that the string contains a URL.
- \value Base64url Indicates that the string contains data encoded using Base64url.
- \value Base64 Indicates that the string contains data encoded using Base64.
- \value RegularExpression Indicates that the string contains a Perl-Compatible Regular
- Expression pattern.
- \value MimeMessage Indicates that the string contains a MIME message (according to
- \l{https://tools.ietf.org/html/rfc2045}){RFC 2045}.
- \value Uuid Indicates that the byte array contains a UUID.
- \value COSE_Encrypt An \c Encrypt map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
- (CBOR Object Signing and Encryption).
- \value COSE_Mac A \c Mac map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
- (CBOR Object Signing and Encryption).
- \value COSE_Sign A \c Sign map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
- (CBOR Object Signing and Encryption).
- \value Signature No change in interpretation; this tag can be used as the outermost
- tag in a CBOR stream as the file header.
-
- The following tags are interpreted by QCborValue during decoding and will
- produce objects with extended Qt types, and it will use those tags when
- encoding the same extended types.
-
- \value DateTimeString \l QDateTime
- \value UnixTime_t \l QDateTime (only in decoding)
- \value Url \l QUrl
- \value Uuid \l QUuid
-
- Additionally, if a QCborValue containing a QByteArray is tagged using one of
- \c ExpectedBase64url, \c ExpectedBase64 or \c ExpectedBase16, QCborValue
- will use the expected encoding when converting to JSON (see
- QCborValue::toJsonValue).
-
- \sa QCborTag, QCborStreamWriter::append(QCborTag),
- QCborStreamReader::isTag(), QCborStreamReader::toTag(),
- QCborValue::isTag(), QCborValue::tag()
- */
-
-/*!
- \class QCborError
- \inmodule QtCore
- \relates <QtCborCommon>
- \reentrant
- \since 5.12
-
- \brief The QCborError class holds the error condition found while parsing or
- validating a CBOR stream.
-
- \sa QCborStreamReader, QCborValue, QCborParserError
- */
-
-/*!
- \enum QCborError::Code
-
- This enum contains the possible error condition codes.
-
- \value NoError No error was detected.
- \value UnknownError An unknown error occurred and no further details are available.
- \value AdvancePastEnd QCborStreamReader::next() was called but there are no more elements in
- the current context.
- \value InputOutputError An I/O error with the QIODevice occurred.
- \value GarbageAtEnd Data was found in the input stream after the last element.
- \value EndOfFile The end of the input stream was unexpectedly reached while processing an
- element.
- \value UnexpectedBreak The CBOR stream contains a Break where it is not allowed (data is
- corrupt and the error is not recoverable).
- \value UnknownType The CBOR stream contains an unknown/unparseable Type (data is corrupt
- and the and the error is not recoverable).
- \value IllegalType The CBOR stream contains a known type in a position it is not allowed
- to exist (data is corrupt and the error is not recoverable).
- \value IllegalNumber The CBOR stream appears to be encoding a number larger than 64-bit
- (data is corrupt and the error is not recoverable).
- \value IllegalSimpleType The CBOR stream contains a Simple Type encoded incorrectly (data is
- corrupt and the error is not recoverable).
- \value InvalidUtf8String The CBOR stream contains a text string that does not decode properly
- as UTF-8 (data is corrupt and the error is not recoverable).
- \value DataTooLarge CBOR string, map or array is too big and cannot be parsed by Qt
- (internal limitation, but the error is not recoverable).
- \value NestingTooDeep Too many levels of arrays or maps encountered while processing the
- input (internal limitation, but the error is not recoverable).
- \value UnsupportedType The CBOR stream contains a known type that the implementation does not
- support (internal limitation, but the error is not recoverable).
- */
-
-// Convert from CborError to QCborError.
-//
-// Centralized in a function in case we need to make more adjustments in the
-// future.
-static QCborError fromCborError(CborError err)
-{
- return { QCborError::Code(int(err)) };
-}
-
-// Convert to CborError from QCborError.
-//
-// Centralized in a function in case we need to make more adjustments in the
-// future.
-static CborError toCborError(QCborError c)
-{
- return CborError(int(c.c));
-}
-
-/*!
- \variable QCborError::c
- \internal
- */
-
-/*!
- \fn QCborError::operator Code() const
-
- Returns the error code that this QCborError object stores.
- */
-
-/*!
- Returns a text string that matches the error code in this QCborError object.
-
- Note: the string is not translated. Applications whose interface allow users
- to parse CBOR streams need to provide their own, translated strings.
-
- \sa QCborError::Code
- */
-QString QCborError::toString() const
-{
- switch (c) {
- case NoError:
- Q_STATIC_ASSERT(int(NoError) == int(CborNoError));
- return QString();
-
- case UnknownError:
- Q_STATIC_ASSERT(int(UnknownError) == int(CborUnknownError));
- return QStringLiteral("Unknown error");
- case AdvancePastEnd:
- Q_STATIC_ASSERT(int(AdvancePastEnd) == int(CborErrorAdvancePastEOF));
- return QStringLiteral("Read past end of buffer (more bytes needed)");
- case InputOutputError:
- Q_STATIC_ASSERT(int(InputOutputError) == int(CborErrorIO));
- return QStringLiteral("Input/Output error");
- case GarbageAtEnd:
- Q_STATIC_ASSERT(int(GarbageAtEnd) == int(CborErrorGarbageAtEnd));
- return QStringLiteral("Data found after the end of the stream");
- case EndOfFile:
- Q_STATIC_ASSERT(int(EndOfFile) == int(CborErrorUnexpectedEOF));
- return QStringLiteral("Unexpected end of input data (more bytes needed)");
- case UnexpectedBreak:
- Q_STATIC_ASSERT(int(UnexpectedBreak) == int(CborErrorUnexpectedBreak));
- return QStringLiteral("Invalid CBOR stream: unexpected 'break' byte");
- case UnknownType:
- Q_STATIC_ASSERT(int(UnknownType) == int(CborErrorUnknownType));
- return QStringLiteral("Invalid CBOR stream: unknown type");
- case IllegalType:
- Q_STATIC_ASSERT(int(IllegalType) == int(CborErrorIllegalType));
- return QStringLiteral("Invalid CBOR stream: illegal type found");
- case IllegalNumber:
- Q_STATIC_ASSERT(int(IllegalNumber) == int(CborErrorIllegalNumber));
- return QStringLiteral("Invalid CBOR stream: illegal number encoding (future extension)");
- case IllegalSimpleType:
- Q_STATIC_ASSERT(int(IllegalSimpleType) == int(CborErrorIllegalSimpleType));
- return QStringLiteral("Invalid CBOR stream: illegal simple type");
- case InvalidUtf8String:
- Q_STATIC_ASSERT(int(InvalidUtf8String) == int(CborErrorInvalidUtf8TextString));
- return QStringLiteral("Invalid CBOR stream: invalid UTF-8 text string");
- case DataTooLarge:
- Q_STATIC_ASSERT(int(DataTooLarge) == int(CborErrorDataTooLarge));
- return QStringLiteral("Internal limitation: data set too large");
- case NestingTooDeep:
- Q_STATIC_ASSERT(int(NestingTooDeep) == int(CborErrorNestingTooDeep));
- return QStringLiteral("Internal limitation: data nesting too deep");
- case UnsupportedType:
- Q_STATIC_ASSERT(int(UnsupportedType) == int(CborErrorUnsupportedType));
- return QStringLiteral("Internal limitation: unsupported type");
- }
-
- // get the error string from TinyCBOR
- CborError err = toCborError(*this);
- return QString::fromLatin1(cbor_error_string(err));
-}
-
-/*!
- \class QCborStreamWriter
- \inmodule QtCore
- \ingroup cbor
- \reentrant
- \since 5.12
-
- \brief The QCborStreamWriter class is a simple CBOR encoder operating on a
- one-way stream.
-
- This class can be used to quickly encode a stream of CBOR content directly
- to either a QByteArray or QIODevice. CBOR is the Concise Binary Object
- Representation, a very compact form of binary data encoding that is
- compatible with JSON. It was created by the IETF Constrained RESTful
- Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
- be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
- protocol}.
-
- QCborStreamWriter provides a StAX-like API, similar to that of
- \l{QXmlStreamWriter}. It is rather low-level and requires a bit of knowledge
- of CBOR encoding. For a simpler API, see \l{QCborValue} and especially the
- encoding function QCborValue::toCbor().
-
- The typical use of QCborStreamWriter is to create the object on the target
- QByteArray or QIODevice, then call one of the append() overloads with the
- desired type to be encoded. To create arrays and maps, QCborStreamWriter
- provides startArray() and startMap() overloads, which must be terminated by
- the corresponding endArray() and endMap() functions.
-
- The following example encodes the equivalent of this JSON content:
-
- \div{class="pre"}
- {
- "label": "journald",
- "autoDetect": false,
- "condition": "libs.journald",
- "output": [ "privateFeature" ]
- }
- \enddiv
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 1
-
- \section1 CBOR support
-
- QCborStreamWriter supports all CBOR features required to create canonical
- and strict streams. It implements almost all of the features specified in
- \l {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
-
- The following table lists the CBOR features that QCborStreamWriter supports.
-
- \table
- \header \li Feature \li Support
- \row \li Unsigned numbers \li Yes (full range)
- \row \li Negative numbers \li Yes (full range)
- \row \li Byte strings \li Yes
- \row \li Text strings \li Yes
- \row \li Chunked strings \li No
- \row \li Tags \li Yes (arbitrary)
- \row \li Booleans \li Yes
- \row \li Null \li Yes
- \row \li Undefined \li Yes
- \row \li Arbitrary simple values \li Yes
- \row \li Half-precision float (16-bit) \li Yes
- \row \li Single-precision float (32-bit) \li Yes
- \row \li Double-precision float (64-bit) \li Yes
- \row \li Infinities and NaN floating point \li Yes
- \row \li Determinate-length arrays and maps \li Yes
- \row \li Indeterminate-length arrays and maps \li Yes
- \row \li Map key types other than strings and integers \li Yes (arbitrary)
- \endtable
-
- \section2 Canonical CBOR encoding
-
- Canonical CBOR encoding is defined by
- \l{https://tools.ietf.org/html/rfc7049#section-3.9}{Section 3.9 of RFC
- 7049}. Canonical encoding is not a requirement for Qt's CBOR decoding
- functionality, but it may be required for some protocols. In particular,
- protocols that require the ability to reproduce the same stream identically
- may require this.
-
- In order to be considered "canonical", a CBOR stream must meet the
- following requirements:
-
- \list
- \li Integers must be as small as possible. QCborStreamWriter always
- does this (no user action is required and it is not possible
- to write overlong integers).
- \li Array, map and string lengths must be as short as possible. As
- above, QCborStreamWriter automatically does this.
- \li Arrays, maps and strings must use explicit length. QCborStreamWriter
- always does this for strings; for arrays and maps, be sure to call
- startArray() and startMap() overloads with explicit length.
- \li Keys in every map must be sorted in ascending order. QCborStreamWriter
- offers no help in this item: the developer must ensure that before
- calling append() for the map pairs.
- \li Floating point values should be as small as possible. QCborStreamWriter
- will not convert floating point values; it is up to the developer
- to perform this check prior to calling append() (see those functions'
- examples).
- \endlist
-
- \section2 Strict CBOR mode
-
- Strict mode is defined by
- \l{https://tools.ietf.org/html/rfc7049#section-3.10}{Section 3.10 of RFC
- 7049}. As for Canonical encoding above, QCborStreamWriter makes it possible
- to create strict CBOR streams, but does not require them or validate that
- the output is so.
-
- \list
- \li Keys in a map must be unique. QCborStreamWriter performs no validation
- of map keys.
- \li Tags may be required to be paired only with the correct types,
- according to their specification. QCborStreamWriter performs no
- validation of tag usage.
- \li Text Strings must be properly-encoded UTF-8. QCborStreamWriter always
- writes proper UTF-8 for strings added with append(), but performs no
- validation for strings added with appendTextString().
- \endlist
-
- \section2 Invalid CBOR stream
-
- It is also possible to misuse QCborStreamWriter and produce invalid CBOR
- streams that will fail to be decoded by a receiver. The following actions
- will produce invalid streams:
-
- \list
- \li Append a tag and not append the corresponding tagged value
- (QCborStreamWriter produces no diagnostic).
- \li Append too many or too few items to an array or map with explicit
- length (endMap() and endArray() will return false and
- QCborStreamWriter will log with qWarning()).
- \endlist
-
- \sa QCborStreamReader, QCborValue, QXmlStreamWriter
- */
-
-class QCborStreamWriterPrivate
-{
-public:
- static Q_CONSTEXPR quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
-
- QIODevice *device;
- CborEncoder encoder;
- QStack<CborEncoder> containerStack;
- bool deleteDevice = false;
-
- QCborStreamWriterPrivate(QIODevice *device)
- : device(device)
- {
- cbor_encoder_init_writer(&encoder, qt_cbor_encoder_write_callback, this);
- }
-
- ~QCborStreamWriterPrivate()
- {
- if (deleteDevice)
- delete device;
- }
-
- template <typename... Args> void executeAppend(CborError (*f)(CborEncoder *, Args...), Args... args)
- {
- f(&encoder, std::forward<Args>(args)...);
- }
-
- void createContainer(CborError (*f)(CborEncoder *, CborEncoder *, size_t), quint64 len = IndefiniteLength)
- {
- Q_STATIC_ASSERT(size_t(IndefiniteLength) == CborIndefiniteLength);
- if (sizeof(len) != sizeof(size_t) && len != IndefiniteLength) {
- if (Q_UNLIKELY(len >= CborIndefiniteLength)) {
- // TinyCBOR can't do this in 32-bit mode
- qWarning("QCborStreamWriter: container of size %llu is too big for a 32-bit build; "
- "will use indeterminate length instead", len);
- len = CborIndefiniteLength;
- }
- }
-
- containerStack.push(encoder);
- f(&containerStack.top(), &encoder, len);
- }
-
- bool closeContainer()
- {
- if (containerStack.isEmpty()) {
- qWarning("QCborStreamWriter: closing map or array that wasn't open");
- return false;
- }
-
- CborEncoder container = containerStack.pop();
- CborError err = cbor_encoder_close_container(&container, &encoder);
- encoder = container;
-
- if (Q_UNLIKELY(err)) {
- if (err == CborErrorTooFewItems)
- qWarning("QCborStreamWriter: not enough items added to array or map");
- else if (err == CborErrorTooManyItems)
- qWarning("QCborStreamWriter: too many items added to array or map");
- return false;
- }
-
- return true;
- }
-};
-
-static CborError qt_cbor_encoder_write_callback(void *self, const void *data, size_t len, CborEncoderAppendType)
-{
- auto that = static_cast<QCborStreamWriterPrivate *>(self);
- if (!that->device)
- return CborNoError;
- qint64 written = that->device->write(static_cast<const char *>(data), len);
- return (written == qsizetype(len) ? CborNoError : CborErrorIO);
-}
-
-/*!
- Creates a QCborStreamWriter object that will write the stream to \a device.
- The device must be opened before the first append() call is made. This
- constructor can be used with any class that derives from QIODevice, such as
- QFile, QProcess or QTcpSocket.
-
- QCborStreamWriter has no buffering, so every append() call will result in
- one or more calls to the device's \l {QIODevice::}{write()} method.
-
- The following example writes an empty map to a file:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 2
-
- QCborStreamWriter does not take ownership of \a device.
-
- \sa device(), setDevice()
- */
-QCborStreamWriter::QCborStreamWriter(QIODevice *device)
- : d(new QCborStreamWriterPrivate(device))
-{
-}
-
-/*!
- Creates a QCborStreamWriter object that will append the stream to \a data.
- All streaming is done immediately to the byte array, without the need for
- flushing any buffers.
-
- The following example writes a number to a byte array then returns
- it.
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 3
-
- QCborStreamWriter does not take ownership of \a data.
- */
-QCborStreamWriter::QCborStreamWriter(QByteArray *data)
- : d(new QCborStreamWriterPrivate(new QBuffer(data)))
-{
- d->deleteDevice = true;
- d->device->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
-}
-
-/*!
- Destroys this QCborStreamWriter object and frees any resources associated.
-
- QCborStreamWriter does not perform error checking to see if all required
- items were written to the stream prior to the object being destroyed. It is
- the programmer's responsibility to ensure that it was done.
- */
-QCborStreamWriter::~QCborStreamWriter()
-{
-}
-
-/*!
- Replaces the device or byte array that this QCborStreamWriter object is
- writing to with \a device.
-
- \sa device()
- */
-void QCborStreamWriter::setDevice(QIODevice *device)
-{
- if (d->deleteDevice)
- delete d->device;
- d->device = device;
- d->deleteDevice = false;
-}
-
-/*!
- Returns the QIODevice that this QCborStreamWriter object is writing to. The
- device must have previously been set with either the constructor or with
- setDevice().
-
- If this object was created by writing to a QByteArray, this function will
- return an internal instance of QBuffer, which is owned by QCborStreamWriter.
-
- \sa setDevice()
- */
-QIODevice *QCborStreamWriter::device() const
-{
- return d->device;
-}
-
-/*!
- \overload
-
- Appends the 64-bit unsigned value \a u to the CBOR stream, creating a CBOR
- Unsigned Integer value. In the following example, we write the values 0,
- 2\sup{32} and \c UINT64_MAX:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 4
-
- \sa QCborStreamReader::isUnsignedInteger(), QCborStreamReader::toUnsignedInteger()
- */
-void QCborStreamWriter::append(quint64 u)
-{
- d->executeAppend(cbor_encode_uint, uint64_t(u));
-}
-
-/*!
- \overload
-
- Appends the 64-bit signed value \a i to the CBOR stream. This will create
- either a CBOR Unsigned Integer or CBOR NegativeInteger value based on the
- sign of the parameter. In the following example, we write the values 0, -1,
- 2\sup{32} and \c INT64_MAX:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 5
-
- \sa QCborStreamReader::isInteger(), QCborStreamReader::toInteger()
- */
-void QCborStreamWriter::append(qint64 i)
-{
- d->executeAppend(cbor_encode_int, int64_t(i));
-}
-
-/*!
- \overload
-
- Appends the 64-bit negative value \a n to the CBOR stream.
- QCborNegativeInteger is a 64-bit enum that holds the absolute value of the
- negative number we want to write. If n is zero, the value written will be
- equivalent to 2\sup{64} (that is, -18,446,744,073,709,551,616).
-
- In the following example, we write the values -1, -2\sup{32} and INT64_MIN:
- \snippet code/src_corelib_serialization_qcborstream.cpp 6
-
- Note how this function can be used to encode numbers that cannot fit a
- standard computer's 64-bit signed integer like \l qint64. That is, if \a n
- is larger than \c{std::numeric_limits<qint64>::max()} or is 0, this will
- represent a negative number smaller than
- \c{std::numeric_limits<qint64>::min()}.
-
- \sa QCborStreamReader::isNegativeInteger(), QCborStreamReader::toNegativeInteger()
- */
-void QCborStreamWriter::append(QCborNegativeInteger n)
-{
- d->executeAppend(cbor_encode_negative_int, uint64_t(n));
-}
-
-/*!
- \fn void QCborStreamWriter::append(const QByteArray &ba)
- \overload
-
- Appends the byte array \a ba to the stream, creating a CBOR Byte String
- value. QCborStreamWriter will attempt to write the entire string in one
- chunk.
-
- The following example will load and append the contents of a file to the
- stream:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 7
-
- As the example shows, unlike JSON, CBOR requires no escaping for binary
- content.
-
- \sa appendByteString(), QCborStreamReader::isByteArray(),
- QCborStreamReader::readByteArray()
- */
-
-/*!
- \overload
-
- Appends the text string \a str to the stream, creating a CBOR Text String
- value. QCborStreamWriter will attempt to write the entire string in one
- chunk.
-
- The following example appends a simple string to the stream:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 8
-
- \b{Performance note}: CBOR requires that all Text Strings be encoded in
- UTF-8, so this function will iterate over the characters in the string to
- determine whether the contents are US-ASCII or not. If the string is found
- to contain characters outside of US-ASCII, it will allocate memory and
- convert to UTF-8. If this check is unnecessary, use appendTextString()
- instead.
-
- \sa QCborStreamReader::isString(), QCborStreamReader::readString()
- */
-void QCborStreamWriter::append(QLatin1String str)
-{
- // We've got Latin-1 but CBOR wants UTF-8, so check if the string is the
- // common subset (US-ASCII).
- if (QtPrivate::isAscii(str)) {
- // it is plain US-ASCII
- appendTextString(str.latin1(), str.size());
- } else {
- // non-ASCII, so we need a pass-through UTF-16
- append(QString(str));
- }
-}
-
-/*!
- \overload
-
- Appends the text string \a str to the stream, creating a CBOR Text String
- value. QCborStreamWriter will attempt to write the entire string in one
- chunk.
-
- The following example writes an arbitrary QString to the stream:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 9
-
- \sa QCborStreamReader::isString(), QCborStreamReader::readString()
- */
-void QCborStreamWriter::append(QStringView str)
-{
- QByteArray utf8 = str.toUtf8();
- appendTextString(utf8.constData(), utf8.size());
-}
-
-/*!
- \overload
-
- Appends the CBOR tag \a tag to the stream, creating a CBOR Tag value. All
- tags must be followed by another type which they provide meaning for.
-
- In the following example, we append a CBOR Tag 36 (Regular Expression) and a
- QRegularExpression's pattern to the stream:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 10
-
- \sa QCborStreamReader::isTag(), QCborStreamReader::toTag()
- */
-void QCborStreamWriter::append(QCborTag tag)
-{
- d->executeAppend(cbor_encode_tag, CborTag(tag));
-}
-
-/*!
- \fn void QCborStreamWriter::append(QCborKnownTags tag)
- \overload
-
- Appends the CBOR tag \a tag to the stream, creating a CBOR Tag value. All
- tags must be followed by another type which they provide meaning for.
-
- In the following example, we append a CBOR Tag 1 (Unix \c time_t) and an
- integer representing the current time to the stream, obtained using the \c
- time() function:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 11
-
- \sa QCborStreamReader::isTag(), QCborStreamReader::toTag()
- */
-
-/*!
- \overload
-
- Appends the CBOR simple type \a st to the stream, creating a CBOR Simple
- Type value. In the following example, we write the simple type for Null as
- well as for type 32, which Qt has no support for.
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 12
-
- \note Using Simple Types for which there is no specification can lead to
- validation errors by the remote receiver. In addition, simple type values 24
- through 31 (inclusive) are reserved and must not be used.
-
- \sa QCborStreamReader::isSimpleType(), QCborStreamReader::toSimpleType()
- */
-void QCborStreamWriter::append(QCborSimpleType st)
-{
- d->executeAppend(cbor_encode_simple_value, uint8_t(st));
-}
-
-/*!
- \overload
-
- Appends the floating point number \a f to the stream, creating a CBOR 16-bit
- Half-Precision Floating Point value. The following code can be used to convert
- a C++ \tt float to \c qfloat16 if there's no loss of precision and append it, or
- instead append the \tt float.
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 13
-
- \sa QCborStreamReader::isFloat16(), QCborStreamReader::toFloat16()
- */
-void QCborStreamWriter::append(qfloat16 f)
-{
- d->executeAppend(cbor_encode_half_float, static_cast<const void *>(&f));
-}
-
-/*!
- \overload
-
- Appends the floating point number \a f to the stream, creating a CBOR 32-bit
- Single-Precision Floating Point value. The following code can be used to convert
- a C++ \tt double to \tt float if there's no loss of precision and append it, or
- instead append the \tt double.
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 14
-
- \sa QCborStreamReader::isFloat(), QCborStreamReader::toFloat()
- */
-void QCborStreamWriter::append(float f)
-{
- d->executeAppend(cbor_encode_float, f);
-}
-
-/*!
- \overload
-
- Appends the floating point number \a d to the stream, creating a CBOR 64-bit
- Double-Precision Floating Point value. QCborStreamWriter always appends the
- number as-is, performing no check for whether the number is the canonical
- form for NaN, an infinite, whether it is denormal or if it could be written
- with a shorter format.
-
- The following code performs all those checks, except for the denormal one,
- which is expected to be taken into account by the system FPU or floating
- point emulation directly.
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 15
-
- Determining if a double can be converted to an integral with no loss of
- precision is left as an exercise to the reader.
-
- \sa QCborStreamReader::isDouble(), QCborStreamReader::toDouble()
- */
-void QCborStreamWriter::append(double d)
-{
- this->d->executeAppend(cbor_encode_double, d);
-}
-
-/*!
- Appends \a len bytes of data starting from \a data to the stream, creating a
- CBOR Byte String value. QCborStreamWriter will attempt to write the entire
- string in one chunk.
-
- Unlike the QByteArray overload of append(), this function is not limited by
- QByteArray's size limits. However, note that neither
- QCborStreamReader::readByteArray() nor QCborValue support reading CBOR
- streams with byte arrays larger than 2 GB.
-
- \sa append(), appendTextString(),
- QCborStreamReader::isByteArray(), QCborStreamReader::readByteArray()
- */
-void QCborStreamWriter::appendByteString(const char *data, qsizetype len)
-{
- d->executeAppend(cbor_encode_byte_string, reinterpret_cast<const uint8_t *>(data), size_t(len));
-}
-
-/*!
- Appends \a len bytes of text starting from \a utf8 to the stream, creating a
- CBOR Text String value. QCborStreamWriter will attempt to write the entire
- string in one chunk.
-
- The string pointed to by \a utf8 is expected to be properly encoded UTF-8.
- QCborStreamWriter performs no validation that this is the case.
-
- Unlike the QLatin1String overload of append(), this function is not limited
- to 2 GB. However, note that neither QCborStreamReader::readString() nor
- QCborValue support reading CBOR streams with text strings larger than 2 GB.
-
- \sa append(QLatin1String), append(QStringView),
- QCborStreamReader::isString(), QCborStreamReader::readString()
- */
-void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
-{
- d->executeAppend(cbor_encode_text_string, utf8, size_t(len));
-}
-
-/*!
- \fn void QCborStreamWriter::append(const char *str, qsizetype size)
- \overload
-
- Appends \a size bytes of text starting from \a str to the stream, creating a
- CBOR Text String value. QCborStreamWriter will attempt to write the entire
- string in one chunk. If \a size is -1, this function will write \c strlen(\a
- str) bytes.
-
- The string pointed to by \a str is expected to be properly encoded UTF-8.
- QCborStreamWriter performs no validation that this is the case.
-
- Unlike the QLatin1String overload of append(), this function is not limited
- to 2 GB. However, note that neither QCborStreamReader nor QCborValue support
- reading CBOR streams with text strings larger than 2 GB.
-
- \sa append(QLatin1String), append(QStringView),
- QCborStreamReader::isString(), QCborStreamReader::readString()
- */
-
-/*!
- \fn void QCborStreamWriter::append(bool b)
- \overload
-
- Appends the boolean value \a b to the stream, creating either a CBOR False
- value or a CBOR True value. This function is equivalent to (and implemented
- as):
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 16
-
- \sa appendNull(), appendUndefined(),
- QCborStreamReader::isBool(), QCborStreamReader::toBool()
- */
-
-/*!
- \fn void QCborStreamWriter::append(std::nullptr_t)
- \overload
-
- Appends a CBOR Null value to the stream. This function is equivalent to (and
- implemented as): The parameter is ignored.
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 17
-
- \sa appendNull(), append(QCborSimpleType), QCborStreamReader::isNull()
- */
-
-/*!
- \fn void QCborStreamWriter::appendNull()
-
- Appends a CBOR Null value to the stream. This function is equivalent to (and
- implemented as):
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 18
-
- \sa append(std::nullptr_t), append(QCborSimpleType), QCborStreamReader::isNull()
- */
-
-/*!
- \fn void QCborStreamWriter::appendUndefined()
-
- Appends a CBOR Undefined value to the stream. This function is equivalent to (and
- implemented as):
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 19
-
- \sa append(QCborSimpleType), QCborStreamReader::isUndefined()
- */
-
-/*!
- Starts a CBOR Array with indeterminate length in the CBOR stream. Each
- startArray() call must be paired with one endArray() call and the current
- CBOR element extends until the end of the array.
-
- The array created by this function has no explicit length. Instead, its
- 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
- passed as input:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 20
-
- \sa startArray(quint64), endArray(), startMap(), QCborStreamReader::isArray(),
- QCborStreamReader::isLengthKnown()
- */
-void QCborStreamWriter::startArray()
-{
- d->createContainer(cbor_encoder_create_array);
-}
-
-/*!
- \overload
-
- Starts a CBOR Array with explicit length of \a count items in the CBOR
- stream. Each startArray call must be paired with one endArray() call and the
- current CBOR element extends until the end of the array.
-
- The array created by this function has an explicit length and therefore
- exactly \a count items must be added to the CBOR stream. Adding fewer or
- more items will result in failure during endArray() and the CBOR stream will
- be corrupt. However, explicit-length arrays are required by canonical CBOR
- encoding.
-
- The following example appends all strings found in the \l QStringList passed as input:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 21
-
- \b{Size limitations}: The parameter to this function is quint64, which would
- seem to allow up to 2\sup{64}-1 elements in the array. However, both
- QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{32}-2
- items on 32-bit systems and 2\sup{64}-2 items on 64-bit ones. Also note that
- QCborArray is currently limited to 2\sup{27} elements in any platform.
-
- \sa startArray(), endArray(), startMap(), QCborStreamReader::isArray(),
- QCborStreamReader::isLengthKnown()
- */
-void QCborStreamWriter::startArray(quint64 count)
-{
- d->createContainer(cbor_encoder_create_array, count);
-}
-
-/*!
- Terminates the array started by either overload of startArray() and returns
- true if the correct number of elements was added to the array. This function
- must be called for every startArray() used.
-
- A return of false indicates error in the application and an unrecoverable
- error in this stream. QCborStreamWriter also writes a warning using
- qWarning() if that happens.
-
- Calling this function when the current container is not an array is also an
- error, though QCborStreamWriter cannot currently detect this condition.
-
- \sa startArray(), startArray(quint64), endMap()
- */
-bool QCborStreamWriter::endArray()
-{
- return d->closeContainer();
-}
-
-/*!
- Starts a CBOR Map with indeterminate length in the CBOR stream. Each
- startMap() call must be paired with one endMap() call and the current CBOR
- element extends until the end of the map.
-
- The map created by this function has no explicit length. Instead, its length
- is implied by the elements contained in it. Note, however, that use of
- 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
- string pairs passed as input:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 22
-
- \sa startMap(quint64), endMap(), startArray(), QCborStreamReader::isMap(),
- QCborStreamReader::isLengthKnown()
- */
-void QCborStreamWriter::startMap()
-{
- d->createContainer(cbor_encoder_create_map);
-}
-
-/*!
- \overload
-
- Starts a CBOR Map with explicit length of \a count items in the CBOR
- stream. Each startMap call must be paired with one endMap() call and the
- current CBOR element extends until the end of the map.
-
- The map created by this function has an explicit length and therefore
- exactly \a count pairs of items must be added to the CBOR stream. Adding
- fewer or more items will result in failure during endMap() and the CBOR
- stream will be corrupt. However, explicit-length map are required by
- canonical CBOR encoding.
-
- The following example appends all strings found in the \l QMap passed as input:
-
- \snippet code/src_corelib_serialization_qcborstream.cpp 23
-
- \b{Size limitations}: The parameter to this function is quint64, which would
- seem to allow up to 2\sup{64}-1 pairs in the map. However, both
- QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{31}-1
- items on 32-bit systems and 2\sup{63}-1 items on 64-bit ones. Also note that
- QCborMap is currently limited to 2\sup{26} elements in any platform.
-
- \sa startMap(), endMap(), startArray(), QCborStreamReader::isMap(),
- QCborStreamReader::isLengthKnown()
- */
-void QCborStreamWriter::startMap(quint64 count)
-{
- d->createContainer(cbor_encoder_create_map, count);
-}
-
-/*!
- Terminates the map started by either overload of startMap() and returns
- true if the correct number of elements was added to the array. This function
- must be called for every startMap() used.
-
- A return of false indicates error in the application and an unrecoverable
- error in this stream. QCborStreamWriter also writes a warning using
- qWarning() if that happens.
-
- Calling this function when the current container is not a map is also an
- error, though QCborStreamWriter cannot currently detect this condition.
-
- \sa startMap(), startMap(quint64), endArray()
- */
-bool QCborStreamWriter::endMap()
-{
- return d->closeContainer();
-}
-
-/*!
\class QCborStreamReader
\inmodule QtCore
\ingroup cbor
@@ -1756,7 +641,7 @@ public:
if (err != CborErrorUnexpectedEOF)
corrupt = true;
- lastError = fromCborError(err);
+ lastError = QCborError { QCborError::Code(int(err)) };
}
void updateBufferAfterString(qsizetype offset, qsizetype size)
@@ -2645,5 +1530,4 @@ QCborStreamReader::readStringChunk(char *ptr, qsizetype maxlen)
QT_END_NAMESPACE
-#include "moc_qcborcommon.cpp"
-#include "moc_qcborstream.cpp"
+#include "moc_qcborstreamreader.cpp"
diff --git a/src/corelib/serialization/qcborstreamreader.h b/src/corelib/serialization/qcborstreamreader.h
new file mode 100644
index 0000000000..6d5feccfcf
--- /dev/null
+++ b/src/corelib/serialization/qcborstreamreader.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCBORSTREAMREADER_H
+#define QCBORSTREAMREADER_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qcborcommon.h>
+#include <QtCore/qfloat16.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
+
+QT_REQUIRE_CONFIG(cborstreamreader);
+
+// See qcborcommon.h for why we check
+#if defined(QT_X11_DEFINES_FOUND)
+# undef True
+# undef False
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QCborStreamReaderPrivate;
+class Q_CORE_EXPORT QCborStreamReader
+{
+ Q_GADGET
+public:
+ enum Type : quint8 {
+ UnsignedInteger = 0x00,
+ NegativeInteger = 0x20,
+ ByteString = 0x40,
+ ByteArray = ByteString,
+ TextString = 0x60,
+ String = TextString,
+ Array = 0x80,
+ Map = 0xa0,
+ Tag = 0xc0,
+ SimpleType = 0xe0,
+ HalfFloat = 0xf9,
+ Float16 = HalfFloat,
+ Float = 0xfa,
+ Double = 0xfb,
+
+ Invalid = 0xff
+ };
+ Q_ENUM(Type)
+
+ enum StringResultCode {
+ EndOfString = 0,
+ Ok = 1,
+ Error = -1
+ };
+ template <typename Container> struct StringResult {
+ Container data;
+ StringResultCode status = Error;
+ };
+ Q_ENUM(StringResultCode)
+
+ QCborStreamReader();
+ QCborStreamReader(const char *data, qsizetype len);
+ QCborStreamReader(const quint8 *data, qsizetype len);
+ explicit QCborStreamReader(const QByteArray &data);
+ explicit QCborStreamReader(QIODevice *device);
+ ~QCborStreamReader();
+ Q_DISABLE_COPY(QCborStreamReader)
+
+ void setDevice(QIODevice *device);
+ QIODevice *device() const;
+ void addData(const QByteArray &data);
+ void addData(const char *data, qsizetype len);
+ void addData(const quint8 *data, qsizetype len)
+ { addData(reinterpret_cast<const char *>(data), len); }
+ void reparse();
+ void clear();
+ void reset();
+
+ QCborError lastError();
+
+ qint64 currentOffset() const;
+
+ bool isValid() const { return !isInvalid(); }
+
+ int containerDepth() const;
+ QCborStreamReader::Type parentContainerType() const;
+ bool hasNext() const noexcept Q_DECL_PURE_FUNCTION;
+ bool next(int maxRecursion = 10000);
+
+ Type type() const { return QCborStreamReader::Type(type_); }
+ bool isUnsignedInteger() const { return type() == UnsignedInteger; }
+ bool isNegativeInteger() const { return type() == NegativeInteger; }
+ bool isInteger() const { return quint8(type()) <= quint8(NegativeInteger); }
+ bool isByteArray() const { return type() == ByteArray; }
+ bool isString() const { return type() == String; }
+ bool isArray() const { return type() == Array; }
+ bool isMap() const { return type() == Map; }
+ bool isTag() const { return type() == Tag; }
+ bool isSimpleType() const { return type() == SimpleType; }
+ bool isFloat16() const { return type() == Float16; }
+ bool isFloat() const { return type() == Float; }
+ bool isDouble() const { return type() == Double; }
+ bool isInvalid() const { return type() == Invalid; }
+
+ bool isSimpleType(QCborSimpleType st) const { return isSimpleType() && toSimpleType() == st; }
+ bool isFalse() const { return isSimpleType(QCborSimpleType::False); }
+ bool isTrue() const { return isSimpleType(QCborSimpleType::True); }
+ bool isBool() const { return isFalse() || isTrue(); }
+ bool isNull() const { return isSimpleType(QCborSimpleType::Null); }
+ bool isUndefined() const { return isSimpleType(QCborSimpleType::Undefined); }
+
+ bool isLengthKnown() const noexcept Q_DECL_PURE_FUNCTION;
+ quint64 length() const;
+
+ bool isContainer() const { return isMap() || isArray(); }
+ bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
+ bool leaveContainer();
+
+ StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
+ StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
+ qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
+ StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
+
+ bool toBool() const { Q_ASSERT(isBool()); return value64 - int(QCborSimpleType::False); }
+ QCborTag toTag() const { Q_ASSERT(isTag()); return QCborTag(value64); }
+ quint64 toUnsignedInteger() const { Q_ASSERT(isUnsignedInteger()); return value64; }
+ QCborNegativeInteger toNegativeInteger() const { Q_ASSERT(isNegativeInteger()); return QCborNegativeInteger(value64 + 1); }
+ QCborSimpleType toSimpleType() const{ Q_ASSERT(isSimpleType()); return QCborSimpleType(value64); }
+ qfloat16 toFloat16() const { Q_ASSERT(isFloat16()); return _toFloatingPoint<qfloat16>(); }
+ float toFloat() const { Q_ASSERT(isFloat()); return _toFloatingPoint<float>(); }
+ double toDouble() const { Q_ASSERT(isDouble()); return _toFloatingPoint<double>(); }
+
+ qint64 toInteger() const
+ {
+ Q_ASSERT(isInteger());
+ qint64 v = qint64(value64);
+ if (isNegativeInteger())
+ return -v - 1;
+ return v;
+ }
+
+private:
+ void preparse();
+ bool _enterContainer_helper();
+ StringResult<QString> _readString_helper();
+ StringResult<QByteArray> _readByteArray_helper();
+ qsizetype _currentStringChunkSize() const;
+
+ template <typename FP> FP _toFloatingPoint() const noexcept
+ {
+ using UIntFP = typename QIntegerForSizeof<FP>::Unsigned;
+ UIntFP u = UIntFP(value64);
+ FP f;
+ memcpy(static_cast<void *>(&f), &u, sizeof(f));
+ return f;
+ }
+
+ friend QCborStreamReaderPrivate;
+ friend class QCborContainerPrivate;
+ quint64 value64;
+ QScopedPointer<QCborStreamReaderPrivate> d;
+ quint8 type_;
+ quint8 reserved[3] = {};
+};
+
+QT_END_NAMESPACE
+
+#if defined(QT_X11_DEFINES_FOUND)
+# define True 1
+# define False 0
+#endif
+
+#endif // QCBORSTREAMREADER_H
diff --git a/src/corelib/serialization/qcborstreamwriter.cpp b/src/corelib/serialization/qcborstreamwriter.cpp
new file mode 100644
index 0000000000..9d78785416
--- /dev/null
+++ b/src/corelib/serialization/qcborstreamwriter.cpp
@@ -0,0 +1,868 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcborstreamwriter.h"
+
+#define CBOR_NO_PARSER_API
+#include <private/qcborcommon_p.h>
+
+#include <private/qnumeric_p.h>
+#include <qbuffer.h>
+#include <qdebug.h>
+#include <qstack.h>
+
+QT_BEGIN_NAMESPACE
+
+static CborError qt_cbor_encoder_write_callback(void *token, const void *data, size_t len, CborEncoderAppendType);
+#define CBOR_ENCODER_WRITER_CONTROL 1
+#define CBOR_ENCODER_WRITE_FUNCTION qt_cbor_encoder_write_callback
+#define CBOR_ENCODER_NO_CHECK_USER
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
+
+#include <cborencoder.c>
+
+QT_WARNING_POP
+
+// silence compilers that complain about this being a static function declared
+// but never defined
+static CborError Q_DECL_UNUSED cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
+{
+ Q_UNREACHABLE();
+ return CborErrorInternalError;
+}
+
+static CborError Q_DECL_UNUSED cbor_encode_float_as_half_float(CborEncoder *, float)
+{
+ Q_UNREACHABLE();
+ return CborErrorInternalError;
+}
+
+Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
+
+/*!
+ \class QCborStreamWriter
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborStreamWriter class is a simple CBOR encoder operating on a
+ one-way stream.
+
+ This class can be used to quickly encode a stream of CBOR content directly
+ to either a QByteArray or QIODevice. CBOR is the Concise Binary Object
+ Representation, a very compact form of binary data encoding that is
+ compatible with JSON. It was created by the IETF Constrained RESTful
+ Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
+ be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ protocol}.
+
+ QCborStreamWriter provides a StAX-like API, similar to that of
+ \l{QXmlStreamWriter}. It is rather low-level and requires a bit of knowledge
+ of CBOR encoding. For a simpler API, see \l{QCborValue} and especially the
+ encoding function QCborValue::toCbor().
+
+ The typical use of QCborStreamWriter is to create the object on the target
+ QByteArray or QIODevice, then call one of the append() overloads with the
+ desired type to be encoded. To create arrays and maps, QCborStreamWriter
+ provides startArray() and startMap() overloads, which must be terminated by
+ the corresponding endArray() and endMap() functions.
+
+ The following example encodes the equivalent of this JSON content:
+
+ \div{class="pre"}
+ {
+ "label": "journald",
+ "autoDetect": false,
+ "condition": "libs.journald",
+ "output": [ "privateFeature" ]
+ }
+ \enddiv
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 1
+
+ \section1 CBOR support
+
+ QCborStreamWriter supports all CBOR features required to create canonical
+ and strict streams. It implements almost all of the features specified in
+ \l {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
+
+ The following table lists the CBOR features that QCborStreamWriter supports.
+
+ \table
+ \header \li Feature \li Support
+ \row \li Unsigned numbers \li Yes (full range)
+ \row \li Negative numbers \li Yes (full range)
+ \row \li Byte strings \li Yes
+ \row \li Text strings \li Yes
+ \row \li Chunked strings \li No
+ \row \li Tags \li Yes (arbitrary)
+ \row \li Booleans \li Yes
+ \row \li Null \li Yes
+ \row \li Undefined \li Yes
+ \row \li Arbitrary simple values \li Yes
+ \row \li Half-precision float (16-bit) \li Yes
+ \row \li Single-precision float (32-bit) \li Yes
+ \row \li Double-precision float (64-bit) \li Yes
+ \row \li Infinities and NaN floating point \li Yes
+ \row \li Determinate-length arrays and maps \li Yes
+ \row \li Indeterminate-length arrays and maps \li Yes
+ \row \li Map key types other than strings and integers \li Yes (arbitrary)
+ \endtable
+
+ \section2 Canonical CBOR encoding
+
+ Canonical CBOR encoding is defined by
+ \l{https://tools.ietf.org/html/rfc7049#section-3.9}{Section 3.9 of RFC
+ 7049}. Canonical encoding is not a requirement for Qt's CBOR decoding
+ functionality, but it may be required for some protocols. In particular,
+ protocols that require the ability to reproduce the same stream identically
+ may require this.
+
+ In order to be considered "canonical", a CBOR stream must meet the
+ following requirements:
+
+ \list
+ \li Integers must be as small as possible. QCborStreamWriter always
+ does this (no user action is required and it is not possible
+ to write overlong integers).
+ \li Array, map and string lengths must be as short as possible. As
+ above, QCborStreamWriter automatically does this.
+ \li Arrays, maps and strings must use explicit length. QCborStreamWriter
+ always does this for strings; for arrays and maps, be sure to call
+ startArray() and startMap() overloads with explicit length.
+ \li Keys in every map must be sorted in ascending order. QCborStreamWriter
+ offers no help in this item: the developer must ensure that before
+ calling append() for the map pairs.
+ \li Floating point values should be as small as possible. QCborStreamWriter
+ will not convert floating point values; it is up to the developer
+ to perform this check prior to calling append() (see those functions'
+ examples).
+ \endlist
+
+ \section2 Strict CBOR mode
+
+ Strict mode is defined by
+ \l{https://tools.ietf.org/html/rfc7049#section-3.10}{Section 3.10 of RFC
+ 7049}. As for Canonical encoding above, QCborStreamWriter makes it possible
+ to create strict CBOR streams, but does not require them or validate that
+ the output is so.
+
+ \list
+ \li Keys in a map must be unique. QCborStreamWriter performs no validation
+ of map keys.
+ \li Tags may be required to be paired only with the correct types,
+ according to their specification. QCborStreamWriter performs no
+ validation of tag usage.
+ \li Text Strings must be properly-encoded UTF-8. QCborStreamWriter always
+ writes proper UTF-8 for strings added with append(), but performs no
+ validation for strings added with appendTextString().
+ \endlist
+
+ \section2 Invalid CBOR stream
+
+ It is also possible to misuse QCborStreamWriter and produce invalid CBOR
+ streams that will fail to be decoded by a receiver. The following actions
+ will produce invalid streams:
+
+ \list
+ \li Append a tag and not append the corresponding tagged value
+ (QCborStreamWriter produces no diagnostic).
+ \li Append too many or too few items to an array or map with explicit
+ length (endMap() and endArray() will return false and
+ QCborStreamWriter will log with qWarning()).
+ \endlist
+
+ \sa QCborStreamReader, QCborValue, QXmlStreamWriter
+ */
+
+class QCborStreamWriterPrivate
+{
+public:
+ static Q_CONSTEXPR quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
+
+ QIODevice *device;
+ CborEncoder encoder;
+ QStack<CborEncoder> containerStack;
+ bool deleteDevice = false;
+
+ QCborStreamWriterPrivate(QIODevice *device)
+ : device(device)
+ {
+ cbor_encoder_init_writer(&encoder, qt_cbor_encoder_write_callback, this);
+ }
+
+ ~QCborStreamWriterPrivate()
+ {
+ if (deleteDevice)
+ delete device;
+ }
+
+ template <typename... Args> void executeAppend(CborError (*f)(CborEncoder *, Args...), Args... args)
+ {
+ f(&encoder, std::forward<Args>(args)...);
+ }
+
+ void createContainer(CborError (*f)(CborEncoder *, CborEncoder *, size_t), quint64 len = IndefiniteLength)
+ {
+ Q_STATIC_ASSERT(size_t(IndefiniteLength) == CborIndefiniteLength);
+ if (sizeof(len) != sizeof(size_t) && len != IndefiniteLength) {
+ if (Q_UNLIKELY(len >= CborIndefiniteLength)) {
+ // TinyCBOR can't do this in 32-bit mode
+ qWarning("QCborStreamWriter: container of size %llu is too big for a 32-bit build; "
+ "will use indeterminate length instead", len);
+ len = CborIndefiniteLength;
+ }
+ }
+
+ containerStack.push(encoder);
+ f(&containerStack.top(), &encoder, len);
+ }
+
+ bool closeContainer()
+ {
+ if (containerStack.isEmpty()) {
+ qWarning("QCborStreamWriter: closing map or array that wasn't open");
+ return false;
+ }
+
+ CborEncoder container = containerStack.pop();
+ CborError err = cbor_encoder_close_container(&container, &encoder);
+ encoder = container;
+
+ if (Q_UNLIKELY(err)) {
+ if (err == CborErrorTooFewItems)
+ qWarning("QCborStreamWriter: not enough items added to array or map");
+ else if (err == CborErrorTooManyItems)
+ qWarning("QCborStreamWriter: too many items added to array or map");
+ return false;
+ }
+
+ return true;
+ }
+};
+
+static CborError qt_cbor_encoder_write_callback(void *self, const void *data, size_t len, CborEncoderAppendType)
+{
+ auto that = static_cast<QCborStreamWriterPrivate *>(self);
+ if (!that->device)
+ return CborNoError;
+ qint64 written = that->device->write(static_cast<const char *>(data), len);
+ return (written == qsizetype(len) ? CborNoError : CborErrorIO);
+}
+
+/*!
+ Creates a QCborStreamWriter object that will write the stream to \a device.
+ The device must be opened before the first append() call is made. This
+ constructor can be used with any class that derives from QIODevice, such as
+ QFile, QProcess or QTcpSocket.
+
+ QCborStreamWriter has no buffering, so every append() call will result in
+ one or more calls to the device's \l {QIODevice::}{write()} method.
+
+ The following example writes an empty map to a file:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 2
+
+ QCborStreamWriter does not take ownership of \a device.
+
+ \sa device(), setDevice()
+ */
+QCborStreamWriter::QCborStreamWriter(QIODevice *device)
+ : d(new QCborStreamWriterPrivate(device))
+{
+}
+
+/*!
+ Creates a QCborStreamWriter object that will append the stream to \a data.
+ All streaming is done immediately to the byte array, without the need for
+ flushing any buffers.
+
+ The following example writes a number to a byte array then returns
+ it.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 3
+
+ QCborStreamWriter does not take ownership of \a data.
+ */
+QCborStreamWriter::QCborStreamWriter(QByteArray *data)
+ : d(new QCborStreamWriterPrivate(new QBuffer(data)))
+{
+ d->deleteDevice = true;
+ d->device->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
+}
+
+/*!
+ Destroys this QCborStreamWriter object and frees any resources associated.
+
+ QCborStreamWriter does not perform error checking to see if all required
+ items were written to the stream prior to the object being destroyed. It is
+ the programmer's responsibility to ensure that it was done.
+ */
+QCborStreamWriter::~QCborStreamWriter()
+{
+}
+
+/*!
+ Replaces the device or byte array that this QCborStreamWriter object is
+ writing to with \a device.
+
+ \sa device()
+ */
+void QCborStreamWriter::setDevice(QIODevice *device)
+{
+ if (d->deleteDevice)
+ delete d->device;
+ d->device = device;
+ d->deleteDevice = false;
+}
+
+/*!
+ Returns the QIODevice that this QCborStreamWriter object is writing to. The
+ device must have previously been set with either the constructor or with
+ setDevice().
+
+ If this object was created by writing to a QByteArray, this function will
+ return an internal instance of QBuffer, which is owned by QCborStreamWriter.
+
+ \sa setDevice()
+ */
+QIODevice *QCborStreamWriter::device() const
+{
+ return d->device;
+}
+
+/*!
+ \overload
+
+ Appends the 64-bit unsigned value \a u to the CBOR stream, creating a CBOR
+ Unsigned Integer value. In the following example, we write the values 0,
+ 2\sup{32} and \c UINT64_MAX:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 4
+
+ \sa QCborStreamReader::isUnsignedInteger(), QCborStreamReader::toUnsignedInteger()
+ */
+void QCborStreamWriter::append(quint64 u)
+{
+ d->executeAppend(cbor_encode_uint, uint64_t(u));
+}
+
+/*!
+ \overload
+
+ Appends the 64-bit signed value \a i to the CBOR stream. This will create
+ either a CBOR Unsigned Integer or CBOR NegativeInteger value based on the
+ sign of the parameter. In the following example, we write the values 0, -1,
+ 2\sup{32} and \c INT64_MAX:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 5
+
+ \sa QCborStreamReader::isInteger(), QCborStreamReader::toInteger()
+ */
+void QCborStreamWriter::append(qint64 i)
+{
+ d->executeAppend(cbor_encode_int, int64_t(i));
+}
+
+/*!
+ \overload
+
+ Appends the 64-bit negative value \a n to the CBOR stream.
+ QCborNegativeInteger is a 64-bit enum that holds the absolute value of the
+ negative number we want to write. If n is zero, the value written will be
+ equivalent to 2\sup{64} (that is, -18,446,744,073,709,551,616).
+
+ In the following example, we write the values -1, -2\sup{32} and INT64_MIN:
+ \snippet code/src_corelib_serialization_qcborstream.cpp 6
+
+ Note how this function can be used to encode numbers that cannot fit a
+ standard computer's 64-bit signed integer like \l qint64. That is, if \a n
+ is larger than \c{std::numeric_limits<qint64>::max()} or is 0, this will
+ represent a negative number smaller than
+ \c{std::numeric_limits<qint64>::min()}.
+
+ \sa QCborStreamReader::isNegativeInteger(), QCborStreamReader::toNegativeInteger()
+ */
+void QCborStreamWriter::append(QCborNegativeInteger n)
+{
+ d->executeAppend(cbor_encode_negative_int, uint64_t(n));
+}
+
+/*!
+ \fn void QCborStreamWriter::append(const QByteArray &ba)
+ \overload
+
+ Appends the byte array \a ba to the stream, creating a CBOR Byte String
+ value. QCborStreamWriter will attempt to write the entire string in one
+ chunk.
+
+ The following example will load and append the contents of a file to the
+ stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 7
+
+ As the example shows, unlike JSON, CBOR requires no escaping for binary
+ content.
+
+ \sa appendByteString(), QCborStreamReader::isByteArray(),
+ QCborStreamReader::readByteArray()
+ */
+
+/*!
+ \overload
+
+ Appends the text string \a str to the stream, creating a CBOR Text String
+ value. QCborStreamWriter will attempt to write the entire string in one
+ chunk.
+
+ The following example appends a simple string to the stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 8
+
+ \b{Performance note}: CBOR requires that all Text Strings be encoded in
+ UTF-8, so this function will iterate over the characters in the string to
+ determine whether the contents are US-ASCII or not. If the string is found
+ to contain characters outside of US-ASCII, it will allocate memory and
+ convert to UTF-8. If this check is unnecessary, use appendTextString()
+ instead.
+
+ \sa QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+void QCborStreamWriter::append(QLatin1String str)
+{
+ // We've got Latin-1 but CBOR wants UTF-8, so check if the string is the
+ // common subset (US-ASCII).
+ if (QtPrivate::isAscii(str)) {
+ // it is plain US-ASCII
+ appendTextString(str.latin1(), str.size());
+ } else {
+ // non-ASCII, so we need a pass-through UTF-16
+ append(QString(str));
+ }
+}
+
+/*!
+ \overload
+
+ Appends the text string \a str to the stream, creating a CBOR Text String
+ value. QCborStreamWriter will attempt to write the entire string in one
+ chunk.
+
+ The following example writes an arbitrary QString to the stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 9
+
+ \sa QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+void QCborStreamWriter::append(QStringView str)
+{
+ QByteArray utf8 = str.toUtf8();
+ appendTextString(utf8.constData(), utf8.size());
+}
+
+/*!
+ \overload
+
+ Appends the CBOR tag \a tag to the stream, creating a CBOR Tag value. All
+ tags must be followed by another type which they provide meaning for.
+
+ In the following example, we append a CBOR Tag 36 (Regular Expression) and a
+ QRegularExpression's pattern to the stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 10
+
+ \sa QCborStreamReader::isTag(), QCborStreamReader::toTag()
+ */
+void QCborStreamWriter::append(QCborTag tag)
+{
+ d->executeAppend(cbor_encode_tag, CborTag(tag));
+}
+
+/*!
+ \fn void QCborStreamWriter::append(QCborKnownTags tag)
+ \overload
+
+ Appends the CBOR tag \a tag to the stream, creating a CBOR Tag value. All
+ tags must be followed by another type which they provide meaning for.
+
+ In the following example, we append a CBOR Tag 1 (Unix \c time_t) and an
+ integer representing the current time to the stream, obtained using the \c
+ time() function:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 11
+
+ \sa QCborStreamReader::isTag(), QCborStreamReader::toTag()
+ */
+
+/*!
+ \overload
+
+ Appends the CBOR simple type \a st to the stream, creating a CBOR Simple
+ Type value. In the following example, we write the simple type for Null as
+ well as for type 32, which Qt has no support for.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 12
+
+ \note Using Simple Types for which there is no specification can lead to
+ validation errors by the remote receiver. In addition, simple type values 24
+ through 31 (inclusive) are reserved and must not be used.
+
+ \sa QCborStreamReader::isSimpleType(), QCborStreamReader::toSimpleType()
+ */
+void QCborStreamWriter::append(QCborSimpleType st)
+{
+ d->executeAppend(cbor_encode_simple_value, uint8_t(st));
+}
+
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \overload
+
+ Appends the floating point number \a f to the stream, creating a CBOR 16-bit
+ Half-Precision Floating Point value. The following code can be used to convert
+ a C++ \tt float to \c qfloat16 if there's no loss of precision and append it, or
+ instead append the \tt float.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 13
+
+ \sa QCborStreamReader::isFloat16(), QCborStreamReader::toFloat16()
+ */
+void QCborStreamWriter::append(qfloat16 f)
+{
+ d->executeAppend(cbor_encode_half_float, static_cast<const void *>(&f));
+}
+#endif // QT_BOOTSTRAPPED
+
+/*!
+ \overload
+
+ Appends the floating point number \a f to the stream, creating a CBOR 32-bit
+ Single-Precision Floating Point value. The following code can be used to convert
+ a C++ \tt double to \tt float if there's no loss of precision and append it, or
+ instead append the \tt double.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 14
+
+ \sa QCborStreamReader::isFloat(), QCborStreamReader::toFloat()
+ */
+void QCborStreamWriter::append(float f)
+{
+ d->executeAppend(cbor_encode_float, f);
+}
+
+/*!
+ \overload
+
+ Appends the floating point number \a d to the stream, creating a CBOR 64-bit
+ Double-Precision Floating Point value. QCborStreamWriter always appends the
+ number as-is, performing no check for whether the number is the canonical
+ form for NaN, an infinite, whether it is denormal or if it could be written
+ with a shorter format.
+
+ The following code performs all those checks, except for the denormal one,
+ which is expected to be taken into account by the system FPU or floating
+ point emulation directly.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 15
+
+ Determining if a double can be converted to an integral with no loss of
+ precision is left as an exercise to the reader.
+
+ \sa QCborStreamReader::isDouble(), QCborStreamReader::toDouble()
+ */
+void QCborStreamWriter::append(double d)
+{
+ this->d->executeAppend(cbor_encode_double, d);
+}
+
+/*!
+ Appends \a len bytes of data starting from \a data to the stream, creating a
+ CBOR Byte String value. QCborStreamWriter will attempt to write the entire
+ string in one chunk.
+
+ Unlike the QByteArray overload of append(), this function is not limited by
+ QByteArray's size limits. However, note that neither
+ QCborStreamReader::readByteArray() nor QCborValue support reading CBOR
+ streams with byte arrays larger than 2 GB.
+
+ \sa append(), appendTextString(),
+ QCborStreamReader::isByteArray(), QCborStreamReader::readByteArray()
+ */
+void QCborStreamWriter::appendByteString(const char *data, qsizetype len)
+{
+ d->executeAppend(cbor_encode_byte_string, reinterpret_cast<const uint8_t *>(data), size_t(len));
+}
+
+/*!
+ Appends \a len bytes of text starting from \a utf8 to the stream, creating a
+ CBOR Text String value. QCborStreamWriter will attempt to write the entire
+ string in one chunk.
+
+ The string pointed to by \a utf8 is expected to be properly encoded UTF-8.
+ QCborStreamWriter performs no validation that this is the case.
+
+ Unlike the QLatin1String overload of append(), this function is not limited
+ to 2 GB. However, note that neither QCborStreamReader::readString() nor
+ QCborValue support reading CBOR streams with text strings larger than 2 GB.
+
+ \sa append(QLatin1String), append(QStringView),
+ QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
+{
+ d->executeAppend(cbor_encode_text_string, utf8, size_t(len));
+}
+
+/*!
+ \fn void QCborStreamWriter::append(const char *str, qsizetype size)
+ \overload
+
+ Appends \a size bytes of text starting from \a str to the stream, creating a
+ CBOR Text String value. QCborStreamWriter will attempt to write the entire
+ string in one chunk. If \a size is -1, this function will write \c strlen(\a
+ str) bytes.
+
+ The string pointed to by \a str is expected to be properly encoded UTF-8.
+ QCborStreamWriter performs no validation that this is the case.
+
+ Unlike the QLatin1String overload of append(), this function is not limited
+ to 2 GB. However, note that neither QCborStreamReader nor QCborValue support
+ reading CBOR streams with text strings larger than 2 GB.
+
+ \sa append(QLatin1String), append(QStringView),
+ QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+
+/*!
+ \fn void QCborStreamWriter::append(bool b)
+ \overload
+
+ Appends the boolean value \a b to the stream, creating either a CBOR False
+ value or a CBOR True value. This function is equivalent to (and implemented
+ as):
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 16
+
+ \sa appendNull(), appendUndefined(),
+ QCborStreamReader::isBool(), QCborStreamReader::toBool()
+ */
+
+/*!
+ \fn void QCborStreamWriter::append(std::nullptr_t)
+ \overload
+
+ Appends a CBOR Null value to the stream. This function is equivalent to (and
+ implemented as): The parameter is ignored.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 17
+
+ \sa appendNull(), append(QCborSimpleType), QCborStreamReader::isNull()
+ */
+
+/*!
+ \fn void QCborStreamWriter::appendNull()
+
+ Appends a CBOR Null value to the stream. This function is equivalent to (and
+ implemented as):
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 18
+
+ \sa append(std::nullptr_t), append(QCborSimpleType), QCborStreamReader::isNull()
+ */
+
+/*!
+ \fn void QCborStreamWriter::appendUndefined()
+
+ Appends a CBOR Undefined value to the stream. This function is equivalent to (and
+ implemented as):
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 19
+
+ \sa append(QCborSimpleType), QCborStreamReader::isUndefined()
+ */
+
+/*!
+ Starts a CBOR Array with indeterminate length in the CBOR stream. Each
+ startArray() call must be paired with one endArray() call and the current
+ CBOR element extends until the end of the array.
+
+ The array created by this function has no explicit length. Instead, its
+ 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
+ passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 20
+
+ \sa startArray(quint64), endArray(), startMap(), QCborStreamReader::isArray(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startArray()
+{
+ d->createContainer(cbor_encoder_create_array);
+}
+
+/*!
+ \overload
+
+ Starts a CBOR Array with explicit length of \a count items in the CBOR
+ stream. Each startArray call must be paired with one endArray() call and the
+ current CBOR element extends until the end of the array.
+
+ The array created by this function has an explicit length and therefore
+ exactly \a count items must be added to the CBOR stream. Adding fewer or
+ more items will result in failure during endArray() and the CBOR stream will
+ be corrupt. However, explicit-length arrays are required by canonical CBOR
+ encoding.
+
+ The following example appends all strings found in the \l QStringList passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 21
+
+ \b{Size limitations}: The parameter to this function is quint64, which would
+ seem to allow up to 2\sup{64}-1 elements in the array. However, both
+ QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{32}-2
+ items on 32-bit systems and 2\sup{64}-2 items on 64-bit ones. Also note that
+ QCborArray is currently limited to 2\sup{27} elements in any platform.
+
+ \sa startArray(), endArray(), startMap(), QCborStreamReader::isArray(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startArray(quint64 count)
+{
+ d->createContainer(cbor_encoder_create_array, count);
+}
+
+/*!
+ Terminates the array started by either overload of startArray() and returns
+ true if the correct number of elements was added to the array. This function
+ must be called for every startArray() used.
+
+ A return of false indicates error in the application and an unrecoverable
+ error in this stream. QCborStreamWriter also writes a warning using
+ qWarning() if that happens.
+
+ Calling this function when the current container is not an array is also an
+ error, though QCborStreamWriter cannot currently detect this condition.
+
+ \sa startArray(), startArray(quint64), endMap()
+ */
+bool QCborStreamWriter::endArray()
+{
+ return d->closeContainer();
+}
+
+/*!
+ Starts a CBOR Map with indeterminate length in the CBOR stream. Each
+ startMap() call must be paired with one endMap() call and the current CBOR
+ element extends until the end of the map.
+
+ The map created by this function has no explicit length. Instead, its length
+ is implied by the elements contained in it. Note, however, that use of
+ 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
+ string pairs passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 22
+
+ \sa startMap(quint64), endMap(), startArray(), QCborStreamReader::isMap(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startMap()
+{
+ d->createContainer(cbor_encoder_create_map);
+}
+
+/*!
+ \overload
+
+ Starts a CBOR Map with explicit length of \a count items in the CBOR
+ stream. Each startMap call must be paired with one endMap() call and the
+ current CBOR element extends until the end of the map.
+
+ The map created by this function has an explicit length and therefore
+ exactly \a count pairs of items must be added to the CBOR stream. Adding
+ fewer or more items will result in failure during endMap() and the CBOR
+ stream will be corrupt. However, explicit-length map are required by
+ canonical CBOR encoding.
+
+ The following example appends all strings found in the \l QMap passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 23
+
+ \b{Size limitations}: The parameter to this function is quint64, which would
+ seem to allow up to 2\sup{64}-1 pairs in the map. However, both
+ QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{31}-1
+ items on 32-bit systems and 2\sup{63}-1 items on 64-bit ones. Also note that
+ QCborMap is currently limited to 2\sup{26} elements in any platform.
+
+ \sa startMap(), endMap(), startArray(), QCborStreamReader::isMap(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startMap(quint64 count)
+{
+ d->createContainer(cbor_encoder_create_map, count);
+}
+
+/*!
+ Terminates the map started by either overload of startMap() and returns
+ true if the correct number of elements was added to the array. This function
+ must be called for every startMap() used.
+
+ A return of false indicates error in the application and an unrecoverable
+ error in this stream. QCborStreamWriter also writes a warning using
+ qWarning() if that happens.
+
+ Calling this function when the current container is not a map is also an
+ error, though QCborStreamWriter cannot currently detect this condition.
+
+ \sa startMap(), startMap(quint64), endArray()
+ */
+bool QCborStreamWriter::endMap()
+{
+ return d->closeContainer();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcborstreamwriter.h b/src/corelib/serialization/qcborstreamwriter.h
new file mode 100644
index 0000000000..f8c94ceb93
--- /dev/null
+++ b/src/corelib/serialization/qcborstreamwriter.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCBORSTREAMWRITER_H
+#define QCBORSTREAMWRITER_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qcborcommon.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
+#ifndef QT_BOOTSTRAPPED
+#include <QtCore/qfloat16.h>
+#endif
+
+QT_REQUIRE_CONFIG(cborstreamwriter);
+
+// See qcborcommon.h for why we check
+#if defined(QT_X11_DEFINES_FOUND)
+# undef True
+# undef False
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QCborStreamWriterPrivate;
+class Q_CORE_EXPORT QCborStreamWriter
+{
+public:
+ explicit QCborStreamWriter(QIODevice *device);
+ explicit QCborStreamWriter(QByteArray *data);
+ ~QCborStreamWriter();
+ Q_DISABLE_COPY(QCborStreamWriter)
+
+ void setDevice(QIODevice *device);
+ QIODevice *device() const;
+
+ void append(quint64 u);
+ void append(qint64 i);
+ void append(QCborNegativeInteger n);
+ void append(const QByteArray &ba) { appendByteString(ba.constData(), ba.size()); }
+ void append(QLatin1String str);
+ void append(QStringView str);
+ void append(QCborTag tag);
+ void append(QCborKnownTags tag) { append(QCborTag(tag)); }
+ void append(QCborSimpleType st);
+ void append(std::nullptr_t) { append(QCborSimpleType::Null); }
+#ifndef QT_BOOTSTRAPPED
+ void append(qfloat16 f);
+#endif
+ void append(float f);
+ void append(double d);
+
+ void appendByteString(const char *data, qsizetype len);
+ void appendTextString(const char *utf8, qsizetype len);
+
+ // convenience
+ void append(bool b) { append(b ? QCborSimpleType::True : QCborSimpleType::False); }
+ void appendNull() { append(QCborSimpleType::Null); }
+ void appendUndefined() { append(QCborSimpleType::Undefined); }
+
+#ifndef Q_QDOC
+ // overloads to make normal code not complain
+ void append(int i) { append(qint64(i)); }
+ void append(uint u) { append(quint64(u)); }
+#endif
+#ifndef QT_NO_CAST_FROM_ASCII
+ void append(const char *str, qsizetype size = -1)
+ { appendTextString(str, (str && size == -1) ? int(strlen(str)) : size); }
+#endif
+
+ void startArray();
+ void startArray(quint64 count);
+ bool endArray();
+ void startMap();
+ void startMap(quint64 count);
+ bool endMap();
+
+ // no API for encoding chunked strings
+
+private:
+ QScopedPointer<QCborStreamWriterPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#if defined(QT_X11_DEFINES_FOUND)
+# define True 1
+# define False 0
+#endif
+
+#endif // QCBORSTREAMWRITER_H
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 61d61dd9ae..db2840704c 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -43,8 +43,12 @@
#include "qcborarray.h"
#include "qcbormap.h"
-#if QT_CONFIG(cborstream)
-#include "qcborstream.h"
+#if QT_CONFIG(cborstreamreader)
+#include "qcborstreamreader.h"
+#endif
+
+#if QT_CONFIG(cborstreamwriter)
+#include "qcborstreamwriter.h"
#endif
#include <qendian.h>
@@ -840,16 +844,20 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
return QCborValue::Tag;
}
-#if QT_CONFIG(cborstream)
+#if QT_CONFIG(cborstreamreader)
// in qcborstream.cpp
extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
+#endif
+#if QT_CONFIG(cborstreamwriter)
static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt)
{
if (qt_is_nan(d)) {
- if (opt & QCborValue::UseFloat16) {
+ if (opt & QCborValue::UseFloat) {
+#ifndef QT_BOOTSTRAPPED
if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16)
return writer.append(std::numeric_limits<qfloat16>::quiet_NaN());
+#endif
return writer.append(std::numeric_limits<float>::quiet_NaN());
}
return writer.append(qt_qnan());
@@ -866,15 +874,17 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E
}
}
- if (opt & QCborValue::UseFloat16) {
+ if (opt & QCborValue::UseFloat) {
float f = float(d);
if (f == d) {
// no data loss, we could use float
+#ifndef QT_BOOTSTRAPPED
if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) {
qfloat16 f16 = f;
if (f16 == f)
return writer.append(f16);
}
+#endif
return writer.append(f);
}
@@ -882,7 +892,7 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E
writer.append(d);
}
-#endif // QT_CONFIG(cborstream)
+#endif // QT_CONFIG(cborstreamwriter)
static inline int typeOrder(Element e1, Element e2)
{
@@ -1305,7 +1315,7 @@ int QCborMap::compare(const QCborMap &other) const noexcept
return compareContainer(d.data(), other.d.data());
}
-#if QT_CONFIG(cborstream)
+#if QT_CONFIG(cborstreamwriter)
static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate *d, qsizetype idx,
QCborValue::EncodingOptions opt)
{
@@ -1393,7 +1403,9 @@ static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate
qWarning("QCborValue: found unknown type 0x%x", e.type);
}
}
+#endif // QT_CONFIG(cborstreamwriter)
+#if QT_CONFIG(cborstreamreader)
static inline double integerOutOfRange(const QCborStreamReader &reader)
{
Q_ASSERT(reader.isInteger());
@@ -1650,7 +1662,7 @@ void QCborContainerPrivate::decodeFromCbor(QCborStreamReader &reader)
if (reader.lastError() == QCborError::NoError)
reader.leaveContainer();
}
-#endif // QT_CONFIG(cborstream)
+#endif // QT_CONFIG(cborstreamreader)
/*!
Creates a QCborValue with byte array value \a ba. The value can later be
@@ -2350,7 +2362,7 @@ QCborValueRef QCborValue::operator[](qint64 key)
return { container, index };
}
-#if QT_CONFIG(cborstream)
+#if QT_CONFIG(cborstreamreader)
/*!
Decodes one item from the CBOR stream found in \a reader and returns the
equivalent representation. This function is recursive: if the item is a map
@@ -2465,7 +2477,9 @@ QCborValue QCborValue::fromCbor(const QByteArray &ba, QCborParserError *error)
overload of this function that accepts a QByteArray, also passing \a error,
if provided.
*/
+#endif // QT_CONFIG(cborstreamreader)
+#if QT_CONFIG(cborstreamwriter)
/*!
Encodes this QCborValue object to its CBOR representation, using the
options specified in \a opt, and return the byte array containing that
@@ -2588,7 +2602,7 @@ void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOption
{
concrete().toCbor(writer, opt);
}
-#endif // QT_CONFIG(cborstream)
+#endif // QT_CONFIG(cborstreamwriter)
void QCborValueRef::assign(QCborValueRef that, const QCborValue &other)
{
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
index 071213e83a..1df8425d45 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -90,7 +90,9 @@ public:
enum EncodingOption {
SortKeysInMaps = 0x01,
UseFloat = 0x02,
+#ifndef QT_BOOTSTRAPPED
UseFloat16 = UseFloat | 0x04,
+#endif
UseIntegers = 0x08,
NoTransformation = 0
@@ -287,13 +289,15 @@ public:
static QCborValue fromJsonValue(const QJsonValue &v);
QJsonValue toJsonValue() const;
-#if QT_CONFIG(cborstream)
+#if QT_CONFIG(cborstreamreader)
static QCborValue fromCbor(QCborStreamReader &reader);
static QCborValue fromCbor(const QByteArray &ba, QCborParserError *error = nullptr);
static QCborValue fromCbor(const char *data, qsizetype len, QCborParserError *error = nullptr)
{ return fromCbor(QByteArray(data, int(len)), error); }
static QCborValue fromCbor(const quint8 *data, qsizetype len, QCborParserError *error = nullptr)
{ 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);
#endif
@@ -441,7 +445,7 @@ public:
QVariant toVariant() const { return concrete().toVariant(); }
QJsonValue toJsonValue() const;
-#if QT_CONFIG(cborstream)
+#if QT_CONFIG(cborstreamwriter)
QByteArray toCbor(QCborValue::EncodingOptions opt = QCborValue::NoTransformation)
{ return concrete().toCbor(opt); }
void toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt = QCborValue::NoTransformation);
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index cd94f39b1f..b7c16018d5 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -296,7 +296,10 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
c.clear();
break;
}
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
c.insertMulti(k, t);
+QT_WARNING_POP
}
return s;
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index c5d4bf0315..08702771a8 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -175,12 +175,6 @@ void QJsonArray::initialize()
*/
QJsonArray::~QJsonArray() = default;
-/*!
- Creates a copy of \a other.
-
- Since QJsonArray is implicitly shared, the copy is shallow
- as long as the object doesn't get modified.
- */
QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
{
initialize();
@@ -188,6 +182,12 @@ QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
append(arg);
}
+/*!
+ Creates a copy of \a other.
+
+ Since QJsonArray is implicitly shared, the copy is shallow
+ as long as the object doesn't get modified.
+ */
QJsonArray::QJsonArray(const QJsonArray &other)
{
a = other.a;
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
index 997cef0106..fbea84fe73 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -755,13 +755,13 @@ QCborValue QCborValue::fromVariant(const QVariant &variant)
return QCborMap::fromJsonObject(doc.object());
}
case QMetaType::QCborValue:
- return variant.value<QCborValue>();
+ return qvariant_cast<QCborValue>(variant);
case QMetaType::QCborArray:
- return variant.value<QCborArray>();
+ return qvariant_cast<QCborArray>(variant);
case QMetaType::QCborMap:
- return variant.value<QCborMap>();
+ return qvariant_cast<QCborMap>(variant);
case QMetaType::QCborSimpleType:
- return variant.value<QCborSimpleType>();
+ return qvariant_cast<QCborSimpleType>(variant);
#endif
default:
break;
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index ae37481f31..a6987279d3 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -1013,7 +1013,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
Returns a pointer to a modifiable reference to the current item.
*/
-/*! \fn QJsonValueRef QJsonObject::iterator::operator[](int j) const
+/*! \fn const QJsonValueRef QJsonObject::iterator::operator[](int j)
Returns a modifiable reference to the item at offset \a j from the
item pointed to by this iterator (the item at position \c{*this + j}).
@@ -1264,7 +1264,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
Returns a pointer to the current item.
*/
-/*! \fn QJsonValue QJsonObject::const_iterator::operator[](int j) const
+/*! \fn const QJsonValue QJsonObject::const_iterator::operator[](int j)
Returns the item at offset \a j from the item pointed to by this iterator (the item at
position \c{*this + j}).
diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index cfb44c9c55..c31be0353d 100644
--- a/src/corelib/serialization/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
@@ -221,7 +221,7 @@ public:
inline const_iterator operator-(int j) const { return operator+(-j); }
inline const_iterator &operator+=(int j) { i += j; return *this; }
inline const_iterator &operator-=(int j) { i -= j; return *this; }
- int operator-(iterator j) const { return i - j.i; }
+ int operator-(const_iterator j) const { return i - j.i; }
inline bool operator==(const iterator &other) const { return i == other.i; }
inline bool operator!=(const iterator &other) const { return i != other.i; }
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index db06a33a9f..4a7fab21d7 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -149,7 +149,7 @@ QJsonValue::QJsonValue(bool b)
}
/*!
- Creates a value of type Double, with value \a n.
+ Creates a value of type Double, with value \a v.
*/
QJsonValue::QJsonValue(double v)
: d(nullptr)
@@ -166,7 +166,7 @@ QJsonValue::QJsonValue(double v)
/*!
\overload
- Creates a value of type Double, with value \a n.
+ Creates a value of type Double, with value \a v.
*/
QJsonValue::QJsonValue(int v)
: n(v), t(QCborValue::Integer)
@@ -175,7 +175,7 @@ QJsonValue::QJsonValue(int v)
/*!
\overload
- Creates a value of type Double, with value \a n.
+ Creates a value of type Double, with value \a v.
NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992).
If you pass in values outside this range expect a loss of precision to occur.
*/
@@ -490,11 +490,11 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
}
case QMetaType::QCborValue:
- return variant.value<QCborValue>().toJsonValue();
+ return qvariant_cast<QCborValue>(variant).toJsonValue();
case QMetaType::QCborArray:
- return variant.value<QCborArray>().toJsonArray();
+ return qvariant_cast<QCborArray>(variant).toJsonArray();
case QMetaType::QCborMap:
- return variant.value<QCborMap>().toJsonObject();
+ return qvariant_cast<QCborMap>(variant).toJsonObject();
#endif
default:
break;
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index cf59cc54c7..4d92b1e0da 100644
--- a/src/corelib/serialization/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
@@ -2689,11 +2689,8 @@ QTextStream &QTextStream::operator<<(const void *ptr)
d->params.numberFlags = oldFlags;
return *this;
}
-#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+
namespace Qt {
-#else
-namespace QTextStreamFunctions {
-#endif
/*!
\relates QTextStream
@@ -3020,7 +3017,7 @@ QTextStream &ws(QTextStream &stream)
return stream;
}
-} // namespace QTextStreamFunctions
+} // namespace Qt
/*!
\fn QTextStreamManipulator qSetFieldWidth(int width)
@@ -3045,11 +3042,7 @@ QTextStream &ws(QTextStream &stream)
#if QT_CONFIG(textcodec)
-#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
namespace Qt {
-#else
-namespace QTextStreamFunctions {
-#endif
/*!
\relates QTextStream
@@ -3064,7 +3057,7 @@ QTextStream &bom(QTextStream &stream)
return stream;
}
-} // namespace QTextStreamFunctions
+} // namespace Qt
/*!
Sets the codec for this stream to \a codec. The codec is used for
@@ -3215,6 +3208,45 @@ QLocale QTextStream::locale() const
return d->locale;
}
+#if QT_DEPRECATED_SINCE(5, 15) && !defined(Q_QDOC)
+// Deprecated source compatible migration versions:
+namespace QTextStreamFunctions {
+QTextStream &bin(QTextStream &s) { return Qt::bin(s); }
+QTextStream &oct(QTextStream &s) { return Qt::oct(s); }
+QTextStream &dec(QTextStream &s) { return Qt::dec(s); }
+QTextStream &hex(QTextStream &s) { return Qt::hex(s); }
+
+QTextStream &showbase(QTextStream &s) { return Qt::showbase(s); }
+QTextStream &forcesign(QTextStream &s) { return Qt::forcesign(s); }
+QTextStream &forcepoint(QTextStream &s) { return Qt::forcepoint(s); }
+QTextStream &noshowbase(QTextStream &s) { return Qt::noshowbase(s); }
+QTextStream &noforcesign(QTextStream &s) { return Qt::noforcesign(s); }
+QTextStream &noforcepoint(QTextStream &s) { return Qt::noforcepoint(s); }
+
+QTextStream &uppercasebase(QTextStream &s) { return Qt::uppercasebase(s); }
+QTextStream &uppercasedigits(QTextStream &s) { return Qt::uppercasedigits(s); }
+QTextStream &lowercasebase(QTextStream &s) { return Qt::lowercasebase(s); }
+QTextStream &lowercasedigits(QTextStream &s) { return Qt::lowercasedigits(s); }
+
+QTextStream &fixed(QTextStream &s) { return Qt::fixed(s); }
+QTextStream &scientific(QTextStream &s) { return Qt::scientific(s); }
+
+QTextStream &left(QTextStream &s) { return Qt::left(s); }
+QTextStream &right(QTextStream &s) { return Qt::right(s); }
+QTextStream &center(QTextStream &s) { return Qt::center(s); }
+
+QTextStream &endl(QTextStream &s) { return Qt::endl(s); }
+QTextStream &flush(QTextStream &s) { return Qt::flush(s); }
+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
+
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
// Binary compatible definitions for Qt<5.14
Q_CORE_EXPORT QTextStream &bin(QTextStream &s) { return Qt::bin(s); }
diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h
index 935ec16536..6f93826d8a 100644
--- a/src/corelib/serialization/qtextstream.h
+++ b/src/corelib/serialization/qtextstream.h
@@ -233,13 +233,7 @@ inline QTextStream &operator<<(QTextStream &s, QTextStreamFunction f)
inline QTextStream &operator<<(QTextStream &s, QTextStreamManipulator m)
{ m.exec(s); return s; }
-#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
namespace Qt {
-#else
-// This namespace only exists for 'using namespace' declarations.
-namespace QTextStreamFunctions {
-#endif
-
Q_CORE_EXPORT QTextStream &bin(QTextStream &s);
Q_CORE_EXPORT QTextStream &oct(QTextStream &s);
Q_CORE_EXPORT QTextStream &dec(QTextStream &s);
@@ -272,12 +266,36 @@ Q_CORE_EXPORT QTextStream &bom(QTextStream &s);
Q_CORE_EXPORT QTextStream &ws(QTextStream &s);
-} // namespace QTextStreamFunctions
+} // namespace Qt
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
-namespace Qt {
-using namespace QTextStreamFunctions;
-}
+#if QT_DEPRECATED_SINCE(5, 15) && !defined(Q_QDOC)
+// This namespace only exists for 'using namespace' declarations.
+namespace QTextStreamFunctions {
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::bin") QTextStream &bin(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::oct") QTextStream &oct(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::dec") QTextStream &dec(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::hex") QTextStream &hex(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::showbase") QTextStream &showbase(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::forcesign") QTextStream &forcesign(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::forcepoint") QTextStream &forcepoint(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::noshowbase") QTextStream &noshowbase(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::noforcesign") QTextStream &noforcesign(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::noforcepoint") QTextStream &noforcepoint(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::uppercasebase") QTextStream &uppercasebase(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::uppercasedigits") QTextStream &uppercasedigits(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::lowercasebase") QTextStream &lowercasebase(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::lowercasedigits") QTextStream &lowercasedigits(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::fixed") QTextStream &fixed(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::scientific") QTextStream &scientific(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::left") QTextStream &left(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::right") QTextStream &right(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::center") QTextStream &center(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::endl") QTextStream &endl(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::flush") QTextStream &flush(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::reset") QTextStream &reset(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::bom") QTextStream &bom(QTextStream &s);
+Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::ws") QTextStream &ws(QTextStream &s);
+} // namespace QTextStreamFunctions
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
@@ -285,7 +303,7 @@ QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
// conflicting definitions compiler errors.
using namespace QTextStreamFunctions;
QT_WARNING_POP
-#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
+#endif // QT_DEPRECATED_SINCE(5, 15) && !defined(Q_QDOC)
inline QTextStreamManipulator qSetFieldWidth(int width)
{
diff --git a/src/corelib/serialization/serialization.pri b/src/corelib/serialization/serialization.pri
index 7407e20d9e..ff653ca8f3 100644
--- a/src/corelib/serialization/serialization.pri
+++ b/src/corelib/serialization/serialization.pri
@@ -3,7 +3,9 @@
HEADERS += \
serialization/qcborarray.h \
serialization/qcborcommon.h \
+ serialization/qcborcommon_p.h \
serialization/qcbormap.h \
+ serialization/qcborstream.h \
serialization/qcborvalue.h \
serialization/qcborvalue_p.h \
serialization/qdatastream.h \
@@ -22,6 +24,7 @@ HEADERS += \
serialization/qxmlutils_p.h
SOURCES += \
+ serialization/qcborcommon.cpp \
serialization/qcbordiagnostic.cpp \
serialization/qcborvalue.cpp \
serialization/qdatastream.cpp \
@@ -36,12 +39,20 @@ SOURCES += \
serialization/qxmlstream.cpp \
serialization/qxmlutils.cpp
-qtConfig(cborstream): {
+qtConfig(cborstreamreader): {
SOURCES += \
- serialization/qcborstream.cpp
+ serialization/qcborstreamreader.cpp
HEADERS += \
- serialization/qcborstream.h
+ serialization/qcborstreamreader.h
+}
+
+qtConfig(cborstreamwriter): {
+ SOURCES += \
+ serialization/qcborstreamwriter.cpp
+
+ HEADERS += \
+ serialization/qcborstreamwriter.h
}
qtConfig(binaryjson): {
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 3fa1868437..ac5f2afb57 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -4999,7 +4999,7 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
*/
/*!
- \fn QByteArray::FromBase64Result::operator QByteArray() const
+ \fn QByteArray &QByteArray::FromBase64Result::operator*() const
Returns the decoded byte array.
*/
@@ -5008,17 +5008,18 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
\fn bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
\relates QByteArray::FromBase64Result
- Compares \a lhs and \a rhs for equality. \a lhs and \a rhs are equal
- if and only if they contain the same decoding status and, if the
- status is QByteArray::Base64DecodingStatus::Ok, if and only if
- they contain the same decoded data.
+ Returns \c true if \a lhs and \a rhs are equal, otherwise returns \c false.
+
+ \a lhs and \a rhs are equal if and only if they contain the same decoding
+ status and, if the status is QByteArray::Base64DecodingStatus::Ok, if and
+ only if they contain the same decoded data.
*/
/*!
\fn bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
\relates QByteArray::FromBase64Result
- Compares \a lhs and \a rhs for inequality.
+ Returns \c true if \a lhs and \a rhs are different, otherwise returns \c false.
*/
/*!
diff --git a/src/corelib/text/qchar.cpp b/src/corelib/text/qchar.cpp
index 847b4f0b08..61b61125b1 100644
--- a/src/corelib/text/qchar.cpp
+++ b/src/corelib/text/qchar.cpp
@@ -418,7 +418,7 @@ QT_BEGIN_NAMESPACE
\value Script_Sogdian Since Qt 5.15
\value Script_SoraSompeng
\value Script_Soyombo Since Qt 5.11
- \value Script_Sundaneseo
+ \value Script_Sundanese
\value Script_SylotiNagri
\value Script_Syriac
\value Script_Tagalog
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index 694d491273..c643c2a514 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -1969,7 +1969,8 @@ QString QLocale::toString(qlonglong i) const
{
int flags = d->m_numberOptions & OmitGroupSeparator
? 0
- : QLocaleData::ThousandsGroup;
+ : (d->m_data->m_country_id == Country::India)
+ ? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
return d->m_data->longLongToString(i, -1, 10, -1, flags);
}
@@ -1984,7 +1985,8 @@ QString QLocale::toString(qulonglong i) const
{
int flags = d->m_numberOptions & OmitGroupSeparator
? 0
- : QLocaleData::ThousandsGroup;
+ : (d->m_data->m_country_id == Country::India)
+ ? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
return d->m_data->unsLongLongToString(i, -1, 10, -1, flags);
}
@@ -3065,7 +3067,7 @@ QList<Qt::DayOfWeek> QLocale::weekdays() const
if (d->m_data == systemData()) {
QVariant res = systemLocale()->query(QSystemLocale::Weekdays, QVariant());
if (!res.isNull())
- return static_cast<QList<Qt::DayOfWeek> >(res.value<QList<Qt::DayOfWeek> >());
+ return static_cast<QList<Qt::DayOfWeek> >(qvariant_cast<QList<Qt::DayOfWeek> >(res));
}
#endif
QList<Qt::DayOfWeek> weekdays;
@@ -3626,10 +3628,19 @@ QT_WARNING_DISABLE_MSVC(4146)
QT_WARNING_POP
uint cnt_thousand_sep = 0;
- if (flags & ThousandsGroup && base == 10) {
- for (int i = num_str.length() - 3; i > 0; i -= 3) {
- num_str.insert(i, group);
- ++cnt_thousand_sep;
+ if (base == 10){
+ if (flags & ThousandsGroup) {
+ for (int i = num_str.length() - 3; i > 0; i -= 3) {
+ num_str.insert(i, group);
+ ++cnt_thousand_sep;
+ }
+ } else if (flags & IndianNumberGrouping) {
+ if (num_str.length() > 3)
+ num_str.insert(num_str.length() - 3 , group);
+ for (int i = num_str.length() - 6; i > 0; i -= 2) {
+ num_str.insert(i, group);
+ ++cnt_thousand_sep;
+ }
}
}
@@ -3713,10 +3724,19 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
}
uint cnt_thousand_sep = 0;
- if (flags & ThousandsGroup && base == 10) {
- for (int i = num_str.length() - 3; i > 0; i -=3) {
- num_str.insert(i, group);
- ++cnt_thousand_sep;
+ if (base == 10) {
+ if (flags & ThousandsGroup) {
+ for (int i = num_str.length() - 3; i > 0; i -=3) {
+ num_str.insert(i, group);
+ ++cnt_thousand_sep;
+ }
+ } else if (flags & IndianNumberGrouping) {
+ if (num_str.length() > 3)
+ num_str.insert(num_str.length() - 3 , group);
+ for (int i = num_str.length() - 6; i > 0; i -= 2) {
+ num_str.insert(i, group);
+ ++cnt_thousand_sep;
+ }
}
}
@@ -3851,7 +3871,10 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
// check distance from the last separator or from the beginning of the digits
// ### FIXME: Some locales allow other groupings!
// See https://en.wikipedia.org/wiki/Thousands_separator
- if (last_separator_idx != -1 && idx - last_separator_idx != 4)
+ if (m_country_id == QLocale::India) {
+ if (last_separator_idx != -1 && idx - last_separator_idx != 3)
+ return false;
+ } else if (last_separator_idx != -1 && idx - last_separator_idx != 4)
return false;
if (last_separator_idx == -1
&& (start_of_digits_idx == -1 || idx - start_of_digits_idx > 3)) {
diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h
index edee3a89c7..bb24009523 100644
--- a/src/corelib/text/qlocale_p.h
+++ b/src/corelib/text/qlocale_p.h
@@ -213,7 +213,8 @@ public:
ShowBase = 0x80,
UppercaseBase = 0x100,
ZeroPadExponent = 0x200,
- ForcePoint = 0x400
+ ForcePoint = 0x400,
+ IndianNumberGrouping= 0x800
};
enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode };
diff --git a/src/corelib/text/qlocale_unix.cpp b/src/corelib/text/qlocale_unix.cpp
index ff4274d932..5e1e47eae7 100644
--- a/src/corelib/text/qlocale_unix.cpp
+++ b/src/corelib/text/qlocale_unix.cpp
@@ -283,9 +283,9 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
return d->uiLanguages.isEmpty() ? QVariant() : QVariant(d->uiLanguages);
}
case StringToStandardQuotation:
- return lc_messages.quoteString(in.value<QStringRef>());
+ return lc_messages.quoteString(qvariant_cast<QStringRef>(in));
case StringToAlternateQuotation:
- return lc_messages.quoteString(in.value<QStringRef>(), QLocale::AlternateQuotation);
+ return lc_messages.quoteString(qvariant_cast<QStringRef>(in), QLocale::AlternateQuotation);
case ListToSeparatedString:
return lc_messages.createSeparatedList(in.toStringList());
case LocaleChanged:
diff --git a/src/corelib/text/qregexp.cpp b/src/corelib/text/qregexp.cpp
index ac4d9bbc36..9301a7e573 100644
--- a/src/corelib/text/qregexp.cpp
+++ b/src/corelib/text/qregexp.cpp
@@ -2528,7 +2528,7 @@ void QRegExpEngine::Box::cat(const Box &b)
eng->addCatTransitions(rs, b.ls);
addAnchorsToEngine(b);
if (minl == 0) {
- lanchors.unite(b.lanchors);
+ lanchors.insert(b.lanchors);
if (skipanchors != 0) {
for (int i = 0; i < b.ls.size(); i++) {
int a = eng->anchorConcatenation(lanchors.value(b.ls.at(i), 0), skipanchors);
@@ -2538,7 +2538,7 @@ void QRegExpEngine::Box::cat(const Box &b)
mergeInto(&ls, b.ls);
}
if (b.minl == 0) {
- ranchors.unite(b.ranchors);
+ ranchors.insert(b.ranchors);
if (b.skipanchors != 0) {
for (int i = 0; i < rs.size(); i++) {
int a = eng->anchorConcatenation(ranchors.value(rs.at(i), 0), b.skipanchors);
@@ -2596,9 +2596,9 @@ void QRegExpEngine::Box::cat(const Box &b)
void QRegExpEngine::Box::orx(const Box &b)
{
mergeInto(&ls, b.ls);
- lanchors.unite(b.lanchors);
+ lanchors.insert(b.lanchors);
mergeInto(&rs, b.rs);
- ranchors.unite(b.ranchors);
+ ranchors.insert(b.ranchors);
if (b.minl == 0) {
if (minl == 0)
diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp
index e05bef450b..068c960910 100644
--- a/src/corelib/text/qregularexpression.cpp
+++ b/src/corelib/text/qregularexpression.cpp
@@ -443,6 +443,38 @@ QT_BEGIN_NAMESPACE
Other differences are outlined below.
+ \section2 Different pattern syntax
+
+ Porting a regular expression from QRegExp to QRegularExpression may require
+ changes to the pattern itself.
+
+ In certain scenarios, QRegExp was too lenient and accepted patterns that
+ are simply invalid when using QRegularExpression. These are somehow easy
+ to detect, because the QRegularExpression objects built with these patterns
+ are not valid (cf. isValid()).
+
+ In other cases, a pattern ported from QRegExp to QRegularExpression may
+ silently change semantics. Therefore, it is necessary to review the
+ patterns used. The most notable cases of silent incompatibility are:
+
+ \list
+
+ \li Curly braces are needed in order to use a hexadecimal escape like
+ \c{\xHHHH} with more than 2 digits. A pattern like \c{\x2022} neeeds to
+ be ported to \c{\x{2022}}, or it will match a space (\c{0x20}) followed
+ by the string \c{"22"}. In general, it is highly recommended to always use
+ curly braces with the \c{\\x} escape, no matter the amount of digits
+ specified.
+
+ \li A 0-to-n quantification like \c{{,n}} needs to be ported to c{{0,n}} to
+ preserve semantics. Otherwise, a pattern such as \c{\d{,3}} would
+ actually match a digit followed by the exact string \c{"{,3}"}.
+
+ \li QRegExp by default does Unicode-aware matching, while
+ QRegularExpression requires a separate option; see below for more details.
+
+ \endlist
+
\section2 Porting from QRegExp::exactMatch()
QRegExp::exactMatch() in Qt 4 served two purposes: it exactly matched
@@ -2835,7 +2867,7 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "numbers out of order in {} quantifier"),
QT_TRANSLATE_NOOP("QRegularExpression", "number too big in {} quantifier"),
QT_TRANSLATE_NOOP("QRegularExpression", "missing terminating ] for character class"),
- QT_TRANSLATE_NOOP("QRegularExpression", "invalid escape sequence in character class"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "escape sequence is invalid in character class"),
QT_TRANSLATE_NOOP("QRegularExpression", "range out of order in character class"),
QT_TRANSLATE_NOOP("QRegularExpression", "quantifier does not follow a repeatable item"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unexpected repeat"),
@@ -2852,46 +2884,46 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "failed to allocate heap memory"),
QT_TRANSLATE_NOOP("QRegularExpression", "unmatched closing parenthesis"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: code overflow"),
- QT_TRANSLATE_NOOP("QRegularExpression", "letter or underscore expected after (?< or (?'"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "missing closing parenthesis for condition"),
QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind assertion is not fixed length"),
- QT_TRANSLATE_NOOP("QRegularExpression", "malformed number or name after (?("),
- QT_TRANSLATE_NOOP("QRegularExpression", "conditional group contains more than two branches"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "a relative value of zero is not allowed"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "conditional subpattern contains more than two branches"),
QT_TRANSLATE_NOOP("QRegularExpression", "assertion expected after (?( or (?(?C)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "(?R or (?[+-]digits must be followed by )"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "digit expected after (?+ or (?-"),
QT_TRANSLATE_NOOP("QRegularExpression", "unknown POSIX class name"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error in pcre2_study(): should not occur"),
QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE2 does not have Unicode support"),
QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested (stack check)"),
QT_TRANSLATE_NOOP("QRegularExpression", "character code point value in \\x{} or \\o{} is too large"),
- QT_TRANSLATE_NOOP("QRegularExpression", "invalid condition (?(0)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "\\C is not allowed in a lookbehind assertion"),
- QT_TRANSLATE_NOOP("QRegularExpression", "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind is too complicated"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "\\C is not allowed in a lookbehind assertion in UTF-" "16" " mode"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2 does not support \\F, \\L, \\l, \\N{name}, \\U, or \\u"),
QT_TRANSLATE_NOOP("QRegularExpression", "number after (?C is greater than 255"),
QT_TRANSLATE_NOOP("QRegularExpression", "closing parenthesis for (?C expected"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid escape sequence in (*VERB) name"),
QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized character after (?P"),
- QT_TRANSLATE_NOOP("QRegularExpression", "syntax error in subpattern name (missing terminator)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "syntax error in subpattern name (missing terminator?)"),
QT_TRANSLATE_NOOP("QRegularExpression", "two named subpatterns have the same name (PCRE2_DUPNAMES not set)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "group name must start with a non-digit"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name must start with a non-digit"),
QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE2 does not have support for \\P, \\p, or \\X"),
QT_TRANSLATE_NOOP("QRegularExpression", "malformed \\P or \\p sequence"),
QT_TRANSLATE_NOOP("QRegularExpression", "unknown property name after \\P or \\p"),
- QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name is too long (maximum " "10000" " characters)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "too many named subpatterns (maximum " "256" ")"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name is too long (maximum " "32" " code units)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "too many named subpatterns (maximum " "10000" ")"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid range in character class"),
QT_TRANSLATE_NOOP("QRegularExpression", "octal value is greater than \\377 in 8-bit non-UTF-8 mode"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: overran compiling workspace"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: previously-checked referenced subpattern not found"),
- QT_TRANSLATE_NOOP("QRegularExpression", "DEFINE group contains more than one branch"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "DEFINE subpattern contains more than one branch"),
QT_TRANSLATE_NOOP("QRegularExpression", "missing opening brace after \\o"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown newline setting"),
QT_TRANSLATE_NOOP("QRegularExpression", "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number"),
- QT_TRANSLATE_NOOP("QRegularExpression", "a numbered reference must not be zero"),
- QT_TRANSLATE_NOOP("QRegularExpression", "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "(?R (recursive pattern call) must be followed by a closing parenthesis"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "obsolete error (should not occur)"),
QT_TRANSLATE_NOOP("QRegularExpression", "(*VERB) not recognized or malformed"),
- QT_TRANSLATE_NOOP("QRegularExpression", "number is too big"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "subpattern number is too big"),
QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name expected"),
- QT_TRANSLATE_NOOP("QRegularExpression", "digit expected after (?+"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error: parsed pattern overflow"),
QT_TRANSLATE_NOOP("QRegularExpression", "non-octal character in \\o{} (closing brace missing?)"),
QT_TRANSLATE_NOOP("QRegularExpression", "different names for subpatterns of the same number are not allowed"),
QT_TRANSLATE_NOOP("QRegularExpression", "(*MARK) must have an argument"),
@@ -2899,16 +2931,16 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "\\c must be followed by a printable ASCII character"),
QT_TRANSLATE_NOOP("QRegularExpression", "\\c must be followed by a letter or one of [\\]^_?"),
QT_TRANSLATE_NOOP("QRegularExpression", "\\k is not followed by a braced, angle-bracketed, or quoted name"),
- QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown opcode in find_fixedlength()"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown meta code in check_lookbehinds()"),
QT_TRANSLATE_NOOP("QRegularExpression", "\\N is not supported in a class"),
- QT_TRANSLATE_NOOP("QRegularExpression", "SPARE ERROR"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "callout string is too long"),
QT_TRANSLATE_NOOP("QRegularExpression", "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)"),
QT_TRANSLATE_NOOP("QRegularExpression", "using UTF is disabled by the application"),
QT_TRANSLATE_NOOP("QRegularExpression", "using UCP is disabled by the application"),
QT_TRANSLATE_NOOP("QRegularExpression", "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)"),
QT_TRANSLATE_NOOP("QRegularExpression", "character code point value in \\u.... sequence is too large"),
- QT_TRANSLATE_NOOP("QRegularExpression", "digits missing in \\x{} or \\o{}"),
- QT_TRANSLATE_NOOP("QRegularExpression", "syntax error in (?(VERSION condition"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "digits missing in \\x{} or \\o{} or \\N{U+}"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "syntax error or number too big in (?(VERSION condition"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown opcode in auto_possessify()"),
QT_TRANSLATE_NOOP("QRegularExpression", "missing terminating delimiter for callout with string argument"),
QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized string delimiter follows (?C"),
@@ -2918,6 +2950,16 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "regular expression is too complicated"),
QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind assertion is too long"),
QT_TRANSLATE_NOOP("QRegularExpression", "pattern string is longer than the limit set by the application"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown code in parsed pattern"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error: bad code value in parsed_skip()"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not allowed in UTF-16 mode"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid option bits with PCRE2_LITERAL"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "\\N{U+dddd} is supported only in Unicode (UTF) mode"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid hyphen in option setting"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "(*alpha_assertion) not recognized"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "script runs require Unicode support, which this version of PCRE2 does not have"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "too many capturing groups (maximum 65535)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "atomic assertion expected after (?( or (?(?C)"),
QT_TRANSLATE_NOOP("QRegularExpression", "no error"),
QT_TRANSLATE_NOOP("QRegularExpression", "no match"),
QT_TRANSLATE_NOOP("QRegularExpression", "partial match"),
@@ -2955,7 +2997,7 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "bad option value"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid replacement string"),
QT_TRANSLATE_NOOP("QRegularExpression", "bad offset into UTF string"),
- QT_TRANSLATE_NOOP("QRegularExpression", "callout error code"), /* Never returned by PCRE2 itself */
+ QT_TRANSLATE_NOOP("QRegularExpression", "callout error code"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid data in workspace for DFA restart"),
QT_TRANSLATE_NOOP("QRegularExpression", "too much recursion for DFA matching"),
QT_TRANSLATE_NOOP("QRegularExpression", "backreference condition or recursion test is not supported for DFA matching"),
@@ -2971,15 +3013,20 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "non-unique substring name"),
QT_TRANSLATE_NOOP("QRegularExpression", "NULL argument passed"),
QT_TRANSLATE_NOOP("QRegularExpression", "nested recursion at the same subject position"),
- QT_TRANSLATE_NOOP("QRegularExpression", "recursion limit exceeded"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "matching depth limit exceeded"),
QT_TRANSLATE_NOOP("QRegularExpression", "requested value is not available"),
QT_TRANSLATE_NOOP("QRegularExpression", "requested value is not set"),
QT_TRANSLATE_NOOP("QRegularExpression", "offset limit set without PCRE2_USE_OFFSET_LIMIT"),
QT_TRANSLATE_NOOP("QRegularExpression", "bad escape sequence in replacement string"),
QT_TRANSLATE_NOOP("QRegularExpression", "expected closing curly bracket in replacement string"),
QT_TRANSLATE_NOOP("QRegularExpression", "bad substitution in replacement string"),
- QT_TRANSLATE_NOOP("QRegularExpression", "match with end before start is not supported"),
- QT_TRANSLATE_NOOP("QRegularExpression", "too many replacements (more than INT_MAX)")
+ QT_TRANSLATE_NOOP("QRegularExpression", "match with end before start or start moved backwards is not supported"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "too many replacements (more than INT_MAX)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad serialized data"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "heap limit exceeded"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid syntax"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error - duplicate substitution match"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching")
};
#endif // #if 0
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 4234b3c402..51d383ea18 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -591,6 +591,20 @@ bool QtPrivate::isLatin1(QStringView s) noexcept
return true;
}
+bool QtPrivate::isValidUtf16(QStringView s) noexcept
+{
+ Q_CONSTEXPR uint InvalidCodePoint = UINT_MAX;
+
+ QStringIterator i(s);
+ while (i.hasNext()) {
+ uint c = i.next(InvalidCodePoint);
+ if (c == InvalidCodePoint)
+ return false;
+ }
+
+ return true;
+}
+
// conversion between Latin 1 and UTF-16
void qt_from_latin1(ushort *dst, const char *str, size_t size) noexcept
{
@@ -8924,6 +8938,21 @@ bool QString::isRightToLeft() const
return QtPrivate::isRightToLeft(QStringView(*this));
}
+/*!
+ \fn bool QString::isValidUtf16() const noexcept
+ \since 5.15
+
+ Returns \c true if the string contains valid UTF-16 encoded data,
+ or \c false otherwise.
+
+ Note that this function does not perform any special validation of the
+ data; it merely checks if it can be successfully decoded from UTF-16.
+ The data is assumed to be in host byte order; the presence of a BOM
+ is meaningless.
+
+ \sa QStringView::isValidUtf16()
+*/
+
/*! \fn QChar *QString::data()
Returns a pointer to the data stored in the QString. The pointer
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 0350dabfc9..65d702ff1c 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -916,6 +916,8 @@ public:
bool isSimpleText() const;
bool isRightToLeft() const;
+ Q_REQUIRED_RESULT bool isValidUtf16() const noexcept
+ { return QStringView(*this).isValidUtf16(); }
QString(int size, Qt::Initialization);
explicit QString(DataPointer dd) : d(dd) {}
diff --git a/src/corelib/text/qstringalgorithms.h b/src/corelib/text/qstringalgorithms.h
index d54e376aa9..0b7774b4f3 100644
--- a/src/corelib/text/qstringalgorithms.h
+++ b/src/corelib/text/qstringalgorithms.h
@@ -99,6 +99,7 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QLatin1String
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QStringView s) noexcept;
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline bool isLatin1(QLatin1String s) noexcept;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isLatin1(QStringView s) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf16(QStringView s) noexcept;
} // namespace QtPRivate
diff --git a/src/corelib/text/qstringview.cpp b/src/corelib/text/qstringview.cpp
index 75de827583..c4ddb06ea4 100644
--- a/src/corelib/text/qstringview.cpp
+++ b/src/corelib/text/qstringview.cpp
@@ -865,6 +865,21 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn bool QStringView::isValidUtf16() const
+ \since 5.15
+
+ Returns \c true if the string contains valid UTF-16 encoded data,
+ or \c false otherwise.
+
+ Note that this function does not perform any special validation of the
+ data; it merely checks if it can be successfully decoded from UTF-16.
+ The data is assumed to be in host byte order; the presence of a BOM
+ is meaningless.
+
+ \sa QString::isValidUtf16()
+*/
+
+/*!
\fn QStringView::toWCharArray(wchar_t *array) const
\since 5.14
diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h
index 4ab4d2570f..06391ffef4 100644
--- a/src/corelib/text/qstringview.h
+++ b/src/corelib/text/qstringview.h
@@ -294,6 +294,8 @@ public:
Q_REQUIRED_RESULT bool isRightToLeft() const noexcept
{ return QtPrivate::isRightToLeft(*this); }
+ Q_REQUIRED_RESULT bool isValidUtf16() const noexcept
+ { return QtPrivate::isValidUtf16(*this); }
Q_REQUIRED_RESULT inline int toWCharArray(wchar_t *array) const; // defined in qstring.h
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
index b1a7edad91..5c3ad9412f 100644
--- a/src/corelib/thread/qatomic.cpp
+++ b/src/corelib/thread/qatomic.cpp
@@ -234,22 +234,26 @@
\sa QAtomicPointer
*/
-/*! \fn QAtomicInt::QAtomicInt(int value)
+/*!
+ \fn QAtomicInt::QAtomicInt(int value)
Constructs a QAtomicInt with the given \a value.
*/
-/*! \fn QAtomicInteger<T>::QAtomicInteger(T value)
+/*!
+ \fn template <typename T> QAtomicInteger<T>::QAtomicInteger(T value)
Constructs a QAtomicInteger with the given \a value.
*/
-/*! \fn template <typename T> QAtomicInteger<T>::QAtomicInteger(const QAtomicInteger &other)
+/*!
+ \fn template <typename T> QAtomicInteger<T>::QAtomicInteger(const QAtomicInteger &other)
Constructs a copy of \a other.
*/
-/*! \fn template <typename T> QAtomicInteger &QAtomicInteger<T>::operator=(const QAtomicInteger &other)
+/*!
+ \fn template <typename T> QAtomicInteger &QAtomicInteger<T>::operator=(const QAtomicInteger &other)
Assigns \a other to this QAtomicInteger and returns a reference to
this QAtomicInteger.
@@ -344,19 +348,22 @@
\sa storeRelaxed(), storeRelease()
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingNative()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingNative()
Returns \c true if reference counting is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingWaitFree()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingWaitFree()
Returns \c true if atomic reference counting is wait-free, false
otherwise.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::ref()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::ref()
Atomically increments the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise.
@@ -394,7 +401,8 @@
\sa ref(), operator++(), operator--(int)
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::deref()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::deref()
Atomically decrements the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise.
@@ -432,18 +440,21 @@
\sa deref(), operator--(), operator++(int)
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isTestAndSetNative()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isTestAndSetNative()
Returns \c true if test-and-set is implemented using atomic processor
instructions, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isTestAndSetWaitFree()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isTestAndSetWaitFree()
Returns \c true if atomic test-and-set is wait-free, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelaxed(T expectedValue, T newValue)
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelaxed(T expectedValue, T newValue)
Atomic test-and-set.
@@ -457,7 +468,8 @@
processor to freely reorder memory accesses.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetAcquire(T expectedValue, T newValue)
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetAcquire(T expectedValue, T newValue)
Atomic test-and-set.
@@ -472,7 +484,8 @@
be re-ordered before the atomic operation.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelease(T expectedValue, T newValue)
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelease(T expectedValue, T newValue)
Atomic test-and-set.
@@ -487,7 +500,8 @@
re-ordered after the atomic operation.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetOrdered(T expectedValue, T newValue)
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetOrdered(T expectedValue, T newValue)
Atomic test-and-set.
@@ -502,19 +516,22 @@
may not be re-ordered.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndStoreNative()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isFetchAndStoreNative()
Returns \c true if fetch-and-store is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndStoreWaitFree()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isFetchAndStoreWaitFree()
Returns \c true if atomic fetch-and-store is wait-free, false
otherwise.
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreRelaxed(T newValue)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreRelaxed(T newValue)
Atomic fetch-and-store.
@@ -526,7 +543,8 @@
processor to freely reorder memory accesses.
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreAcquire(T newValue)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreAcquire(T newValue)
Atomic fetch-and-store.
@@ -539,7 +557,8 @@
be re-ordered before the atomic operation.
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreRelease(T newValue)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreRelease(T newValue)
Atomic fetch-and-store.
@@ -552,7 +571,8 @@
re-ordered after the atomic operation.
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreOrdered(T newValue)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreOrdered(T newValue)
Atomic fetch-and-store.
@@ -565,19 +585,22 @@
may not be re-ordered.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndAddNative()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isFetchAndAddNative()
Returns \c true if fetch-and-add is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndAddWaitFree()
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::isFetchAndAddWaitFree()
Returns \c true if atomic fetch-and-add is wait-free, false
otherwise.
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddRelaxed(T valueToAdd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAddRelaxed(T valueToAdd)
Atomic fetch-and-add.
@@ -591,7 +614,8 @@
\sa operator+=(), fetchAndSubRelaxed()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddAcquire(T valueToAdd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAddAcquire(T valueToAdd)
Atomic fetch-and-add.
@@ -606,7 +630,8 @@
\sa operator+=(), fetchAndSubAcquire()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddRelease(T valueToAdd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAddRelease(T valueToAdd)
Atomic fetch-and-add.
@@ -621,7 +646,8 @@
\sa operator+=(), fetchAndSubRelease()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddOrdered(T valueToAdd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAddOrdered(T valueToAdd)
Atomic fetch-and-add.
@@ -636,7 +662,8 @@
\sa operator+=(), fetchAndSubOrdered()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::operator+=(T value)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::operator+=(T value)
\since 5.3
Atomic add-and-fetch.
@@ -650,7 +677,8 @@
\sa fetchAndAddOrdered(), operator-=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubRelaxed(T valueToSub)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndSubRelaxed(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -665,7 +693,8 @@
\sa operator-=(), fetchAndAddRelaxed()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubAcquire(T valueToSub)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndSubAcquire(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -681,7 +710,8 @@
\sa operator-=(), fetchAndAddAcquire()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubRelease(T valueToSub)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndSubRelease(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -697,7 +727,8 @@
\sa operator-=(), fetchAndAddRelease()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubOrdered(T valueToSub)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndSubOrdered(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -713,7 +744,8 @@
\sa operator-=(), fetchAndAddOrdered()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::operator-=(T value)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::operator-=(T value)
\since 5.3
Atomic sub-and-fetch.
@@ -727,7 +759,8 @@
\sa fetchAndSubOrdered(), operator+=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrRelaxed(T valueToOr)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndOrRelaxed(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -742,7 +775,8 @@
\sa operator|=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrAcquire(T valueToOr)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndOrAcquire(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -758,7 +792,8 @@
\sa operator|=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrRelease(T valueToOr)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndOrRelease(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -774,7 +809,8 @@
\sa operator|=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrOrdered(T valueToOr)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndOrOrdered(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -790,7 +826,8 @@
\sa operator|=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::operator|=(T value)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::operator|=(T value)
\since 5.3
Atomic or-and-fetch.
@@ -804,7 +841,8 @@
\sa fetchAndOrOrdered()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorRelaxed(T valueToXor)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndXorRelaxed(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -819,7 +857,8 @@
\sa operator^=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorAcquire(T valueToXor)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndXorAcquire(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -835,7 +874,8 @@
\sa operator^=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorRelease(T valueToXor)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndXorRelease(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -851,7 +891,8 @@
\sa operator^=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorOrdered(T valueToXor)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndXorOrdered(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -867,7 +908,8 @@
\sa operator^=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::operator^=(T value)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::operator^=(T value)
\since 5.3
Atomic xor-and-fetch.
@@ -881,7 +923,8 @@
\sa fetchAndXorOrdered()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndRelaxed(T valueToAnd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAndRelaxed(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -896,7 +939,8 @@
\sa operator&=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndAcquire(T valueToAnd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAndAcquire(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -912,7 +956,8 @@
\sa operator&=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndRelease(T valueToAnd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAndRelease(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -928,7 +973,8 @@
\sa operator&=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndOrdered(T valueToAnd)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::fetchAndAndOrdered(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -944,7 +990,8 @@
\sa operator&=()
*/
-/*! \fn template <typename T> T QAtomicInteger<T>::operator&=(T value)
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::operator&=(T value)
\since 5.3
Atomic add-and-fetch.
@@ -1287,17 +1334,20 @@
\sa QAtomicInteger
*/
-/*! \fn template <typename T> QAtomicPointer<T>::QAtomicPointer(T *value)
+/*!
+ \fn template <typename T> QAtomicPointer<T>::QAtomicPointer(T *value)
Constructs a QAtomicPointer with the given \a value.
*/
-/*! \fn template <typename T> QAtomicPointer<T>::QAtomicPointer(const QAtomicPointer<T> &other)
+/*!
+ \fn template <typename T> QAtomicPointer<T>::QAtomicPointer(const QAtomicPointer<T> &other)
Constructs a copy of \a other.
*/
-/*! \fn template <typename T> QAtomicPointer &QAtomicPointer<T>::operator=(const QAtomicPointer &other)
+/*!
+ \fn template <typename T> QAtomicPointer &QAtomicPointer<T>::operator=(const QAtomicPointer &other)
Assigns \a other to this QAtomicPointer and returns a reference to
this QAtomicPointer.
@@ -1369,18 +1419,21 @@
\sa storeRelaxed(), loadRelaxed()
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetNative()
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetNative()
Returns \c true if test-and-set is implemented using atomic processor
instructions, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetWaitFree()
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetWaitFree()
Returns \c true if atomic test-and-set is wait-free, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1394,7 +1447,8 @@
processor to freely reorder memory accesses.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1409,7 +1463,8 @@
be re-ordered before the atomic operation.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1424,7 +1479,8 @@
re-ordered after the atomic operation.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1439,19 +1495,22 @@
may not be re-ordered.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndStoreNative()
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::isFetchAndStoreNative()
Returns \c true if fetch-and-store is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndStoreWaitFree()
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::isFetchAndStoreWaitFree()
Returns \c true if atomic fetch-and-store is wait-free, false
otherwise.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
Atomic fetch-and-store.
@@ -1463,7 +1522,8 @@
processor to freely reorder memory accesses.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
Atomic fetch-and-store.
@@ -1476,7 +1536,8 @@
be re-ordered before the atomic operation.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
Atomic fetch-and-store.
@@ -1489,7 +1550,8 @@
re-ordered after the atomic operation.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
Atomic fetch-and-store.
@@ -1502,19 +1564,22 @@
may not be re-ordered.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndAddNative()
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::isFetchAndAddNative()
Returns \c true if fetch-and-add is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndAddWaitFree()
+/*!
+ \fn template <typename T> bool QAtomicPointer<T>::isFetchAndAddWaitFree()
Returns \c true if atomic fetch-and-add is wait-free, false
otherwise.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
Atomic fetch-and-add.
@@ -1526,7 +1591,8 @@
processor to freely reorder memory accesses.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
Atomic fetch-and-add.
@@ -1539,7 +1605,8 @@
be re-ordered before the atomic operation.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
Atomic fetch-and-add.
@@ -1552,7 +1619,8 @@
re-ordered after the atomic operation.
*/
-/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
+/*!
+ \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
Atomic fetch-and-add.
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
index a3b9be0729..aa57ddc610 100644
--- a/src/corelib/thread/qatomic.h
+++ b/src/corelib/thread/qatomic.h
@@ -50,6 +50,10 @@ QT_BEGIN_NAMESPACE
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wextra")
+#ifdef Q_CLANG_QDOC
+# undef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
+#endif
+
// High-level atomic integer operations
template <typename T>
class QAtomicInteger : public QBasicAtomicInteger<T>
@@ -194,7 +198,9 @@ public:
#ifdef Q_QDOC
T *load() const;
T *loadAcquire() const;
+ T *loadRelaxed() const;
void store(T *newValue);
+ void storeRelaxed(T *newValue);
void storeRelease(T *newValue);
static Q_DECL_CONSTEXPR bool isTestAndSetNative();
diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h
index 079049af25..0a47ac3717 100644
--- a/src/corelib/thread/qwaitcondition.h
+++ b/src/corelib/thread/qwaitcondition.h
@@ -58,14 +58,11 @@ public:
bool wait(QMutex *lockedMutex,
QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever));
+ bool wait(QMutex *lockedMutex, unsigned long time);
+
bool wait(QReadWriteLock *lockedReadWriteLock,
QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever));
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_VERSION_X_5_15("Use wait(QMutex *lockedMutex, QDeadlineTimer deadline) instead")
- bool wait(QMutex *lockedMutex, unsigned long time);
- QT_DEPRECATED_VERSION_X_5_15("Use wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline) instead")
bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time);
-#endif
void wakeOne();
void wakeAll();
@@ -94,10 +91,8 @@ public:
{ return true; }
bool wait(QReadWriteLock *, QDeadlineTimer = QDeadlineTimer(QDeadlineTimer::Forever))
{ return true; }
-#if QT_DEPRECATED_SINCE(5, 15)
bool wait(QMutex *, unsigned long) { return true; }
bool wait(QReadWriteLock *, unsigned long) { return true; }
-#endif
void wakeOne() {}
void wakeAll() {}
diff --git a/src/corelib/thread/qwaitcondition.qdoc b/src/corelib/thread/qwaitcondition.qdoc
index 9da6f6f25c..014d549477 100644
--- a/src/corelib/thread/qwaitcondition.qdoc
+++ b/src/corelib/thread/qwaitcondition.qdoc
@@ -119,16 +119,14 @@
\sa wakeOne()
*/
-#if QT_DEPRECATED_SINCE(5, 15)
/*!
\fn bool QWaitCondition::wait(QMutex *lockedMutex, unsigned long time)
- \obsolete use wait(QMutex *lockedMutex, QDeadlineTimer deadline) instead
+ \overload
*/
/*!
\fn bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, unsigned long time)
- \obsolete use wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline) instead
+ \overload
*/
-#endif
/*!
\fn bool QWaitCondition::wait(QMutex *lockedMutex, QDeadlineTimer deadline)
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index 80f9e780e7..88b058f410 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -202,14 +202,12 @@ void QWaitCondition::wakeAll()
report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeAll()", "mutex unlock");
}
-#if QT_DEPRECATED_SINCE(5, 15)
bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
{
if (time == std::numeric_limits<unsigned long>::max())
return wait(mutex, QDeadlineTimer(QDeadlineTimer::Forever));
return wait(mutex, QDeadlineTimer(time));
}
-#endif
bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
{
@@ -231,14 +229,12 @@ bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
return returnValue;
}
-#if QT_DEPRECATED_SINCE(5, 15)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{
if (time == std::numeric_limits<unsigned long>::max())
return wait(readWriteLock, QDeadlineTimer(QDeadlineTimer::Forever));
return wait(readWriteLock, QDeadlineTimer(time));
}
-#endif
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline)
{
diff --git a/src/corelib/time/qcalendar.cpp b/src/corelib/time/qcalendar.cpp
index d308aeba2b..6a4623ce92 100644
--- a/src/corelib/time/qcalendar.cpp
+++ b/src/corelib/time/qcalendar.cpp
@@ -100,7 +100,7 @@ struct Registry {
if (id == QCalendar::System::User) {
byId.push_back(calendar);
} else {
- Q_ASSERT(byId.at(size_t(id)) == nullptr);
+ Q_ASSERT(byId[size_t(id)] == nullptr);
byId[size_t(id)] = calendar;
}
if (id == QCalendar::System::Gregorian) {
@@ -618,7 +618,7 @@ const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
if (calendarRegistry.isDestroyed() || system == QCalendar::System::User)
return nullptr;
Q_ASSERT(calendarRegistry->byId.size() >= size_t(system));
- if (auto *c = calendarRegistry->byId.at(size_t(system)))
+ if (auto *c = calendarRegistry->byId[size_t(system)])
return c;
switch (system) {
case QCalendar::System::Gregorian:
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index d2d09ceee6..67d37f19d8 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -1626,6 +1626,29 @@ qint64 QDate::daysTo(const QDate &d) const
*/
#if QT_CONFIG(datestring)
+namespace {
+
+struct ParsedInt { int value = 0; bool ok = false; };
+
+/*
+ /internal
+
+ Read an int that must be the whole text. QStringRef::toInt() will ignore
+ spaces happily; but ISO date format should not.
+*/
+ParsedInt readInt(QStringView text)
+{
+ ParsedInt result;
+ for (const auto &ch : text) {
+ if (ch.isSpace())
+ return result;
+ }
+ result.value = QLocale::c().toInt(text, &result.ok);
+ return result;
+}
+
+}
+
/*!
Returns the QDate represented by the \a string, using the
\a format given, or an invalid date if the string cannot be
@@ -1677,17 +1700,18 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
return QDate(year, month, day);
}
#endif // textdate
- case Qt::ISODate: {
- // Semi-strict parsing, must be long enough and have non-numeric separators
- if (string.size() < 10 || string.at(4).isDigit() || string.at(7).isDigit()
- || (string.size() > 10 && string.at(10).isDigit())) {
- return QDate();
- }
- const int year = string.midRef(0, 4).toInt();
- if (year <= 0 || year > 9999)
- return QDate();
- return QDate(year, string.midRef(5, 2).toInt(), string.midRef(8, 2).toInt());
+ case Qt::ISODate:
+ // Semi-strict parsing, must be long enough and have punctuators as separators
+ if (string.size() >= 10 && string.at(4).isPunct() && string.at(7).isPunct()
+ && (string.size() == 10 || !string.at(10).isDigit())) {
+ QStringView view(string);
+ const ParsedInt year = readInt(view.mid(0, 4));
+ const ParsedInt month = readInt(view.mid(5, 2));
+ const ParsedInt day = readInt(view.mid(8, 2));
+ if (year.ok && year.value > 0 && year.value <= 9999 && month.ok && day.ok)
+ return QDate(year.value, month.value, day.value);
}
+ break;
}
return QDate();
}
@@ -2331,17 +2355,15 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
*isMidnight24 = false;
const int size = string.size();
- if (size < 5)
+ if (size < 5 || string.at(2) != QLatin1Char(':'))
return QTime();
- const QLocale C(QLocale::c());
- bool ok = false;
- int hour = C.toInt(string.mid(0, 2), &ok);
- if (!ok)
- return QTime();
- const int minute = C.toInt(string.mid(3, 2), &ok);
- if (!ok)
+ ParsedInt hour = readInt(string.mid(0, 2));
+ ParsedInt minute = readInt(string.mid(3, 2));
+ if (!hour.ok || !minute.ok)
return QTime();
+ // FIXME: ISO 8601 allows [,.]\d+ after hour, just as it does after minute
+
int second = 0;
int msec = 0;
@@ -2361,44 +2383,56 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
// will then be rounded up AND clamped to 999.
const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
- const long minuteFractionInt = C.toLong(minuteFractionStr, &ok);
- if (!ok)
+ const ParsedInt parsed = readInt(minuteFractionStr);
+ if (!parsed.ok)
return QTime();
- const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.size()));
+ const float secondWithMs
+ = double(parsed.value) * 60 / (std::pow(double(10), minuteFractionStr.size()));
- const float secondWithMs = minuteFraction * 60;
- const float secondNoMs = std::floor(secondWithMs);
- const float secondFraction = secondWithMs - secondNoMs;
- second = secondNoMs;
+ second = std::floor(secondWithMs);
+ const float secondFraction = secondWithMs - second;
msec = qMin(qRound(secondFraction * 1000.0), 999);
- } else {
+ } else if (string.at(5) == QLatin1Char(':')) {
// HH:mm:ss or HH:mm:ss.zzz
- second = C.toInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)), &ok);
- if (!ok)
+ const ParsedInt parsed = readInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)));
+ if (!parsed.ok)
return QTime();
- if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
+ second = parsed.value;
+ if (size <= 8) {
+ // No fractional part to read
+ } else if (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.')) {
QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
- // toInt() ignores leading spaces, so catch them before calling it
+ bool ok = true;
+ // Can't use readInt() here, as we *do* allow trailing space - but not leading:
if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
return QTime();
- // We do, however, want to ignore *trailing* spaces.
msecStr = msecStr.trimmed();
- int msecInt = msecStr.isEmpty() ? 0 : C.toInt(msecStr, &ok);
+ int msecInt = msecStr.isEmpty() ? 0 : QLocale::c().toInt(msecStr, &ok);
if (!ok)
return QTime();
const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
msec = qMin(qRound(secondFraction * 1000.0), 999);
+ } else {
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) // behavior change
+ // Stray cruft after date-time: tolerate trailing space, but nothing else.
+ for (const auto &ch : string.mid(8)) {
+ if (!ch.isSpace())
+ return QTime();
+ }
+#endif
}
+ } else {
+ return QTime();
}
const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
- if (isISODate && hour == 24 && minute == 0 && second == 0 && msec == 0) {
+ if (isISODate && hour.value == 24 && minute.value == 0 && second == 0 && msec == 0) {
if (isMidnight24)
*isMidnight24 = true;
- hour = 0;
+ hour.value = 0;
}
- return QTime(hour, minute, second, msec);
+ return QTime(hour.value, minute.value, second, msec);
}
/*!
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index dcac91778f..77c8da7f4a 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -1120,21 +1120,6 @@ uint qHash(long double key, uint seed) noexcept
\snippet code/src_corelib_tools_qhash.cpp 9
- However, you can store multiple values per key by using
- insertMulti() instead of insert() (or using the convenience
- subclass QMultiHash). If you want to retrieve all
- the values for a single key, you can use values(const Key &key),
- which returns a QList<T>:
-
- \snippet code/src_corelib_tools_qhash.cpp 10
-
- The items that share the same key are available from most
- recently to least recently inserted. A more efficient approach is
- to call find() to get the iterator for the first item with a key
- and iterate from there:
-
- \snippet code/src_corelib_tools_qhash.cpp 11
-
If you only need to extract the values from a hash (not the keys),
you can also use \l{foreach}:
@@ -1435,9 +1420,8 @@ uint qHash(long double key, uint seed) noexcept
/*! \fn template <class Key, class T> int QHash<Key, T>::remove(const Key &key)
Removes all the items that have the \a key from the hash.
- Returns the number of items removed which is usually 1 but will
- be 0 if the key isn't in the hash, or greater than 1 if
- insertMulti() has been used with the \a key.
+ Returns the number of items removed which is 1 if the key exists in the hash,
+ and 0 otherwise.
\sa clear(), take(), QMultiHash::remove()
*/
@@ -1507,27 +1491,25 @@ uint qHash(long double key, uint seed) noexcept
/*! \fn template <class Key, class T> QList<Key> QHash<Key, T>::uniqueKeys() const
\since 4.2
+ \obsolete
Returns a list containing all the keys in the map. Keys that occur multiple
times in the map (because items were inserted with insertMulti(), or
unite() was used) occur only once in the returned list.
- \sa keys(), values()
+ \sa QMultiHash::uniqueKeys()
*/
/*! \fn template <class Key, class T> QList<Key> QHash<Key, T>::keys() const
Returns a list containing all the keys in the hash, in an
arbitrary order. Keys that occur multiple times in the hash
- (because items were inserted with insertMulti(), or unite() was
- used) also occur multiple times in the list.
-
- To obtain a list of unique keys, where each key from the map only
- occurs once, use uniqueKeys().
+ (because the method is operating on a QMultiHash) also occur
+ multiple times in the list.
The order is guaranteed to be the same as that used by values().
- \sa uniqueKeys(), values(), key()
+ \sa QMultiMap::uniqueKeys(), values(), key()
*/
/*! \fn template <class Key, class T> QList<Key> QHash<Key, T>::keys(const T &value) const
@@ -1555,7 +1537,7 @@ uint qHash(long double key, uint seed) noexcept
*/
/*! \fn template <class Key, class T> QList<T> QHash<Key, T>::values(const Key &key) const
-
+ \obsolete
\overload
Returns a list of all the values associated with the \a key,
@@ -1592,6 +1574,7 @@ uint qHash(long double key, uint seed) noexcept
*/
/*! \fn template <class Key, class T> int QHash<Key, T>::count(const Key &key) const
+ \obsolete
Returns the number of items associated with the \a key.
@@ -1803,8 +1786,6 @@ uint qHash(long double key, uint seed) noexcept
If there are multiple items with the \a key, the most
recently inserted item's value is replaced with \a value.
-
- \sa insertMulti()
*/
/*! \fn template <class Key, class T> void QHash<Key, T>::insert(const QHash &other)
@@ -1820,6 +1801,7 @@ uint qHash(long double key, uint seed) noexcept
*/
/*! \fn template <class Key, class T> QHash<Key, T>::iterator QHash<Key, T>::insertMulti(const Key &key, const T &value)
+ \obsolete
Inserts a new item with the \a key and a value of \a value.
@@ -1828,16 +1810,17 @@ uint qHash(long double key, uint seed) noexcept
different from insert(), which overwrites the value of an
existing item.)
+ This function is obsolete. Use QMultiHash or QMultiMap instead.
+
\sa insert(), values()
*/
/*! \fn template <class Key, class T> QHash &QHash<Key, T>::unite(const QHash &other)
+ \obsolete
Inserts all the items in the \a other hash into this hash. If a
key is common to both hashes, the resulting hash will contain the
key multiple times.
-
- \sa insertMulti()
*/
/*! \fn template <class Key, class T> bool QHash<Key, T>::empty() const
@@ -1978,10 +1961,7 @@ uint qHash(long double key, uint seed) noexcept
\snippet code/src_corelib_tools_qhash.cpp 17
Unlike QMap, which orders its items by key, QHash stores its
- items in an arbitrary order. The only guarantee is that items that
- share the same key (because they were inserted using
- QHash::insertMulti()) will appear consecutively, from the most
- recently to the least recently inserted value.
+ items in an arbitrary order.
Let's see a few examples of things we can do with a
QHash::iterator that we cannot do with a QHash::const_iterator.
@@ -2048,7 +2028,7 @@ uint qHash(long double key, uint seed) noexcept
There is no direct way of changing an item's key through an
iterator, although it can be done by calling QHash::erase()
- followed by QHash::insert() or QHash::insertMulti().
+ followed by QHash::insert().
\sa value()
*/
@@ -2210,7 +2190,7 @@ uint qHash(long double key, uint seed) noexcept
Unlike QMap, which orders its items by key, QHash stores its
items in an arbitrary order. The only guarantee is that items that
share the same key (because they were inserted using
- QHash::insertMulti()) will appear consecutively, from the most
+ a QMultiHash) will appear consecutively, from the most
recently to the least recently inserted value.
Multiple iterators can be used on the same hash. However, be aware
@@ -2543,18 +2523,22 @@ uint qHash(long double key, uint seed) noexcept
It inherits QHash and extends it with a few convenience functions
that make it more suitable than QHash for storing multi-valued
hashes. A multi-valued hash is a hash that allows multiple values
- with the same key; QHash normally doesn't allow that, unless you
- call QHash::insertMulti().
+ with the same key.
Because QMultiHash inherits QHash, all of QHash's functionality also
applies to QMultiHash. For example, you can use isEmpty() to test
whether the hash is empty, and you can traverse a QMultiHash using
- QHash's iterator classes (for example, QHashIterator). But in
- addition, it provides an insert() function that corresponds to
- QHash::insertMulti(), and a replace() function that corresponds to
+ QHash's iterator classes (for example, QHashIterator). But opposed to
+ QHash, it provides an insert() function will allow the insertion of
+ multiple items with the same key. The replace() function corresponds to
QHash::insert(). It also provides convenient operator+() and
operator+=().
+ Unlike QMultiMap, QMultiHash does not provide and ordering of the
+ inserted items. The only guarantee is that items that
+ share the same key will appear consecutively, from the most
+ recently to the least recently inserted value.
+
Example:
\snippet code/src_corelib_tools_qhash.cpp 24
@@ -2645,7 +2629,8 @@ uint qHash(long double key, uint seed) noexcept
\sa replace()
*/
-/*! \fn template <class Key, class T> QMultiHash &QMultiHash<Key, T>::operator+=(const QMultiHash &other)
+/*! \fn template <class Key, class T> QMultiHash &QMultiHash<Key, T>::unite(const QMultiHash &other)
+ \since 5.13
Inserts all the items in the \a other hash into this hash
and returns a reference to this hash.
@@ -2653,6 +2638,32 @@ uint qHash(long double key, uint seed) noexcept
\sa insert()
*/
+/*! \fn template <class Key, class T> QList<Key> QMultiHash<Key, T>::uniqueKeys() const
+ \since 5.13
+
+ Returns a list containing all the keys in the map. Keys that occur multiple
+ times in the map occur only once in the returned list.
+
+ \sa keys(), values()
+*/
+
+/*! \fn template <class Key, class T> QList<T> QMultiHash<Key, T>::values(const Key &key) const
+ \overload
+
+ Returns a list of all the values associated with the \a key,
+ from the most recently inserted to the least recently inserted.
+
+ \sa count(), insert()
+*/
+
+/*! \fn template <class Key, class T> QMultiHash &QMultiHash<Key, T>::operator+=(const QMultiHash &other)
+
+ Inserts all the items in the \a other hash into this hash
+ and returns a reference to this hash.
+
+ \sa unite(), insert()
+*/
+
/*! \fn template <class Key, class T> QMultiHash QMultiHash<Key, T>::operator+(const QMultiHash &other) const
Returns a hash that contains all the items in this hash in
@@ -2682,6 +2693,13 @@ uint qHash(long double key, uint seed) noexcept
\sa QHash::remove()
*/
+/*! \fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key) const
+
+ Returns the number of items associated with the \a key.
+
+ \sa contains(), insert()
+*/
+
/*!
\fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key, const T &value) const
\since 4.3
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 84e6b0f944..c56324eef7 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -305,12 +305,14 @@ public:
T &operator[](const Key &key);
const T operator[](const Key &key) const;
- QList<Key> uniqueKeys() const;
QList<Key> keys() const;
QList<Key> keys(const T &value) const;
QList<T> values() const;
- QList<T> values(const Key &key) const;
- int count(const Key &key) const;
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<Key> uniqueKeys() const;
+ QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<T> values(const Key &key) const;
+ QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") int count(const Key &key) const;
+#endif
class const_iterator;
@@ -380,6 +382,7 @@ public:
{
friend class iterator;
friend class QHash<Key, T>;
+ friend class QMultiHash<Key, T>;
friend class QSet<Key>;
QHashData::Node *i;
@@ -508,8 +511,10 @@ public:
const_iterator constFind(const Key &key) const;
iterator insert(const Key &key, const T &value);
void insert(const QHash &hash);
- iterator insertMulti(const Key &key, const T &value);
- QHash &unite(const QHash &other);
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
+ QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other);
+#endif
// STL compatibility
typedef T mapped_type;
@@ -551,6 +556,7 @@ private:
#endif
}
friend class QSet<Key>;
+ friend class QMultiHash<Key, T>;
};
@@ -589,38 +595,6 @@ QHash<Key, T>::createNode(uint ah, const Key &akey, const T &avalue, Node **anex
}
template <class Key, class T>
-Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::unite(const QHash &other)
-{
- if (d == &QHashData::shared_null) {
- *this = other;
- } else {
-#if QT_DEPRECATED_SINCE(5, 15)
- QHash copy(other);
- const_iterator it = copy.constEnd();
- while (it != copy.constBegin()) {
- it.i = QHashData::previousNode(it.i);
- insertMulti(it.key(), it.value());
- }
-#else
- QHash copy(other);
- const_iterator it = copy.cbegin();
- const const_iterator end = copy.cend();
- while (it != end) {
- const auto rangeStart = it++;
- while (it != end && rangeStart.key() == it.key())
- ++it;
- const qint64 last = std::distance(rangeStart, it) - 1;
- for (qint64 i = last; i >= 0; --i) {
- auto next = std::next(rangeStart, i);
- insertMulti(next.key(), next.value());
- }
- }
-#endif
- }
- return *this;
-}
-
-template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x)
{
x->free_helper(deleteNode2);
@@ -679,26 +653,6 @@ Q_INLINE_TEMPLATE const T QHash<Key, T>::value(const Key &akey, const T &adefaul
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const
-{
- QList<Key> res;
- res.reserve(size()); // May be too much, but assume short lifetime
- const_iterator i = begin();
- if (i != end()) {
- for (;;) {
- const Key &aKey = i.key();
- res.append(aKey);
- do {
- if (++i == end())
- goto break_out_of_outer_loop;
- } while (aKey == i.key());
- }
- }
-break_out_of_outer_loop:
- return res;
-}
-
-template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::keys() const
{
QList<Key> res;
@@ -757,32 +711,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values() const
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values(const Key &akey) const
-{
- QList<T> res;
- Node *node = *findNode(akey);
- if (node != e) {
- do {
- res.append(node->value);
- } while ((node = node->next) != e && node->key == akey);
- }
- return res;
-}
-
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
-{
- int cnt = 0;
- Node *node = *findNode(akey);
- if (node != e) {
- do {
- ++cnt;
- } while ((node = node->next) != e && node->key == akey);
- }
- return cnt;
-}
-
-template <class Key, class T>
Q_INLINE_TEMPLATE const T QHash<Key, T>::operator[](const Key &akey) const
{
return value(akey);
@@ -848,18 +776,6 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::insert(const QHash &hash)
}
template <class Key, class T>
-Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insertMulti(const Key &akey,
- const T &avalue)
-{
- detach();
- d->willGrow();
-
- uint h;
- Node **nextNode = findNode(akey, &h);
- return iterator(createNode(h, akey, avalue, nextNode));
-}
-
-template <class Key, class T>
Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::remove(const Key &akey)
{
if (isEmpty()) // prevents detaching shared null
@@ -1109,11 +1025,12 @@ public:
inline typename QHash<Key, T>::iterator replace(const Key &key, const T &value)
{ return QHash<Key, T>::insert(key, value); }
- inline typename QHash<Key, T>::iterator insert(const Key &key, const T &value)
- { return QHash<Key, T>::insertMulti(key, value); }
+ typename QHash<Key, T>::iterator insert(const Key &key, const T &value);
+
+ inline QMultiHash &unite(const QMultiHash &other);
inline QMultiHash &operator+=(const QMultiHash &other)
- { this->unite(other); return *this; }
+ { return unite(other); }
inline QMultiHash operator+(const QMultiHash &other) const
{ QMultiHash result = *this; result += other; return result; }
@@ -1122,13 +1039,27 @@ public:
using QHash<Key, T>::count;
using QHash<Key, T>::find;
using QHash<Key, T>::constFind;
+ using QHash<Key, T>::values;
+ using QHash<Key, T>::findNode;
+ using QHash<Key, T>::createNode;
+ using QHash<Key, T>::concrete;
+ using QHash<Key, T>::detach;
+
+ using typename QHash<Key, T>::Node;
+ using typename QHash<Key, T>::iterator;
+ using typename QHash<Key, T>::const_iterator;
bool contains(const Key &key, const T &value) const;
int remove(const Key &key, const T &value);
+ int count(const Key &key) const;
int count(const Key &key, const T &value) const;
+ QList<Key> uniqueKeys() const;
+
+ QList<T> values(const Key &akey) const;
+
typename QHash<Key, T>::iterator find(const Key &key, const T &value) {
typename QHash<Key, T>::iterator i(find(key));
typename QHash<Key, T>::iterator end(this->end());
@@ -1157,6 +1088,50 @@ private:
};
template <class Key, class T>
+Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QMultiHash<Key, T>::insert(const Key &akey, const T &avalue)
+{
+ detach();
+ this->d->willGrow();
+
+ uint h;
+ Node **nextNode = findNode(akey, &h);
+ return iterator(createNode(h, akey, avalue, nextNode));
+}
+
+template <class Key, class T>
+Q_INLINE_TEMPLATE QMultiHash<Key, T> &QMultiHash<Key, T>::unite(const QMultiHash &other)
+{
+ if (this->d == &QHashData::shared_null) {
+ *this = other;
+ } else {
+#if QT_DEPRECATED_SINCE(5, 15)
+ QMultiHash copy(other);
+ const_iterator it = copy.constEnd();
+ while (it != copy.constBegin()) {
+ it.i = QHashData::previousNode(it.i);
+ insert(it.key(), it.value());
+ }
+#else
+ const QMultiHash copy(other);
+ const_iterator it = copy.cbegin();
+ const const_iterator end = copy.cend();
+ while (it != end) {
+ const auto rangeStart = it++;
+ while (it != end && rangeStart.key() == it.key())
+ ++it;
+ const qint64 last = std::distance(rangeStart, it) - 1;
+ for (qint64 i = last; i >= 0; --i) {
+ auto next = std::next(rangeStart, i);
+ insert(next.key(), next.value());
+ }
+ }
+#endif
+ }
+ return *this;
+}
+
+
+template <class Key, class T>
Q_INLINE_TEMPLATE bool QMultiHash<Key, T>::contains(const Key &key, const T &value) const
{
return constFind(key, value) != QHash<Key, T>::constEnd();
@@ -1193,7 +1168,84 @@ Q_INLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &key, const T &value)
return n;
}
-template<class Key, class T>
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<Key> QMultiHash<Key, T>::uniqueKeys() const
+{
+ QList<Key> res;
+ res.reserve(QHash<Key, T>::size()); // May be too much, but assume short lifetime
+ typename QHash<Key, T>::const_iterator i = QHash<Key, T>::begin();
+ if (i != QHash<Key, T>::end()) {
+ for (;;) {
+ const Key &aKey = i.key();
+ res.append(aKey);
+ do {
+ if (++i == QHash<Key, T>::end())
+ goto break_out_of_outer_loop;
+ } while (aKey == i.key());
+ }
+ }
+break_out_of_outer_loop:
+ return res;
+}
+
+#if QT_DEPRECATED_SINCE(5, 15)
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insertMulti(const Key &key, const T &value) {
+ return static_cast<QMultiHash<Key, T> *>(this)->insert(key, value);
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::unite(const QHash &other) {
+ return static_cast<QMultiHash<Key, T> *>(this)->unite(other);
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values(const Key &akey) const
+{
+ return static_cast<const QMultiHash<Key, T> *>(this)->values(akey);
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
+{
+ return static_cast<const QMultiHash<Key, T> *>(this)->count(akey);
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const
+{
+ return static_cast<const QMultiHash<Key, T> *>(this)->uniqueKeys();
+}
+#endif
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE QList<T> QMultiHash<Key, T>::values(const Key &akey) const
+{
+ QList<T> res;
+ Node *node = *findNode(akey);
+ if (node != this->e) {
+ do {
+ res.append(node->value);
+ } while ((node = node->next) != this->e && node->key == akey);
+ }
+ return res;
+}
+
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &akey) const
+{
+ int cnt = 0;
+ Node *node = *findNode(akey);
+ if (node != this->e) {
+ do {
+ ++cnt;
+ } while ((node = node->next) != this->e && node->key == akey);
+ }
+ return cnt;
+}
+
+template <class Key, class T>
class QHashIterator
{
typedef typename QHash<Key, T>::const_iterator const_iterator;
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index a0ec372f9a..970373101f 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -1150,6 +1150,20 @@ void QMapDataBase::freeData(QMapDataBase *d)
\sa insertMulti()
*/
+/*! \fn template <class Key, class T> void QMap<Key, T>::insert(const QMap<Key, T> &map)
+ \since 5.15
+
+ Inserts all the items in \a map into this map.
+
+ If a key is common to both maps, its value will be replaced with
+ the value stored in \a map.
+
+ \note If \a map contains multiple entries with the same key then the
+ final value of the key is undefined.
+
+ \sa insertMulti()
+*/
+
/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value)
Inserts a new item with the key \a key and a value of \a value.
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index f169ed5e49..5cc3116903 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -552,6 +552,7 @@ public:
const_iterator upperBound(const Key &key) const;
iterator insert(const Key &key, const T &value);
iterator insert(const_iterator pos, const Key &key, const T &value);
+ void insert(const QMap<Key, T> &map);
iterator insertMulti(const Key &key, const T &value);
iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
QMap<Key, T> &unite(const QMap<Key, T> &other);
@@ -763,6 +764,49 @@ typename QMap<Key, T>::iterator QMap<Key, T>::insert(const_iterator pos, const K
}
template <class Key, class T>
+Q_INLINE_TEMPLATE void QMap<Key, T>::insert(const QMap<Key, T> &map)
+{
+ if (d == map.d)
+ return;
+
+ detach();
+
+ Node *n = d->root();
+ auto it = map.cbegin();
+ const auto e = map.cend();
+ while (it != e) {
+ // Insertion here is based on insert(Key, T)
+ auto parent = d->end();
+ bool left = true;
+ Node *lastNode = nullptr;
+ while (n) {
+ parent = n;
+ if (!qMapLessThanKey(n->key, it.key())) {
+ lastNode = n;
+ n = n->leftNode();
+ left = true;
+ } else {
+ n = n->rightNode();
+ left = false;
+ }
+ }
+ if (lastNode && !qMapLessThanKey(it.key(), lastNode->key)) {
+ lastNode->value = it.value();
+ n = lastNode;
+ } else {
+ n = d->createNode(it.key(), it.value(), parent, left);
+ }
+ ++it;
+ if (it != e) {
+ // Move back up the tree until we find the next branch or node which is
+ // relevant for the next key.
+ while (n != d->root() && qMapLessThanKey(n->key, it.key()))
+ n = static_cast<Node *>(n->parent());
+ }
+ }
+}
+
+template <class Key, class T>
Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &akey,
const T &avalue)
{
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index df6db45abc..8d01b7ec12 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -107,6 +107,7 @@ private:
const std::less<const T*> less = {};
return !less(d->end(), i) && !less(i, d->begin());
}
+public:
QVector(DataPointer dd) noexcept
: d(dd)
{