OpenCoverage

generateloader.cpp

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/tools/qmlcachegen/generateloader.cpp
Switch to Source codePreprocessed file
LineSourceCount
1QString mangledIdentifier(const QString &str)-
2{-
3 ((!str.isEmpty()) ? static_cast<void>(0) : qt_assert("!str.isEmpty()", __FILE__, 54));-
4-
5 QString mangled;-
6 mangled.reserve(str.size());-
7-
8 int i = 0;-
9 if (str.startsWith(QLatin1Char('_'))
str.startsWith...tin1Char('_'))Description
TRUEnever evaluated
FALSEnever evaluated
&& str.size() > 1
str.size() > 1Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
10 QChar ch = str.at(1);-
11 if (ch == QLatin1Char('_')
ch == QLatin1Char('_')Description
TRUEnever evaluated
FALSEnever evaluated
0
12 || (ch >= QLatin1Char('A')
ch >= QLatin1Char('A')Description
TRUEnever evaluated
FALSEnever evaluated
&& ch <= QLatin1Char('Z')
ch <= QLatin1Char('Z')Description
TRUEnever evaluated
FALSEnever evaluated
)) {
0
13 mangled += QLatin1String("_0x5f_");-
14 ++i;-
15 }
never executed: end of block
0
16 }
never executed: end of block
0
17-
18 for (int ei = str.length(); i != ei
i != eiDescription
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
19 auto c = str.at(i).unicode();-
20 if ((c >= QLatin1Char('0')
c >= QLatin1Char('0')Description
TRUEnever evaluated
FALSEnever evaluated
&& c <= QLatin1Char('9')
c <= QLatin1Char('9')Description
TRUEnever evaluated
FALSEnever evaluated
)
0
21 || (c >= QLatin1Char('a')
c >= QLatin1Char('a')Description
TRUEnever evaluated
FALSEnever evaluated
&& c <= QLatin1Char('z')
c <= QLatin1Char('z')Description
TRUEnever evaluated
FALSEnever evaluated
)
0
22 || (c >= QLatin1Char('A')
c >= QLatin1Char('A')Description
TRUEnever evaluated
FALSEnever evaluated
&& c <= QLatin1Char('Z')
c <= QLatin1Char('Z')Description
TRUEnever evaluated
FALSEnever evaluated
)
0
23 || c == QLatin1Char('_')
c == QLatin1Char('_')Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
24 mangled += c;-
25 }
never executed: end of block
else {
0
26 mangled += QLatin1String("_0x") + QString::number(c, 16) + QLatin1Char('_');-
27 }
never executed: end of block
0
28 }-
29-
30 return
never executed: return mangled;
mangled;
never executed: return mangled;
0
31}-
32-
33QString symbolNamespaceForPath(const QString &relativePath)-
34{-
35 QFileInfo fi(relativePath);-
36 QString symbol = fi.path();-
37 if (symbol.length() == 1
symbol.length() == 1Description
TRUEnever evaluated
FALSEnever evaluated
&& symbol.startsWith(QLatin1Char('.'))
symbol.startsW...tin1Char('.'))Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
38 symbol.clear();-
39 }
never executed: end of block
else {
0
40 symbol.replace(QLatin1Char('/'), QLatin1Char('_'));-
41 symbol += QLatin1Char('_');-
42 }
never executed: end of block
0
43 symbol += fi.baseName();-
44 symbol += QLatin1Char('_');-
45 symbol += fi.completeSuffix();-
46 return
never executed: return mangledIdentifier(symbol);
mangledIdentifier(symbol);
never executed: return mangledIdentifier(symbol);
0
47}-
48-
49struct VirtualDirectoryEntry-
50{-
51 QString name;-
52 QVector<VirtualDirectoryEntry*> dirEntries;-
53 int firstChildIndex = -1;-
54 bool isDirectory = true;-
55-
56 VirtualDirectoryEntry()-
57 {}-
58-
59 ~VirtualDirectoryEntry()-
60 {-
61 qDeleteAll(dirEntries);-
62 }
never executed: end of block
0
63-
64 VirtualDirectoryEntry *append(const QString &name)-
65 {-
66 for (QVector<VirtualDirectoryEntry*>::Iterator it = dirEntries.begin(), end = dirEntries.end();-
67 it != end
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
; ++it) {
0
68 if ((*
(*it)->name == nameDescription
TRUEnever evaluated
FALSEnever evaluated
it)->name == name
(*it)->name == nameDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
69 return
never executed: return *it;
*it;
never executed: return *it;
0
70 }
never executed: end of block
0
71-
72 VirtualDirectoryEntry *subEntry = new VirtualDirectoryEntry;-
73 subEntry->name = name;-
74 dirEntries.append(subEntry);-
75 return
never executed: return subEntry;
subEntry;
never executed: return subEntry;
0
76 }-
77-
78 void appendEmptyFile(const QString &name)-
79 {-
80 VirtualDirectoryEntry *subEntry = new VirtualDirectoryEntry;-
81 subEntry->name = name;-
82 subEntry->isDirectory = false;-
83 dirEntries.append(subEntry);-
84 }
never executed: end of block
0
85-
86 bool isEmpty() const { return
never executed: return dirEntries.isEmpty();
dirEntries.isEmpty();
never executed: return dirEntries.isEmpty();
}
0
87};-
88-
89struct DataStream-
90{-
91 DataStream(QVector<unsigned char > *data = nullptr)-
92 : data(data)-
93 {}
never executed: end of block
0
94-
95 qint64 currentOffset() const { return
never executed: return data->size();
data->size();
never executed: return data->size();
}
0
96-
97 DataStream &operator<<(quint16 value)-
98 {-
99 unsigned char d[2];-
100 qToBigEndian(value, d);-
101 data->append(d[0]);-
102 data->append(d[1]);-
103 return
never executed: return *this;
*this;
never executed: return *this;
0
104 }-
105 DataStream &operator<<(quint32 value)-
106 {-
107 unsigned char d[4];-
108 qToBigEndian(value, d);-
109 data->append(d[0]);-
110 data->append(d[1]);-
111 data->append(d[2]);-
112 data->append(d[3]);-
113 return
never executed: return *this;
*this;
never executed: return *this;
0
114 }-
115private:-
116 QVector<unsigned char> *data;-
117};-
118-
119static bool resource_sort_order(const VirtualDirectoryEntry *lhs, const VirtualDirectoryEntry *rhs)-
120{-
121 return
never executed: return qt_hash(lhs->name) < qt_hash(rhs->name);
qt_hash(lhs->name) < qt_hash(rhs->name);
never executed: return qt_hash(lhs->name) < qt_hash(rhs->name);
0
122}-
123-
124struct ResourceTree-
125{-
126 ResourceTree()-
127 {}-
128-
129 void serialize(VirtualDirectoryEntry &root, QVector<unsigned char> *treeData, QVector<unsigned char> *stringData)-
130 {-
131 treeStream = DataStream(treeData);-
132 stringStream = DataStream(stringData);-
133-
134 QStack<VirtualDirectoryEntry *> directories;-
135-
136 {-
137 directories.push(&root);-
138 while (!directories.isEmpty()
!directories.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
139 VirtualDirectoryEntry *entry = directories.pop();-
140 registerString(entry->name);-
141 if (entry->isDirectory
entry->isDirectoryDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
142 directories << entry->dirEntries;
never executed: directories << entry->dirEntries;
0
143 }
never executed: end of block
0
144 }-
145-
146 {-
147 quint32 currentDirectoryIndex = 1;-
148 directories.push(&root);-
149 while (!directories.isEmpty()
!directories.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
150 VirtualDirectoryEntry *entry = directories.pop();-
151 entry->firstChildIndex = currentDirectoryIndex;-
152 currentDirectoryIndex += entry->dirEntries.count();-
153 std::sort(entry->dirEntries.begin(), entry->dirEntries.end(), resource_sort_order);-
154-
155 for (QVector<VirtualDirectoryEntry*>::ConstIterator child = entry->dirEntries.constBegin(), end = entry->dirEntries.constEnd();-
156 child != end
child != endDescription
TRUEnever evaluated
FALSEnever evaluated
; ++child) {
0
157 if ((*
(*child)->isDirectoryDescription
TRUEnever evaluated
FALSEnever evaluated
child)->isDirectory
(*child)->isDirectoryDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
158 directories << *child;
never executed: directories << *child;
0
159 }
never executed: end of block
0
160 }
never executed: end of block
0
161 }-
162-
163 {-
164 writeTreeEntry(&root);-
165 directories.push(&root);-
166 while (!directories.isEmpty()
!directories.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
167 VirtualDirectoryEntry *entry = directories.pop();-
168-
169 for (QVector<VirtualDirectoryEntry*>::ConstIterator child = entry->dirEntries.constBegin(), end = entry->dirEntries.constEnd();-
170 child != end
child != endDescription
TRUEnever evaluated
FALSEnever evaluated
; ++child) {
0
171 writeTreeEntry(*child);-
172 if ((*
(*child)->isDirectoryDescription
TRUEnever evaluated
FALSEnever evaluated
child)->isDirectory
(*child)->isDirectoryDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
173 directories << (*child);
never executed: directories << (*child);
0
174 }
never executed: end of block
0
175 }
never executed: end of block
0
176 }-
177 }
never executed: end of block
0
178-
179private:-
180 DataStream treeStream;-
181 DataStream stringStream;-
182 QHash<QString, qint64> stringOffsets;-
183-
184 void registerString(const QString &name)-
185 {-
186 if (stringOffsets.contains(name)
stringOffsets.contains(name)Description
TRUEnever evaluated
FALSEnever evaluated
)
0
187 return;
never executed: return;
0
188 const qint64 offset = stringStream.currentOffset();-
189 stringOffsets.insert(name, offset);-
190-
191 stringStream << quint16(name.length())-
192 << quint32(qt_hash(name));-
193 for (int i = 0; i < name.length()
i < name.length()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i)
0
194 stringStream << quint16(name.at(i).unicode());
never executed: stringStream << quint16(name.at(i).unicode());
0
195 }
never executed: end of block
0
196-
197 void writeTreeEntry(VirtualDirectoryEntry *entry)-
198 {-
199 treeStream << quint32(stringOffsets.value(entry->name))-
200 << quint16(entry->isDirectory ? 0x2 : 0x0);-
201-
202 if (entry->isDirectory
entry->isDirectoryDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
203 treeStream << quint32(entry->dirEntries.count())-
204 << quint32(entry->firstChildIndex);-
205 }
never executed: end of block
else {
0
206 treeStream << quint16(QLocale::AnyCountry) << quint16(QLocale::C)-
207 << quint32(0x0);-
208 }
never executed: end of block
0
209 }-
210};-
211-
212static QByteArray generateResourceDirectoryTree(QTextStream &code, const QStringList &qrcFiles)-
213{-
214 QByteArray call;-
215 if (qrcFiles.isEmpty()
qrcFiles.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
216 return
never executed: return call;
call;
never executed: return call;
0
217-
218 VirtualDirectoryEntry resourceDirs;-
219 resourceDirs.name = ([]() noexcept -> QString { enum { Size = sizeof(u"" "/")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "/" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }());-
220-
221 for (auto _container_ = QtPrivate::qMakeForeachContainer(qrcFiles); _container_.control
_container_.controlDescription
TRUEnever evaluated
FALSEnever evaluated
&& _container_.i != _container_.e
_container_.i != _container_.eDescription
TRUEnever evaluated
FALSEnever evaluated
; ++_container_.i, _container_.control ^= 1) for (const QString &entry = *_container_.i; _container_.control
_container_.controlDescription
TRUEnever evaluated
FALSEnever evaluated
; _container_.control = 0) {
0
222 const QStringList segments = entry.split(QLatin1Char('/'), QString::SkipEmptyParts);-
223-
224 VirtualDirectoryEntry *dirEntry = &resourceDirs;-
225-
226 for (int i = 0; i < segments.count() - 1
i < segments.count() - 1Description
TRUEnever evaluated
FALSEnever evaluated
; ++i)
0
227 dirEntry = dirEntry->append(segments.at(i));
never executed: dirEntry = dirEntry->append(segments.at(i));
0
228 dirEntry->appendEmptyFile(segments.last());-
229 }
never executed: end of block
0
230-
231 if (resourceDirs.isEmpty()
resourceDirs.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
232 return
never executed: return call;
call;
never executed: return call;
0
233-
234 QVector<unsigned char> names;-
235 QVector<unsigned char> tree;-
236 ResourceTree().serialize(resourceDirs, &tree, &names);-
237-
238 code << "static const unsigned char qt_resource_tree[] = {\n";-
239 for (int i = 0; i < tree.count()
i < tree.count()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
240 code << uint(tree.at(i));-
241 if (i < tree.count() - 1
i < tree.count() - 1Description
TRUEnever evaluated
FALSEnever evaluated
)
0
242 code << ',';
never executed: code << ',';
0
243 if (i % 16 == 0
i % 16 == 0Description
TRUEnever evaluated
FALSEnever evaluated
)
0
244 code << '\n';
never executed: code << '\n';
0
245 }
never executed: end of block
0
246 code << "};\n";-
247-
248 code << "static const unsigned char qt_resource_names[] = {\n";-
249 for (int i = 0; i < names.count()
i < names.count()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
250 code << uint(names.at(i));-
251 if (i < names.count() - 1
i < names.count() - 1Description
TRUEnever evaluated
FALSEnever evaluated
)
0
252 code << ',';
never executed: code << ',';
0
253 if (i % 16 == 0
i % 16 == 0Description
TRUEnever evaluated
FALSEnever evaluated
)
0
254 code << '\n';
never executed: code << '\n';
0
255 }
never executed: end of block
0
256 code << "};\n";-
257-
258 code << "static const unsigned char qt_resource_empty_payout[] = { 0, 0, 0, 0, 0 };\n";-
259-
260 code << "QT_BEGIN_NAMESPACE\n";-
261 code << "extern Q_CORE_EXPORT bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);\n";-
262 code << "QT_END_NAMESPACE\n";-
263-
264 call = "QT_PREPEND_NAMESPACE(qRegisterResourceData)(/*version*/0x01, qt_resource_tree, qt_resource_names, qt_resource_empty_payout);\n";-
265-
266 return
never executed: return call;
call;
never executed: return call;
0
267}-
268-
269static QString qtResourceNameForFile(const QString &fileName)-
270{-
271 QFileInfo fi(fileName);-
272 QString name = fi.completeBaseName();-
273 if (name.isEmpty()
name.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
274 name = fi.fileName();
never executed: name = fi.fileName();
0
275 name.replace(QRegExp(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));-
276 return
never executed: return name;
name;
never executed: return name;
0
277}-
278-
279bool generateLoader(const QStringList &compiledFiles, const QString &outputFileName, const QStringList &resourceFileMappings, QString *errorString)-
280{-
281 QByteArray generatedLoaderCode;-
282-
283 {-
284 QTextStream stream(&generatedLoaderCode);-
285 stream << "#include <QtQml/qqmlprivate.h>\n";-
286 stream << "#include <QtCore/qdir.h>\n";-
287 stream << "#include <QtCore/qurl.h>\n";-
288 stream << "\n";-
289-
290 QByteArray resourceRegisterCall = generateResourceDirectoryTree(stream, compiledFiles);-
291-
292 stream << "namespace QmlCacheGeneratedCode {\n";-
293 for (int i = 0; i < compiledFiles.count()
i < compiledFiles.count()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
294 const QString compiledFile = compiledFiles.at(i);-
295 const QString ns = symbolNamespaceForPath(compiledFile);-
296 stream << "namespace " << symbolNamespaceForPath(compiledFile) << " { \n";-
297 stream << " extern const unsigned char qmlData[];\n";-
298 stream << " const QQmlPrivate::CachedQmlUnit unit = {\n";-
299 stream << " reinterpret_cast<const QV4::CompiledData::Unit*>(&qmlData), nullptr, nullptr\n";-
300 stream << " };\n";-
301 stream << "}\n";-
302 }
never executed: end of block
0
303-
304 stream << "\n}\n";-
305 stream << "namespace {\n";-
306-
307 stream << "struct Registry {\n";-
308 stream << " Registry();\n";-
309 stream << " QHash<QString, const QQmlPrivate::CachedQmlUnit*> resourcePathToCachedUnit;\n";-
310 stream << " static const QQmlPrivate::CachedQmlUnit *lookupCachedUnit(const QUrl &url);\n";-
311 stream << "};\n\n";-
312 stream << "Q_GLOBAL_STATIC(Registry, unitRegistry)\n";-
313 stream << "\n\n";-
314-
315 stream << "Registry::Registry() {\n";-
316-
317 for (int i = 0; i < compiledFiles.count()
i < compiledFiles.count()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
318 const QString qrcFile = compiledFiles.at(i);-
319 const QString ns = symbolNamespaceForPath(qrcFile);-
320 stream << " resourcePathToCachedUnit.insert(QStringLiteral(\"" << qrcFile << "\"), &QmlCacheGeneratedCode::" << ns << "::unit);\n";-
321 }
never executed: end of block
0
322-
323 stream << " QQmlPrivate::RegisterQmlUnitCacheHook registration;\n";-
324 stream << " registration.version = 0;\n";-
325 stream << " registration.lookupCachedQmlUnit = &lookupCachedUnit;\n";-
326 stream << " QQmlPrivate::qmlregister(QQmlPrivate::QmlUnitCacheHookRegistration, &registration);\n";-
327-
328 if (!resourceRegisterCall.isEmpty()
!resourceRegis...Call.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
329 stream << resourceRegisterCall;
never executed: stream << resourceRegisterCall;
0
330-
331 stream << "}\n";-
332 stream << "const QQmlPrivate::CachedQmlUnit *Registry::lookupCachedUnit(const QUrl &url) {\n";-
333 stream << " if (url.scheme() != QLatin1String(\"qrc\"))\n";-
334 stream << " return nullptr;\n";-
335 stream << " QString resourcePath = QDir::cleanPath(url.path());\n";-
336 stream << " if (resourcePath.isEmpty())\n";-
337 stream << " return nullptr;\n";-
338 stream << " if (!resourcePath.startsWith(QLatin1Char('/')))\n";-
339 stream << " resourcePath.prepend(QLatin1Char('/'));\n";-
340 stream << " return unitRegistry()->resourcePathToCachedUnit.value(resourcePath, nullptr);\n";-
341 stream << "}\n";-
342 stream << "}\n";-
343-
344 for (const QString &mapping: resourceFileMappings) {-
345 QString originalResourceFile = mapping;-
346 QString newResourceFile;-
347 const int mappingSplit = originalResourceFile.indexOf(QLatin1Char('='));-
348 if (mappingSplit != -1
mappingSplit != -1Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
349 newResourceFile = originalResourceFile.mid(mappingSplit + 1);-
350 originalResourceFile.truncate(mappingSplit);-
351 }
never executed: end of block
0
352-
353 const QString suffix = qtResourceNameForFile(originalResourceFile);-
354 const QString initFunction = QLatin1String("qInitResources_") + suffix;-
355-
356 stream << ([]() noexcept -> QString { enum { Size = sizeof(u"" "int QT_MANGLE_NAMESPACE(%1)() {\n")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "int QT_MANGLE_NAMESPACE(%1)() {\n" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return
never executed: return qstring_literal_temp;
qstring_literal_temp;
never executed: return qstring_literal_temp;
}()).arg(initFunction);
0
357 stream << " ::unitRegistry();\n";-
358 if (!newResourceFile.isEmpty()
!newResourceFile.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
359 stream << " Q_INIT_RESOURCE(" << qtResourceNameForFile(newResourceFile) << ");\n";
never executed: stream << " Q_INIT_RESOURCE(" << qtResourceNameForFile(newResourceFile) << ");\n";
0
360 stream << " return 1;\n";-
361 stream << "}\n";-
362 stream << "Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(" << initFunction << "))\n";-
363-
364 const QString cleanupFunction = QLatin1String("qCleanupResources_") + suffix;-
365 stream << ([]() noexcept -> QString { enum { Size = sizeof(u"" "int QT_MANGLE_NAMESPACE(%1)() {\n")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "int QT_MANGLE_NAMESPACE(%1)() {\n" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return
never executed: return qstring_literal_temp;
qstring_literal_temp;
never executed: return qstring_literal_temp;
}()).arg(cleanupFunction);
0
366 if (!newResourceFile.isEmpty()
!newResourceFile.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
367 stream << " Q_CLEANUP_RESOURCE(" << qtResourceNameForFile(newResourceFile) << ");\n";
never executed: stream << " Q_CLEANUP_RESOURCE(" << qtResourceNameForFile(newResourceFile) << ");\n";
0
368 stream << " return 1;\n";-
369 stream << "}\n";-
370 }
never executed: end of block
0
371 }-
372-
373 QSaveFile f(outputFileName);-
374 if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)
!f.open(QIODev...ice::Truncate)Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
375 *errorString = f.errorString();-
376 return
never executed: return false;
false;
never executed: return false;
0
377 }-
378-
379 if (f.write(generatedLoaderCode) != generatedLoaderCode.size()
f.write(genera...derCode.size()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
380 *errorString = f.errorString();-
381 return
never executed: return false;
false;
never executed: return false;
0
382 }-
383-
384 if (!f.commit()
!f.commit()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
385 *errorString = f.errorString();-
386 return
never executed: return false;
false;
never executed: return false;
0
387 }-
388-
389 return
never executed: return true;
true;
never executed: return true;
0
390}-
Switch to Source codePreprocessed file

Generated by Squish Coco 4.2.0