Merge "Merge remote-tracking branch 'origin/dev' into wip/cmake" into wip/cmake
This commit is contained in:
commit
bc1cae774a
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -53,7 +53,7 @@
|
||||
#include <QtWidgets>
|
||||
|
||||
SpreadSheetDelegate::SpreadSheetDelegate(QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{}
|
||||
|
||||
QWidget *SpreadSheetDelegate::createEditor(QWidget *parent,
|
||||
|
@ -51,9 +51,9 @@
|
||||
#ifndef SPREADSHEETDELEGATE_H
|
||||
#define SPREADSHEETDELEGATE_H
|
||||
|
||||
#include <QItemDelegate>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class SpreadSheetDelegate : public QItemDelegate
|
||||
class SpreadSheetDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -55,9 +55,8 @@
|
||||
|
||||
//! [0]
|
||||
ImageDelegate::ImageDelegate(QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
: QStyledItemDelegate(parent)
|
||||
{}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
#include <cstdlib>
|
||||
|
||||
//! [0]
|
||||
TabletCanvas::TabletCanvas()
|
||||
|
@ -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=
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.*"): \
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
|
@ -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 \
|
||||
|
8
src/3rdparty/double-conversion/README
vendored
8
src/3rdparty/double-conversion/README
vendored
@ -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.
|
@ -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(¤t, 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(¤t, 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_;
|
||||
}
|
||||
|
@ -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
|
||||
|
4
src/3rdparty/double-conversion/ieee.h
vendored
4
src/3rdparty/double-conversion/ieee.h
vendored
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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",
|
||||
|
2
src/3rdparty/libjpeg/jconfig.h
vendored
2
src/3rdparty/libjpeg/jconfig.h
vendored
@ -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
|
||||
|
||||
|
2
src/3rdparty/libjpeg/jconfigint.h
vendored
2
src/3rdparty/libjpeg/jconfigint.h
vendored
@ -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
|
||||
|
2
src/3rdparty/libjpeg/qt_attribution.json
vendored
2
src/3rdparty/libjpeg/qt_attribution.json
vendored
@ -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",
|
||||
|
38
src/3rdparty/libjpeg/src/ChangeLog.md
vendored
38
src/3rdparty/libjpeg/src/ChangeLog.md
vendored
@ -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
|
||||
=====
|
||||
|
||||
|
28
src/3rdparty/libjpeg/src/README.md
vendored
28
src/3rdparty/libjpeg/src/README.md
vendored
@ -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.
|
||||
|
6
src/3rdparty/libjpeg/src/jchuff.c
vendored
6
src/3rdparty/libjpeg/src/jchuff.c
vendored
@ -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() \
|
||||
|
2
src/3rdparty/libjpeg/src/jcmaster.c
vendored
2
src/3rdparty/libjpeg/src/jcmaster.c
vendored
@ -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. */
|
||||
|
10
src/3rdparty/libjpeg/src/jdhuff.c
vendored
10
src/3rdparty/libjpeg/src/jdhuff.c
vendored
@ -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;
|
||||
|
2
src/3rdparty/libjpeg/src/jdmerge.c
vendored
2
src/3rdparty/libjpeg/src/jdmerge.c
vendored
@ -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); \
|
||||
|
14
src/3rdparty/libjpeg/src/jdsample.c
vendored
14
src/3rdparty/libjpeg/src/jdsample.c
vendored
@ -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++;
|
||||
|
92
src/3rdparty/md4c/md4c.c
vendored
92
src/3rdparty/md4c/md4c.c
vendored
@ -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 &&
|
||||
|
15
src/3rdparty/md4c/md4c.h
vendored
15
src/3rdparty/md4c/md4c.h
vendored
@ -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)
|
||||
|
4
src/3rdparty/md4c/qt_attribution.json
vendored
4
src/3rdparty/md4c/qt_attribution.json
vendored
@ -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áš"
|
||||
}
|
||||
|
@ -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)
|
||||
|
4
src/3rdparty/sqlite/qt_attribution.json
vendored
4
src/3rdparty/sqlite/qt_attribution.json
vendored
@ -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."
|
||||
}
|
||||
|
9188
src/3rdparty/sqlite/sqlite3.c
vendored
9188
src/3rdparty/sqlite/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
81
src/3rdparty/sqlite/sqlite3.h
vendored
81
src/3rdparty/sqlite/sqlite3.h
vendored
@ -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
|
||||
|
197
src/corelib/Qt5AndroidSupport.cmake
Normal file
197
src/corelib/Qt5AndroidSupport.cmake
Normal 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()
|
@ -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@)
|
||||
|
@ -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
|
||||
|
@ -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" ]
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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");
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -67,7 +67,6 @@
|
||||
\li QImage
|
||||
\li QKeySequence
|
||||
\li QLinkedList<T>
|
||||
\li QList<T>
|
||||
\li QMap<Key, T>
|
||||
\li QMargins
|
||||
\li QMatrix4x4
|
||||
|
@ -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.
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 ©Name)
|
||||
|
||||
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 ©Name)
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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 ©Name)
|
||||
{
|
||||
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)
|
||||
|
@ -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(')');
|
||||
|
@ -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:
|
||||
|
@ -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
@ -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>
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
415
src/corelib/serialization/qbinaryjson.cpp
Normal file
415
src/corelib/serialization/qbinaryjson.cpp
Normal 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
|
617
src/corelib/serialization/qbinaryjson_p.h
Normal file
617
src/corelib/serialization/qbinaryjson_p.h
Normal 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
|
137
src/corelib/serialization/qbinaryjsonarray.cpp
Normal file
137
src/corelib/serialization/qbinaryjsonarray.cpp
Normal 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
|
||||
|
98
src/corelib/serialization/qbinaryjsonarray_p.h
Normal file
98
src/corelib/serialization/qbinaryjsonarray_p.h
Normal 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
|
149
src/corelib/serialization/qbinaryjsonobject.cpp
Normal file
149
src/corelib/serialization/qbinaryjsonobject.cpp
Normal 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
|
97
src/corelib/serialization/qbinaryjsonobject_p.h
Normal file
97
src/corelib/serialization/qbinaryjsonobject_p.h
Normal 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
|
155
src/corelib/serialization/qbinaryjsonvalue.cpp
Normal file
155
src/corelib/serialization/qbinaryjsonvalue.cpp
Normal 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
|
134
src/corelib/serialization/qbinaryjsonvalue_p.h
Normal file
134
src/corelib/serialization/qbinaryjsonvalue_p.h
Normal 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
|
@ -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
Loading…
Reference in New Issue
Block a user