summaryrefslogtreecommitdiffstats
path: root/src/tools/rcc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rcc')
-rw-r--r--src/tools/rcc/CMakeLists.txt24
-rw-r--r--src/tools/rcc/main.cpp116
-rw-r--r--src/tools/rcc/rcc.cpp299
-rw-r--r--src/tools/rcc/rcc.h34
4 files changed, 222 insertions, 251 deletions
diff --git a/src/tools/rcc/CMakeLists.txt b/src/tools/rcc/CMakeLists.txt
index 8b0d9c8182..35a72c43fe 100644
--- a/src/tools/rcc/CMakeLists.txt
+++ b/src/tools/rcc/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from rcc.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## rcc Tool:
@@ -6,10 +7,10 @@
qt_get_tool_target_name(target_name rcc)
qt_internal_add_tool(${target_name}
- BOOTSTRAP
+ TRY_RUN
TARGET_DESCRIPTION "Qt Resource Compiler"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
main.cpp
rcc.cpp rcc.h
@@ -17,25 +18,16 @@ qt_internal_add_tool(${target_name}
QT_NO_CAST_FROM_ASCII
QT_NO_FOREACH
QT_RCC
+ QT_USE_NODISCARD_FILE_OPEN
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
)
-
-#### Keys ignored in scope 1:.:.:rcc.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt Resource Compiler"
-# _OPTION = "host_build"
+qt_internal_return_unless_building_tools()
## Scopes:
#####################################################################
-qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_zstd AND NOT CMAKE_CROSSCOMPILING
- DEFINES
- QT_FEATURE_zstd=1
+qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_zstd
LIBRARIES
- ZSTD::ZSTD
-)
-
-qt_internal_extend_target(${target_name} CONDITION CMAKE_CROSSCOMPILING OR NOT QT_FEATURE_zstd
- DEFINES
- QT_FEATURE_zstd=-1
+ WrapZSTD::WrapZSTD
)
diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp
index eca7991280..03709ccbd4 100644
--- a/src/tools/rcc/main.cpp
+++ b/src/tools/rcc/main.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <rcc.h>
@@ -49,6 +24,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
void dumpRecursive(const QDir &dir, QTextStream &out)
{
const QFileInfoList entries = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot
@@ -57,9 +34,9 @@ void dumpRecursive(const QDir &dir, QTextStream &out)
if (entry.isDir()) {
dumpRecursive(entry.filePath(), out);
} else {
- out << QLatin1String("<file>")
+ out << "<file>"_L1
<< entry.filePath()
- << QLatin1String("</file>\n");
+ << "</file>\n"_L1;
}
}
}
@@ -69,7 +46,7 @@ int createProject(const QString &outFileName)
QDir currentDir = QDir::current();
QString currentDirName = currentDir.dirName();
if (currentDirName.isEmpty())
- currentDirName = QLatin1String("root");
+ currentDirName = "root"_L1;
QFile file;
bool isOk = false;
@@ -87,14 +64,14 @@ int createProject(const QString &outFileName)
}
QTextStream out(&file);
- out << QLatin1String("<!DOCTYPE RCC><RCC version=\"1.0\">\n"
- "<qresource>\n");
+ out << "<!DOCTYPE RCC><RCC version=\"1.0\">\n"
+ "<qresource>\n"_L1;
- // use "." as dir to get relative file pathes
- dumpRecursive(QDir(QLatin1String(".")), out);
+ // use "." as dir to get relative file paths
+ dumpRecursive(QDir("."_L1), out);
- out << QLatin1String("</qresource>\n"
- "</RCC>\n");
+ out << "</qresource>\n"
+ "</RCC>\n"_L1;
return 0;
}
@@ -105,11 +82,11 @@ QString makefileEscape(const QString &filepath)
// Always use forward slashes
QString result = QDir::cleanPath(filepath);
// Spaces are escaped with a backslash
- result.replace(QLatin1Char(' '), QLatin1String("\\ "));
+ result.replace(u' ', "\\ "_L1);
// Pipes are escaped with a backslash
- result.replace(QLatin1Char('|'), QLatin1String("\\|"));
+ result.replace(u'|', "\\|"_L1);
// Dollars are escaped with a dollar
- result.replace(QLatin1Char('$'), QLatin1String("$$"));
+ result.replace(u'$', "$$"_L1);
return result;
}
@@ -118,16 +95,16 @@ void writeDepFile(QIODevice &iodev, const QStringList &depsList, const QString &
{
QTextStream out(&iodev);
out << qPrintable(makefileEscape(targetName));
- out << QLatin1Char(':');
+ out << QChar(u':');
// Write depfile
for (int i = 0; i < depsList.size(); ++i) {
- out << QLatin1Char(' ');
+ out << QChar(u' ');
out << qPrintable(makefileEscape(depsList.at(i)));
}
- out << QLatin1Char('\n');
+ out << QChar(u'\n');
}
int runRcc(int argc, char *argv[])
@@ -139,7 +116,7 @@ int runRcc(int argc, char *argv[])
// If you use this code as an example for a translated app, make sure to translate the strings.
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
- parser.setApplicationDescription(QLatin1String("Qt Resource Compiler version " QT_VERSION_STR));
+ parser.setApplicationDescription("Qt Resource Compiler version " QT_VERSION_STR ""_L1);
parser.addHelpOption();
parser.addVersionOption();
@@ -233,9 +210,9 @@ int runRcc(int argc, char *argv[])
bool ok = false;
formatVersion = parser.value(formatVersionOption).toUInt(&ok);
if (!ok) {
- errorMsg = QLatin1String("Invalid format version specified");
+ errorMsg = "Invalid format version specified"_L1;
} else if (formatVersion < 1 || formatVersion > 3) {
- errorMsg = QLatin1String("Unsupported format version specified");
+ errorMsg = "Unsupported format version specified"_L1;
}
}
@@ -244,19 +221,22 @@ int runRcc(int argc, char *argv[])
library.setInitName(parser.value(nameOption));
if (parser.isSet(rootOption)) {
library.setResourceRoot(QDir::cleanPath(parser.value(rootOption)));
- if (library.resourceRoot().isEmpty()
- || library.resourceRoot().at(0) != QLatin1Char('/'))
- errorMsg = QLatin1String("Root must start with a /");
+ if (library.resourceRoot().isEmpty() || library.resourceRoot().at(0) != u'/')
+ errorMsg = "Root must start with a /"_L1;
}
if (parser.isSet(compressionAlgoOption))
library.setCompressionAlgorithm(RCCResourceLibrary::parseCompressionAlgorithm(parser.value(compressionAlgoOption), &errorMsg));
- if (formatVersion < 3 && library.compressionAlgorithm() == RCCResourceLibrary::CompressionAlgorithm::Zstd)
- errorMsg = QLatin1String("Zstandard compression requires format version 3 or higher");
- if (parser.isSet(nocompressOption))
- library.setCompressionAlgorithm(RCCResourceLibrary::CompressionAlgorithm::None);
if (parser.isSet(noZstdOption))
library.setNoZstd(true);
+ if (library.compressionAlgorithm() == RCCResourceLibrary::CompressionAlgorithm::Zstd) {
+ if (formatVersion < 3)
+ errorMsg = "Zstandard compression requires format version 3 or higher"_L1;
+ if (library.noZstd())
+ errorMsg = "--compression-algo=zstd and --no-zstd both specified."_L1;
+ }
+ if (parser.isSet(nocompressOption))
+ library.setCompressionAlgorithm(RCCResourceLibrary::CompressionAlgorithm::None);
if (parser.isSet(compressOption) && errorMsg.isEmpty()) {
int level = library.parseCompressionLevel(library.compressionAlgorithm(), parser.value(compressOption), &errorMsg);
library.setCompressLevel(level);
@@ -267,25 +247,25 @@ int runRcc(int argc, char *argv[])
library.setFormat(RCCResourceLibrary::Binary);
if (parser.isSet(generatorOption)) {
auto value = parser.value(generatorOption);
- if (value == QLatin1String("cpp")) {
+ if (value == "cpp"_L1) {
library.setFormat(RCCResourceLibrary::C_Code);
- } else if (value == QLatin1String("python")) {
+ } else if (value == "python"_L1) {
library.setFormat(RCCResourceLibrary::Python_Code);
- } else if (value == QLatin1String("python2")) { // ### fixme Qt 7: remove
+ } else if (value == "python2"_L1) { // ### fixme Qt 7: remove
qWarning("Format python2 is no longer supported, defaulting to python.");
library.setFormat(RCCResourceLibrary::Python_Code);
} else {
- errorMsg = QLatin1String("Invalid generator: ") + value;
+ errorMsg = "Invalid generator: "_L1 + value;
}
}
if (parser.isSet(passOption)) {
- if (parser.value(passOption) == QLatin1String("1"))
+ if (parser.value(passOption) == "1"_L1)
library.setFormat(RCCResourceLibrary::Pass1);
- else if (parser.value(passOption) == QLatin1String("2"))
+ else if (parser.value(passOption) == "2"_L1)
library.setFormat(RCCResourceLibrary::Pass2);
else
- errorMsg = QLatin1String("Pass number must be 1 or 2");
+ errorMsg = "Pass number must be 1 or 2"_L1;
}
if (parser.isSet(namespaceOption))
library.setUseNameSpace(!library.useNameSpace());
@@ -298,7 +278,7 @@ int runRcc(int argc, char *argv[])
const QStringList filenamesIn = parser.positionalArguments();
for (const QString &file : filenamesIn) {
- if (file == QLatin1String("-"))
+ if (file == "-"_L1)
continue;
else if (!QFile::exists(file)) {
qWarning("%s: File does not exist '%s'", argv[0], qPrintable(file));
@@ -323,7 +303,8 @@ int runRcc(int argc, char *argv[])
return 1;
}
QFile errorDevice;
- errorDevice.open(stderr, QIODevice::WriteOnly|QIODevice::Text);
+ if (!errorDevice.open(stderr, QIODevice::WriteOnly|QIODevice::Text))
+ return 1;
if (library.verbose())
errorDevice.write("Qt resource compiler\n");
@@ -350,7 +331,7 @@ int runRcc(int argc, char *argv[])
}
- if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
+ if (outFilename.isEmpty() || outFilename == "-"_L1) {
#ifdef Q_OS_WIN
// Make sure fwrite to stdout doesn't do LF->CRLF
if (library.format() == RCCResourceLibrary::Binary)
@@ -361,7 +342,12 @@ int runRcc(int argc, char *argv[])
mode &= ~QIODevice::Text;
#endif // Q_OS_WIN
// using this overload close() only flushes.
- out.open(stdout, mode);
+ if (!out.open(stdout, mode)) {
+ const QString msg = QString::fromLatin1("Unable to open standard output for writing: %1\n")
+ .arg(out.errorString());
+ errorDevice.write(msg.toUtf8());
+ return 1;
+ }
} else {
out.setFileName(outFilename);
if (!out.open(mode)) {
@@ -398,7 +384,7 @@ int runRcc(int argc, char *argv[])
QFile depout;
depout.setFileName(depFilename);
- if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
+ if (outFilename.isEmpty() || outFilename == "-"_L1) {
const QString msg = QString::fromUtf8("Unable to write depfile when outputting to stdout!\n");
errorDevice.write(msg.toUtf8());
return 1;
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 1825c77b53..2bda7f2977 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "rcc.h"
@@ -33,7 +8,7 @@
#include <qdatetime.h>
#include <qdebug.h>
#include <qdir.h>
-#include <qdiriterator.h>
+#include <qdirlisting.h>
#include <qfile.h>
#include <qiodevice.h>
#include <qlocale.h>
@@ -50,6 +25,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
enum {
CONSTANT_USENAMESPACE = 1,
CONSTANT_COMPRESSLEVEL_DEFAULT = -1,
@@ -58,14 +35,6 @@ enum {
CONSTANT_COMPRESSTHRESHOLD_DEFAULT = 70
};
-#if QT_CONFIG(zstd) && QT_VERSION >= QT_VERSION_CHECK(6,0,0)
-# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::Zstd
-#elif !defined(QT_NO_COMPRESS)
-# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::Zlib
-#else
-# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::None
-#endif
-
void RCCResourceLibrary::write(const char *str, int len)
{
int n = m_out.size();
@@ -106,15 +75,18 @@ public:
CompressedZstd = 0x04
};
- RCCFileInfo(const QString &name = QString(), const QFileInfo &fileInfo = QFileInfo(),
- QLocale::Language language = QLocale::C,
- QLocale::Territory territory = QLocale::AnyTerritory,
- uint flags = NoFlags,
- RCCResourceLibrary::CompressionAlgorithm compressAlgo = CONSTANT_COMPRESSALGO_DEFAULT,
- int compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT,
- int compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT,
- bool noZstd = false);
+
+ RCCFileInfo() = default;
+ RCCFileInfo(const QString &name, const QFileInfo &fileInfo, QLocale::Language language,
+ QLocale::Territory territory, uint flags,
+ RCCResourceLibrary::CompressionAlgorithm compressAlgo, int compressLevel,
+ int compressThreshold, bool noZstd, bool isEmpty);
+
~RCCFileInfo();
+ RCCFileInfo(const RCCFileInfo &) = delete;
+ RCCFileInfo &operator=(const RCCFileInfo &) = delete;
+ RCCFileInfo(RCCFileInfo &&) = default;
+ RCCFileInfo &operator=(RCCFileInfo &&other) = delete;
QString resourceName() const;
@@ -123,41 +95,40 @@ public:
qint64 writeDataName(RCCResourceLibrary &, qint64 offset);
void writeDataInfo(RCCResourceLibrary &lib);
- int m_flags;
+ int m_flags = NoFlags;
+ QLocale::Language m_language = QLocale::C;
+ QLocale::Territory m_territory = QLocale::AnyTerritory;
QString m_name;
- QLocale::Language m_language;
- QLocale::Territory m_territory;
QFileInfo m_fileInfo;
- RCCFileInfo *m_parent;
+ RCCFileInfo *m_parent = nullptr;
QMultiHash<QString, RCCFileInfo *> m_children;
- RCCResourceLibrary::CompressionAlgorithm m_compressAlgo;
- int m_compressLevel;
- int m_compressThreshold;
-
- qint64 m_nameOffset;
- qint64 m_dataOffset;
- qint64 m_childOffset;
- bool m_noZstd;
+
+ RCCResourceLibrary::CompressionAlgorithm m_compressAlgo = RCCResourceLibrary::CompressionAlgorithm::Best;
+ int m_compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT;
+ int m_compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT;
+ bool m_noZstd = false;
+ bool m_isEmpty = false;
+
+ qint64 m_nameOffset = 0;
+ qint64 m_dataOffset = 0;
+ qint64 m_childOffset = 0;
};
-RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo,
- QLocale::Language language, QLocale::Territory territory, uint flags,
- RCCResourceLibrary::CompressionAlgorithm compressAlgo, int compressLevel, int compressThreshold,
- bool noZstd)
+RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo, QLocale::Language language,
+ QLocale::Territory territory, uint flags,
+ RCCResourceLibrary::CompressionAlgorithm compressAlgo, int compressLevel,
+ int compressThreshold, bool noZstd, bool isEmpty)
+ : m_flags(flags),
+ m_language(language),
+ m_territory(territory),
+ m_name(name),
+ m_fileInfo(fileInfo),
+ m_compressAlgo(compressAlgo),
+ m_compressLevel(compressLevel),
+ m_compressThreshold(compressThreshold),
+ m_noZstd(noZstd),
+ m_isEmpty(isEmpty)
{
- m_name = name;
- m_fileInfo = fileInfo;
- m_language = language;
- m_territory = territory;
- m_flags = flags;
- m_parent = nullptr;
- m_nameOffset = 0;
- m_dataOffset = 0;
- m_childOffset = 0;
- m_compressAlgo = compressAlgo;
- m_compressLevel = compressLevel;
- m_compressThreshold = compressThreshold;
- m_noZstd = noZstd;
}
RCCFileInfo::~RCCFileInfo()
@@ -169,8 +140,9 @@ QString RCCFileInfo::resourceName() const
{
QString resource = m_name;
for (RCCFileInfo *p = m_parent; p; p = p->m_parent)
- resource = resource.prepend(p->m_name + QLatin1Char('/'));
- return QLatin1Char(':') + resource;
+ resource = resource.prepend(p->m_name + u'/');
+ resource.prepend(u':');
+ return resource;
}
void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
@@ -229,7 +201,7 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
if (lib.formatVersion() >= 2) {
// last modified time stamp
- const QDateTime lastModified = m_fileInfo.lastModified();
+ const QDateTime lastModified = m_fileInfo.lastModified(QTimeZone::UTC);
quint64 lastmod = quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0);
static const quint64 sourceDate = 1000 * qgetenv("QT_RCC_SOURCE_DATE_OVERRIDE").toULongLong();
if (sourceDate != 0)
@@ -256,14 +228,18 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
//capture the offset
m_dataOffset = offset;
+ QByteArray data;
- //find the data to be written
- QFile file(m_fileInfo.absoluteFilePath());
- if (!file.open(QFile::ReadOnly)) {
- *errorMessage = msgOpenReadFailed(m_fileInfo.absoluteFilePath(), file.errorString());
- return 0;
+ if (!m_isEmpty) {
+ //find the data to be written
+ QFile file(m_fileInfo.absoluteFilePath());
+ if (!file.open(QFile::ReadOnly)) {
+ *errorMessage = msgOpenReadFailed(m_fileInfo.absoluteFilePath(), file.errorString());
+ return 0;
+ }
+
+ data = file.readAll();
}
- QByteArray data = file.readAll();
// Check if compression is useful for this file
if (data.size() != 0) {
@@ -345,7 +321,7 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
// some info
if (text || pass1) {
lib.writeString(" // ");
- lib.writeByteArray(m_fileInfo.absoluteFilePath().toLocal8Bit());
+ lib.writeByteArray(m_fileInfo.fileName().toLocal8Bit());
lib.writeString("\n ");
}
@@ -402,7 +378,7 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
}
// write the length
- lib.writeNumber2(m_name.length());
+ lib.writeNumber2(m_name.size());
if (text || pass1)
lib.writeString("\n ");
else if (python)
@@ -419,14 +395,14 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
// write the m_name
const QChar *unicode = m_name.unicode();
- for (int i = 0; i < m_name.length(); ++i) {
+ for (int i = 0; i < m_name.size(); ++i) {
lib.writeNumber2(unicode[i].unicode());
if ((text || pass1) && i % 16 == 0)
lib.writeString("\n ");
else if (python && i % 16 == 0)
lib.writeString("\\\n");
}
- offset += m_name.length()*2;
+ offset += m_name.size()*2;
// done
if (text || pass1)
@@ -445,14 +421,15 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
///////////////////////////////////////////////////////////
RCCResourceLibrary::Strings::Strings() :
- TAG_RCC(QLatin1String("RCC")),
- TAG_RESOURCE(QLatin1String("qresource")),
- TAG_FILE(QLatin1String("file")),
- ATTRIBUTE_LANG(QLatin1String("lang")),
- ATTRIBUTE_PREFIX(QLatin1String("prefix")),
- ATTRIBUTE_ALIAS(QLatin1String("alias")),
- ATTRIBUTE_THRESHOLD(QLatin1String("threshold")),
- ATTRIBUTE_COMPRESS(QLatin1String("compress")),
+ TAG_RCC("RCC"_L1),
+ TAG_RESOURCE("qresource"_L1),
+ TAG_FILE("file"_L1),
+ ATTRIBUTE_LANG("lang"_L1),
+ ATTRIBUTE_PREFIX("prefix"_L1),
+ ATTRIBUTE_ALIAS("alias"_L1),
+ ATTRIBUTE_EMPTY("empty"_L1),
+ ATTRIBUTE_THRESHOLD("threshold"_L1),
+ ATTRIBUTE_COMPRESS("compress"_L1),
ATTRIBUTE_COMPRESSALGO(QStringLiteral("compression-algorithm"))
{
}
@@ -461,7 +438,7 @@ RCCResourceLibrary::RCCResourceLibrary(quint8 formatVersion)
: m_root(nullptr),
m_format(C_Code),
m_verbose(false),
- m_compressionAlgo(CONSTANT_COMPRESSALGO_DEFAULT),
+ m_compressionAlgo(CompressionAlgorithm::Best),
m_compressLevel(CONSTANT_COMPRESSLEVEL_DEFAULT),
m_compressThreshold(CONSTANT_COMPRESSTHRESHOLD_DEFAULT),
m_treeOffset(0),
@@ -495,11 +472,22 @@ enum RCCXmlTag {
};
Q_DECLARE_TYPEINFO(RCCXmlTag, Q_PRIMITIVE_TYPE);
+static bool parseBoolean(QStringView value, QString *errorMsg)
+{
+ if (value.compare("true"_L1, Qt::CaseInsensitive) == 0)
+ return true;
+ if (value.compare("false"_L1, Qt::CaseInsensitive) == 0)
+ return false;
+
+ *errorMsg = QString::fromLatin1("Invalid value for boolean attribute: '%1'").arg(value);
+ return false;
+}
+
bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
const QString &fname, QString currentPath, bool listMode)
{
Q_ASSERT(m_errorDevice);
- const QChar slash = QLatin1Char('/');
+ const QChar slash = u'/';
if (!currentPath.isEmpty() && !currentPath.endsWith(slash))
currentPath += slash;
@@ -510,6 +498,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
QLocale::Language language = QLocale::c().language();
QLocale::Territory territory = QLocale::c().territory();
QString alias;
+ bool empty = false;
auto compressAlgo = m_compressionAlgo;
int compressLevel = m_compressLevel;
int compressThreshold = m_compressThreshold;
@@ -520,12 +509,12 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
case QXmlStreamReader::StartElement:
if (reader.name() == m_strings.TAG_RCC) {
if (!tokens.isEmpty())
- reader.raiseError(QLatin1String("expected <RCC> tag"));
+ reader.raiseError("expected <RCC> tag"_L1);
else
tokens.push(RccTag);
} else if (reader.name() == m_strings.TAG_RESOURCE) {
if (tokens.isEmpty() || tokens.top() != RccTag) {
- reader.raiseError(QLatin1String("unexpected <RESOURCE> tag"));
+ reader.raiseError("unexpected <RESOURCE> tag"_L1);
} else {
tokens.push(ResourceTag);
@@ -537,7 +526,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
QString attribute = attributes.value(m_strings.ATTRIBUTE_LANG).toString();
QLocale lang = QLocale(attribute);
language = lang.language();
- if (2 == attribute.length()) {
+ if (2 == attribute.size()) {
// Language only
territory = QLocale::AnyTerritory;
} else {
@@ -555,7 +544,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
}
} else if (reader.name() == m_strings.TAG_FILE) {
if (tokens.isEmpty() || tokens.top() != ResourceTag) {
- reader.raiseError(QLatin1String("unexpected <FILE> tag"));
+ reader.raiseError("unexpected <FILE> tag"_L1);
} else {
tokens.push(FileTag);
@@ -569,6 +558,11 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
compressThreshold = m_compressThreshold;
QString errorString;
+ if (attributes.hasAttribute(m_strings.ATTRIBUTE_EMPTY))
+ empty = parseBoolean(attributes.value(m_strings.ATTRIBUTE_EMPTY), &errorString);
+ else
+ empty = false;
+
if (attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESSALGO))
compressAlgo = parseCompressionAlgorithm(attributes.value(m_strings.ATTRIBUTE_COMPRESSALGO), &errorString);
if (errorString.isEmpty() && attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) {
@@ -587,7 +581,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
reader.raiseError(errorString);
}
} else {
- reader.raiseError(QString(QLatin1String("unexpected tag: %1")).arg(reader.name().toString()));
+ reader.raiseError("unexpected tag: %1"_L1.arg(reader.name().toString()));
}
break;
@@ -596,17 +590,17 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
if (!tokens.isEmpty() && tokens.top() == RccTag)
tokens.pop();
else
- reader.raiseError(QLatin1String("unexpected closing tag"));
+ reader.raiseError("unexpected closing tag"_L1);
} else if (reader.name() == m_strings.TAG_RESOURCE) {
if (!tokens.isEmpty() && tokens.top() == ResourceTag)
tokens.pop();
else
- reader.raiseError(QLatin1String("unexpected closing tag"));
+ reader.raiseError("unexpected closing tag"_L1);
} else if (reader.name() == m_strings.TAG_FILE) {
if (!tokens.isEmpty() && tokens.top() == FileTag)
tokens.pop();
else
- reader.raiseError(QLatin1String("unexpected closing tag"));
+ reader.raiseError("unexpected closing tag"_L1);
}
break;
@@ -614,7 +608,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
if (reader.isWhitespace())
break;
if (tokens.isEmpty() || tokens.top() != FileTag) {
- reader.raiseError(QLatin1String("unexpected text"));
+ reader.raiseError("unexpected text"_L1);
} else {
QString fileName = reader.text().toString();
if (fileName.isEmpty()) {
@@ -626,7 +620,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
alias = fileName;
alias = QDir::cleanPath(alias);
- while (alias.startsWith(QLatin1String("../")))
+ while (alias.startsWith("../"_L1))
alias.remove(0, 3);
alias = QDir::cleanPath(m_resourceRoot) + prefix + alias;
@@ -640,13 +634,12 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
alias += slash;
QStringList filePaths;
- QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories);
- while (it.hasNext()) {
- it.next();
- if (it.fileName() == QLatin1String(".")
- || it.fileName() == QLatin1String(".."))
+ using F = QDirListing::IteratorFlag;
+ for (const auto &entry : QDirListing(dir, F::FollowSymlinks | F::Recursive)) {
+ const QString &fileName = entry.fileName();
+ if (fileName == "."_L1 || fileName == ".."_L1)
continue;
- filePaths.append(it.filePath());
+ filePaths.emplace_back(entry.filePath());
}
// make rcc output deterministic
@@ -660,7 +653,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
child.isDir() ? RCCFileInfo::Directory
: RCCFileInfo::NoFlags,
compressAlgo, compressLevel, compressThreshold,
- m_noZstd));
+ m_noZstd, empty));
if (!arc)
m_failedResources.push_back(child.fileName());
}
@@ -675,7 +668,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
compressAlgo,
compressLevel,
compressThreshold,
- m_noZstd)
+ m_noZstd, empty)
);
if (!arc)
m_failedResources.push_back(absFileName);
@@ -714,15 +707,15 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
m_errorDevice->write(msg.toUtf8());
if (!listMode && m_format == Binary) {
// create dummy entry, otherwise loading with QResource will crash
- m_root = new RCCFileInfo(QString(), QFileInfo(),
- QLocale::C, QLocale::AnyTerritory, RCCFileInfo::Directory);
+ m_root = new RCCFileInfo{};
+ m_root->m_flags = RCCFileInfo::Directory;
}
}
return true;
}
-bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
+bool RCCResourceLibrary::addFile(const QString &alias, RCCFileInfo file)
{
Q_ASSERT(m_errorDevice);
if (file.m_fileInfo.size() > 0xffffffff) {
@@ -730,17 +723,21 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
m_errorDevice->write(msg.toUtf8());
return false;
}
- if (!m_root)
- m_root = new RCCFileInfo(QString(), QFileInfo(), QLocale::C, QLocale::AnyTerritory, RCCFileInfo::Directory);
+ if (!m_root) {
+ m_root = new RCCFileInfo{};
+ m_root->m_flags = RCCFileInfo::Directory;
+ }
RCCFileInfo *parent = m_root;
- const QStringList nodes = alias.split(QLatin1Char('/'));
+ const QStringList nodes = alias.split(u'/');
for (int i = 1; i < nodes.size()-1; ++i) {
const QString node = nodes.at(i);
if (node.isEmpty())
continue;
if (!parent->m_children.contains(node)) {
- RCCFileInfo *s = new RCCFileInfo(node, QFileInfo(), QLocale::C, QLocale::AnyTerritory, RCCFileInfo::Directory);
+ RCCFileInfo *s = new RCCFileInfo{};
+ s->m_name = node;
+ s->m_flags = RCCFileInfo::Directory;
s->m_parent = parent;
parent->m_children.insert(node, s);
parent = s;
@@ -750,14 +747,14 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
}
const QString filename = nodes.at(nodes.size()-1);
- RCCFileInfo *s = new RCCFileInfo(file);
+ RCCFileInfo *s = new RCCFileInfo(std::move(file));
s->m_parent = parent;
auto cbegin = parent->m_children.constFind(filename);
auto cend = parent->m_children.constEnd();
for (auto it = cbegin; it != cend; ++it) {
if (it.key() == filename && it.value()->m_language == s->m_language &&
it.value()->m_territory == s->m_territory) {
- for (const QString &name : qAsConst(m_fileNames)) {
+ for (const QString &name : std::as_const(m_fileNames)) {
qWarning("%s: Warning: potential duplicate alias detected: '%s'",
qPrintable(name), qPrintable(filename));
}
@@ -793,8 +790,8 @@ bool RCCResourceLibrary::readFiles(bool listMode, QIODevice &errorDevice)
QFile fileIn;
QString fname = m_fileNames.at(i);
QString pwd;
- if (fname == QLatin1String("-")) {
- fname = QLatin1String("(stdin)");
+ if (fname == "-"_L1) {
+ fname = "(stdin)"_L1;
pwd = QDir::currentPath();
fileIn.setFileName(fname);
if (!fileIn.open(stdin, QIODevice::ReadOnly)) {
@@ -845,7 +842,7 @@ QStringList RCCResourceLibrary::dataFiles() const
// Determine map of resource identifier (':/newPrefix/images/p1.png') to file via recursion
static void resourceDataFileMapRecursion(const RCCFileInfo *m_root, const QString &path, RCCResourceLibrary::ResourceDataFileMap &m)
{
- const QChar slash = QLatin1Char('/');
+ const QChar slash = u'/';
const auto cend = m_root->m_children.constEnd();
for (auto it = m_root->m_children.constBegin(); it != cend; ++it) {
const RCCFileInfo *child = it.value();
@@ -862,27 +859,27 @@ RCCResourceLibrary::ResourceDataFileMap RCCResourceLibrary::resourceDataFileMap(
{
ResourceDataFileMap rc;
if (m_root)
- resourceDataFileMapRecursion(m_root, QString(QLatin1Char(':')), rc);
+ resourceDataFileMapRecursion(m_root, QString(u':'), rc);
return rc;
}
RCCResourceLibrary::CompressionAlgorithm RCCResourceLibrary::parseCompressionAlgorithm(QStringView value, QString *errorMsg)
{
- if (value == QLatin1String("best"))
+ if (value == "best"_L1)
return CompressionAlgorithm::Best;
- if (value == QLatin1String("zlib")) {
+ if (value == "zlib"_L1) {
#ifdef QT_NO_COMPRESS
- *errorMsg = QLatin1String("zlib support not compiled in");
+ *errorMsg = "zlib support not compiled in"_L1;
#else
return CompressionAlgorithm::Zlib;
#endif
- } else if (value == QLatin1String("zstd")) {
+ } else if (value == "zstd"_L1) {
#if QT_CONFIG(zstd)
return CompressionAlgorithm::Zstd;
#else
- *errorMsg = QLatin1String("Zstandard support not compiled in");
+ *errorMsg = "Zstandard support not compiled in"_L1;
#endif
- } else if (value != QLatin1String("none")) {
+ } else if (value != "none"_L1) {
*errorMsg = QString::fromLatin1("Unknown compression algorithm '%1'").arg(value);
}
@@ -932,13 +929,17 @@ bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &tempDevice, QIO
m_errorDevice->write("No data signature found\n");
return false;
}
+
+ if (c != pattern[i]) {
+ for (int k = 0; k < i; ++k)
+ outDevice.putChar(pattern[k]);
+ i = 0;
+ }
+
if (c == pattern[i]) {
++i;
} else {
- for (int k = 0; k < i; ++k)
- outDevice.putChar(pattern[k]);
outDevice.putChar(c);
- i = 0;
}
}
@@ -1097,6 +1098,10 @@ bool RCCResourceLibrary::writeHeader()
writeString("\n**\n");
writeString("** WARNING! All changes made in this file will be lost!\n");
writeString( "*****************************************************************************/\n\n");
+ writeString("#ifdef _MSC_VER\n"
+ "// disable informational message \"function ... selected for automatic inline expansion\"\n"
+ "#pragma warning (disable: 4711)\n"
+ "#endif\n\n");
break;
case Python_Code:
writeString("# Resource object code (Python 3)\n");
@@ -1348,7 +1353,7 @@ bool RCCResourceLibrary::writeInitializer()
//write("\nQT_BEGIN_NAMESPACE\n");
QString initNameStr = m_initName;
if (!initNameStr.isEmpty()) {
- initNameStr.prepend(QLatin1Char('_'));
+ initNameStr.prepend(u'_');
auto isAsciiLetterOrNumber = [] (QChar c) -> bool {
ushort ch = c.unicode();
return (ch >= '0' && ch <= '9') ||
@@ -1358,7 +1363,7 @@ bool RCCResourceLibrary::writeInitializer()
};
for (QChar &c : initNameStr) {
if (!isAsciiLetterOrNumber(c))
- c = QLatin1Char('_');
+ c = u'_';
}
}
QByteArray initName = initNameStr.toLatin1();
@@ -1377,7 +1382,9 @@ bool RCCResourceLibrary::writeInitializer()
"# define QT_RCC_MANGLE_NAMESPACE(name) name\n"
"#endif\n\n");
- writeString("#ifdef QT_NAMESPACE\n"
+ writeString("#if defined(QT_INLINE_NAMESPACE)\n"
+ "inline namespace QT_NAMESPACE {\n"
+ "#elif defined(QT_NAMESPACE)\n"
"namespace QT_NAMESPACE {\n"
"#endif\n\n");
}
@@ -1478,6 +1485,11 @@ bool RCCResourceLibrary::writeInitializer()
writeString(" return 1;\n");
writeString("}\n\n");
+ // -Wexit-time-destructors was added to clang 3.0.0 in 2011.
+ writeString("#ifdef __clang__\n"
+ "# pragma clang diagnostic push\n"
+ "# pragma clang diagnostic ignored \"-Wexit-time-destructors\"\n"
+ "#endif\n\n");
writeString("namespace {\n"
" struct initializer {\n");
@@ -1490,7 +1502,12 @@ bool RCCResourceLibrary::writeInitializer()
" ~initializer() { " + cleanResources + "(); }\n");
}
writeString(" } dummy;\n"
- "}\n");
+ "}\n\n");
+
+ writeString("#ifdef __clang__\n"
+ "# pragma clang diagnostic pop\n"
+ "#endif\n");
+
} else if (m_format == Binary) {
int i = 4;
diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h
index b6fcb21f5f..60af1c67cf 100644
--- a/src/tools/rcc/rcc.h
+++ b/src/tools/rcc/rcc.h
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// Note: A copy of this file is used in Qt Designer (qttools/src/designer/src/lib/shared/rcc_p.h)
@@ -121,13 +96,14 @@ private:
const QString ATTRIBUTE_LANG;
const QString ATTRIBUTE_PREFIX;
const QString ATTRIBUTE_ALIAS;
+ const QString ATTRIBUTE_EMPTY;
const QString ATTRIBUTE_THRESHOLD;
const QString ATTRIBUTE_COMPRESS;
const QString ATTRIBUTE_COMPRESSALGO;
};
friend class RCCFileInfo;
void reset();
- bool addFile(const QString &alias, const RCCFileInfo &file);
+ bool addFile(const QString &alias, RCCFileInfo file);
bool interpretResourceFile(QIODevice *inputDevice, const QString &file,
QString currentPath = QString(), bool listMode = false);
bool writeHeader();