Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmljsloadergenerator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5
6#include <QByteArray>
7#include <QRegularExpression>
8#include <QString>
9#include <QStringList>
10#include <QTextStream>
11#include <QVector>
12#include <QtEndian>
13#include <QStack>
14#include <QFileInfo>
15#include <QSaveFile>
16
17#include <algorithm>
18
20
36{
38
39 QString mangled;
40 mangled.reserve(str.size());
41
42 int i = 0;
43 if (str.startsWith(QLatin1Char('_')) && str.size() > 1) {
44 QChar ch = str.at(1);
45 if (ch == QLatin1Char('_')
46 || (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z'))) {
47 mangled += QLatin1String("_0x5f_");
48 ++i;
49 }
50 }
51
52 for (int ei = str.size(); i != ei; ++i) {
53 auto c = str.at(i).unicode();
54 if ((c >= QLatin1Char('0') && c <= QLatin1Char('9'))
55 || (c >= QLatin1Char('a') && c <= QLatin1Char('z'))
56 || (c >= QLatin1Char('A') && c <= QLatin1Char('Z'))
57 || c == QLatin1Char('_')) {
58 mangled += QChar(c);
59 } else {
60 mangled += QLatin1String("_0x") + QString::number(c, 16) + QLatin1Char('_');
61 }
62 }
63
64 return mangled;
65}
66
68{
69 QFileInfo fi(relativePath);
70 QString symbol = fi.path();
71 if (symbol.size() == 1 && symbol.startsWith(QLatin1Char('.'))) {
72 symbol.clear();
73 } else {
74 symbol.replace(QLatin1Char('/'), QLatin1Char('_'));
75 symbol += QLatin1Char('_');
76 }
77 symbol += fi.baseName();
78 symbol += QLatin1Char('_');
79 symbol += fi.completeSuffix();
80 return mangledIdentifier(symbol);
81}
82
84{
87 if (name.isEmpty())
88 name = fi.fileName();
90 return name;
91}
92
93bool qQmlJSGenerateLoader(const QStringList &compiledFiles, const QString &outputFileName,
94 const QStringList &resourceFileMappings, QString *errorString)
95{
96 QByteArray generatedLoaderCode;
97
98 {
99 QTextStream stream(&generatedLoaderCode);
100 stream << "#include <QtQml/qqmlprivate.h>\n";
101 stream << "#include <QtCore/qdir.h>\n";
102 stream << "#include <QtCore/qurl.h>\n";
103 stream << "#include <QtCore/qhash.h>\n";
104 stream << "#include <QtCore/qstring.h>\n";
105 stream << "\n";
106
107 stream << "namespace QmlCacheGeneratedCode {\n";
108 for (int i = 0; i < compiledFiles.size(); ++i) {
109 const QString compiledFile = compiledFiles.at(i);
110 const QString ns = qQmlJSSymbolNamespaceForPath(compiledFile);
111 stream << "namespace " << ns << " { \n";
112 stream << " extern const unsigned char qmlData[];\n";
113 stream << " extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[];\n";
114 stream << " const QQmlPrivate::CachedQmlUnit unit = {\n";
115 stream << " reinterpret_cast<const QV4::CompiledData::Unit*>(&qmlData), &aotBuiltFunctions[0], nullptr\n";
116 stream << " };\n";
117 stream << "}\n";
118 }
119
120 stream << "\n}\n";
121 stream << "namespace {\n";
122
123 stream << "struct Registry {\n";
124 stream << " Registry();\n";
125 stream << " ~Registry();\n";
126 stream << " QHash<QString, const QQmlPrivate::CachedQmlUnit*> resourcePathToCachedUnit;\n";
127 stream << " static const QQmlPrivate::CachedQmlUnit *lookupCachedUnit(const QUrl &url);\n";
128 stream << "};\n\n";
129 stream << "Q_GLOBAL_STATIC(Registry, unitRegistry)\n";
130 stream << "\n\n";
131
132 stream << "Registry::Registry() {\n";
133
134 for (int i = 0; i < compiledFiles.size(); ++i) {
135 const QString qrcFile = compiledFiles.at(i);
136 const QString ns = qQmlJSSymbolNamespaceForPath(qrcFile);
137 stream << " resourcePathToCachedUnit.insert(QStringLiteral(\"" << qrcFile << "\"), &QmlCacheGeneratedCode::" << ns << "::unit);\n";
138 }
139
140 stream << " QQmlPrivate::RegisterQmlUnitCacheHook registration;\n";
141 stream << " registration.structVersion = 0;\n";
142 stream << " registration.lookupCachedQmlUnit = &lookupCachedUnit;\n";
143 stream << " QQmlPrivate::qmlregister(QQmlPrivate::QmlUnitCacheHookRegistration, &registration);\n";
144
145 stream << "}\n\n";
146 stream << "Registry::~Registry() {\n";
147 stream << " QQmlPrivate::qmlunregister(QQmlPrivate::QmlUnitCacheHookRegistration, quintptr(&lookupCachedUnit));\n";
148 stream << "}\n\n";
149
150 stream << "const QQmlPrivate::CachedQmlUnit *Registry::lookupCachedUnit(const QUrl &url) {\n";
151 stream << " if (url.scheme() != QLatin1String(\"qrc\"))\n";
152 stream << " return nullptr;\n";
153 stream << " QString resourcePath = QDir::cleanPath(url.path());\n";
154 stream << " if (resourcePath.isEmpty())\n";
155 stream << " return nullptr;\n";
156 stream << " if (!resourcePath.startsWith(QLatin1Char('/')))\n";
157 stream << " resourcePath.prepend(QLatin1Char('/'));\n";
158 stream << " return unitRegistry()->resourcePathToCachedUnit.value(resourcePath, nullptr);\n";
159 stream << "}\n";
160 stream << "}\n";
161
162 for (const QString &mapping: resourceFileMappings) {
163 QString originalResourceFile = mapping;
164 QString newResourceFile;
165 const int mappingSplit = originalResourceFile.indexOf(QLatin1Char('='));
166 if (mappingSplit != -1) {
167 newResourceFile = originalResourceFile.mid(mappingSplit + 1);
168 originalResourceFile.truncate(mappingSplit);
169 }
170
171 const QString suffix = qtResourceNameForFile(originalResourceFile);
172 const QString initFunction = QLatin1String("qInitResources_") + suffix;
173
174 stream << QStringLiteral("int QT_MANGLE_NAMESPACE(%1)() {\n").arg(initFunction);
175 stream << " ::unitRegistry();\n";
176 if (!newResourceFile.isEmpty())
177 stream << " Q_INIT_RESOURCE(" << qtResourceNameForFile(newResourceFile) << ");\n";
178 stream << " return 1;\n";
179 stream << "}\n";
180 stream << "Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(" << initFunction << "))\n";
181
182 const QString cleanupFunction = QLatin1String("qCleanupResources_") + suffix;
183 stream << QStringLiteral("int QT_MANGLE_NAMESPACE(%1)() {\n").arg(cleanupFunction);
184 if (!newResourceFile.isEmpty())
185 stream << " Q_CLEANUP_RESOURCE(" << qtResourceNameForFile(newResourceFile) << ");\n";
186 stream << " return 1;\n";
187 stream << "}\n";
188 }
189 }
190
191#if QT_CONFIG(temporaryfile)
192 QSaveFile f(outputFileName);
193#else
194 QFile f(outputFileName);
195#endif
197 *errorString = f.errorString();
198 return false;
199 }
200
201 if (f.write(generatedLoaderCode) != generatedLoaderCode.size()) {
202 *errorString = f.errorString();
203 return false;
204 }
205
206#if QT_CONFIG(temporaryfile)
207 if (!f.commit()) {
208 *errorString = f.errorString();
209 return false;
210 }
211#endif
212
213 return true;
214}
215
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
\inmodule QtCore
Definition qchar.h:48
constexpr char16_t unicode() const noexcept
Returns the numeric Unicode value of the QChar.
Definition qchar.h:458
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString baseName() const
Returns the base name of the file without the path.
QString completeSuffix() const
Returns the complete suffix (extension) of the file.
QString fileName() const
Returns the name of the file, excluding the path.
QString completeBaseName() const
Returns the complete base name of the file without the path.
QString path() const
Returns the file's path.
\inmodule QtCore
Definition qfile.h:93
\inmodule QtCore \reentrant
\inmodule QtCore
Definition qsavefile.h:24
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3794
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
Definition qstring.h:1173
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6159
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
\inmodule QtCore
QString str
[2]
Combined button and popup list for selecting options.
EGLStreamKHR stream
GLfloat GLfloat f
GLuint name
const GLubyte * c
GLenum GLenum GLenum GLenum mapping
static QString qtResourceNameForFile(const QString &fileName)
bool qQmlJSGenerateLoader(const QStringList &compiledFiles, const QString &outputFileName, const QStringList &resourceFileMappings, QString *errorString)
QT_BEGIN_NAMESPACE QString mangledIdentifier(const QString &str)
QString qQmlJSSymbolNamespaceForPath(const QString &relativePath)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
QFileInfo fi("c:/temp/foo")
[newstuff]
\inmodule QtCore \reentrant
Definition qchar.h:17