Merge "Merge remote-tracking branch 'origin/dev' into wip/cmake" into wip/cmake

This commit is contained in:
The Qt Project 2019-11-25 14:49:13 +00:00
commit bc1cae774a
606 changed files with 60140 additions and 49842 deletions

View File

@ -733,7 +733,13 @@ defineTest(qtConfOutput_preparePaths) {
}
have_prefix = false
} else {
config.input.prefix = $$absolute_path($$config.input.prefix, $$OUT_PWD)
equals(XSPEC, $$[QMAKE_SPEC]) {
# Only make the user-specified prefix absolute if we're not cross-compiling.
config.input.prefix = $$absolute_path($$config.input.prefix, $$OUT_PWD)
} else {
# But we still must normalize path separators.
config.input.prefix = $$replace(config.input.prefix, \\\\, /)
}
have_prefix = true
}

View File

@ -11,6 +11,12 @@ dita.metadata.default.audience = programmer
navigation.homepage = index.html
navigation.hometitle = "Qt $QT_VER"
#Words to ignore for auto-linking
ignorewords += \
macOS \
WebChannel \
OpenGL
sourcedirs += includes $$BUILDDIR
url = http://doc.qt.io/qt-5

View File

@ -52,21 +52,6 @@
#include <QDebug>
//! [Message class implementation]
Message::Message()
{
}
Message::Message(const Message &other)
: m_body(other.m_body), m_headers(other.m_headers)
{
}
Message::~Message()
{
}
//! [Message class implementation]
Message::Message(const QString &body, const QStringList &headers)
: m_body(body), m_headers(headers)
{

View File

@ -58,9 +58,10 @@
class Message
{
public:
Message();
Message(const Message &other);
~Message();
Message() = default;
~Message() = default;
Message(const Message &) = default;
Message &operator=(const Message &) = default;
Message(const QString &body, const QStringList &headers);

View File

@ -50,19 +50,6 @@
#include "message.h"
Message::Message()
{
}
Message::Message(const Message &other)
: m_body(other.m_body), m_headers(other.m_headers)
{
}
Message::~Message()
{
}
Message::Message(const QString &body, const QStringList &headers)
: m_body(body), m_headers(headers)
{

View File

@ -58,9 +58,10 @@
class Message
{
public:
Message();
Message(const Message &other);
~Message();
Message() = default;
~Message() = default;
Message(const Message &) = default;
Message &operator=(const Message &) = default;
Message(const QString &body, const QStringList &headers);

View File

@ -81,11 +81,6 @@
\section1 The Message Class Implementation
The implementation of the default constructor, copy constructor and destructor
are straightforward for the \c Message class:
\snippet tools/customtype/message.cpp Message class implementation
The streaming operator is implemented in the following way:
\snippet tools/customtype/message.cpp custom type streaming operator

View File

@ -53,7 +53,7 @@
#include <QtWidgets>
SpreadSheetDelegate::SpreadSheetDelegate(QObject *parent)
: QItemDelegate(parent)
: QStyledItemDelegate(parent)
{}
QWidget *SpreadSheetDelegate::createEditor(QWidget *parent,

View File

@ -51,9 +51,9 @@
#ifndef SPREADSHEETDELEGATE_H
#define SPREADSHEETDELEGATE_H
#include <QItemDelegate>
#include <QStyledItemDelegate>
class SpreadSheetDelegate : public QItemDelegate
class SpreadSheetDelegate : public QStyledItemDelegate
{
Q_OBJECT

View File

@ -55,9 +55,8 @@
//! [0]
ImageDelegate::ImageDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
: QStyledItemDelegate(parent)
{}
//! [0]
//! [1]

View File

@ -51,10 +51,10 @@
#ifndef IMAGEDELEGATE_H
#define IMAGEDELEGATE_H
#include <QItemDelegate>
#include <QStyledItemDelegate>
//! [0]
class ImageDelegate : public QItemDelegate
class ImageDelegate : public QStyledItemDelegate
{
Q_OBJECT
@ -72,7 +72,7 @@ public:
//! [1] //! [2]
private slots:
void emitCommitData();
};
//! [2]
};
#endif

View File

@ -216,16 +216,13 @@ void MainWindow::changeIcon()
QImage image(fileName);
if (!image.isNull())
icon.addPixmap(QPixmap::fromImage(image), mode, state);
//! [8] //! [9]
//! [8]
}
//! [9] //! [10]
}
//! [10]
//! [11]
previewArea->setIcon(icon);
}
//! [11]
}
void MainWindow::addSampleImages()
{
@ -280,17 +277,15 @@ void MainWindow::loadImages(const QStringList &fileNames)
.arg(QDir::toNativeSeparators(fileInfo.absolutePath()), fileInfo.fileName())
.arg(fileInfo2x.exists() ? fileInfo2x.fileName() : tr("<None>"))
.arg(image.width()).arg(image.height());
//! [13] //! [14]
QTableWidgetItem *fileItem = new QTableWidgetItem(imageName);
fileItem->setData(Qt::UserRole, fileName);
fileItem->setIcon(QPixmap::fromImage(image));
fileItem->setFlags((fileItem->flags() | Qt::ItemIsUserCheckable) & ~Qt::ItemIsEditable);
fileItem->setToolTip(toolTip);
//! [14]
//! [13]
//! [15]
QIcon::Mode mode = QIcon::Normal;
//! [15] //! [16]
QIcon::State state = QIcon::Off;
if (guessModeStateAct->isChecked()) {
if (imageName.contains(QLatin1String("_act"), Qt::CaseInsensitive))
@ -302,13 +297,11 @@ void MainWindow::loadImages(const QStringList &fileNames)
if (imageName.contains(QLatin1String("_on"), Qt::CaseInsensitive))
state = QIcon::On;
//! [16] //! [17]
//! [15]
}
//! [17]
//! [18]
imagesTable->setItem(row, 0, fileItem);
//! [18] //! [19]
QTableWidgetItem *modeItem =
new QTableWidgetItem(IconPreviewArea::iconModeNames().at(IconPreviewArea::iconModes().indexOf(mode)));
modeItem->setToolTip(toolTip);
@ -321,9 +314,9 @@ void MainWindow::loadImages(const QStringList &fileNames)
imagesTable->openPersistentEditor(stateItem);
fileItem->setCheckState(Qt::Checked);
//! [18]
}
}
//! [19]
void MainWindow::useHighDpiPixmapsChanged(int checkState)
{
@ -350,9 +343,7 @@ QWidget *MainWindow::createImagesGroupBox()
//! [21]
//! [22]
QStringList labels;
//! [22] //! [23]
labels << tr("Image") << tr("Mode") << tr("State");
const QStringList labels({tr("Image"), tr("Mode"), tr("State")});
imagesTable->horizontalHeader()->setDefaultSectionSize(90);
imagesTable->setColumnCount(3);
@ -361,18 +352,17 @@ QWidget *MainWindow::createImagesGroupBox()
imagesTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed);
imagesTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed);
imagesTable->verticalHeader()->hide();
//! [23]
//! [22]
//! [24]
connect(imagesTable, &QTableWidget::itemChanged,
//! [24] //! [25]
this, &MainWindow::changeIcon);
QVBoxLayout *layout = new QVBoxLayout(imagesGroupBox);
layout->addWidget(imagesTable);
return imagesGroupBox;
}
//! [25]
}
//! [26]
QWidget *MainWindow::createIconSizeGroupBox()
@ -428,8 +418,8 @@ QWidget *MainWindow::createIconSizeGroupBox()
layout->addLayout(otherSizeLayout, 3, 0, 1, 2);
layout->setRowStretch(4, 1);
return iconSizeGroupBox;
}
//! [27]
}
void MainWindow::screenChanged()
{

View File

@ -53,6 +53,7 @@
#include <QCoreApplication>
#include <QPainter>
#include <QtMath>
#include <cstdlib>
//! [0]
TabletCanvas::TabletCanvas()

View File

@ -43,13 +43,6 @@ isEmpty(ALL_ANDROID_ABIS): ALL_ANDROID_ABIS = arm64-v8a armeabi-v7a x86_64 x86
CONFIG += $$ANDROID_PLATFORM
QMAKE_PCH_OUTPUT_EXT = .gch
QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
NDK_LLVM_PATH = $$NDK_ROOT/toolchains/llvm/prebuilt/$$NDK_HOST
QMAKE_CC = $$NDK_LLVM_PATH/bin/clang
QMAKE_CXX = $$NDK_LLVM_PATH/bin/clang++
@ -70,8 +63,8 @@ QMAKE_CFLAGS_THREAD = -D_REENTRANT
QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden
QMAKE_CFLAGS_NEON = -mfpu=neon
QMAKE_LFLAGS_APP = -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_APP = -Wl,--build-id=sha1 -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_SHLIB = -Wl,--build-id=sha1 -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
QMAKE_LFLAGS_RPATH = -Wl,-rpath=

View File

@ -20,7 +20,7 @@ CONFIG += plugin no_plugin_name_prefix
javac.input = JAVASOURCES
javac.output = $$CLASS_DIR
javac.CONFIG += combine
javac.commands = javac -source 6 -target 6 -Xlint:unchecked -bootclasspath $$ANDROID_JAR_FILE -cp $$shell_quote($$system_path($$join(JAVACLASSPATH, $$DIRLIST_SEPARATOR))) -d $$shell_quote($$CLASS_DIR) ${QMAKE_FILE_IN}
javac.commands = javac -source 7 -target 7 -Xlint:unchecked -bootclasspath $$ANDROID_JAR_FILE -cp $$shell_quote($$system_path($$join(JAVACLASSPATH, $$DIRLIST_SEPARATOR))) -d $$shell_quote($$CLASS_DIR) ${QMAKE_FILE_IN}
# Force rebuild every time, because we don't know the paths of the destination files
# as they depend on the code.
javac.depends = FORCE

View File

@ -2,17 +2,25 @@ qtPrepareTool(MOC_COLLECT_JSON, moc)
QMAKE_MOC_OPTIONS += --output-json
MOC_JSON_H_BASE = $${QMAKE_H_MOD_MOC}
MOC_JSON_CPP_BASE = $${QMAKE_CPP_MOD_MOC}
!isEmpty(MOC_DIR) {
MOC_JSON_H_BASE = $$MOC_DIR/$${MOC_JSON_H_BASE}
MOC_JSON_CPP_BASE = $$MOC_DIR/$${MOC_JSON_CPP_BASE}
}
moc_json_header.input = HEADERS
moc_json_header.output = $$MOC_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}.json
moc_json_header.output = $${MOC_JSON_H_BASE}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}.json
moc_json_header.CONFIG = no_link moc_verify
moc_json_header.depends = $$MOC_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}
moc_json_header.depends = $${MOC_JSON_H_BASE}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}
moc_json_header.commands = $$escape_expand(\\n) # force creation of rule
moc_json_header.variable_out = MOC_JSON_FILES
moc_json_source.input = SOURCES
moc_json_source.output = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}.json
moc_json_source.output = $${MOC_JSON_CPP_BASE}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}.json
moc_json_source.CONFIG = no_link moc_verify
moc_json_source.depends = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}
moc_json_source.depends = $${MOC_JSON_CPP_BASE}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}
moc_json_source.commands = $$escape_expand(\\n) # force creation of rule
moc_json_source.variable_out = MOC_JSON_FILES

View File

@ -25,14 +25,16 @@ defineTest(addInstallFiles) {
export($$1)
}
probase = $$relative_path($$_PRO_FILE_PWD_, $$dirname(_QMAKE_CONF_)/examples)
moduleRoot = $$dirname(_QMAKE_CONF_)
probase = $$relative_path($$_PRO_FILE_PWD_, $$moduleRoot/examples)
isEmpty(probase)|contains(probase, ^\\..*): \
return()
isEmpty(_QMAKE_CACHE_) {
!equals(OUT_PWD, $$_PRO_FILE_PWD_): \
return()
error("You cannot build examples inside the Qt source tree, except as part of a proper Qt build.")
moduleRootRelativeToBuildDir = $$relative_path($$moduleRoot, $$OUT_PWD)
# Check if OUT_PWD is inside module root
equals(moduleRootRelativeToBuildDir, .)|contains(moduleRootRelativeToBuildDir, \(\.\./\)+\(\.\.\)?): \
error("You cannot build examples inside the Qt source tree, except as part of a proper Qt build.")
}
contains(TEMPLATE, "vc.*"): \

View File

@ -22,7 +22,7 @@ QMAKE_CFLAGS_WARN_OFF = -W0
QMAKE_CFLAGS_DEBUG = $$QMAKE_CFLAGS_OPTIMIZE_DEBUG -Zi -MDd
QMAKE_CFLAGS_UTF8_SOURCE = -Qoption,cpp,--unicode_source_kind,UTF-8
QMAKE_CFLAGS_LTCG = -Qipo
QMAKE_CFLAGS_DISABLE_LTCG = -Qno-ipo
QMAKE_CFLAGS_DISABLE_LTCG = -Qipo-
QMAKE_CFLAGS_SSE2 = -QxSSE2
QMAKE_CFLAGS_SSE3 = -QxSSE3
@ -39,6 +39,11 @@ QMAKE_CFLAGS_AVX512DQ += -QxCORE-AVX512
QMAKE_CFLAGS_AVX512BW += -QxCORE-AVX512
QMAKE_CFLAGS_AVX512VL += -QxCORE-AVX512
QMAKE_CFLAGS_F16C = $$QMAKE_CFLAGS_AVX2
QMAKE_CFLAGS_RDRND = $$QMAKE_CFLAGS_AVX2
# ICC on Windows lacks the mrdseed compiler option that sets the RDSEED macro
QMAKE_CFLAGS_RDSEED = -D__RDSEED__=1
QMAKE_CFLAGS_ARCH_HASWELL = $$QMAKE_CFLAGS_AVX2
QMAKE_CFLAGS_AESNI = -QxSSE2
QMAKE_CFLAGS_SHANI = -QxSSE4.2

View File

@ -24,12 +24,12 @@ QOBJS = \
qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o \
qfilesystementry.o qfsfileengine.o qfsfileengine_iterator.o \
qiodevice.o qsettings.o qtemporaryfile.o qtextstream.o \
qjsonarray.o qjson.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \
qcborvalue.o qjsoncbor.o qjsonarray.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \
qmetatype.o qsystemerror.o qvariant.o \
quuid.o \
qarraydata.o qbitarray.o qbytearray.o qbytearraylist.o qbytearraymatcher.o \
qcalendar.o qgregoriancalendar.o qromancalendar.o \
qcryptographichash.o qdatetime.o qhash.o qlist.o \
qcryptographichash.o qdatetime.o qhash.o \
qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \
qstringbuilder.o qstring.o qstringlist.o qversionnumber.o \
qvsnprintf.o qxmlstream.o qxmlutils.o \
@ -96,9 +96,10 @@ DEPEND_SRC = \
$(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
$(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
$(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qcborvalue.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qdatastream.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qjsonarray.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qjson.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qjsoncbor.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qjsondocument.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qjsonobject.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qjsonparser.cpp \
@ -124,7 +125,6 @@ DEPEND_SRC = \
$(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \
$(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \
$(SOURCE_PATH)/src/corelib/tools/qhash.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlist.cpp \
$(SOURCE_PATH)/src/corelib/tools/qmap.cpp \
$(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
$(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \
@ -370,9 +370,6 @@ qversionnumber.o: $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp
qbuffer.o: $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
@ -466,7 +463,10 @@ qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
qdatastream.o: $(SOURCE_PATH)/src/corelib/serialization/qdatastream.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
qjson.o: $(SOURCE_PATH)/src/corelib/serialization/qjson.cpp
qcborvalue.o: $(SOURCE_PATH)/src/corelib/serialization/qcborvalue.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
qjsoncbor.o: $(SOURCE_PATH)/src/corelib/serialization/qjsoncbor.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
qjsondocument.o: $(SOURCE_PATH)/src/corelib/serialization/qjsondocument.cpp

View File

@ -90,7 +90,6 @@ QTOBJS= \
qiodevice.obj \
qringbuffer.obj \
qdebug.obj \
qlist.obj \
qlocale.obj \
qlocale_tools.obj \
qlocale_win.obj \
@ -118,7 +117,8 @@ QTOBJS= \
qxmlutils.obj \
qnumeric.obj \
qlogging.obj \
qjson.obj \
qcborvalue.obj \
qjsoncbor.obj \
qjsondocument.obj \
qjsonparser.obj \
qjsonarray.obj \

View File

@ -4690,7 +4690,7 @@
The definitions above define a qmake target called \c mytarget, containing a
Makefile target called \c{.buildfile} which in turn is generated with the
\l{touchfunction}{touch()} function. Finally, the
\c touch command. Finally, the
\c{.depends} member specifies that \c mytarget depends on \c mytarget2,
another target that is defined afterwards. \c mytarget2 is a dummy target.
It is only defined to echo some text to the console.

View File

@ -198,9 +198,8 @@ UnixMakefileGenerator::init()
QString headerSuffix;
if (project->isActiveConfig("clang_pch_style"))
headerSuffix = project->first("QMAKE_PCH_OUTPUT_EXT").toQString();
else
pchBaseName += project->first("QMAKE_PCH_OUTPUT_EXT").toQString();
pchBaseName += project->first("QMAKE_PCH_OUTPUT_EXT").toQString();
pchBaseName += Option::dir_sep;
ProString language = project->first(ProKey("QMAKE_LANGUAGE_" + compiler));
@ -319,8 +318,7 @@ QStringList
if(!project->isEmpty("PRECOMPILED_DIR"))
header_prefix = project->first("PRECOMPILED_DIR").toQString();
header_prefix += project->first("QMAKE_ORIG_TARGET").toQString();
if (!project->isActiveConfig("clang_pch_style"))
header_prefix += project->first("QMAKE_PCH_OUTPUT_EXT").toQString();
header_prefix += project->first("QMAKE_PCH_OUTPUT_EXT").toQString();
if (project->isActiveConfig("icc_pch_style")) {
// icc style
ProStringList pchArchs = project->values("QMAKE_PCH_ARCHS");

View File

@ -1006,8 +1006,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isEmpty("PRECOMPILED_DIR"))
precomph_out_dir = project->first("PRECOMPILED_DIR");
precomph_out_dir += project->first("QMAKE_ORIG_TARGET");
if (!project->isActiveConfig("clang_pch_style"))
precomph_out_dir += project->first("QMAKE_PCH_OUTPUT_EXT");
precomph_out_dir += project->first("QMAKE_PCH_OUTPUT_EXT");
if (project->isActiveConfig("icc_pch_style")) {
// icc style
@ -1126,8 +1125,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isEmpty("PRECOMPILED_DIR"))
pchOutput = project->first("PRECOMPILED_DIR");
pchOutput += pchBaseName;
if (!project->isActiveConfig("clang_pch_style"))
pchOutput += project->first("QMAKE_PCH_OUTPUT_EXT");
pchOutput += project->first("QMAKE_PCH_OUTPUT_EXT");
if (!project->isActiveConfig("icc_pch_style")) {
// gcc style (including clang_pch_style)

View File

@ -1043,7 +1043,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
for (int d = 0; d < dirs.count(); d++) {
QString dir = dirs[d];
QDir qdir(pfx + dir);
for (int i = 0; i < (int)qdir.count(); ++i) {
for (int i = 0, count = int(qdir.count()); i < count; ++i) {
if (qdir[i] == statics.strDot || qdir[i] == statics.strDotDot)
continue;
QString fname = dir + qdir[i];

View File

@ -116,6 +116,7 @@ SOURCES += \
qbytearray.cpp \
qbytearraymatcher.cpp \
qcalendar.cpp \
qcborvalue.cpp \
qcryptographichash.cpp \
qdatetime.cpp \
qdir.cpp \
@ -131,8 +132,8 @@ SOURCES += \
qgregoriancalendar.cpp \
qhash.cpp \
qiodevice.cpp \
qjson.cpp \
qjsonarray.cpp \
qjsoncbor.cpp \
qjsondocument.cpp \
qjsonobject.cpp \
qjsonparser.cpp \
@ -174,6 +175,8 @@ HEADERS += \
qcalendar.h \
qcalendarbackend_p.h \
qcalendarmath_p.h \
qcborvalue.h \
qcborvalue_p.h \
qchar.h \
qcryptographichash.h \
qdatetime.h \

View File

@ -1,8 +0,0 @@
This is a copy of the library for binary-decimal and decimal-binary
conversion routines for IEEE doubles, available from
https://github.com/google/double-conversion
commit 2fb03de56faa32bbba5e02222528e7b760f71d77
See the LICENSE file for license information.

View File

@ -255,6 +255,12 @@ bool DoubleToStringConverter::ToExponential(
const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
char decimal_rep[kDecimalRepCapacity];
#ifndef NDEBUG
// Problem: there is an assert in StringBuilder::AddSubstring() that
// will pass this buffer to strlen(), and this buffer is not generally
// null-terminated.
memset(decimal_rep, 0, sizeof(decimal_rep));
#endif
int decimal_rep_length;
if (requested_digits == -1) {
@ -534,7 +540,7 @@ static double SignedZero(bool sign) {
// because it constant-propagated the radix and concluded that the last
// condition was always true. By moving it into a separate function the
// compiler wouldn't warn anymore.
#if _MSC_VER
#ifdef _MSC_VER
#pragma optimize("",off)
static bool IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
@ -558,7 +564,7 @@ static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
// Returns true, when the iterator is equal to end.
template<class Iterator>
static bool Advance (Iterator* it, char separator, int base, Iterator& end) {
static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) {
if (separator == StringToDoubleConverter::kNoSeparator) {
++(*it);
return *it == end;
@ -586,7 +592,7 @@ static bool Advance (Iterator* it, char separator, int base, Iterator& end) {
template<class Iterator>
static bool IsHexFloatString(Iterator start,
Iterator end,
char separator,
uc16 separator,
bool allow_trailing_junk) {
ASSERT(start != end);
@ -603,8 +609,8 @@ static bool IsHexFloatString(Iterator start,
saw_digit = true;
if (Advance(&current, separator, 16, end)) return false;
}
if (!saw_digit) return false; // Only the '.', but no digits.
}
if (!saw_digit) return false;
if (*current != 'p' && *current != 'P') return false;
if (Advance(&current, separator, 16, end)) return false;
if (*current == '+' || *current == '-') {
@ -627,7 +633,7 @@ template <int radix_log_2, class Iterator>
static double RadixStringToIeee(Iterator* current,
Iterator end,
bool sign,
char separator,
uc16 separator,
bool parse_as_hex_float,
bool allow_trailing_junk,
double junk_string_value,
@ -762,7 +768,11 @@ static double RadixStringToIeee(Iterator* current,
}
int written_exponent = 0;
while (IsDecimalDigitForRadix(**current, 10)) {
written_exponent = 10 * written_exponent + **current - '0';
// No need to read exponents if they are too big. That could potentially overflow
// the `written_exponent` variable.
if (abs(written_exponent) <= 100 * Double::kMaxExponent) {
written_exponent = 10 * written_exponent + **current - '0';
}
if (Advance(current, separator, radix, end)) break;
}
if (is_negative) written_exponent = -written_exponent;
@ -898,10 +908,11 @@ double StringToDoubleConverter::StringToIeee(
(*current == 'x' || *current == 'X')) {
++current;
if (current == end) return junk_string_value_; // "0x"
bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
IsHexFloatString(current, end, separator_, allow_trailing_junk);
if (current == end) return junk_string_value_; // "0x"
if (!parse_as_hex_float && !isDigit(*current, 16)) {
return junk_string_value_;
}

View File

@ -1,4 +1,4 @@
INCLUDEPATH += $$PWD/.. $$PWD/include $$PWD/include/double-conversion
INCLUDEPATH += $$PWD/.. $$PWD/include
SOURCES += \
$$PWD/bignum.cc \
$$PWD/bignum-dtoa.cc \
@ -20,5 +20,3 @@ HEADERS += \
$$PWD/ieee.h \
$$PWD/strtod.h \
$$PWD/include/double-conversion/utils.h
OTHER_FILES += README

View File

@ -47,6 +47,8 @@ class Double {
static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
static const int kSignificandSize = 53;
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kMaxExponent = 0x7FF - kExponentBias;
Double() : d64_(0) {}
explicit Double(double d) : d64_(double_to_uint64(d)) {}
@ -222,9 +224,7 @@ class Double {
}
private:
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kDenormalExponent = -kExponentBias + 1;
static const int kMaxExponent = 0x7FF - kExponentBias;
static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);

View File

@ -56,6 +56,13 @@ inline void abort_noreturn() { abort(); }
#endif
#endif
#ifndef DOUBLE_CONVERSION_UNUSED
#ifdef __GNUC__
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
#else
#define DOUBLE_CONVERSION_UNUSED
#endif
#endif
// Double operations detection based on target architecture.
// Linux uses a 80bit wide floating point stack on x86. This induces double
@ -91,10 +98,11 @@ int main(int argc, char** argv) {
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
defined(__riscv) || defined(__EMSCRIPTEN__) || \
defined(__or1k__)
defined(__riscv) || \
defined(__or1k__) || defined(__arc__) || \
defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(__mc68000__) || \
defined(__pnacl__) || defined(__native_client__)
@ -343,6 +351,7 @@ inline Dest BitCast(const Source& source) {
static_assert(sizeof(Dest) == sizeof(Source),
"source and destination size mismatch");
#else
DOUBLE_CONVERSION_UNUSED
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
#endif

View File

@ -5,8 +5,8 @@
"QtUsage": "Used in Qt Core. Configure with -system-doubleconversion or -no-doubleconversion to avoid.",
"Homepage": "https://github.com/google/double-conversion",
"Version": "3.1.1",
"DownloadLocation": "https://github.com/google/double-conversion/commit/4199ef3d456ed0549e5665cf4186f0ee6210db3b",
"Version": "3.1.5",
"DownloadLocation": "https://github.com/google/double-conversion/commit/5fa81e88ef24e735b4283b8f7454dc59693ac1fc",
"License": "BSD 3-clause \"New\" or \"Revised\" License",
"LicenseId": "BSD-3-Clause",
"LicenseFile": "LICENSE",

View File

@ -2,7 +2,7 @@
#define JPEG_LIB_VERSION 80
#define LIBJPEG_TURBO_VERSION 2.0.2
#define LIBJPEG_TURBO_VERSION 2.0.3
#define LIBJPEG_TURBO_VERSION_NUMBER 2000002

View File

@ -8,7 +8,7 @@
#define PACKAGE_NAME "libjpeg-turbo"
#define VERSION "2.0.0"
#define VERSION "2.0.3"
#if SIZE_MAX == 0xffffffff
#define SIZEOF_SIZE_T 4

View File

@ -6,7 +6,7 @@
"Description": "The Independent JPEG Group's JPEG software",
"Homepage": "http://libjpeg-turbo.virtualgl.org/",
"Version": "2.0.2",
"Version": "2.0.3",
"License": "Independent JPEG Group License",
"LicenseId": "IJG",
"LicenseFile": "LICENSE",

View File

@ -1,3 +1,41 @@
2.0.3
=====
### Significant changes relative to 2.0.2:
1. Fixed "using JNI after critical get" errors that occurred on Android
platforms when passing invalid arguments to certain methods in the TurboJPEG
Java API.
2. Fixed a regression in the SIMD feature detection code, introduced by
the AVX2 SIMD extensions (2.0 beta1[1]), that was known to cause an illegal
instruction exception, in rare cases, on CPUs that lack support for CPUID leaf
07H (or on which the maximum CPUID leaf has been limited by way of a BIOS
setting.)
3. The 4:4:0 (h1v2) fancy (smooth) chroma upsampling algorithm in the
decompressor now uses a similar bias pattern to that of the 4:2:2 (h2v1) fancy
chroma upsampling algorithm, rounding up or down the upsampled result for
alternate pixels rather than always rounding down. This ensures that,
regardless of whether a 4:2:2 JPEG image is rotated or transposed prior to
decompression (in the frequency domain) or after decompression (in the spatial
domain), the final image will be similar.
4. Fixed an integer overflow and subsequent segfault that occurred when
attempting to compress or decompress images with more than 1 billion pixels
using the TurboJPEG API.
5. Fixed a regression introduced by 2.0 beta1[15] whereby attempting to
generate a progressive JPEG image on an SSE2-capable CPU using a scan script
containing one or more scans with lengths divisible by 16 would result in an
error ("Missing Huffman code table entry") and an invalid JPEG image.
6. Fixed an issue whereby `tjDecodeYUV()` and `tjDecodeYUVPlanes()` would throw
an error ("Invalid progressive parameters") or a warning ("Inconsistent
progression sequence") if passed a TurboJPEG instance that was previously used
to decompress a progressive JPEG image.
2.0.2
=====

View File

@ -135,12 +135,11 @@ without recompiling. libjpeg-turbo does not claim to support all of the
libjpeg v7+ features, nor to produce identical output to libjpeg v7+ in all
cases (see below.)
By passing an argument of `--with-jpeg7` or `--with-jpeg8` to `configure`, or
an argument of `-DWITH_JPEG7=1` or `-DWITH_JPEG8=1` to `cmake`, you can build a
version of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so that
programs that are built against libjpeg v7 or v8 can be run with libjpeg-turbo.
The following section describes which libjpeg v7+ features are supported and
which aren't.
By passing an argument of `-DWITH_JPEG7=1` or `-DWITH_JPEG8=1` to `cmake`, you
can build a version of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so
that programs that are built against libjpeg v7 or v8 can be run with
libjpeg-turbo. The following section describes which libjpeg v7+ features are
supported and which aren't.
### Support for libjpeg v7 and v8 Features
@ -247,9 +246,8 @@ don't, and it allows those functions to be provided in the "official"
libjpeg-turbo binaries.
Those who are concerned about maintaining strict conformance with the libjpeg
v6b or v7 API can pass an argument of `--without-mem-srcdst` to `configure` or
an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to building
libjpeg-turbo. This will restore the pre-1.3 behavior, in which
v6b or v7 API can pass an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to
building libjpeg-turbo. This will restore the pre-1.3 behavior, in which
`jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the
libjpeg v8 API/ABI.
@ -344,3 +342,15 @@ quality of 98-100. Thus, libjpeg-turbo must use the non-SIMD quantization
function in those cases. This causes performance to drop by as much as 40%.
It is therefore strongly advised that you use the slow integer forward DCT
whenever encoding images with a JPEG quality of 98 or higher.
Memory Debugger Pitfalls
========================
Valgrind and Memory Sanitizer (MSan) can generate false positives
(specifically, incorrect reports of uninitialized memory accesses) when used
with libjpeg-turbo's SIMD extensions. It is generally recommended that the
SIMD extensions be disabled, either by passing an argument of `-DWITH_SIMD=0`
to `cmake` when configuring the build or by setting the environment variable
`JSIMD_FORCENONE` to `1` at run time, when testing libjpeg-turbo with Valgrind,
MSan, or other memory debuggers.

View File

@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2014-2016, 2018, D. R. Commander.
* Copyright (C) 2009-2011, 2014-2016, 2018-2019, D. R. Commander.
* Copyright (C) 2015, Matthieu Darbois.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@ -356,6 +356,8 @@ dump_buffer(working_state *state)
put_buffer = (put_buffer << size) | code; \
}
#if SIZEOF_SIZE_T != 8 && !defined(_WIN64)
#define CHECKBUF15() { \
if (put_bits > 15) { \
EMIT_BYTE() \
@ -363,6 +365,8 @@ dump_buffer(working_state *state)
} \
}
#endif
#define CHECKBUF31() { \
if (put_bits > 31) { \
EMIT_BYTE() \

View File

@ -492,8 +492,8 @@ prepare_for_pass(j_compress_ptr cinfo)
*/
master->pass_type = output_pass;
master->pass_number++;
/*FALLTHROUGH*/
#endif
/*FALLTHROUGH*/
case output_pass:
/* Do a data-output pass. */
/* We need not repeat per-scan setup if prior optimization pass did it. */

View File

@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2016, 2018, D. R. Commander.
* Copyright (C) 2009-2011, 2016, 2018-2019, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@ -589,7 +589,11 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) {
/* Convert DC difference to actual value, update last_dc_val */
int ci = cinfo->MCU_membership[blkn];
s += state.last_dc_val[ci];
/* This is really just
* s += state.last_dc_val[ci];
* It is written this way in order to shut up UBSan.
*/
s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
state.last_dc_val[ci] = s;
if (block) {
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
@ -684,7 +688,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) {
int ci = cinfo->MCU_membership[blkn];
s += state.last_dc_val[ci];
s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
state.last_dc_val[ci] = s;
if (block)
(*block)[0] = (JCOEF)s;

View File

@ -429,8 +429,6 @@ h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
#define WRITE_TWO_PIXELS_LE(addr, pixels) { \
((INT16 *)(addr))[0] = (INT16)(pixels); \
((INT16 *)(addr))[1] = (INT16)((pixels) >> 16); \

View File

@ -8,6 +8,7 @@
* Copyright (C) 2010, 2015-2016, D. R. Commander.
* Copyright (C) 2014, MIPS Technologies, Inc., California.
* Copyright (C) 2015, Google, Inc.
* Copyright (C) 2019, Arm Limited.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@ -315,9 +316,9 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPARRAY output_data = *output_data_ptr;
JSAMPROW inptr0, inptr1, outptr;
#if BITS_IN_JSAMPLE == 8
int thiscolsum;
int thiscolsum, bias;
#else
JLONG thiscolsum;
JLONG thiscolsum, bias;
#endif
JDIMENSION colctr;
int inrow, outrow, v;
@ -327,15 +328,18 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
for (v = 0; v < 2; v++) {
/* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow];
if (v == 0) /* next nearest is row above */
if (v == 0) { /* next nearest is row above */
inptr1 = input_data[inrow - 1];
else /* next nearest is row below */
bias = 1;
} else { /* next nearest is row below */
inptr1 = input_data[inrow + 1];
bias = 2;
}
outptr = output_data[outrow++];
for (colctr = 0; colctr < compptr->downsampled_width; colctr++) {
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
*outptr++ = (JSAMPLE)((thiscolsum + 1) >> 2);
*outptr++ = (JSAMPLE)((thiscolsum + bias) >> 2);
}
}
inrow++;

View File

@ -127,7 +127,7 @@ struct MD_CTX_tag {
#endif
/* For resolving of inline spans. */
MD_MARKCHAIN mark_chains[11];
MD_MARKCHAIN mark_chains[12];
#define PTR_CHAIN ctx->mark_chains[0]
#define TABLECELLBOUNDARIES ctx->mark_chains[1]
#define ASTERISK_OPENERS_extraword_mod3_0 ctx->mark_chains[2]
@ -139,8 +139,9 @@ struct MD_CTX_tag {
#define UNDERSCORE_OPENERS ctx->mark_chains[8]
#define TILDE_OPENERS ctx->mark_chains[9]
#define BRACKET_OPENERS ctx->mark_chains[10]
#define DOLLAR_OPENERS ctx->mark_chains[11]
#define OPENERS_CHAIN_FIRST 2
#define OPENERS_CHAIN_LAST 10
#define OPENERS_CHAIN_LAST 11
int n_table_cell_boundaries;
@ -1128,7 +1129,7 @@ md_is_html_comment(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF
if(off+1 < lines[0].end && CH(off) == _T('-') && CH(off+1) == _T('>'))
return FALSE;
/* HTML comment must not contyain "--", so we scan just for "--" instead
/* HTML comment must not contain "--", so we scan just for "--" instead
* of "-->" and verify manually that '>' follows. */
if(md_scan_for_html_closer(ctx, _T("--"), 2,
lines, n_lines, off, max_end, p_end, &ctx->html_comment_horizon))
@ -1686,7 +1687,7 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
}
/* Make the bucket capable of holding more ref. defs. */
list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF));
list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF*));
if(list == NULL) {
MD_LOG("malloc() failed.");
goto abort;
@ -1703,7 +1704,7 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
list = (MD_REF_DEF_LIST*) bucket;
if(list->n_ref_defs >= list->alloc_ref_defs) {
MD_REF_DEF_LIST* list_tmp = (MD_REF_DEF_LIST*) realloc(list,
sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF));
sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF*));
if(list_tmp == NULL) {
MD_LOG("realloc() failed.");
goto abort;
@ -2683,6 +2684,9 @@ md_build_mark_char_map(MD_CTX* ctx)
if(ctx->parser.flags & MD_FLAG_STRIKETHROUGH)
ctx->mark_char_map['~'] = 1;
if(ctx->parser.flags & MD_FLAG_LATEXMATHSPANS)
ctx->mark_char_map['$'] = 1;
if(ctx->parser.flags & MD_FLAG_PERMISSIVEEMAILAUTOLINKS)
ctx->mark_char_map['@'] = 1;
@ -3251,6 +3255,21 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
continue;
}
/* A potential equation start/end */
if(ch == _T('$')) {
/* We can have at most two consecutive $ signs,
* where two dollar signs signify a display equation. */
OFF tmp = off+1;
while(tmp < line_end && CH(tmp) == _T('$'))
tmp++;
if (tmp - off <= 2)
PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER);
off = tmp;
continue;
}
/* Turn non-trivial whitespace into single space. */
if(ISWHITESPACE_(ch)) {
OFF tmp = off+1;
@ -3630,6 +3649,36 @@ md_analyze_tilde(MD_CTX* ctx, int mark_index)
}
}
static void
md_analyze_dollar(MD_CTX* ctx, int mark_index)
{
/* This should mimic the way inline equations work in LaTeX, so there
* can only ever be one item in the chain (i.e. the dollars can't be
* nested). This is basically the same as the md_analyze_tilde function,
* except that we require matching openers and closers to be of the same
* length.
*
* E.g.: $abc$$def$$ => abc (display equation) def (end equation) */
if(DOLLAR_OPENERS.head >= 0) {
/* If the potential closer has a non-matching number of $, discard */
MD_MARK* open = &ctx->marks[DOLLAR_OPENERS.head];
MD_MARK* close = &ctx->marks[mark_index];
int opener_index = DOLLAR_OPENERS.head;
md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_ALL);
if (open->end - open->beg == close->end - close->beg) {
/* We are the matching closer */
md_resolve_range(ctx, &DOLLAR_OPENERS, opener_index, mark_index);
} else {
/* We don't match the opener, so discard old opener and insert as opener */
md_mark_chain_append(ctx, &DOLLAR_OPENERS, mark_index);
}
} else {
/* No unmatched openers, so we are opener */
md_mark_chain_append(ctx, &DOLLAR_OPENERS, mark_index);
}
}
static void
md_analyze_permissive_url_autolink(MD_CTX* ctx, int mark_index)
{
@ -3785,6 +3834,7 @@ md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
case '_': /* Pass through. */
case '*': md_analyze_emph(ctx, i); break;
case '~': md_analyze_tilde(ctx, i); break;
case '$': md_analyze_dollar(ctx, i); break;
case '.': /* Pass through. */
case ':': md_analyze_permissive_url_autolink(ctx, i); break;
case '@': md_analyze_permissive_email_autolink(ctx, i); break;
@ -3841,7 +3891,7 @@ static void
md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
int mark_beg, int mark_end)
{
md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~@:."));
md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~$@:."));
ASTERISK_OPENERS_extraword_mod3_0.head = -1;
ASTERISK_OPENERS_extraword_mod3_0.tail = -1;
ASTERISK_OPENERS_extraword_mod3_1.head = -1;
@ -3858,6 +3908,8 @@ md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
UNDERSCORE_OPENERS.tail = -1;
TILDE_OPENERS.head = -1;
TILDE_OPENERS.tail = -1;
DOLLAR_OPENERS.head = -1;
DOLLAR_OPENERS.tail = -1;
}
static int
@ -3974,6 +4026,16 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
MD_LEAVE_SPAN(MD_SPAN_DEL, NULL);
break;
case '$':
if(mark->flags & MD_MARK_OPENER) {
MD_ENTER_SPAN((mark->end - off) % 2 ? MD_SPAN_LATEXMATH : MD_SPAN_LATEXMATH_DISPLAY, NULL);
text_type = MD_TEXT_LATEXMATH;
} else {
MD_LEAVE_SPAN((mark->end - off) % 2 ? MD_SPAN_LATEXMATH : MD_SPAN_LATEXMATH_DISPLAY, NULL);
text_type = MD_TEXT_NORMAL;
}
break;
case '[': /* Link, image. */
case '!':
case ']':
@ -4072,12 +4134,12 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
if(off >= end)
break;
if(text_type == MD_TEXT_CODE) {
if(text_type == MD_TEXT_CODE || text_type == MD_TEXT_LATEXMATH) {
OFF tmp;
MD_ASSERT(prev_mark != NULL);
MD_ASSERT(prev_mark->ch == '`' && (prev_mark->flags & MD_MARK_OPENER));
MD_ASSERT(mark->ch == '`' && (mark->flags & MD_MARK_CLOSER));
MD_ASSERT(ISANYOF2_(prev_mark->ch, '`', '$') && (prev_mark->flags & MD_MARK_OPENER));
MD_ASSERT(ISANYOF2_(mark->ch, '`', '$') && (mark->flags & MD_MARK_CLOSER));
/* Inside a code span, trailing line whitespace has to be
* outputted. */
@ -4085,12 +4147,11 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
while(off < ctx->size && ISBLANK(off))
off++;
if(off > tmp)
MD_TEXT(MD_TEXT_CODE, STR(tmp), off-tmp);
MD_TEXT(text_type, STR(tmp), off-tmp);
/* and new lines are transformed into single spaces. */
if(prev_mark->end < off && off < mark->beg)
MD_TEXT(MD_TEXT_CODE, _T(" "), 1);
MD_TEXT(text_type, _T(" "), 1);
} else if(text_type == MD_TEXT_HTML) {
/* Inside raw HTML, we output the new line verbatim, including
* any trailing spaces. */
@ -5425,7 +5486,10 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA
p_container->start = p_container->start * 10 + CH(off) - _T('0');
off++;
}
if(off+1 < ctx->size && (CH(off) == _T('.') || CH(off) == _T(')')) && (ISBLANK(off+1) || ISNEWLINE(off+1))) {
if(off > beg && off+1 < ctx->size &&
(CH(off) == _T('.') || CH(off) == _T(')')) &&
(ISBLANK(off+1) || ISNEWLINE(off+1)))
{
p_container->ch = CH(off);
p_container->is_loose = FALSE;
p_container->is_task = FALSE;
@ -5700,7 +5764,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
md_is_container_mark(ctx, line->indent, off, &off, &container))
{
if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers &&
(off >= ctx->size || ISNEWLINE(off)))
(off >= ctx->size || ISNEWLINE(off)) && container.ch != _T('>'))
{
/* Noop. List mark followed by a blank line cannot interrupt a paragraph. */
} else if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers &&

View File

@ -129,7 +129,13 @@ typedef enum MD_SPANTYPE {
/* <del>...</del>
* Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled.
*/
MD_SPAN_DEL
MD_SPAN_DEL,
/* For recognizing inline ($) and display ($$) equations
* Note: Recognized only when MD_FLAG_LATEXMATHSPANS is enabled.
*/
MD_SPAN_LATEXMATH,
MD_SPAN_LATEXMATH_DISPLAY
} MD_SPANTYPE;
/* Text is the actual textual contents of span. */
@ -168,7 +174,11 @@ typedef enum MD_TEXTTYPE {
/* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not
* an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used.
* The text contains verbatim '\n' for the new lines. */
MD_TEXT_HTML
MD_TEXT_HTML,
/* Text is inside an equation. This is processed the same way as inlined code
* spans (`code`). */
MD_TEXT_LATEXMATH
} MD_TEXTTYPE;
@ -275,6 +285,7 @@ typedef struct MD_SPAN_IMG_DETAIL {
#define MD_FLAG_STRIKETHROUGH 0x0200 /* Enable strikethrough extension. */
#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x0400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */
#define MD_FLAG_TASKLISTS 0x0800 /* Enable task list extension. */
#define MD_FLAG_LATEXMATHSPANS 0x1000 /* Enable $ and $$ containing LaTeX equations. */
#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS)
#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS)

View File

@ -9,7 +9,7 @@
"License": "MIT License",
"LicenseId": "MIT",
"LicenseFile": "LICENSE.md",
"Version": "0.3.3",
"DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.3.3",
"Version": "0.3.4",
"DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.3.4",
"Copyright": "Copyright © 2016-2019 Martin Mitáš"
}

View File

@ -1,42 +0,0 @@
From 3442a3ce9c2bd366eb0bd1c18d37a6ce732a888d Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.shaw@qt.io>
Date: Wed, 25 Sep 2019 09:17:01 +0200
Subject: [PATCH] Fix CVE-2019-16168 in SQLite
v3.29.0 is the latest and there is no indication as to when the next
release is so we will apply this separately for now and it can be
reverted once it is in a release that we ship with.
This patch is taken from https://www.sqlite.org/src/info/98357d8c1263920b
Change-Id: I82d398b093b67842a4369e3220c01e7eea30763a
---
src/3rdparty/sqlite/sqlite3.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 61bfdeb766..b3e6ae27b6 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -105933,7 +105933,9 @@ static void decodeIntArray(
if( sqlite3_strglob("unordered*", z)==0 ){
pIndex->bUnordered = 1;
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
- pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
+ int sz = sqlite3Atoi(z+3);
+ if( sz<2 ) sz = 2;
+ pIndex->szIdxRow = sqlite3LogEst(sz);
}else if( sqlite3_strglob("noskipscan*", z)==0 ){
pIndex->noSkipScan = 1;
}
@@ -143260,6 +143262,7 @@ static int whereLoopAddBtreeIndex(
** it to pNew->rRun, which is currently set to the cost of the index
** seek only. Then, if this is a non-covering index, add the cost of
** visiting the rows in the main table. */
+ assert( pSrc->pTab->szTabRow>0 );
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
--
2.20.1 (Apple Git-117)

View File

@ -6,8 +6,8 @@
"Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.",
"Homepage": "https://www.sqlite.org/",
"Version": "3.29.0",
"DownloadLocation": "https://www.sqlite.org/2019/sqlite-amalgamation-3290000.zip",
"Version": "3.30.1",
"DownloadLocation": "https://www.sqlite.org/2019/sqlite-amalgamation-3300100.zip",
"License": "Public Domain",
"Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed."
}

File diff suppressed because it is too large Load Diff

View File

@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.29.0"
#define SQLITE_VERSION_NUMBER 3029000
#define SQLITE_SOURCE_ID "2019-07-10 17:32:03 fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6"
#define SQLITE_VERSION "3.30.1"
#define SQLITE_VERSION_NUMBER 3030001
#define SQLITE_SOURCE_ID "2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -2093,6 +2093,17 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable views,
** positive to enable views or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
** which case the view setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the
@ -2265,7 +2276,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */
#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */
#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */
#define SQLITE_DBCONFIG_MAX 1014 /* Largest DBCONFIG */
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
#define SQLITE_DBCONFIG_MAX 1015 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@ -3814,7 +3826,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** ^The specific value of WHERE-clause [parameter] might influence the
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
** </li>
** </ol>
**
@ -4849,6 +4861,12 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** perform additional optimizations on deterministic functions, so use
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
**
** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
** flag, which if present prevents the function from being invoked from
** within VIEWs or TRIGGERs. For security reasons, the [SQLITE_DIRECTONLY]
** flag is recommended for any application-defined SQL function that has
** side-effects.
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
**
@ -4965,8 +4983,30 @@ SQLITE_API int sqlite3_create_window_function(
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
**
** The SQLITE_DETERMINISTIC flag means that the new function will always
** maps the same inputs into the same output. The abs() function is
** deterministic, for example, but randomblob() is not.
**
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. This is
** a security feature which is recommended for all
** [application-defined SQL functions] that have side-effects. This flag
** prevents an attacker from adding triggers and views to a schema then
** tricking a high-privilege application into causing unintended side-effects
** while performing ordinary queries.
**
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** Specifying this flag makes no difference for scalar or aggregate user
** functions. However, if it is not specified for a user-defined window
** function, then any sub-types belonging to arguments passed to the window
** function may be discarded before the window function is called (i.e.
** sqlite3_value_subtype() will always return 0).
*/
#define SQLITE_DETERMINISTIC 0x800
#define SQLITE_DETERMINISTIC 0x000000800
#define SQLITE_DIRECTONLY 0x000080000
#define SQLITE_SUBTYPE 0x000100000
/*
** CAPI3REF: Deprecated Functions
@ -6612,6 +6652,12 @@ struct sqlite3_index_info {
** ^The sqlite3_create_module()
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
**
** ^If the third parameter (the pointer to the sqlite3_module object) is
** NULL then no new module is create and any existing modules with the
** same name are dropped.
**
** See also: [sqlite3_drop_modules()]
*/
SQLITE_API int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
@ -6627,6 +6673,23 @@ SQLITE_API int sqlite3_create_module_v2(
void(*xDestroy)(void*) /* Module destructor function */
);
/*
** CAPI3REF: Remove Unnecessary Virtual Table Implementations
** METHOD: sqlite3
**
** ^The sqlite3_drop_modules(D,L) interface removes all virtual
** table modules from database connection D except those named on list L.
** The L parameter must be either NULL or a pointer to an array of pointers
** to strings where the array is terminated by a single NULL pointer.
** ^If the L parameter is NULL, then all virtual table modules are removed.
**
** See also: [sqlite3_create_module()]
*/
SQLITE_API int sqlite3_drop_modules(
sqlite3 *db, /* Remove modules from this connection */
const char **azKeep /* Except, do not remove the ones named here */
);
/*
** CAPI3REF: Virtual Table Instance Object
** KEYWORDS: sqlite3_vtab
@ -7335,7 +7398,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_FIRST 5
#define SQLITE_TESTCTRL_PRNG_SAVE 5
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
#define SQLITE_TESTCTRL_PRNG_RESET 7
#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
#define SQLITE_TESTCTRL_BITVEC_TEST 8
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
@ -7358,7 +7421,9 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_IMPOSTER 25
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
#define SQLITE_TESTCTRL_LAST 27 /* Largest TESTCTRL */
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking

View File

@ -0,0 +1,197 @@
if (NOT ${PROJECT_NAME}-MultiAbiBuild)
set(ANDROID_ABIS armeabi-v7a arm64-v8a x86 x86_64)
# Match Android's sysroots
set(ANDROID_SYSROOT_armeabi-v7a arm-linux-androideabi)
set(ANDROID_SYSROOT_arm64-v8a aarch64-linux-android)
set(ANDROID_SYSROOT_x86 i686-linux-android)
set(ANDROID_SYSROOT_x86_64 x86_64-linux-android)
foreach(abi IN LISTS ANDROID_ABIS)
set(abi_initial_value OFF)
if (abi STREQUAL ${ANDROID_ABI})
set(abi_initial_value ON)
endif()
find_library(Qt5Core_${abi}_Probe Qt5Core_${abi})
if (Qt5Core_${abi}_Probe)
option(ANDROID_BUILD_ABI_${abi} "Enable the build for Android ${abi}" ${abi_initial_value})
endif()
endforeach()
# Make sure to delete the "android-build" directory, which contains all the
# build artefacts, and also the androiddeployqt/gradle artefacts
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${CMAKE_BINARY_DIR}/android-build)
if (CMAKE_VERSION VERSION_LESS 3.15)
message(STATUS "-----------------------------------------------------------------------------------------------------------")
message(STATUS "CMake version 3.15 is required to clean the <build_dir>/android-build when issuing the \"clean\" target.\n\n"
"For this CMake version please use the \"clean-android-build\" support target additionally to the \"clean\" target.")
message(STATUS "-----------------------------------------------------------------------------------------------------------")
add_custom_target(clean-android-build
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/android-build
VERBATIM)
endif()
# Write the android_<project_name>_deployment_settings.json file
file(WRITE ${CMAKE_BINARY_DIR}/android_deployment_settings.json.in
[=[{
"_description": "This file is created by CMake to be read by androiddeployqt and should not be modified by hand.",
"application-binary": "@QT_ANDROID_APPLICATION_BINARY@",
"architectures": {
@QT_ANDROID_ARCHITECTURES@
},
@QT_ANDROID_DEPLOYMENT_DEPENDENCIES@
@QT_ANDROID_EXTRA_PLUGINS@
@QT_ANDROID_PACKAGE_SOURCE_DIR@
@QT_ANDROID_VERSION_CODE@
@QT_ANDROID_VERSION_NAME@
@QT_ANDROID_EXTRA_LIBS@
@QT_QML_IMPORT_PATH@
"ndk": "@ANDROID_NDK@",
"ndk-host": "@ANDROID_HOST_TAG@",
"qml-root-path": "@CMAKE_CURRENT_SOURCE_DIR@",
"qt": "@QT_DIR@",
"sdk": "@ANDROID_SDK@",
"stdcpp-path": "@ANDROID_TOOLCHAIN_ROOT@/sysroot/usr/lib/",
"tool-prefix": "llvm",
"toolchain-prefix": "llvm",
"useLLVM": true
}]=])
if (NOT QT_ANDROID_APPLICATION_BINARY)
set(QT_ANDROID_APPLICATION_BINARY ${PROJECT_NAME})
endif()
if(NOT ANDROID_SDK)
get_filename_component(ANDROID_SDK ${ANDROID_NDK}/../ ABSOLUTE)
endif()
find_program(ANDROID_DEPLOY_QT androiddeployqt)
get_filename_component(QT_DIR ${ANDROID_DEPLOY_QT}/../../ ABSOLUTE)
unset(QT_ANDROID_ARCHITECTURES)
foreach(abi IN LISTS ANDROID_ABIS)
if (ANDROID_BUILD_ABI_${abi})
list(APPEND QT_ANDROID_ARCHITECTURES " \"${abi}\" : \"${ANDROID_SYSROOT_${abi}}\"")
endif()
endforeach()
string(REPLACE ";" ",\n" QT_ANDROID_ARCHITECTURES "${QT_ANDROID_ARCHITECTURES}")
macro(generate_json_variable_list var_list json_key)
if (${var_list})
set(QT_${var_list} "\"${json_key}\": \"")
string(REPLACE ";" "," joined_var_list "${${var_list}}")
string(APPEND QT_${var_list} "${joined_var_list}\",")
endif()
endmacro()
macro(generate_json_variable var json_key)
if (${var})
set(QT_${var} "\"${json_key}\": \"${${var}}\",")
endif()
endmacro()
generate_json_variable_list(ANDROID_DEPLOYMENT_DEPENDENCIES "deployment-dependencies")
generate_json_variable_list(ANDROID_EXTRA_PLUGINS "android-extra-plugins")
generate_json_variable(ANDROID_PACKAGE_SOURCE_DIR "android-package-source-directory")
generate_json_variable(ANDROID_VERSION_CODE "android-version-code")
generate_json_variable(ANDROID_VERSION_NAME "android-version-name")
generate_json_variable_list(ANDROID_EXTRA_LIBS "android-extra-libs")
generate_json_variable_list(QML_IMPORT_PATH "qml-import-paths")
configure_file(
"${CMAKE_BINARY_DIR}/android_deployment_settings.json.in"
"${CMAKE_BINARY_DIR}/android_deployment_settings.json" @ONLY)
# Create "apk" and "aab" targets
if (DEFINED ENV{JAVA_HOME})
set(JAVA_HOME $ENV{JAVA_HOME} CACHE INTERNAL "Saved JAVA_HOME variable")
endif()
if (JAVA_HOME)
set(android_deploy_qt_jdk "--jdk ${JAVA_HOME}")
endif()
if (ANDROID_SDK_PLATFORM)
set(android_deploy_qt_platform "--android-platform ${ANDROID_SDK_PLATFORM}")
endif()
add_custom_target(apk
COMMAND ${CMAKE_COMMAND} -E env JAVA_HOME=${JAVA_HOME} ${ANDROID_DEPLOY_QT}
--input "${CMAKE_BINARY_DIR}/android_deployment_settings.json"
--output "${CMAKE_BINARY_DIR}/android-build"
--apk "${CMAKE_BINARY_DIR}/android-build/${PROJECT_NAME}.apk"
${android_deploy_qt_platform}
${android_deploy_qt_jdk}
VERBATIM)
add_custom_target(aab
COMMAND ${CMAKE_COMMAND} -E env JAVA_HOME=${JAVA_HOME} ${ANDROID_DEPLOY_QT}
--input "${CMAKE_BINARY_DIR}/android_deployment_settings.json"
--output "${CMAKE_BINARY_DIR}/android-build"
--apk "${CMAKE_BINARY_DIR}/android-build/${PROJECT_NAME}.apk"
--aab
${android_deploy_qt_platform}
${android_deploy_qt_jdk}
VERBATIM)
include(ExternalProject)
macro (setup_library library_name android_abi)
# Use Qt Creator's 4.12 settings file if present
unset(QTC_SETTINGS_PARAMETER)
if (EXISTS ${CMAKE_BINARY_DIR}/qtcsettings.cmake)
set(QTC_SETTINGS_PARAMETER -C ${CMAKE_BINARY_DIR}/qtcsettings.cmake)
endif()
# Build all the given ABI as an external project
ExternalProject_Add(${library_name}-builder
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
PREFIX MultiAbi
BUILD_ALWAYS YES
DOWNLOAD_COMMAND ""
INSTALL_COMMAND ""
UPDATE_COMMAND ""
PATCH_COMMAND ""
CMAKE_ARGS
${QTC_SETTINGS_PARAMETER}
-D ANDROID_ABI=${android_abi}
-D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH}
-D CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}
-D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-D ANDROID_PLATFORM=${ANDROID_PLATFORM}
-D ANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL}
-D CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
-D CMAKE_FIND_ROOT_PATH_MODE_PROGRAM=${CMAKE_FIND_ROOT_PATH_MODE_PROGRAM}
-D CMAKE_FIND_ROOT_PATH_MODE_LIBRARY=${CMAKE_FIND_ROOT_PATH_MODE_LIBRARY}
-D CMAKE_FIND_ROOT_PATH_MODE_INCLUDE=${CMAKE_FIND_ROOT_PATH_MODE_INCLUDE}
-D CMAKE_FIND_ROOT_PATH_MODE_PACKAGE=${CMAKE_FIND_ROOT_PATH_MODE_PACKAGE}
-D CMAKE_SHARED_LIBRARY_SUFFIX_CXX=_${android_abi}.so
-D CMAKE_SHARED_MODULE_SUFFIX_CXX=_${android_abi}.so
-D CMAKE_SHARED_LIBRARY_SUFFIX_C=_${android_abi}.so
-D CMAKE_SHARED_MODULE_SUFFIX_C=_${android_abi}.so
-D CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_BINARY_DIR}/android-build/libs/${android_abi}
-D ${PROJECT_NAME}-MultiAbiBuild=ON
)
endmacro()
foreach(abi IN LISTS ANDROID_ABIS)
if (NOT abi STREQUAL ${ANDROID_ABI})
if (ANDROID_BUILD_ABI_${abi})
setup_library(${PROJECT_NAME}-${abi} ${abi} ${CMAKE_PREFIX_PATH})
endif()
else()
# For the default abi just use the regular cmake run, to have
# nice IDE integration and so on
set(CMAKE_SHARED_MODULE_SUFFIX_CXX "_${ANDROID_ABI}.so")
set(CMAKE_SHARED_LIBRARY_SUFFIX_CXX "_${ANDROID_ABI}.so")
set(CMAKE_SHARED_MODULE_SUFFIX_C "_${ANDROID_ABI}.so")
set(CMAKE_SHARED_LIBRARY_SUFFIX_C "_${ANDROID_ABI}.so")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/android-build/libs/${ANDROID_ABI})
endif()
endforeach()
else()
# unset the variable, just not to issue an unused variable warning
unset(${PROJECT_NAME}-MultiAbiBuild)
endif()

View File

@ -34,6 +34,8 @@ if (NOT QT_NO_CREATE_TARGETS)
set_property(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::Core PROPERTY INTERFACE_COMPILE_FEATURES cxx_decltype)
endif()
set(CMAKE_AUTOMOC_MACRO_NAMES "Q_OBJECT" "Q_GADGET" "Q_NAMESPACE" "Q_NAMESPACE_EXPORT")
# install layout information, following what qmake -query provides
get_filename_component(QT@PROJECT_VERSION_MAJOR@_INSTALL_PREFIX ${CMAKE_CURRENT_LIST_DIR}/../@QT_INVERSE_CONFIG_INSTALL_DIR@ ABSOLUTE)
set(QT@PROJECT_VERSION_MAJOR@_INSTALL_ARCHDATA ${QT@PROJECT_VERSION_MAJOR@_INSTALL_PREFIX}/@INSTALL_ARCHDATADIR@)

View File

@ -4,7 +4,7 @@ get_filename_component(_qt5_root_dir \"${CMAKE_CURRENT_LIST_DIR}/../../../..\" A
file(GLOB qtmodules ${_qt5_root_dir} "${_qt5_root_dir}/*")
foreach(qtmodule ${qtmodules})
if(IS_DIRECTORY ${qtmodule})
list(APPEND _qt5_module_paths ${qtmodule})
list(APPEND _qt5_module_paths "${qtmodule}" "${qtmodule}/lib/cmake")
endif()
endforeach()
!!ELSE

View File

@ -821,6 +821,12 @@
],
"output": [ "publicFeature", "feature" ]
},
"shortcut": {
"label": "QShortcut",
"purpose": "Provides keyboard accelerators and shortcuts.",
"section": "Kernel",
"output": [ "publicFeature", "feature" ]
},
"systemsemaphore": {
"label": "QSystemSemaphore",
"purpose": "Provides a general counting system semaphore.",
@ -1091,6 +1097,12 @@
Note that this is required for plugin loading. Qt GUI needs QPA plugins for basic operation.",
"section": "Utilities",
"output": [ "publicFeature" ]
},
"binaryjson": {
"label": "Binary JSON (deprecated)",
"purpose": "Provides support for the deprecated binary JSON format.",
"section": "Utilities",
"output": [ "publicFeature" ]
}
},

View File

@ -1,6 +1,6 @@
TARGET = QtCore
QT =
CONFIG += exceptions
CONFIG += exceptions metatypes install_metatypes
MODULE = core # not corelib, as per project file
MODULE_CONFIG = moc resources
@ -99,6 +99,12 @@ cmake_umbrella_config_module_location_for_install.output = $$DESTDIR/cmake/insta
cmake_umbrella_config_version_file.input = $$PWD/../../mkspecs/features/data/cmake/Qt5ConfigVersion.cmake.in
cmake_umbrella_config_version_file.output = $$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake
android {
cmake_android_support.input = $$PWD/Qt5AndroidSupport.cmake
cmake_android_support.output = $$DESTDIR/cmake/Qt5Core/Qt5AndroidSupport.cmake
cmake_android_support.CONFIG = verbatim
}
load(cmake_functions)
defineTest(pathIsAbsolute) {
@ -144,6 +150,11 @@ QMAKE_SUBSTITUTES += \
cmake_extras_mkspec_dir \
cmake_extras_mkspec_dir_for_install
android {
QMAKE_SUBSTITUTES += cmake_android_support
ctest_qt5_module_files.files += $$cmake_android_support.output
}
ctest_qt5_module_files.files += $$ctest_macros_file.output $$cmake_extras_mkspec_dir_for_install.output
ctest_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5Core

View File

@ -312,3 +312,11 @@ int j = *i; // Undefined behavior!
but with QVector this is likely to crash.
*/
//! [24]
//! [25]
QVector<int> vector{1, 2, 3, 4, 4, 5};
QSet<int> set(vector.begin(), vector.end());
/*
Will generate a QSet containing 1, 2, 4, 5.
*/
//! [25]

View File

@ -372,16 +372,13 @@ a = str.toFloat(&ok); // a == 0, ok == false
//! [39]
QByteArray text("Qt is great!");
text.toBase64(); // returns "UXQgaXMgZ3JlYXQh"
//! [39]
//! [39bis]
QByteArray text("<p>Hello?</p>");
text.toBase64(QByteArray::Base64Encoding | QByteArray::OmitTrailingEquals); // returns "PHA+SGVsbG8/PC9wPg"
text.toBase64(QByteArray::Base64Encoding); // returns "PHA+SGVsbG8/PC9wPg=="
text.toBase64(QByteArray::Base64UrlEncoding); // returns "PHA-SGVsbG8_PC9wPg=="
text.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); // returns "PHA-SGVsbG8_PC9wPg"
//! [39bis]
//! [39]
//! [40]
QByteArray ba;
@ -422,13 +419,10 @@ QDataStream in(&data, QIODevice::ReadOnly);
//! [44]
QByteArray text = QByteArray::fromBase64("UXQgaXMgZ3JlYXQh");
text.data(); // returns "Qt is great!"
//! [44]
//! [44bis]
QByteArray::fromBase64("PHA+SGVsbG8/PC9wPg==", QByteArray::Base64Encoding); // returns "<p>Hello?</p>"
QByteArray::fromBase64("PHA-SGVsbG8_PC9wPg==", QByteArray::Base64UrlEncoding); // returns "<p>Hello?</p>"
//! [44bis]
//! [44]
//! [45]
QByteArray text = QByteArray::fromHex("517420697320677265617421");

View File

@ -433,14 +433,12 @@ void Widget::firstIndexOfFunction()
//! [93]
QString str = "the minimum";
str.indexOf(QRegularExpression("m[aeiou]"), 0); // returns 4
//! [93]
//! [99]
QString str = "the minimum";
QRegularExpressionMatch match;
str.indexOf(QRegularExpression("m[aeiou]"), 0, &match); // returns 4
// match.captured() == mi
//! [99]
//! [93]
}
void Widget::insertFunction()
@ -490,14 +488,12 @@ void Widget::lastIndexOfFunction()
//! [94]
QString str = "the minimum";
str.lastIndexOf(QRegularExpression("m[aeiou]")); // returns 8
//! [94]
//! [100]
QString str = "the minimum";
QRegularExpressionMatch match;
str.lastIndexOf(QRegularExpression("m[aeiou]"), -1, &match); // returns 8
// match.captured() == mu
//! [100]
//! [94]
}
void Widget::leftFunction()

View File

@ -66,14 +66,18 @@
Qt also offers a \l{foreach} keyword that make it very
easy to iterate over all the items stored in a container.
\note Since Qt 5.14, range constructors are available for most of the
container classes. QMultiMap is a notable exception. Their use is
encouraged in place of the various from/to methods. For example:
\snippet code/doc_src_containers.cpp 25
\section1 The Container Classes
Qt provides the following sequential containers: QList,
QLinkedList, QVector, QStack, and QQueue. For most
applications, QList is the best type to use. Although it is
implemented as an array-list, it provides very fast prepends and
appends. If you really need a linked-list, use QLinkedList; if you
want your items to occupy consecutive memory locations, use QVector.
Qt provides the following sequential containers: QVector,
QLinkedList, QStack, and QQueue. For most
applications, QVector is the best type to use. It provides very fast
appends. If you really need a linked-list, use QLinkedList.
QStack and QQueue are convenience classes that provide LIFO and
FIFO semantics.
@ -89,30 +93,19 @@
\table
\header \li Class \li Summary
\row \li \l{QList}<T>
\li This is by far the most commonly used container class. It
stores a list of values of a given type (T) that can be accessed
by index. Internally, the QList is implemented using an array,
ensuring that index-based access is very fast.
Items can be added at either end of the list using
QList::append() and QList::prepend(), or they can be inserted in
the middle using QList::insert(). More than any other container
class, QList is highly optimized to expand to as little code as
possible in the executable. QStringList inherits from
QList<QString>.
\row \li \l{QLinkedList}<T>
\li This is similar to QList, except that it uses
iterators rather than integer indexes to access items. It also
provides better performance than QList when inserting in the
\li This class implements a doubly linked list. It
provides better performance than QVector when inserting in the
middle of a huge list, and it has nicer iterator semantics.
(Iterators pointing to an item in a QLinkedList remain valid as
long as the item exists, whereas iterators to a QList can become
long as the item exists, whereas iterators to a QVector can become
invalid after any insertion or removal.)
\row \li \l{QVector}<T>
\li This stores an array of values of a given type at adjacent
\li This is by far the most commonly used container class. It
stores a list of values of a given type (T) that can be accessed
by index. Internally, it stores an array of values of a
given type at adjacent
positions in memory. Inserting at the front or in the middle of
a vector can be quite slow, because it can lead to large numbers
of items having to be moved by one position in memory.
@ -125,9 +118,9 @@
and \l{QStack::top()}{top()}.
\row \li \l{QQueue}<T>
\li This is a convenience subclass of QList that provides
\li This is a convenience subclass of QVector that provides
"first in, first out" (FIFO) semantics. It adds the following
functions to those already present in QList:
functions to those already present in QQVector:
\l{QQueue::enqueue()}{enqueue()},
\l{QQueue::dequeue()}{dequeue()}, and \l{QQueue::head()}{head()}.
@ -158,8 +151,8 @@
\endtable
Containers can be nested. For example, it is perfectly possible
to use a QMap<QString, QList<int>>, where the key type is
QString and the value type QList<int>.
to use a QMap<QString, QVector<int>>, where the key type is
QString and the value type QVector<int>.
The containers are defined in individual header files with the
same name as the container (e.g., \c <QLinkedList>). For
@ -178,10 +171,10 @@
double, pointer types, and Qt data types such as QString, QDate,
and QTime, but it doesn't cover QObject or any QObject subclass
(QWidget, QDialog, QTimer, etc.). If you attempt to instantiate a
QList<QWidget>, the compiler will complain that QWidget's copy
QVector<QWidget>, the compiler will complain that QWidget's copy
constructor and assignment operators are disabled. If you want to
store these kinds of objects in a container, store them as
pointers, for example as QList<QWidget *>.
pointers, for example as QVector<QWidget *>.
Here's an example custom data type that meets the requirement of
an assignable data type:
@ -254,11 +247,10 @@
\table
\header \li Containers \li Read-only iterator
\li Read-write iterator
\row \li QList<T>, QQueue<T> \li QListIterator<T>
\li QMutableListIterator<T>
\row \li QLinkedList<T> \li QLinkedListIterator<T>
\li QMutableLinkedListIterator<T>
\row \li QVector<T>, QStack<T> \li QVectorIterator<T>
\row \li QVector<T>, QStack<T>, QQueue<T> \li QVectorIterator<T>
\li QMutableVectorIterator<T>
\row \li QSet<T> \li QSetIterator<T>
\li QMutableSetIterator<T>
@ -268,9 +260,9 @@
\li QMutableHashIterator<Key, T>
\endtable
In this discussion, we will concentrate on QList and QMap. The
In this discussion, we will concentrate on QVector and QMap. The
iterator types for QLinkedList, QVector, and QSet have exactly
the same interface as QList's iterators; similarly, the iterator
the same interface as QVector's iterators; similarly, the iterator
types for QHash have the same interface as QMap's iterators.
Unlike STL-style iterators (covered \l{STL-style
@ -285,59 +277,59 @@
\image javaiterators1.png
Here's a typical loop for iterating through all the elements of a
QList<QString> in order and printing them to the console:
QVector<QString> in order and printing them to the console:
\snippet code/doc_src_containers.cpp 1
It works as follows: The QList to iterate over is passed to the
QListIterator constructor. At that point, the iterator is located
It works as follows: The QVector to iterate over is passed to the
QVectorIterator constructor. At that point, the iterator is located
just in front of the first item in the list (before item "A").
Then we call \l{QListIterator::hasNext()}{hasNext()} to
Then we call \l{QVectorIterator::hasNext()}{hasNext()} to
check whether there is an item after the iterator. If there is, we
call \l{QListIterator::next()}{next()} to jump over that
call \l{QVectorIterator::next()}{next()} to jump over that
item. The next() function returns the item that it jumps over. For
a QList<QString>, that item is of type QString.
a QVector<QString>, that item is of type QString.
Here's how to iterate backward in a QList:
Here's how to iterate backward in a QVector:
\snippet code/doc_src_containers.cpp 2
The code is symmetric with iterating forward, except that we
start by calling \l{QListIterator::toBack()}{toBack()}
start by calling \l{QVectorIterator::toBack()}{toBack()}
to move the iterator after the last item in the list.
The diagram below illustrates the effect of calling
\l{QListIterator::next()}{next()} and
\l{QListIterator::previous()}{previous()} on an iterator:
\l{QVectorIterator::next()}{next()} and
\l{QVectorIterator::previous()}{previous()} on an iterator:
\image javaiterators2.png
The following table summarizes the QListIterator API:
The following table summarizes the QVectorIterator API:
\table
\header \li Function \li Behavior
\row \li \l{QListIterator::toFront()}{toFront()}
\row \li \l{QVectorIterator::toFront()}{toFront()}
\li Moves the iterator to the front of the list (before the first item)
\row \li \l{QListIterator::toBack()}{toBack()}
\row \li \l{QVectorIterator::toBack()}{toBack()}
\li Moves the iterator to the back of the list (after the last item)
\row \li \l{QListIterator::hasNext()}{hasNext()}
\row \li \l{QVectorIterator::hasNext()}{hasNext()}
\li Returns \c true if the iterator isn't at the back of the list
\row \li \l{QListIterator::next()}{next()}
\row \li \l{QVectorIterator::next()}{next()}
\li Returns the next item and advances the iterator by one position
\row \li \l{QListIterator::peekNext()}{peekNext()}
\row \li \l{QVectorIterator::peekNext()}{peekNext()}
\li Returns the next item without moving the iterator
\row \li \l{QListIterator::hasPrevious()}{hasPrevious()}
\row \li \l{QVectorIterator::hasPrevious()}{hasPrevious()}
\li Returns \c true if the iterator isn't at the front of the list
\row \li \l{QListIterator::previous()}{previous()}
\row \li \l{QVectorIterator::previous()}{previous()}
\li Returns the previous item and moves the iterator back by one position
\row \li \l{QListIterator::peekPrevious()}{peekPrevious()}
\row \li \l{QVectorIterator::peekPrevious()}{peekPrevious()}
\li Returns the previous item without moving the iterator
\endtable
QListIterator provides no functions to insert or remove items
QVectorIterator provides no functions to insert or remove items
from the list as we iterate. To accomplish this, you must use
QMutableListIterator. Here's an example where we remove all
odd numbers from a QList<int> using QMutableListIterator:
odd numbers from a QVector<int> using QMutableListIterator:
\snippet code/doc_src_containers.cpp 3
@ -371,11 +363,11 @@
\snippet code/doc_src_containers.cpp 6
As mentioned above, QLinkedList's, QVector's, and QSet's iterator
classes have exactly the same API as QList's. We will now turn to
classes have exactly the same API as QVector's. We will now turn to
QMapIterator, which is somewhat different because it iterates on
(key, value) pairs.
Like QListIterator, QMapIterator provides
Like QVectorIterator, QMapIterator provides
\l{QMapIterator::toFront()}{toFront()},
\l{QMapIterator::toBack()}{toBack()},
\l{QMapIterator::hasNext()}{hasNext()},
@ -423,11 +415,9 @@
\table
\header \li Containers \li Read-only iterator
\li Read-write iterator
\row \li QList<T>, QQueue<T> \li QList<T>::const_iterator
\li QList<T>::iterator
\row \li QLinkedList<T> \li QLinkedList<T>::const_iterator
\li QLinkedList<T>::iterator
\row \li QVector<T>, QStack<T> \li QVector<T>::const_iterator
\row \li QVector<T>, QStack<T>, QQueue<T> \li QVector<T>::const_iterator
\li QVector<T>::iterator
\row \li QSet<T> \li QSet<T>::const_iterator
\li QSet<T>::iterator
@ -446,24 +436,24 @@
and the \l{QVector::iterator}{const_iterator} type is
just a typedef for \c{const T *}.
In this discussion, we will concentrate on QList and QMap. The
In this discussion, we will concentrate on QVector and QMap. The
iterator types for QLinkedList, QVector, and QSet have exactly
the same interface as QList's iterators; similarly, the iterator
the same interface as QVector's iterators; similarly, the iterator
types for QHash have the same interface as QMap's iterators.
Here's a typical loop for iterating through all the elements of a
QList<QString> in order and converting them to lowercase:
QVector<QString> in order and converting them to lowercase:
\snippet code/doc_src_containers.cpp 10
Unlike \l{Java-style iterators}, STL-style iterators point
directly at items. The \l{QList::begin()}{begin()} function of a container returns an
directly at items. The \l{QVector::begin()}{begin()} function of a container returns an
iterator that points to the first item in the container. The
\l{QList::end()}{end()} function of a container returns an iterator to the
\l{QVector::end()}{end()} function of a container returns an iterator to the
imaginary item one position past the last item in the container.
\l {QList::end()}{end()} marks an invalid position; it must never be dereferenced.
\l {QVector::end()}{end()} marks an invalid position; it must never be dereferenced.
It is typically used in a loop's break condition. If the list is
empty, \l{QList::begin}{begin()} equals \l{QList::end()}{end()}, so we never execute the loop.
empty, \l{QVector::begin}{begin()} equals \l{QVector::end()}{end()}, so we never execute the loop.
The diagram below shows the valid iterator positions as red
arrows for a vector containing four items:
@ -480,8 +470,8 @@
compilers also allow us to write \c{i->toLower()}, but some
don't.
For read-only access, you can use const_iterator, \l{QList::constBegin}{constBegin()},
and \l{QList::constEnd()}{constEnd()}. For example:
For read-only access, you can use const_iterator, \l{QVector::constBegin}{constBegin()},
and \l{QVector::constEnd()}{constEnd()}. For example:
\snippet code/doc_src_containers.cpp 12
@ -519,7 +509,7 @@
Thanks to \l{implicit sharing}, it is very inexpensive for a
function to return a container per value. The Qt API contains
dozens of functions that return a QList or QStringList per value
dozens of functions that return a QVector or QStringList per value
(e.g., QSplitter::sizes()). If you want to iterate over these
using an STL iterator, you should always take a copy of the
container and iterate over the copy. For example:
@ -689,7 +679,6 @@
\table
\header \li \li Index lookup \li Insertion \li Prepending \li Appending
\row \li QLinkedList<T> \li O(\e n) \li O(1) \li O(1) \li O(1)
\row \li QList<T> \li O(1) \li O(n) \li Amort. O(1) \li Amort. O(1)
\row \li QVector<T> \li O(1) \li O(n) \li O(n) \li Amort. O(1)
\endtable
@ -720,11 +709,8 @@
\section1 Growth Strategies
QVector<T>, QString, and QByteArray store their items
contiguously in memory; QList<T> maintains an array of pointers
to the items it stores to provide fast index-based access (unless
T is a pointer type or a basic type of the size of a pointer, in
which case the value itself is stored in the array); QHash<Key,
T> keeps a hash table whose size is proportional to the number
contiguously in memory; QHash<Key, T> keeps a
hash table whose size is proportional to the number
of items in the hash. To avoid reallocating the data every single
time an item is added at the end of the container, these classes
typically allocate more memory than necessary.
@ -758,7 +744,7 @@
on the first and last pages actually needs to be copied.
\endlist
QByteArray and QList<T> use more or less the same algorithm as
QByteArray uses more or less the same algorithm as
QString.
QVector<T> also uses that algorithm for data types that can be

View File

@ -67,7 +67,6 @@
\li QImage
\li QKeySequence
\li QLinkedList<T>
\li QList<T>
\li QMap<Key, T>
\li QMargins
\li QMatrix4x4

View File

@ -0,0 +1,2 @@
\note Since Qt 5.14, range constructors are available for Qt's generic
\l{container classes} and should be used in place of this method.

View File

@ -91,8 +91,6 @@
# define Q_OUTOFLINE_TEMPLATE inline
# define Q_COMPILER_MANGLES_RETURN_TYPE
# define Q_FUNC_INFO __FUNCSIG__
# define Q_ALIGNOF(type) __alignof(type)
# define Q_DECL_ALIGN(n) __declspec(align(n))
# define Q_ASSUME_IMPL(expr) __assume(expr)
# define Q_UNREACHABLE_IMPL() __assume(0)
# define Q_NORETURN __declspec(noreturn)
@ -222,10 +220,8 @@
# endif
# define Q_FUNC_INFO __PRETTY_FUNCTION__
# define Q_ALIGNOF(type) __alignof__(type)
# define Q_TYPEOF(expr) __typeof__(expr)
# define Q_DECL_DEPRECATED __attribute__ ((__deprecated__))
# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
# define Q_DECL_UNUSED __attribute__((__unused__))
# define Q_LIKELY(expr) __builtin_expect(!!(expr), true)
# define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false)
@ -272,9 +268,7 @@
# if __xlC__ < 0x400
# error "Compiler not supported"
# elif __xlC__ >= 0x0600
# define Q_ALIGNOF(type) __alignof__(type)
# define Q_TYPEOF(expr) __typeof__(expr)
# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
# define Q_PACKED __attribute__((__packed__))
# endif
@ -352,7 +346,6 @@
# define Q_PACKED __attribute__ ((__packed__))
# define Q_FUNC_INFO __PRETTY_FUNCTION__
# define Q_TYPEOF(expr) __typeof__(expr)
# define Q_ALIGNOF(type) __alignof__(type)
# define Q_UNREACHABLE_IMPL()
# if defined(__cplusplus)
# define Q_COMPILER_AUTO_TYPE
@ -450,9 +443,7 @@
# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
/* see http://developers.sun.com/sunstudio/support/Ccompare.html */
# if __SUNPRO_CC >= 0x590
# define Q_ALIGNOF(type) __alignof__(type)
# define Q_TYPEOF(expr) __typeof__(expr)
# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
# endif
# if __SUNPRO_CC >= 0x550
# define Q_DECL_EXPORT __global
@ -489,9 +480,6 @@
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
# endif
# if __HP_aCC-0 >= 061200
# define Q_DECL_ALIGN(n) __attribute__((aligned(n)))
# endif
# if __HP_aCC-0 >= 062000
# define Q_DECL_EXPORT __attribute__((visibility("default")))
# define Q_DECL_HIDDEN __attribute__((visibility("hidden")))
@ -1128,14 +1116,12 @@
#endif
#define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
#if defined(Q_COMPILER_ALIGNOF)
# undef Q_ALIGNOF
# define Q_ALIGNOF(x) alignof(x)
#ifndef Q_ALIGNOF
# define Q_ALIGNOF(x) alignof(x)
#endif
#if defined(Q_COMPILER_ALIGNAS)
# undef Q_DECL_ALIGN
# define Q_DECL_ALIGN(n) alignas(n)
#ifndef Q_DECL_ALIGN
# define Q_DECL_ALIGN(n) alignas(n)
#endif
#if QT_HAS_CPP_ATTRIBUTE(nodiscard) && !defined(Q_CC_CLANG) // P0188R1

View File

@ -74,6 +74,7 @@
#else
# define QT_FEATURE_alloca_malloc_h -1
#endif
#define QT_FEATURE_binaryjson -1
#define QT_FEATURE_cborstream -1
#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1
#define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1)
@ -110,6 +111,7 @@
# define QT_FEATURE_renameat2 -1
#endif
#define QT_FEATURE_sharedmemory -1
#define QT_FEATURE_shortcut -1
#define QT_FEATURE_signaling_nan -1
#define QT_FEATURE_slog2 -1
#ifdef __GLIBC_PREREQ

View File

@ -765,7 +765,7 @@ QT_BEGIN_NAMESPACE
#if defined(__SSSE3__)
using ShuffleMask = uchar[16];
Q_DECL_ALIGN(16) static const ShuffleMask shuffleMasks[3] = {
alignas(16) static const ShuffleMask shuffleMasks[3] = {
// 16-bit
{1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14},
// 32-bit

View File

@ -327,9 +327,9 @@ public:
return pre;
}
static constexpr QSpecialInteger max()
static Q_DECL_CONSTEXPR QSpecialInteger max()
{ return QSpecialInteger(std::numeric_limits<T>::max()); }
static constexpr QSpecialInteger min()
static Q_DECL_CONSTEXPR QSpecialInteger min()
{ return QSpecialInteger(std::numeric_limits<T>::min()); }
};
@ -373,8 +373,8 @@ public:
QLEInteger &operator ++(int);
QLEInteger &operator --(int);
static constexpr QLEInteger max();
static constexpr QLEInteger min();
static Q_DECL_CONSTEXPR QLEInteger max();
static Q_DECL_CONSTEXPR QLEInteger min();
};
template<typename T>
@ -400,8 +400,8 @@ public:
QBEInteger &operator ++(int);
QBEInteger &operator --(int);
static constexpr QBEInteger max();
static constexpr QBEInteger min();
static Q_DECL_CONSTEXPR QBEInteger max();
static Q_DECL_CONSTEXPR QBEInteger min();
};
#else

View File

@ -114,8 +114,8 @@ extern "C" {
// without full system POSIX.
# pragma weak shm_area_password
# pragma weak shm_area_name
char *shm_area_password = "dummy";
char *shm_area_name = "dummy";
char shm_area_password[] = "dummy";
char shm_area_name[] = "dummy";
}
#endif

View File

@ -86,15 +86,9 @@
#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)
#define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not available.")
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
// ### Qt6: FIXME and get rid of unsharable containers
//# define QT_NO_UNSHARABLE_CONTAINERS
# define QT6_VIRTUAL virtual
# define QT6_NOT_VIRTUAL
#else
# define QT6_VIRTUAL
# define QT6_NOT_VIRTUAL virtual
#endif
// ### Clean those up, once all code is adjusted
#define QT6_VIRTUAL virtual
#define QT6_NOT_VIRTUAL
/* These two macros makes it possible to turn the builtin line expander into a
* string literal. */
@ -499,53 +493,6 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOEXCEPT;
# define Q_DESTRUCTOR_FUNCTION(AFUNC) Q_DESTRUCTOR_FUNCTION0(AFUNC)
#endif
namespace QtPrivate {
template <class T>
struct AlignOfHelper
{
char c;
T type;
AlignOfHelper();
~AlignOfHelper();
};
template <class T>
struct AlignOf_Default
{
enum { Value = sizeof(AlignOfHelper<T>) - sizeof(T) };
};
template <class T> struct AlignOf : AlignOf_Default<T> { };
template <class T> struct AlignOf<T &> : AlignOf<T> {};
template <class T> struct AlignOf<T &&> : AlignOf<T> {};
template <size_t N, class T> struct AlignOf<T[N]> : AlignOf<T> {};
#if defined(Q_PROCESSOR_X86_32) && !defined(Q_OS_WIN)
template <class T> struct AlignOf_WorkaroundForI386Abi { enum { Value = sizeof(T) }; };
// x86 ABI weirdness
// Alignment of naked type is 8, but inside struct has alignment 4.
template <> struct AlignOf<double> : AlignOf_WorkaroundForI386Abi<double> {};
template <> struct AlignOf<qint64> : AlignOf_WorkaroundForI386Abi<qint64> {};
template <> struct AlignOf<quint64> : AlignOf_WorkaroundForI386Abi<quint64> {};
#ifdef Q_CC_CLANG
// GCC and Clang seem to disagree wrt to alignment of arrays
template <size_t N> struct AlignOf<double[N]> : AlignOf_Default<double> {};
template <size_t N> struct AlignOf<qint64[N]> : AlignOf_Default<qint64> {};
template <size_t N> struct AlignOf<quint64[N]> : AlignOf_Default<quint64> {};
#endif
#endif
} // namespace QtPrivate
#define QT_EMULATED_ALIGNOF(T) \
(size_t(QT_PREPEND_NAMESPACE(QtPrivate)::AlignOf<T>::Value))
#ifndef Q_ALIGNOF
#define Q_ALIGNOF(T) QT_EMULATED_ALIGNOF(T)
#endif
/*
quintptr and qptrdiff is guaranteed to be the same size as a pointer, i.e.

View File

@ -202,7 +202,7 @@ namespace {
This function works for v containing infinities, but not NaN. It's the
caller's responsibility to exclude that possibility before calling it.
*/
template <typename T> static inline bool convertDoubleTo(double v, T *value)
template <typename T> static inline bool convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
{
Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
@ -227,6 +227,10 @@ template <typename T> static inline bool convertDoubleTo(double v, T *value)
supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
v = fabs(v);
}
if (std::is_integral<T>::value && sizeof(T) > 4 && !allow_precision_upgrade) {
if (v > double(Q_INT64_C(1)<<53) || v < double(-((Q_INT64_C(1)<<53) + 1)))
return false;
}
*value = std::numeric_limits<T>::max();
if (v >= supremum)

View File

@ -355,7 +355,7 @@ struct QRandomGenerator::SystemAndGlobalGenerators
// the state in case another thread tries to lock the mutex. It's not
// a common scenario, but since sizeof(QRandomGenerator) >= 2560, the
// overhead is actually acceptable.
// 2) We use both Q_DECL_ALIGN and std::aligned_storage<..., 64> because
// 2) We use both alignas and std::aligned_storage<..., 64> because
// some implementations of std::aligned_storage can't align to more
// than a primitive type's alignment.
// 3) We don't store the entire system QRandomGenerator, only the space
@ -364,7 +364,7 @@ struct QRandomGenerator::SystemAndGlobalGenerators
QBasicMutex globalPRNGMutex;
struct ShortenedSystem { uint type; } system_;
SystemGenerator sys;
Q_DECL_ALIGN(64) std::aligned_storage<sizeof(QRandomGenerator64), 64>::type global_;
alignas(64) std::aligned_storage<sizeof(QRandomGenerator64), 64>::type global_;
#ifdef Q_COMPILER_CONSTEXPR
constexpr SystemAndGlobalGenerators()

View File

@ -196,7 +196,7 @@ private:
RandomEngine &engine() { return twister; }
const RandomEngine &engine() const { return twister; }
#else
std::aligned_storage<sizeof(RandomEngine), Q_ALIGNOF(RandomEngine)>::type buffer;
std::aligned_storage<sizeof(RandomEngine), alignof(RandomEngine)>::type buffer;
RandomEngine &engine() { return reinterpret_cast<RandomEngine &>(buffer); }
const RandomEngine &engine() const { return reinterpret_cast<const RandomEngine &>(buffer); }
#endif

View File

@ -209,7 +209,6 @@ public: \
}; \
}
Q_DECLARE_MOVABLE_CONTAINER(QList);
Q_DECLARE_MOVABLE_CONTAINER(QVector);
Q_DECLARE_MOVABLE_CONTAINER(QQueue);
Q_DECLARE_MOVABLE_CONTAINER(QStack);

View File

@ -234,12 +234,6 @@ inline QDebug printSequentialContainer(QDebug debug, const char *which, const Se
} // namespace QtPrivate
template <class T>
inline QDebug operator<<(QDebug debug, const QList<T> &list)
{
return QtPrivate::printSequentialContainer(debug, "" /*for historical reasons*/, list);
}
template <typename T>
inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
{

View File

@ -58,6 +58,36 @@
QT_BEGIN_NAMESPACE
#define Q_RETURN_ON_INVALID_FILENAME(message, result) \
{ \
QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).warning(message); \
errno = EINVAL; \
return (result); \
}
inline bool qIsFilenameBroken(const QByteArray &name)
{
return name.contains('\0');
}
inline bool qIsFilenameBroken(const QString &name)
{
return name.contains(QLatin1Char('\0'));
}
inline bool qIsFilenameBroken(const QFileSystemEntry &entry)
{
return qIsFilenameBroken(entry.nativeFilePath());
}
#define Q_CHECK_FILE_NAME(name, result) \
do { \
if (Q_UNLIKELY((name).isEmpty())) \
Q_RETURN_ON_INVALID_FILENAME("Empty filename passed to function", (result)); \
if (Q_UNLIKELY(qIsFilenameBroken(name))) \
Q_RETURN_ON_INVALID_FILENAME("Broken filename passed to function", (result)); \
} while (false)
class QFileSystemEngine
{
public:

View File

@ -118,13 +118,6 @@ enum {
#endif
};
#define emptyFileEntryWarning() emptyFileEntryWarning_(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC)
static void emptyFileEntryWarning_(const char *file, int line, const char *function)
{
QMessageLogger(file, line, function).warning("Empty filename passed to function");
errno = EINVAL;
}
#if defined(Q_OS_DARWIN)
static inline bool hasResourcePropertyFlag(const QFileSystemMetaData &data,
const QFileSystemEntry &entry,
@ -625,8 +618,7 @@ void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
//static
QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
{
if (Q_UNLIKELY(link.isEmpty()))
return emptyFileEntryWarning(), link;
Q_CHECK_FILE_NAME(link, link);
QByteArray s = qt_readlink(link.nativeFilePath().constData());
if (s.length() > 0) {
@ -685,10 +677,7 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
//static
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
{
if (Q_UNLIKELY(entry.isEmpty()))
return emptyFileEntryWarning(), entry;
if (entry.isRoot())
return entry;
Q_CHECK_FILE_NAME(entry, entry);
#if !defined(Q_OS_MAC) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_HAIKU) && _POSIX_VERSION < 200809L
// realpath(X,0) is not supported
@ -738,8 +727,8 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
//static
QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
{
if (Q_UNLIKELY(entry.isEmpty()))
return emptyFileEntryWarning(), entry;
Q_CHECK_FILE_NAME(entry, entry);
if (entry.isAbsolute() && entry.isClean())
return entry;
@ -773,8 +762,7 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
//static
QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
{
if (Q_UNLIKELY(entry.isEmpty()))
return emptyFileEntryWarning(), QByteArray();
Q_CHECK_FILE_NAME(entry, QByteArray());
QT_STATBUF statResult;
if (QT_STAT(entry.nativeFilePath().constData(), &statResult)) {
@ -887,8 +875,7 @@ QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what)
{
if (Q_UNLIKELY(entry.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(entry, false);
#if defined(Q_OS_DARWIN)
if (what & QFileSystemMetaData::BundleType) {
@ -1157,8 +1144,7 @@ static bool createDirectoryWithParents(const QByteArray &nativeName, bool should
bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
{
QString dirName = entry.filePath();
if (Q_UNLIKELY(dirName.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(dirName, false);
// Darwin doesn't support trailing /'s, so remove for everyone
while (dirName.size() > 1 && dirName.endsWith(QLatin1Char('/')))
@ -1177,8 +1163,7 @@ bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool crea
//static
bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
{
if (Q_UNLIKELY(entry.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(entry, false);
if (removeEmptyParents) {
QString dirName = QDir::cleanPath(entry.filePath());
@ -1203,8 +1188,9 @@ bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool remo
//static
bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
if (Q_UNLIKELY(source.isEmpty() || target.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(source, false);
Q_CHECK_FILE_NAME(target, false);
if (::symlink(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
return true;
error = QSystemError(errno, QSystemError::StandardLibraryError);
@ -1233,8 +1219,9 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
{
QFileSystemEntry::NativePath srcPath = source.nativeFilePath();
QFileSystemEntry::NativePath tgtPath = target.nativeFilePath();
if (Q_UNLIKELY(srcPath.isEmpty() || tgtPath.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(srcPath, false);
Q_CHECK_FILE_NAME(tgtPath, false);
#if defined(RENAME_NOREPLACE) && QT_CONFIG(renameat2)
if (renameat2(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_NOREPLACE) == 0)
@ -1302,8 +1289,9 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
//static
bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
if (Q_UNLIKELY(source.isEmpty() || target.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(source, false);
Q_CHECK_FILE_NAME(target, false);
if (::rename(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
return true;
error = QSystemError(errno, QSystemError::StandardLibraryError);
@ -1313,8 +1301,7 @@ bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source, cons
//static
bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
{
if (Q_UNLIKELY(entry.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(entry, false);
if (unlink(entry.nativeFilePath().constData()) == 0)
return true;
error = QSystemError(errno, QSystemError::StandardLibraryError);
@ -1349,8 +1336,7 @@ static mode_t toMode_t(QFile::Permissions permissions)
//static
bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
{
if (Q_UNLIKELY(entry.isEmpty()))
return emptyFileEntryWarning(), false;
Q_CHECK_FILE_NAME(entry, false);
mode_t mode = toMode_t(permissions);
bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0;

View File

@ -461,7 +461,9 @@ void QFileSystemEngine::clearWinStatData(QFileSystemMetaData &data)
QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
QFileSystemMetaData &data)
{
if (data.missingFlags(QFileSystemMetaData::LinkType))
Q_CHECK_FILE_NAME(link, link);
if (data.missingFlags(QFileSystemMetaData::LinkType))
QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType);
QString target;
@ -480,6 +482,8 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
//static
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
{
Q_CHECK_FILE_NAME(entry, entry);
if (data.missingFlags(QFileSystemMetaData::ExistsAttribute))
QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute);
@ -492,6 +496,8 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
//static
QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path)
{
Q_CHECK_FILE_NAME(path, QString());
// can be //server or //server/share
QString absPath;
QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1));
@ -527,6 +533,8 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path)
//static
QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
{
Q_CHECK_FILE_NAME(entry, entry);
QString ret;
if (!entry.isRelative()) {
@ -609,6 +617,8 @@ QByteArray fileIdWin8(HANDLE handle)
//static
QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
{
Q_CHECK_FILE_NAME(entry, QByteArray());
QByteArray result;
#ifndef Q_OS_WINRT
@ -999,6 +1009,7 @@ static bool isDirPath(const QString &dirPath, bool *existed);
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what)
{
Q_CHECK_FILE_NAME(entry, false);
what |= QFileSystemMetaData::WinLnkType | QFileSystemMetaData::WinStatFlags;
data.entryFlags &= ~what;
@ -1112,71 +1123,70 @@ static bool isDirPath(const QString &dirPath, bool *existed)
return fileAttrib & FILE_ATTRIBUTE_DIRECTORY;
}
// NOTE: if \a shouldMkdirFirst is false, we assume the caller did try to mkdir
// before calling this function.
static bool createDirectoryWithParents(const QString &nativeName, bool shouldMkdirFirst = true)
{
const auto isUNCRoot = [](const QString &nativeName) {
return nativeName.startsWith(QLatin1String("\\\\")) && nativeName.count(QDir::separator()) <= 3;
};
const auto isDriveName = [](const QString &nativeName) {
return nativeName.size() == 2 && nativeName.at(1) == QLatin1Char(':');
};
const auto isDir = [](const QString &nativeName) {
bool exists = false;
return isDirPath(nativeName, &exists) && exists;
};
// Do not try to mkdir a UNC root path or a drive letter.
if (isUNCRoot(nativeName) || isDriveName(nativeName))
return false;
if (shouldMkdirFirst) {
if (mkDir(nativeName))
return true;
}
const int backSlash = nativeName.lastIndexOf(QDir::separator());
if (backSlash < 1)
return false;
const QString parentNativeName = nativeName.left(backSlash);
if (!createDirectoryWithParents(parentNativeName))
return false;
// try again
if (mkDir(nativeName))
return true;
return isDir(nativeName);
}
//static
bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
{
QString dirName = entry.filePath();
if (createParents) {
dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
// We spefically search for / so \ would break it..
int oldslash = -1;
if (dirName.startsWith(QLatin1String("\\\\"))) {
// Don't try to create the root path of a UNC path;
// CreateDirectory() will just return ERROR_INVALID_NAME.
for (int i = 0; i < dirName.size(); ++i) {
if (dirName.at(i) != QDir::separator()) {
oldslash = i;
break;
}
}
if (oldslash != -1)
oldslash = dirName.indexOf(QDir::separator(), oldslash);
} else if (dirName.size() > 2
&& dirName.at(1) == QLatin1Char(':')) {
// Don't try to call mkdir with just a drive letter
oldslash = 2;
}
for (int slash=0; slash != -1; oldslash = slash) {
slash = dirName.indexOf(QDir::separator(), oldslash+1);
if (slash == -1) {
if (oldslash == dirName.length())
break;
slash = dirName.length();
}
if (slash) {
DWORD lastError;
QString chunk = dirName.left(slash);
if (!mkDir(chunk, &lastError)) {
if (lastError == ERROR_ALREADY_EXISTS || lastError == ERROR_ACCESS_DENIED) {
bool existed = false;
if (isDirPath(chunk, &existed) && existed)
continue;
#ifdef Q_OS_WINRT
static QThreadStorage<QString> dataLocation;
if (!dataLocation.hasLocalData())
dataLocation.setLocalData(QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation)));
static QThreadStorage<QString> tempLocation;
if (!tempLocation.hasLocalData())
tempLocation.setLocalData(QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::TempLocation)));
// We try to create something outside the sandbox, which is forbidden
// However we could still try to pass into the sandbox
if (dataLocation.localData().startsWith(chunk) || tempLocation.localData().startsWith(chunk))
continue;
#endif
}
return false;
}
}
}
Q_CHECK_FILE_NAME(dirName, false);
dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
// try to mkdir this directory
DWORD lastError;
if (mkDir(dirName, &lastError))
return true;
}
return mkDir(entry.filePath());
// mkpath should return true, if the directory already exists, mkdir false.
if (!createParents)
return false;
if (lastError == ERROR_ALREADY_EXISTS)
return isDirPath(dirName, nullptr);
return createDirectoryWithParents(dirName, false);
}
//static
bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
{
QString dirName = entry.filePath();
Q_CHECK_FILE_NAME(dirName, false);
if (removeEmptyParents) {
dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
@ -1381,6 +1391,9 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst
//static
bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
Q_CHECK_FILE_NAME(source, false);
Q_CHECK_FILE_NAME(target, false);
#ifndef Q_OS_WINRT
bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(),
(wchar_t*)target.nativeFilePath().utf16()) != 0;
@ -1396,6 +1409,9 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
//static
bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
Q_CHECK_FILE_NAME(source, false);
Q_CHECK_FILE_NAME(target, false);
bool ret = ::MoveFileEx(reinterpret_cast<const wchar_t *>(source.nativeFilePath().utf16()),
reinterpret_cast<const wchar_t *>(target.nativeFilePath().utf16()),
MOVEFILE_REPLACE_EXISTING) != 0;
@ -1407,6 +1423,8 @@ bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source, cons
//static
bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
{
Q_CHECK_FILE_NAME(entry, false);
bool ret = ::DeleteFile((wchar_t*)entry.nativeFilePath().utf16()) != 0;
if(!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
@ -1417,6 +1435,8 @@ bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &
bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
QFileSystemMetaData *data)
{
Q_CHECK_FILE_NAME(entry, false);
Q_UNUSED(data);
int mode = 0;

View File

@ -911,14 +911,7 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
}
/*! \fn bool QFSFileEngine::caseSensitive() const
Returns \c true for Windows, false for Unix.
*/
/*! \fn bool QFSFileEngine::copy(const QString &copyName)
For Windows or Apple platforms, copy the file to file \a copyName.
Not implemented for other Unix platforms.
Returns \c false for Windows, true for Unix.
*/
/*! \fn QString QFSFileEngine::currentPath(const QString &fileName)
@ -950,11 +943,34 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
\reimp
*/
/*! \fn QString QFSFileEngine::homePath()
/*!
Returns the home path of the current user.
\sa rootPath()
*/
QString QFSFileEngine::homePath()
{
return QFileSystemEngine::homePath();
}
/*!
Returns the root path.
\sa homePath()
*/
QString QFSFileEngine::rootPath()
{
return QFileSystemEngine::rootPath();
}
/*!
Returns the temporary path (i.e., a path in which it is safe
to store temporary files).
*/
QString QFSFileEngine::tempPath()
{
return QFileSystemEngine::tempPath();
}
/*! \fn bool QFSFileEngine::isRelativePath() const
\reimp
@ -968,9 +984,6 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
true if successful; otherwise returns \c false.
*/
/*! \fn bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
\reimp
*/
/*! \fn uint QFSFileEngine::ownerId(QAbstractFileEngine::FileOwner own) const
In Unix, if stat() is successful, the \c uid is returned if
@ -984,35 +997,87 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
\reimp
*/
/*! \fn bool QFSFileEngine::remove()
/*!
For Windows or Apple platforms, copy the file to file \a copyName.
Not implemented for other Unix platforms.
*/
bool QFSFileEngine::copy(const QString &copyName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(copyName), error);
if (!ret)
setError(QFile::CopyError, error.toString());
return ret;
}
/*!
\reimp
*/
bool QFSFileEngine::remove()
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
d->metaData.clear();
if (!ret)
setError(QFile::RemoveError, error.toString());
return ret;
}
/*! \fn bool QFSFileEngine::rename(const QString &newName)
/*!
\reimp
*/
/*! \fn bool QFSFileEngine::renameOverwrite(const QString &newName)
bool QFSFileEngine::rename(const QString &newName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret)
setError(QFile::RenameError, error.toString());
return ret;
}
/*!
\reimp
*/
bool QFSFileEngine::renameOverwrite(const QString &newName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::renameOverwriteFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret)
setError(QFile::RenameError, error.toString());
return ret;
}
/*! \fn bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
/*!
\reimp
*/
bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
{
return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
}
/*! \fn QString QFSFileEngine::rootPath()
Returns the root path.
\sa homePath()
/*!
\reimp
*/
bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
{
return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
}
/*! \fn bool QFSFileEngine::setCurrentPath(const QString &path)
/*!
Sets the current path (e.g., for QDir), to \a path. Returns \c true if the
new path exists; otherwise this function does nothing, and returns \c false.
\sa currentPath()
*/
bool QFSFileEngine::setCurrentPath(const QString &path)
{
return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
}
/*! \fn bool QFSFileEngine::setPermissions(uint perms)
\reimp
@ -1022,11 +1087,6 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
\reimp
*/
/*! \fn QString QFSFileEngine::tempPath()
Returns the temporary path (i.e., a path in which it is safe
to store temporary files).
*/
/*! \fn QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const
\internal
*/

View File

@ -304,54 +304,6 @@ bool QFSFileEnginePrivate::nativeIsSequential() const
return isSequentialFdFh();
}
bool QFSFileEngine::remove()
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
d->metaData.clear();
if (!ret) {
setError(QFile::RemoveError, error.toString());
}
return ret;
}
bool QFSFileEngine::copy(const QString &newName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret) {
setError(QFile::CopyError, error.toString());
}
return ret;
}
bool QFSFileEngine::renameOverwrite(const QString &newName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::renameOverwriteFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret)
setError(QFile::RenameError, error.toString());
return ret;
}
bool QFSFileEngine::rename(const QString &newName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret) {
setError(QFile::RenameError, error.toString());
}
return ret;
}
bool QFSFileEngine::link(const QString &newName)
{
Q_D(QFSFileEngine);
@ -368,45 +320,16 @@ qint64 QFSFileEnginePrivate::nativeSize() const
return sizeFdFh();
}
bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
{
return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
}
bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
{
return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
}
bool QFSFileEngine::caseSensitive() const
{
return true;
}
bool QFSFileEngine::setCurrentPath(const QString &path)
{
return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
}
QString QFSFileEngine::currentPath(const QString &)
{
return QFileSystemEngine::currentPath().filePath();
}
QString QFSFileEngine::homePath()
{
return QFileSystemEngine::homePath();
}
QString QFSFileEngine::rootPath()
{
return QFileSystemEngine::rootPath();
}
QString QFSFileEngine::tempPath()
{
return QFileSystemEngine::tempPath();
}
QFileInfoList QFSFileEngine::drives()
{

View File

@ -443,66 +443,11 @@ bool QFSFileEnginePrivate::nativeIsSequential() const
#endif
}
bool QFSFileEngine::remove()
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
if (!ret)
setError(QFile::RemoveError, error.toString());
return ret;
}
bool QFSFileEngine::copy(const QString &copyName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(copyName), error);
if (!ret)
setError(QFile::CopyError, error.toString());
return ret;
}
bool QFSFileEngine::rename(const QString &newName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret)
setError(QFile::RenameError, error.toString());
return ret;
}
bool QFSFileEngine::renameOverwrite(const QString &newName)
{
Q_D(QFSFileEngine);
QSystemError error;
bool ret = QFileSystemEngine::renameOverwriteFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret)
setError(QFile::RenameError, error.toString());
return ret;
}
bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
{
return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
}
bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
{
return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
}
bool QFSFileEngine::caseSensitive() const
{
return false;
}
bool QFSFileEngine::setCurrentPath(const QString &path)
{
return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
}
QString QFSFileEngine::currentPath(const QString &fileName)
{
#if !defined(Q_OS_WINRT)
@ -530,21 +475,6 @@ QString QFSFileEngine::currentPath(const QString &fileName)
#endif // Q_OS_WINRT
}
QString QFSFileEngine::homePath()
{
return QFileSystemEngine::homePath();
}
QString QFSFileEngine::rootPath()
{
return QFileSystemEngine::rootPath();
}
QString QFSFileEngine::tempPath()
{
return QFileSystemEngine::tempPath();
}
#if !defined(Q_OS_WINRT)
// cf QStorageInfo::isReady
static inline bool isDriveReady(const wchar_t *path)

View File

@ -420,7 +420,10 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
case QVariant::UInt:
case QVariant::Bool:
case QVariant::Double:
case QVariant::KeySequence: {
#if QT_CONFIG(shortcut)
case QVariant::KeySequence:
#endif
{
result = v.toString();
if (result.contains(QChar::Null))
result = QLatin1String("@String(") + result + QLatin1Char(')');

View File

@ -142,36 +142,45 @@ QString QStandardPaths::writableLocation(StandardLocation type)
}
case RuntimeLocation:
{
const uint myUid = uint(geteuid());
// http://standards.freedesktop.org/basedir-spec/latest/
const uint myUid = uint(geteuid());
// since the current user is the owner, set both xxxUser and xxxOwner
const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
| QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
QFileInfo fileInfo;
QString xdgRuntimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
if (xdgRuntimeDir.isEmpty()) {
const QString userName = QFileSystemEngine::resolveUserName(myUid);
xdgRuntimeDir = QDir::tempPath() + QLatin1String("/runtime-") + userName;
fileInfo.setFile(xdgRuntimeDir);
if (!fileInfo.isDir()) {
if (!QDir().mkdir(xdgRuntimeDir)) {
qErrnoWarning("QStandardPaths: error creating runtime directory %ls",
qUtf16Printable(xdgRuntimeDir));
return QString();
}
}
#ifndef Q_OS_WASM
qWarning("QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '%ls'", qUtf16Printable(xdgRuntimeDir));
#endif
} else {
fileInfo.setFile(xdgRuntimeDir);
if (!fileInfo.exists()) {
qWarning("QStandardPaths: XDG_RUNTIME_DIR points to non-existing path '%ls', "
"please create it with 0700 permissions.", qUtf16Printable(xdgRuntimeDir));
return QString();
}
}
if (fileInfo.exists()) {
if (!fileInfo.isDir()) {
qWarning("QStandardPaths: XDG_RUNTIME_DIR points to '%ls' which is not a directory",
qUtf16Printable(xdgRuntimeDir));
return QString();
}
} else {
QFileSystemEntry entry(xdgRuntimeDir);
if (!QFileSystemEngine::createDirectory(entry, false)) {
if (errno != EEXIST) {
qErrnoWarning("QStandardPaths: error creating runtime directory %ls",
qUtf16Printable(xdgRuntimeDir));
return QString();
}
} else {
QSystemError error;
if (!QFileSystemEngine::setPermissions(entry, wantedPerms, error)) {
qWarning("QStandardPaths: could not set correct permissions on runtime directory %ls: %ls",
qUtf16Printable(xdgRuntimeDir), qUtf16Printable(error.toString()));
return QString();
}
}
}
// "The directory MUST be owned by the user"
if (fileInfo.ownerId() != myUid) {
@ -181,17 +190,12 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return QString();
}
// "and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700."
// since the current user is the owner, set both xxxUser and xxxOwner
const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
| QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
if (fileInfo.permissions() != wantedPerms) {
QFile file(xdgRuntimeDir);
if (!file.setPermissions(wantedPerms)) {
qWarning("QStandardPaths: could not set correct permissions on runtime directory %ls: %ls",
qUtf16Printable(xdgRuntimeDir), qUtf16Printable(file.errorString()));
return QString();
}
qWarning("QStandardPaths: wrong permissions on runtime directory %ls, %x instead of %x",
qUtf16Printable(xdgRuntimeDir), uint(fileInfo.permissions()), uint(wantedPerms));
return QString();
}
return xdgRuntimeDir;
}
default:

View File

@ -20,7 +20,7 @@ supported by Qt (by the QNetworkCookieJar class).",
"Homepage": "Consult https://github.com/publicsuffix/list for the sha1 but download from ...",
"Homepage": "http://publicsuffix.org/",
"Version": "d6331e2b65fffbe9fe299dae1689db8de8fd6190, fetched on 2019-02-20",
"Version": "3bd641472776a5df4a8c6407da4a4846282cba94, fetched on 2019-10-23",
"License": "Mozilla Public License 2.0",
"LicenseFile": "PSL-LICENSE.txt",
"LicenseId": "MPL-2.0",

File diff suppressed because it is too large Load Diff

View File

@ -171,11 +171,11 @@ public:
QModelIndex currentIndex() const;
Q_INVOKABLE bool isSelected(const QModelIndex &index) const;
Q_INVOKABLE bool isRowSelected(int row, const QModelIndex &parent) const;
Q_INVOKABLE bool isColumnSelected(int column, const QModelIndex &parent) const;
Q_INVOKABLE bool isRowSelected(int row, const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE bool isColumnSelected(int column, const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE bool rowIntersectsSelection(int row, const QModelIndex &parent) const;
Q_INVOKABLE bool columnIntersectsSelection(int column, const QModelIndex &parent) const;
Q_INVOKABLE bool rowIntersectsSelection(int row, const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE bool columnIntersectsSelection(int column, const QModelIndex &parent = QModelIndex()) const;
bool hasSelection() const;
@ -241,7 +241,7 @@ inline uint qHash(const QItemSelectionRange &) { return 0; }
# define Q_TEMPLATE_EXTERN extern
# endif
# endif
Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QList<QItemSelectionRange>;
Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QItemSelectionRange>;
#endif // Q_CC_MSVC
class Q_CORE_EXPORT QItemSelection : public QList<QItemSelectionRange>

View File

@ -377,6 +377,7 @@ public:
void sort();
bool update_source_sort_column();
int find_source_sort_column() const;
void sort_source_rows(QVector<int> &source_rows,
const QModelIndex &source_parent) const;
QVector<QPair<int, QVector<int > > > proxy_intervals_for_source_items_to_add(
@ -479,11 +480,8 @@ void QSortFilterProxyModelPrivate::_q_clearMapping()
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
if (dynamic_sortfilter && update_source_sort_column()) {
//update_source_sort_column might have created wrong mapping so we have to clear it again
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
}
if (dynamic_sortfilter)
source_sort_column = find_source_sort_column();
// update the persistent indexes
update_persistent_indexes(source_indexes);
@ -640,6 +638,31 @@ bool QSortFilterProxyModelPrivate::update_source_sort_column()
return old_source_sort_column != source_sort_column;
}
/*!
\internal
Find the source_sort_column without creating a full mapping and
without updating anything.
*/
int QSortFilterProxyModelPrivate::find_source_sort_column() const
{
if (proxy_sort_column == -1)
return -1;
const QModelIndex rootIndex;
const int source_cols = model->columnCount();
int accepted_columns = -1;
Q_Q(const QSortFilterProxyModel);
for (int i = 0; i < source_cols; ++i) {
if (q->filterAcceptsColumn(i, rootIndex)) {
if (++accepted_columns == proxy_sort_column)
return i;
}
}
return -1;
}
/*!
\internal
@ -1591,11 +1614,8 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersisten
update_persistent_indexes(saved_persistent_indexes);
saved_persistent_indexes.clear();
if (dynamic_sortfilter && update_source_sort_column()) {
//update_source_sort_column might have created wrong mapping so we have to clear it again
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
}
if (dynamic_sortfilter)
source_sort_column = find_source_sort_column();
emit q->layoutChanged(saved_layoutChange_parents);
saved_layoutChange_parents.clear();

View File

@ -682,7 +682,9 @@ static void argumentTypesFromString(const char *str, const char *end,
--level;
++str;
}
types += QArgumentType(QByteArray(begin, str - begin));
QByteArray argType(begin, str - begin);
argType.replace("QList<", "QVector<");
types += QArgumentType(std::move(argType));
}
}

View File

@ -213,6 +213,9 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc
}
}
// Qt 5 compatibility, make sure we use the correct type name for QList
result.replace("QList<", "QVector<");
return result;
}

View File

@ -1103,7 +1103,7 @@ int QMetaStringTable::enter(const QByteArray &value)
int QMetaStringTable::preferredAlignment()
{
return Q_ALIGNOF(QByteArrayData);
return alignof(QByteArrayData);
}
// Returns the size (in bytes) required for serializing this string table.

View File

@ -37,6 +37,8 @@
**
****************************************************************************/
#include <bitset>
#include "qmetatype.h"
#include "qmetatype_p.h"
#include "qobjectdefs.h"
@ -2416,6 +2418,50 @@ const QMetaObject *metaObjectForQWidget()
return nullptr;
return qMetaObjectWidgetsHelper;
}
void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName)
{
// In Qt6 QList got typedef'ed to QVector. To keep runtime behavior compatibility
// with Qt5 we install corresponding aliases. For example if one register
// QVector<QVector<int>>
// we need to register the type plus all possible aliases:
// QVector<QList<int>>
// QList<QVector<int>>
// QList<QList<int>>
// ### Qt6 TODO This is slow, as it allocates couple of strings we would need to
// if def this call with something like QT_NO_QLIST
const char *vectorName = "QVector<";
const char *listName = "QList<";
auto isSubstringOfAType = [](char c) { return c != ' ' && c != ',' && c != '<'; };
QVarLengthArray<int> indexes;
for (auto containerName: {vectorName, listName}) {
for (int i = normalizedTypeName.indexOf(containerName, 0); i != -1; i = normalizedTypeName.indexOf(containerName, i + 1)) {
if (!i || (i > 0 && !isSubstringOfAType(normalizedTypeName[i - 1])))
indexes.append(i);
}
}
// To avoid problems with the constantly changing size we start replacements
// from the end of normalizedTypeName
std::sort(indexes.rbegin(), indexes.rend());
for (quint64 combination = 1; ; ++combination) {
std::bitset<64> bits(combination);
QByteArray name = normalizedTypeName;
for (auto j = 0; j < indexes.size(); ++j) {
if (bits.test(j)) {
auto i = indexes[j];
auto replaceFrom = normalizedTypeName[i + 1] == 'V' ? vectorName : listName;
auto replaceTo = normalizedTypeName[i + 1] == 'V' ? listName : vectorName;
name.replace(i, sizeof(replaceFrom), replaceTo);
}
}
QMetaType::registerNormalizedTypedef(name, id);
if (bits.count() >= size_t(indexes.size()))
break;
}
}
}
namespace QtMetaTypePrivate {

View File

@ -151,6 +151,13 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QVariantHash, 28, QVariantHash) \
F(QByteArrayList, 49, QByteArrayList) \
#if QT_CONFIG(shortcut)
#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\
F(QKeySequence, 75, QKeySequence)
#else
#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
#endif
#define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
F(QFont, 64, QFont) \
F(QPixmap, 65, QPixmap) \
@ -163,7 +170,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QRegion, 72, QRegion) \
F(QBitmap, 73, QBitmap) \
F(QCursor, 74, QCursor) \
F(QKeySequence, 75, QKeySequence) \
QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \
F(QPen, 76, QPen) \
F(QTextLength, 77, QTextLength) \
F(QTextFormat, 78, QTextFormat) \
@ -200,10 +207,11 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(UInt, -1, uint, "quint32") \
F(LongLong, -1, qlonglong, "qint64") \
F(ULongLong, -1, qulonglong, "quint64") \
F(QVariantList, -1, QVariantList, "QVector<QVariant>") \
F(QVariantList, -1, QVariantList, "QList<QVariant>") \
F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
F(QByteArrayList, -1, QByteArrayList, "QVector<QByteArray>") \
#define QT_FOR_EACH_STATIC_TYPE(F)\
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
@ -218,7 +226,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
TypeName = Id,
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
F(QList) \
F(QVector) \
F(QQueue) \
F(QStack) \
@ -996,10 +1003,6 @@ struct ContainerAPI : CapabilitiesImpl<T>
static int size(const T *t) { return int(std::distance(t->begin(), t->end())); }
};
template<typename T>
struct ContainerAPI<QList<T> > : CapabilitiesImpl<QList<T> >
{ static int size(const QList<T> *t) { return t->size(); } };
template<typename T>
struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
{ static int size(const QVector<T> *t) { return t->size(); } };
@ -1643,6 +1646,23 @@ namespace QtPrivate
static bool registerConverter(int) { return false; }
};
template<class T>
struct Qt5CompatibilityHook
{
static inline void postRegister(int, const QByteArray &) {};
};
Q_CORE_EXPORT void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName);
template<class T>
struct Qt5CompatibilityHook<QVector<T>>
{
static inline void postRegister(int id, const QByteArray &normalizedTypeName)
{
qt5CompatibilityHookPostRegister(id, normalizedTypeName);
}
};
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
@ -1769,6 +1789,7 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
QtPrivate::Qt5CompatibilityHook<T>::postRegister(id, normalizedTypeName);
}
return id;
@ -1992,7 +2013,7 @@ typedef QHash<QString, QVariant> QVariantHash;
#ifdef Q_CLANG_QDOC
class QByteArrayList;
#else
typedef QList<QByteArray> QByteArrayList;
typedef QVector<QByteArray> QByteArrayList;
#endif
#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \

View File

@ -232,9 +232,6 @@ template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = fals
#if !QT_CONFIG(regularexpression)
template<> struct TypeDefinition<QRegularExpression> { static const bool IsAvailable = false; };
#endif
#ifdef QT_NO_SHORTCUT
template<> struct TypeDefinition<QKeySequence> { static const bool IsAvailable = false; };
#endif
#ifdef QT_NO_CURSOR
template<> struct TypeDefinition<QCursor> { static const bool IsAvailable = false; };
#endif

View File

@ -362,6 +362,7 @@ public:
}
public:
ExtraData *extraData; // extra data set by the user
QThreadData *getThreadData() const { return threadData; }
QThreadData *threadData; // id of the thread that owns the object
using ConnectionDataPointer = QExplicitlySharedDataPointer<ConnectionData>;

View File

@ -1470,7 +1470,7 @@ static void customConstruct(QVariant::Private *d, const void *copy)
} else {
// Private::Data contains long long, and long double is the biggest standard type.
const size_t maxAlignment =
qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double));
qMax(alignof(QVariant::Private::Data), alignof(long double));
const size_t s = sizeof(QVariant::PrivateShared);
const size_t offset = s + ((s * maxAlignment - s) % maxAlignment);
void *data = operator new(offset + size);
@ -2469,7 +2469,9 @@ static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
QVariant::DateTime,
QVariant::ByteArray,
QVariant::BitArray,
#if QT_CONFIG(shortcut)
QVariant::KeySequence,
#endif
QVariant::Pen,
QVariant::LongLong,
QVariant::ULongLong,
@ -2574,7 +2576,11 @@ void QVariant::save(QDataStream &s) const
typeId += 97;
} else if (typeId == QMetaType::QSizePolicy) {
typeId = 75;
#if QT_CONFIG(shortcut)
} else if (typeId >= QMetaType::QKeySequence && typeId <= QMetaType::QQuaternion) {
#else
} else if (typeId >= QMetaType::QPen && typeId <= QMetaType::QQuaternion) {
#endif
// and as a result these types received lower ids too
typeId +=1;
} else if (typeId == QMetaType::QPolygonF) {
@ -3647,9 +3653,11 @@ bool QVariant::canConvert(int targetTypeId) const
if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
switch (uint(targetTypeId)) {
case QVariant::Int:
#if QT_CONFIG(shortcut)
if (currentType == QVariant::KeySequence)
return true;
Q_FALLTHROUGH();
#endif
case QVariant::UInt:
case QVariant::LongLong:
case QVariant::ULongLong:
@ -3672,11 +3680,16 @@ bool QVariant::canConvert(int targetTypeId) const
return currentType == QVariant::Color || currentType == QMetaType::Nullptr
|| ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
case QVariant::String:
return currentType == QVariant::KeySequence || currentType == QVariant::Font
|| currentType == QVariant::Color || currentType == QMetaType::Nullptr
|| ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
return currentType == QVariant::Font
|| currentType == QVariant::Color || currentType == QMetaType::Nullptr
#if QT_CONFIG(shortcut)
|| currentType == QVariant::KeySequence
#endif
|| ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
#if QT_CONFIG(shortcut)
case QVariant::KeySequence:
return currentType == QVariant::String || currentType == QVariant::Int;
#endif
case QVariant::Font:
return currentType == QVariant::String;
case QVariant::Color:

View File

@ -184,7 +184,9 @@ class Q_CORE_EXPORT QVariant
Region = QMetaType::QRegion,
Bitmap = QMetaType::QBitmap,
Cursor = QMetaType::QCursor,
#if QT_CONFIG(shortcut)
KeySequence = QMetaType::QKeySequence,
#endif
Pen = QMetaType::QPen,
TextLength = QMetaType::QTextLength,
TextFormat = QMetaType::QTextFormat,

View File

@ -0,0 +1,415 @@
/****************************************************************************
**
** Copyright (C) 2016 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$
**
****************************************************************************/
#include "qbinaryjson_p.h"
#include <qjsonobject.h>
#include <qjsonarray.h>
QT_BEGIN_NAMESPACE
namespace QBinaryJsonPrivate {
static Q_CONSTEXPR Base emptyArray = {
{ qle_uint(sizeof(Base)) },
{ 0 },
{ qle_uint(0) }
};
static Q_CONSTEXPR Base emptyObject = {
{ qle_uint(sizeof(Base)) },
{ qToLittleEndian(1U) },
{ qle_uint(0) }
};
void MutableData::compact()
{
Q_STATIC_ASSERT(sizeof(Value) == sizeof(offset));
Base *base = header->root();
int reserve = 0;
if (base->is_object) {
auto *o = static_cast<Object *>(base);
for (uint i = 0; i < o->length; ++i)
reserve += o->entryAt(i)->usedStorage(o);
} else {
auto *a = static_cast<Array *>(base);
for (uint i = 0; i < a->length; ++i)
reserve += a->at(i)->usedStorage(a);
}
uint size = sizeof(Base) + reserve + base->length * sizeof(offset);
uint alloc = sizeof(Header) + size;
auto *h = reinterpret_cast<Header *>(malloc(alloc));
Q_CHECK_PTR(h);
h->tag = QJsonDocument::BinaryFormatTag;
h->version = 1;
Base *b = h->root();
b->size = size;
b->is_object = header->root()->is_object;
b->length = base->length;
b->tableOffset = reserve + sizeof(Array);
uint offset = sizeof(Base);
if (b->is_object) {
const auto *o = static_cast<const Object *>(base);
auto *no = static_cast<Object *>(b);
for (uint i = 0; i < o->length; ++i) {
no->table()[i] = offset;
const Entry *e = o->entryAt(i);
Entry *ne = no->entryAt(i);
uint s = e->size();
memcpy(ne, e, s);
offset += s;
uint dataSize = e->value.usedStorage(o);
if (dataSize) {
memcpy(reinterpret_cast<char *>(no) + offset, e->value.data(o), dataSize);
ne->value.value = offset;
offset += dataSize;
}
}
} else {
const auto *a = static_cast<const Array *>(base);
auto *na = static_cast<Array *>(b);
for (uint i = 0; i < a->length; ++i) {
const Value *v = a->at(i);
Value *nv = na->at(i);
*nv = *v;
uint dataSize = v->usedStorage(a);
if (dataSize) {
memcpy(reinterpret_cast<char *>(na) + offset, v->data(a), dataSize);
nv->value = offset;
offset += dataSize;
}
}
}
Q_ASSERT(offset == uint(b->tableOffset));
free(header);
header = h;
this->alloc = alloc;
compactionCounter = 0;
}
bool ConstData::isValid() const
{
if (header->tag != QJsonDocument::BinaryFormatTag || header->version != 1U)
return false;
const Base *root = header->root();
const uint maxSize = alloc - sizeof(Header);
return root->is_object
? static_cast<const Object *>(root)->isValid(maxSize)
: static_cast<const Array *>(root)->isValid(maxSize);
}
QJsonDocument ConstData::toJsonDocument() const
{
const Base *root = header->root();
return root->is_object
? QJsonDocument(static_cast<const Object *>(root)->toJsonObject())
: QJsonDocument(static_cast<const Array *>(root)->toJsonArray());
}
uint Base::reserveSpace(uint dataSize, uint posInTable, uint numItems, bool replace)
{
Q_ASSERT(posInTable <= length);
if (size + dataSize >= Value::MaxSize) {
qWarning("QJson: Document too large to store in data structure %d %d %d",
uint(size), dataSize, Value::MaxSize);
return 0;
}
offset off = tableOffset;
// move table to new position
if (replace) {
memmove(reinterpret_cast<char *>(table()) + dataSize, table(), length * sizeof(offset));
} else {
memmove(reinterpret_cast<char *>(table() + posInTable + numItems) + dataSize,
table() + posInTable, (length - posInTable) * sizeof(offset));
memmove(reinterpret_cast<char *>(table()) + dataSize, table(), posInTable * sizeof(offset));
}
tableOffset += dataSize;
for (uint i = 0; i < numItems; ++i)
table()[posInTable + i] = off;
size += dataSize;
if (!replace) {
length += numItems;
size += numItems * sizeof(offset);
}
return off;
}
uint Object::indexOf(QStringView key, bool *exists) const
{
uint min = 0;
uint n = length;
while (n > 0) {
uint half = n >> 1;
uint middle = min + half;
if (*entryAt(middle) >= key) {
n = half;
} else {
min = middle + 1;
n -= half + 1;
}
}
if (min < length && *entryAt(min) == key) {
*exists = true;
return min;
}
*exists = false;
return min;
}
QJsonObject Object::toJsonObject() const
{
QJsonObject object;
for (uint i = 0; i < length; ++i) {
const Entry *e = entryAt(i);
object.insert(e->key(), e->value.toJsonValue(this));
}
return object;
}
bool Object::isValid(uint maxSize) const
{
if (size > maxSize || tableOffset + length * sizeof(offset) > size)
return false;
QString lastKey;
for (uint i = 0; i < length; ++i) {
if (table()[i] + sizeof(Entry) >= tableOffset)
return false;
const Entry *e = entryAt(i);
if (!e->isValid(tableOffset - table()[i]))
return false;
const QString key = e->key();
if (key < lastKey)
return false;
if (!e->value.isValid(this))
return false;
lastKey = key;
}
return true;
}
QJsonArray Array::toJsonArray() const
{
QJsonArray array;
const offset *values = table();
for (uint i = 0; i < length; ++i)
array.append(reinterpret_cast<const Value *>(values + i)->toJsonValue(this));
return array;
}
bool Array::isValid(uint maxSize) const
{
if (size > maxSize || tableOffset + length * sizeof(offset) > size)
return false;
const offset *values = table();
for (uint i = 0; i < length; ++i) {
if (!reinterpret_cast<const Value *>(values + i)->isValid(this))
return false;
}
return true;
}
uint Value::usedStorage(const Base *b) const
{
uint s = 0;
switch (type) {
case QJsonValue::Double:
if (!latinOrIntValue)
s = sizeof(double);
break;
case QJsonValue::String: {
const char *d = data(b);
s = latinOrIntValue
? (sizeof(ushort)
+ qFromLittleEndian(*reinterpret_cast<const ushort *>(d)))
: (sizeof(int)
+ sizeof(ushort) * qFromLittleEndian(*reinterpret_cast<const int *>(d)));
break;
}
case QJsonValue::Array:
case QJsonValue::Object:
s = base(b)->size;
break;
case QJsonValue::Null:
case QJsonValue::Bool:
default:
break;
}
return alignedSize(s);
}
QJsonValue Value::toJsonValue(const Base *b) const
{
switch (type) {
case QJsonValue::Null:
return QJsonValue(QJsonValue::Null);
case QJsonValue::Bool:
return QJsonValue(toBoolean());
case QJsonValue::Double:
return QJsonValue(toDouble(b));
case QJsonValue::String:
return QJsonValue(toString(b));
case QJsonValue::Array:
return static_cast<const Array *>(base(b))->toJsonArray();
case QJsonValue::Object:
return static_cast<const Object *>(base(b))->toJsonObject();
case QJsonValue::Undefined:
return QJsonValue(QJsonValue::Undefined);
}
Q_UNREACHABLE();
return QJsonValue(QJsonValue::Undefined);
}
inline bool isValidValueOffset(uint offset, uint tableOffset)
{
return offset >= sizeof(Base)
&& offset + sizeof(uint) <= tableOffset;
}
bool Value::isValid(const Base *b) const
{
switch (type) {
case QJsonValue::Null:
case QJsonValue::Bool:
return true;
case QJsonValue::Double:
return latinOrIntValue || isValidValueOffset(value, b->tableOffset);
case QJsonValue::String:
if (!isValidValueOffset(value, b->tableOffset))
return false;
if (latinOrIntValue)
return asLatin1String(b).isValid(b->tableOffset - value);
return asString(b).isValid(b->tableOffset - value);
case QJsonValue::Array:
return isValidValueOffset(value, b->tableOffset)
&& static_cast<const Array *>(base(b))->isValid(b->tableOffset - value);
case QJsonValue::Object:
return isValidValueOffset(value, b->tableOffset)
&& static_cast<const Object *>(base(b))->isValid(b->tableOffset - value);
default:
return false;
}
}
uint Value::requiredStorage(const QBinaryJsonValue &v, bool *compressed)
{
*compressed = false;
switch (v.type()) {
case QJsonValue::Double:
if (QBinaryJsonPrivate::compressedNumber(v.toDouble()) != INT_MAX) {
*compressed = true;
return 0;
}
return sizeof(double);
case QJsonValue::String: {
QString s = v.toString();
*compressed = QBinaryJsonPrivate::useCompressed(s);
return QBinaryJsonPrivate::qStringSize(s, *compressed);
}
case QJsonValue::Array:
case QJsonValue::Object:
return v.base ? uint(v.base->size) : sizeof(QBinaryJsonPrivate::Base);
case QJsonValue::Undefined:
case QJsonValue::Null:
case QJsonValue::Bool:
break;
}
return 0;
}
uint Value::valueToStore(const QBinaryJsonValue &v, uint offset)
{
switch (v.type()) {
case QJsonValue::Undefined:
case QJsonValue::Null:
break;
case QJsonValue::Bool:
return v.toBool();
case QJsonValue::Double: {
int c = QBinaryJsonPrivate::compressedNumber(v.toDouble());
if (c != INT_MAX)
return c;
}
Q_FALLTHROUGH();
case QJsonValue::String:
case QJsonValue::Array:
case QJsonValue::Object:
return offset;
}
return 0;
}
void Value::copyData(const QBinaryJsonValue &v, char *dest, bool compressed)
{
switch (v.type()) {
case QJsonValue::Double:
if (!compressed)
qToLittleEndian(v.toDouble(), dest);
break;
case QJsonValue::String: {
const QString str = v.toString();
QBinaryJsonPrivate::copyString(dest, str, compressed);
break;
}
case QJsonValue::Array:
case QJsonValue::Object: {
const QBinaryJsonPrivate::Base *b = v.base;
if (!b)
b = (v.type() == QJsonValue::Array ? &emptyArray : &emptyObject);
memcpy(dest, b, b->size);
break;
}
default:
break;
}
}
} // namespace QBinaryJsonPrivate
QT_END_NAMESPACE

View File

@ -0,0 +1,617 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 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 QBINARYJSON_P_H
#define QBINARYJSON_P_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.
//
#include <private/qbinaryjsonvalue_p.h>
#include <private/qendian_p.h>
#include <qjsondocument.h>
#include <limits>
QT_REQUIRE_CONFIG(binaryjson);
QT_BEGIN_NAMESPACE
// in qstring.cpp
void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len);
void qt_from_latin1(ushort *dst, const char *str, size_t size) noexcept;
/*
This defines a binary data structure for Json data. The data structure is optimised for fast reading
and minimum allocations. The whole data structure can be mmap'ed and used directly.
In most cases the binary structure is not as space efficient as a utf8 encoded text representation, but
much faster to access.
The size requirements are:
String:
Latin1 data: 2 bytes header + string.length()
Full Unicode: 4 bytes header + 2*(string.length())
Values: 4 bytes + size of data (size can be 0 for some data)
bool: 0 bytes
double: 8 bytes (0 if integer with less than 27bits)
string: see above
array: size of array
object: size of object
Array: 12 bytes + 4*length + size of Value data
Object: 12 bytes + 8*length + size of Key Strings + size of Value data
For an example such as
{ // object: 12 + 5*8 = 52
"firstName": "John", // key 12, value 8 = 20
"lastName" : "Smith", // key 12, value 8 = 20
"age" : 25, // key 8, value 0 = 8
"address" : // key 12, object below = 140
{ // object: 12 + 4*8
"streetAddress": "21 2nd Street", // key 16, value 16
"city" : "New York", // key 8, value 12
"state" : "NY", // key 8, value 4
"postalCode" : "10021" // key 12, value 8
}, // object total: 128
"phoneNumber": // key: 16, value array below = 172
[ // array: 12 + 2*4 + values below: 156
{ // object 12 + 2*8
"type" : "home", // key 8, value 8
"number": "212 555-1234" // key 8, value 16
}, // object total: 68
{ // object 12 + 2*8
"type" : "fax", // key 8, value 8
"number": "646 555-4567" // key 8, value 16
} // object total: 68
] // array total: 156
} // great total: 412 bytes
The uncompressed text file used roughly 500 bytes, so in this case we end up using about
the same space as the text representation.
Other measurements have shown a slightly bigger binary size than a compact text
representation where all possible whitespace was stripped out.
*/
namespace QBinaryJsonPrivate {
class Array;
class Object;
class Value;
class Entry;
template<typename T>
using q_littleendian = QLEInteger<T>;
using qle_short = q_littleendian<short>;
using qle_ushort = q_littleendian<unsigned short>;
using qle_int = q_littleendian<int>;
using qle_uint = q_littleendian<unsigned int>;
template<int pos, int width>
using qle_bitfield = QLEIntegerBitfield<uint, pos, width>;
template<int pos, int width>
using qle_signedbitfield = QLEIntegerBitfield<int, pos, width>;
using offset = qle_uint;
// round the size up to the next 4 byte boundary
inline uint alignedSize(uint size) { return (size + 3) & ~3; }
const int MaxLatin1Length = 0x7fff;
static inline bool useCompressed(QStringView s)
{
if (s.length() > MaxLatin1Length)
return false;
return QtPrivate::isLatin1(s);
}
static inline bool useCompressed(QLatin1String s)
{
return s.size() <= MaxLatin1Length;
}
static inline uint qStringSize(const QString &string, bool compress)
{
uint l = 2 + string.size();
if (!compress)
l *= 2;
return alignedSize(l);
}
// returns INT_MAX if it can't compress it into 28 bits
static inline int compressedNumber(double d)
{
// this relies on details of how ieee floats are represented
const int exponent_off = 52;
const quint64 fraction_mask = 0x000fffffffffffffULL;
const quint64 exponent_mask = 0x7ff0000000000000ULL;
quint64 val;
memcpy (&val, &d, sizeof(double));
int exp = (int)((val & exponent_mask) >> exponent_off) - 1023;
if (exp < 0 || exp > 25)
return std::numeric_limits<int>::max();
quint64 non_int = val & (fraction_mask >> exp);
if (non_int)
return std::numeric_limits<int>::max();
bool neg = (val >> 63) != 0;
val &= fraction_mask;
val |= ((quint64)1 << 52);
int res = (int)(val >> (52 - exp));
return neg ? -res : res;
}
class Latin1String;
class String
{
public:
explicit String(const char *data) : d(reinterpret_cast<const Data *>(data)) {}
struct Data {
qle_uint length;
qle_ushort utf16[1];
};
const Data *d;
uint byteSize() const { return sizeof(uint) + sizeof(ushort) * d->length; }
bool isValid(uint maxSize) const
{
// Check byteSize() <= maxSize, avoiding integer overflow
return maxSize >= sizeof(uint)
&& uint(d->length) <= (maxSize - sizeof(uint)) / sizeof(ushort);
}
static void copy(char *dest, QStringView str)
{
Data *data = reinterpret_cast<Data *>(dest);
data->length = str.length();
qToLittleEndian<quint16>(str.utf16(), str.length(), data->utf16);
fillTrailingZeros(data);
}
static void fillTrailingZeros(Data *data)
{
if (data->length & 1)
data->utf16[data->length] = 0;
}
bool operator ==(QStringView str) const
{
int slen = str.length();
int l = d->length;
if (slen != l)
return false;
const auto *s = reinterpret_cast<const ushort *>(str.utf16());
const qle_ushort *a = d->utf16;
const ushort *b = s;
while (l-- && *a == *b)
a++,b++;
return (l == -1);
}
bool operator ==(const String &str) const
{
if (d->length != str.d->length)
return false;
return !memcmp(d->utf16, str.d->utf16, d->length * sizeof(ushort));
}
QString toString() const
{
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
return QString(reinterpret_cast<const QChar *>(d->utf16), d->length);
#else
const uint l = d->length;
QString str(l, Qt::Uninitialized);
QChar *ch = str.data();
for (uint i = 0; i < l; ++i)
ch[i] = QChar(d->utf16[i]);
return str;
#endif
}
};
class Latin1String
{
public:
explicit Latin1String(const char *data) : d(reinterpret_cast<const Data *>(data)) {}
struct Data {
qle_ushort length;
char latin1[1];
};
const Data *d;
uint byteSize() const { return sizeof(ushort) + sizeof(char) * (d->length); }
bool isValid(uint maxSize) const { return byteSize() <= maxSize; }
static void copy(char *dest, QStringView src)
{
Data *data = reinterpret_cast<Data *>(dest);
data->length = src.length();
auto *l = reinterpret_cast<uchar *>(data->latin1);
const auto *uc = reinterpret_cast<const ushort *>(src.utf16());
qt_to_latin1_unchecked(l, uc, data->length);
for (uint len = data->length; quintptr(l + len) & 0x3; ++len)
l[len] = 0;
}
QLatin1String toQLatin1String() const noexcept { return QLatin1String(d->latin1, d->length); }
QString toString() const { return QString::fromLatin1(d->latin1, d->length); }
};
static inline void copyString(char *dest, QStringView str, bool compress)
{
if (compress)
Latin1String::copy(dest, str);
else
String::copy(dest, str);
}
/*
Base is the base class for both Object and Array. Both classes work more or less the same way.
The class starts with a header (defined by the struct below), then followed by data (the data for
values in the Array case and Entry's (see below) for objects.
After the data a table follows (tableOffset points to it) containing Value objects for Arrays, and
offsets from the beginning of the object to Entry's in the case of Object.
Entry's in the Object's table are lexicographically sorted by key in the table(). This allows the usage
of a binary search over the keys in an Object.
*/
class Base
{
public:
qle_uint size;
union {
uint _dummy;
qle_bitfield<0, 1> is_object;
qle_bitfield<1, 31> length;
};
offset tableOffset;
// content follows here
bool isObject() const { return !!is_object; }
bool isArray() const { return !isObject(); }
offset *table()
{
return reinterpret_cast<offset *>(reinterpret_cast<char *>(this) + tableOffset);
}
const offset *table() const
{
return reinterpret_cast<const offset *>(reinterpret_cast<const char *>(this) + tableOffset);
}
uint reserveSpace(uint dataSize, uint posInTable, uint numItems, bool replace);
};
class Object : public Base
{
public:
const Entry *entryAt(uint i) const
{
return reinterpret_cast<const Entry *>(reinterpret_cast<const char *>(this) + table()[i]);
}
Entry *entryAt(uint i)
{
return reinterpret_cast<Entry *>(reinterpret_cast<char *>(this) + table()[i]);
}
uint indexOf(QStringView key, bool *exists) const;
QJsonObject toJsonObject() const;
bool isValid(uint maxSize) const;
};
class Array : public Base
{
public:
const Value *at(uint i) const { return reinterpret_cast<const Value *>(table() + i); }
Value *at(uint i) { return reinterpret_cast<Value *>(table() + i); }
QJsonArray toJsonArray() const;
bool isValid(uint maxSize) const;
};
class Value
{
public:
enum {
MaxSize = (1 << 27) - 1
};
union {
uint _dummy;
qle_bitfield<0, 3> type;
qle_bitfield<3, 1> latinOrIntValue;
qle_bitfield<4, 1> latinKey;
qle_bitfield<5, 27> value;
qle_signedbitfield<5, 27> int_value;
};
inline const char *data(const Base *b) const
{
return reinterpret_cast<const char *>(b) + value;
}
uint usedStorage(const Base *b) const;
bool toBoolean() const
{
Q_ASSERT(type == QJsonValue::Bool);
return value != 0;
}
double toDouble(const Base *b) const
{
Q_ASSERT(type == QJsonValue::Double);
if (latinOrIntValue)
return int_value;
auto i = qFromLittleEndian<quint64>(reinterpret_cast<const uchar *>(b) + value);
double d;
memcpy(&d, &i, sizeof(double));
return d;
}
QString toString(const Base *b) const
{
return latinOrIntValue
? asLatin1String(b).toString()
: asString(b).toString();
}
String asString(const Base *b) const
{
Q_ASSERT(type == QJsonValue::String && !latinOrIntValue);
return String(data(b));
}
Latin1String asLatin1String(const Base *b) const
{
Q_ASSERT(type == QJsonValue::String && latinOrIntValue);
return Latin1String(data(b));
}
const Base *base(const Base *b) const
{
Q_ASSERT(type == QJsonValue::Array || type == QJsonValue::Object);
return reinterpret_cast<const Base *>(data(b));
}
QJsonValue toJsonValue(const Base *b) const;
bool isValid(const Base *b) const;
static uint requiredStorage(const QBinaryJsonValue &v, bool *compressed);
static uint valueToStore(const QBinaryJsonValue &v, uint offset);
static void copyData(const QBinaryJsonValue &v, char *dest, bool compressed);
};
class Entry {
public:
Value value;
// key
// value data follows key
uint size() const
{
uint s = sizeof(Entry);
if (value.latinKey)
s += shallowLatin1Key().byteSize();
else
s += shallowKey().byteSize();
return alignedSize(s);
}
uint usedStorage(Base *b) const
{
return size() + value.usedStorage(b);
}
String shallowKey() const
{
Q_ASSERT(!value.latinKey);
return String(reinterpret_cast<const char *>(this) + sizeof(Entry));
}
Latin1String shallowLatin1Key() const
{
Q_ASSERT(value.latinKey);
return Latin1String(reinterpret_cast<const char *>(this) + sizeof(Entry));
}
QString key() const
{
return value.latinKey
? shallowLatin1Key().toString()
: shallowKey().toString();
}
bool isValid(uint maxSize) const
{
if (maxSize < sizeof(Entry))
return false;
maxSize -= sizeof(Entry);
return value.latinKey
? shallowLatin1Key().isValid(maxSize)
: shallowKey().isValid(maxSize);
}
bool operator ==(QStringView key) const
{
return value.latinKey
? (shallowLatin1Key().toQLatin1String() == key)
: (shallowKey() == key);
}
bool operator >=(QStringView key) const
{
return value.latinKey
? (shallowLatin1Key().toQLatin1String() >= key)
: (shallowKey().toString() >= key);
}
};
class Header {
public:
qle_uint tag; // 'qbjs'
qle_uint version; // 1
Base *root() { return reinterpret_cast<Base *>(this + 1); }
const Base *root() const { return reinterpret_cast<const Base *>(this + 1); }
};
class ConstData
{
Q_DISABLE_COPY_MOVE(ConstData)
public:
const uint alloc;
union {
const char *rawData;
const Header *header;
};
ConstData(const char *raw, uint a) : alloc(a), rawData(raw) {}
bool isValid() const;
QJsonDocument toJsonDocument() const;
};
class MutableData
{
Q_DISABLE_COPY_MOVE(MutableData)
public:
QAtomicInt ref;
uint alloc;
union {
char *rawData;
Header *header;
};
uint compactionCounter : 31;
MutableData(char *raw, uint a)
: alloc(a), rawData(raw), compactionCounter(0)
{
}
MutableData(uint reserved, QJsonValue::Type valueType)
: rawData(nullptr), compactionCounter(0)
{
Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object);
alloc = sizeof(Header) + sizeof(Base) + reserved + sizeof(offset);
header = reinterpret_cast<Header *>(malloc(alloc));
Q_CHECK_PTR(header);
header->tag = QJsonDocument::BinaryFormatTag;
header->version = 1;
Base *b = header->root();
b->size = sizeof(Base);
b->is_object = (valueType == QJsonValue::Object);
b->tableOffset = sizeof(Base);
b->length = 0;
}
~MutableData()
{
free(rawData);
}
MutableData *clone(const Base *b, uint reserve = 0)
{
uint size = sizeof(Header) + b->size;
if (b == header->root() && ref.loadRelaxed() == 1 && alloc >= size + reserve)
return this;
if (reserve) {
if (reserve < 128)
reserve = 128;
size = qMax(size + reserve, qMin(size *2, uint(Value::MaxSize)));
if (size > Value::MaxSize) {
qWarning("QJson: Document too large to store in data structure");
return nullptr;
}
}
char *raw = reinterpret_cast<char *>(malloc(size));
Q_CHECK_PTR(raw);
memcpy(raw + sizeof(Header), b, b->size);
auto *h = reinterpret_cast<Header *>(raw);
h->tag = QJsonDocument::BinaryFormatTag;
h->version = 1;
auto *d = new MutableData(raw, size);
d->compactionCounter = (b == header->root()) ? compactionCounter : 0;
return d;
}
char *takeRawData(uint *size)
{
*size = alloc;
char *result = rawData;
rawData = nullptr;
alloc = 0;
return result;
}
void compact();
};
} // namespace QBinaryJsonPrivate
Q_DECLARE_TYPEINFO(QBinaryJsonPrivate::Value, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
#endif // QBINARYJSON_P_H

View File

@ -0,0 +1,137 @@
/****************************************************************************
**
** Copyright (C) 2016 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$
**
****************************************************************************/
#include "qbinaryjsonarray_p.h"
#include "qbinaryjson_p.h"
#include <qjsonarray.h>
QT_BEGIN_NAMESPACE
QBinaryJsonArray::~QBinaryJsonArray()
{
if (d && !d->ref.deref())
delete d;
}
QBinaryJsonArray QBinaryJsonArray::fromJsonArray(const QJsonArray &array)
{
QBinaryJsonArray binary;
for (const QJsonValue &value : array)
binary.append(QBinaryJsonValue::fromJsonValue(value));
if (binary.d) // We want to compact it as it is a root item now
binary.d->compactionCounter++;
binary.compact();
return binary;
}
void QBinaryJsonArray::append(const QBinaryJsonValue &value)
{
const uint i = a ? a->length : 0;
bool compressed;
uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(value, &compressed);
if (!detach(valueSize + sizeof(QBinaryJsonPrivate::Value)))
return;
if (!a->length)
a->tableOffset = sizeof(QBinaryJsonPrivate::Array);
uint valueOffset = a->reserveSpace(valueSize, i, 1, false);
if (!valueOffset)
return;
QBinaryJsonPrivate::Value *v = a->at(i);
v->type = (value.t == QJsonValue::Undefined ? QJsonValue::Null : value.t);
v->latinOrIntValue = compressed;
v->latinKey = false;
v->value = QBinaryJsonPrivate::Value::valueToStore(value, valueOffset);
if (valueSize) {
QBinaryJsonPrivate::Value::copyData(value, reinterpret_cast<char *>(a) + valueOffset,
compressed);
}
}
char *QBinaryJsonArray::takeRawData(uint *size)
{
if (d)
return d->takeRawData(size);
*size = 0;
return nullptr;
}
bool QBinaryJsonArray::detach(uint reserve)
{
if (!d) {
if (reserve >= QBinaryJsonPrivate::Value::MaxSize) {
qWarning("QBinaryJson: Document too large to store in data structure");
return false;
}
d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Array);
a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
d->ref.ref();
return true;
}
if (reserve == 0 && d->ref.loadRelaxed() == 1)
return true;
QBinaryJsonPrivate::MutableData *x = d->clone(a, reserve);
if (!x)
return false;
x->ref.ref();
if (!d->ref.deref())
delete d;
d = x;
a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
return true;
}
void QBinaryJsonArray::compact()
{
if (!d || !d->compactionCounter)
return;
detach();
d->compact();
a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
}
QT_END_NAMESPACE

View File

@ -0,0 +1,98 @@
/****************************************************************************
**
** 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 QBINARYJSONARRAY_P_H
#define QBINARYJSONARRAY_P_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.
//
#include "qbinaryjsonvalue_p.h"
QT_REQUIRE_CONFIG(binaryjson);
QT_BEGIN_NAMESPACE
class QBinaryJsonArray
{
Q_DISABLE_COPY(QBinaryJsonArray)
public:
QBinaryJsonArray() = default;
~QBinaryJsonArray();
QBinaryJsonArray(QBinaryJsonArray &&other) noexcept
: d(other.d),
a(other.a)
{
other.d = nullptr;
other.a = nullptr;
}
QBinaryJsonArray &operator =(QBinaryJsonArray &&other) noexcept
{
qSwap(d, other.d);
qSwap(a, other.a);
return *this;
}
static QBinaryJsonArray fromJsonArray(const QJsonArray &array);
char *takeRawData(uint *size);
private:
friend class QBinaryJsonValue;
void append(const QBinaryJsonValue &value);
void compact();
bool detach(uint reserve = 0);
QBinaryJsonPrivate::MutableData *d = nullptr;
QBinaryJsonPrivate::Array *a = nullptr;
};
QT_END_NAMESPACE
#endif // QBINARYJSONARRAY_P_H

View File

@ -0,0 +1,149 @@
/****************************************************************************
**
** Copyright (C) 2016 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$
**
****************************************************************************/
#include "qbinaryjsonobject_p.h"
#include "qbinaryjson_p.h"
#include <qjsonobject.h>
QT_BEGIN_NAMESPACE
QBinaryJsonObject::~QBinaryJsonObject()
{
if (d && !d->ref.deref())
delete d;
}
QBinaryJsonObject QBinaryJsonObject::fromJsonObject(const QJsonObject &object)
{
QBinaryJsonObject binary;
for (auto it = object.begin(), end = object.end(); it != end; ++it)
binary.insert(it.key(), QBinaryJsonValue::fromJsonValue(it.value()));
if (binary.d) // We want to compact it as it is a root item now
binary.d->compactionCounter++;
binary.compact();
return binary;
}
void QBinaryJsonObject::insert(const QString &key, const QBinaryJsonValue &value)
{
bool latinOrIntValue;
uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(value, &latinOrIntValue);
bool latinKey = QBinaryJsonPrivate::useCompressed(key);
uint valueOffset = sizeof(QBinaryJsonPrivate::Entry)
+ QBinaryJsonPrivate::qStringSize(key, latinKey);
uint requiredSize = valueOffset + valueSize;
if (!detach(requiredSize + sizeof(QBinaryJsonPrivate::offset))) // offset for the new index entry
return;
if (!o->length)
o->tableOffset = sizeof(QBinaryJsonPrivate::Object);
bool keyExists = false;
uint pos = o->indexOf(key, &keyExists);
if (keyExists)
++d->compactionCounter;
uint off = o->reserveSpace(requiredSize, pos, 1, keyExists);
if (!off)
return;
QBinaryJsonPrivate::Entry *e = o->entryAt(pos);
e->value.type = value.t;
e->value.latinKey = latinKey;
e->value.latinOrIntValue = latinOrIntValue;
e->value.value = QBinaryJsonPrivate::Value::valueToStore(
value, reinterpret_cast<char *>(e) - reinterpret_cast<char *>(o) + valueOffset);
QBinaryJsonPrivate::copyString(reinterpret_cast<char *>(e + 1), key, latinKey);
if (valueSize) {
QBinaryJsonPrivate::Value::copyData(value, reinterpret_cast<char *>(e) + valueOffset,
latinOrIntValue);
}
if (d->compactionCounter > 32U && d->compactionCounter >= unsigned(o->length) / 2U)
compact();
}
char *QBinaryJsonObject::takeRawData(uint *size) const
{
if (d)
return d->takeRawData(size);
*size = 0;
return nullptr;
}
bool QBinaryJsonObject::detach(uint reserve)
{
if (!d) {
if (reserve >= QBinaryJsonPrivate::Value::MaxSize) {
qWarning("QBinaryJson: Document too large to store in data structure");
return false;
}
d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Object);
o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
d->ref.ref();
return true;
}
if (reserve == 0 && d->ref.loadRelaxed() == 1)
return true;
QBinaryJsonPrivate::MutableData *x = d->clone(o, reserve);
if (!x)
return false;
x->ref.ref();
if (!d->ref.deref())
delete d;
d = x;
o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
return true;
}
void QBinaryJsonObject::compact()
{
if (!d || !d->compactionCounter)
return;
detach();
d->compact();
o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
}
QT_END_NAMESPACE

View File

@ -0,0 +1,97 @@
/****************************************************************************
**
** 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 QBINARYJSONOBJECT_H
#define QBINARYJSONOBJECT_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.
//
#include "qbinaryjsonvalue_p.h"
QT_REQUIRE_CONFIG(binaryjson);
QT_BEGIN_NAMESPACE
class QBinaryJsonObject
{
Q_DISABLE_COPY(QBinaryJsonObject)
public:
QBinaryJsonObject() = default;
~QBinaryJsonObject();
QBinaryJsonObject(QBinaryJsonObject &&other) noexcept
: d(other.d), o(other.o)
{
other.d = nullptr;
other.o = nullptr;
}
QBinaryJsonObject &operator =(QBinaryJsonObject &&other) noexcept
{
qSwap(d, other.d);
qSwap(o, other.o);
return *this;
}
static QBinaryJsonObject fromJsonObject(const QJsonObject &object);
char *takeRawData(uint *size) const;
private:
friend class QBinaryJsonValue;
void insert(const QString &key, const QBinaryJsonValue &value);
bool detach(uint reserve = 0);
void compact();
QBinaryJsonPrivate::MutableData *d = nullptr;
QBinaryJsonPrivate::Object *o = nullptr;
};
QT_END_NAMESPACE
#endif // QBINARYJSONOBJECT_P_H

View File

@ -0,0 +1,155 @@
/****************************************************************************
**
** Copyright (C) 2016 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$
**
****************************************************************************/
#include "qbinaryjsonobject_p.h"
#include "qbinaryjsonvalue_p.h"
#include "qbinaryjsonarray_p.h"
#include "qbinaryjson_p.h"
#include <qjsonarray.h>
#include <qjsonobject.h>
QT_BEGIN_NAMESPACE
QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
QBinaryJsonPrivate::Base *parent,
const QBinaryJsonPrivate::Value &v)
: t(QJsonValue::Type(uint(v.type)))
{
switch (t) {
case QJsonValue::Undefined:
case QJsonValue::Null:
dbl = 0;
break;
case QJsonValue::Bool:
b = v.toBoolean();
break;
case QJsonValue::Double:
dbl = v.toDouble(parent);
break;
case QJsonValue::String: {
QString s = v.toString(parent);
stringData = s.data_ptr();
stringData->ref.ref();
break;
}
case QJsonValue::Array:
case QJsonValue::Object:
d = data;
base = v.base(parent);
break;
}
if (d)
d->ref.ref();
}
QBinaryJsonValue::QBinaryJsonValue(QString string)
: stringData(*reinterpret_cast<QStringData **>(&string)), t(QJsonValue::String)
{
stringData->ref.ref();
}
QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonArray &a)
: base(a.a), d(a.d), t(QJsonValue::Array)
{
if (d)
d->ref.ref();
}
QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonObject &o)
: base(o.o), d(o.d), t(QJsonValue::Object)
{
if (d)
d->ref.ref();
}
QBinaryJsonValue::~QBinaryJsonValue()
{
if (t == QJsonValue::String && stringData && !stringData->ref.deref())
free(stringData);
if (d && !d->ref.deref())
delete d;
}
QBinaryJsonValue QBinaryJsonValue::fromJsonValue(const QJsonValue &json)
{
switch (json.type()) {
case QJsonValue::Bool:
return QBinaryJsonValue(json.toBool());
case QJsonValue::Double:
return QBinaryJsonValue(json.toDouble());
case QJsonValue::String:
return QBinaryJsonValue(json.toString());
case QJsonValue::Array:
return QBinaryJsonArray::fromJsonArray(json.toArray());
case QJsonValue::Object:
return QBinaryJsonObject::fromJsonObject(json.toObject());
case QJsonValue::Null:
return QBinaryJsonValue(QJsonValue::Null);
case QJsonValue::Undefined:
return QBinaryJsonValue(QJsonValue::Undefined);
}
Q_UNREACHABLE();
return QBinaryJsonValue(QJsonValue::Null);
}
QString QBinaryJsonValue::toString() const
{
if (t != QJsonValue::String)
return QString();
stringData->ref.ref(); // the constructor below doesn't add a ref.
QStringDataPtr holder = { stringData };
return QString(holder);
}
void QBinaryJsonValue::detach()
{
if (!d)
return;
QBinaryJsonPrivate::MutableData *x = d->clone(base);
x->ref.ref();
if (!d->ref.deref())
delete d;
d = x;
base = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
}
QT_END_NAMESPACE

View File

@ -0,0 +1,134 @@
/****************************************************************************
**
** 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 QBINARYJSONVALUE_P_H
#define QBINARYJSONVALUE_P_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.
//
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qjsonvalue.h>
QT_REQUIRE_CONFIG(binaryjson);
QT_BEGIN_NAMESPACE
class QBinaryJsonArray;
class QBinaryJsonObject;
namespace QBinaryJsonPrivate {
class ConstData;
class MutableData;
class Base;
class Value;
class Object;
class Array;
}
class Q_CORE_EXPORT QBinaryJsonValue
{
Q_DISABLE_COPY(QBinaryJsonValue)
public:
explicit QBinaryJsonValue(QJsonValue::Type type) : ui(0), t(type) {}
explicit QBinaryJsonValue(bool b) : b(b), t(QJsonValue::Bool) {}
explicit QBinaryJsonValue(double n) : dbl(n), t(QJsonValue::Double) {}
explicit QBinaryJsonValue(QString s);
QBinaryJsonValue(const QBinaryJsonArray &a);
QBinaryJsonValue(const QBinaryJsonObject &o);
~QBinaryJsonValue();
QBinaryJsonValue(QBinaryJsonValue &&other) noexcept
: ui(other.ui),
d(other.d),
t(other.t)
{
other.ui = 0;
other.d = nullptr;
other.t = QJsonValue::Null;
}
QBinaryJsonValue &operator =(QBinaryJsonValue &&other) noexcept
{
qSwap(ui, other.ui);
qSwap(d, other.d);
qSwap(t, other.t);
return *this;
}
static QBinaryJsonValue fromJsonValue(const QJsonValue &json);
QJsonValue::Type type() const { return t; }
bool toBool() const { return (t == QJsonValue::Bool) && b; }
double toDouble() const { return (t == QJsonValue::Double) ? dbl : 0; }
QString toString() const;
private:
friend class QBinaryJsonPrivate::Value;
friend class QBinaryJsonArray;
friend class QBinaryJsonObject;
QBinaryJsonValue(QBinaryJsonPrivate::MutableData *d, QBinaryJsonPrivate::Base *parent,
const QBinaryJsonPrivate::Value &v);
void detach();
union {
quint64 ui;
bool b;
double dbl;
QStringData *stringData;
const QBinaryJsonPrivate::Base *base;
};
QBinaryJsonPrivate::MutableData *d = nullptr; // needed for Objects and Arrays
QJsonValue::Type t = QJsonValue::Null;
};
QT_END_NAMESPACE
#endif // QBINARYJSONVALUE_P_H

View File

@ -166,21 +166,6 @@ Q_STATIC_ASSERT(int(QCborStreamReader::Invalid) == CborInvalidType);
QCborStreamReader::toSimpleType(), QCborValue::isSimpleType(), QCborValue::toSimpleType()
*/
Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
{
switch (st) {
case QCborSimpleType::False:
return "False";
case QCborSimpleType::True:
return "True";
case QCborSimpleType::Null:
return "Null";
case QCborSimpleType::Undefined:
return "Undefined";
}
return nullptr;
}
#if !defined(QT_NO_DATASTREAM)
QDataStream &operator<<(QDataStream &ds, QCborSimpleType st)
{
@ -196,18 +181,6 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
}
#endif
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug dbg, QCborSimpleType st)
{
QDebugStateSaver saver(dbg);
const char *id = qt_cbor_simpletype_id(st);
if (id)
return dbg.nospace() << "QCborSimpleType::" << id;
return dbg.nospace() << "QCborSimpleType(" << uint(st) << ')';
}
#endif
/*!
\enum QCborTag
\relates <QtCborCommon>
@ -230,79 +203,6 @@ QDebug operator<<(QDebug dbg, QCborSimpleType st)
QCborValue::isTag(), QCborValue::tag()
*/
Q_CORE_EXPORT const char *qt_cbor_tag_id(QCborTag tag)
{
// Casting to QCborKnownTags's underlying type will make the comparison
// below fail if the tag value is out of range.
auto n = std::underlying_type<QCborKnownTags>::type(tag);
if (QCborTag(n) == tag) {
switch (QCborKnownTags(n)) {
case QCborKnownTags::DateTimeString:
return "DateTimeString";
case QCborKnownTags::UnixTime_t:
return "UnixTime_t";
case QCborKnownTags::PositiveBignum:
return "PositiveBignum";
case QCborKnownTags::NegativeBignum:
return "NegativeBignum";
case QCborKnownTags::Decimal:
return "Decimal";
case QCborKnownTags::Bigfloat:
return "Bigfloat";
case QCborKnownTags::COSE_Encrypt0:
return "COSE_Encrypt0";
case QCborKnownTags::COSE_Mac0:
return "COSE_Mac0";
case QCborKnownTags::COSE_Sign1:
return "COSE_Sign1";
case QCborKnownTags::ExpectedBase64url:
return "ExpectedBase64url";
case QCborKnownTags::ExpectedBase64:
return "ExpectedBase64";
case QCborKnownTags::ExpectedBase16:
return "ExpectedBase16";
case QCborKnownTags::EncodedCbor:
return "EncodedCbor";
case QCborKnownTags::Url:
return "Url";
case QCborKnownTags::Base64url:
return "Base64url";
case QCborKnownTags::Base64:
return "Base64";
case QCborKnownTags::RegularExpression:
return "RegularExpression";
case QCborKnownTags::MimeMessage:
return "MimeMessage";
case QCborKnownTags::Uuid:
return "Uuid";
case QCborKnownTags::COSE_Encrypt:
return "COSE_Encrypt";
case QCborKnownTags::COSE_Mac:
return "COSE_Mac";
case QCborKnownTags::COSE_Sign:
return "COSE_Sign";
case QCborKnownTags::Signature:
return "Signature";
}
}
return nullptr;
}
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug dbg, QCborTag tag)
{
QDebugStateSaver saver(dbg);
const char *id = qt_cbor_tag_id(tag);
dbg.nospace() << "QCborTag(";
if (id)
dbg.nospace() << "QCborKnownTags::" << id;
else
dbg.nospace() << quint64(tag);
return dbg << ')';
}
#endif
/*!
\enum QCborKnownTags
\relates <QtCborCommon>
@ -381,18 +281,6 @@ QDebug operator<<(QDebug dbg, QCborTag tag)
QCborValue::isTag(), QCborValue::tag()
*/
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug dbg, QCborKnownTags tag)
{
QDebugStateSaver saver(dbg);
const char *id = qt_cbor_tag_id(QCborTag(int(tag)));
if (id)
return dbg.nospace() << "QCborKnownTags::" << id;
return dbg.nospace() << "QCborKnownTags(" << int(tag) << ')';
}
#endif
/*!
\class QCborError
\inmodule QtCore

Some files were not shown because too many files have changed in this diff Show More