1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28#include <QString>
29#include <QXmlStreamReader>
30#include <QFile>
31#include <QDir>
32
33int filterResourceFile(const QString &input, const QString &output)
34{
35 enum State {
36 InitialState,
37 InRCC,
38 InResource,
39 InFile
40 };
41 State state = InitialState;
42
43 QString prefix;
44 QString currentFileName;
45 QXmlStreamAttributes fileAttributes;
46
47 QFile file(input);
48 if (!file.open(flags: QIODevice::ReadOnly)) {
49 fprintf(stderr, format: "Cannot open %s for reading.\n", qPrintable(input));
50 return EXIT_FAILURE;
51 }
52
53 QDir inputDirectory = QFileInfo(file).absoluteDir();
54 QDir outputDirectory = QFileInfo(output).absoluteDir();
55
56 QString outputString;
57 QXmlStreamWriter writer(&outputString);
58 writer.setAutoFormatting(true);
59
60 QXmlStreamReader reader(&file);
61 while (!reader.atEnd()) {
62 switch (reader.readNext()) {
63 case QXmlStreamReader::StartDocument: {
64 QStringRef version = reader.documentVersion();
65 if (!version.isEmpty())
66 writer.writeStartDocument(version: version.toString());
67 else
68 writer.writeStartDocument();
69 break;
70 }
71 case QXmlStreamReader::EndDocument:
72 writer.writeEndDocument();
73 break;
74 case QXmlStreamReader::StartElement:
75 if (reader.name() == QStringLiteral("RCC")) {
76 if (state != InitialState) {
77 fprintf(stderr, format: "Unexpected RCC tag in line %d\n", int(reader.lineNumber()));
78 return EXIT_FAILURE;
79 }
80 state = InRCC;
81 } else if (reader.name() == QStringLiteral("qresource")) {
82 if (state != InRCC) {
83 fprintf(stderr, format: "Unexpected qresource tag in line %d\n", int(reader.lineNumber()));
84 return EXIT_FAILURE;
85 }
86 state = InResource;
87 QXmlStreamAttributes attributes = reader.attributes();
88 if (attributes.hasAttribute(QStringLiteral("prefix")))
89 prefix = attributes.value(QStringLiteral("prefix")).toString();
90 if (!prefix.startsWith(c: QLatin1Char('/')))
91 prefix.prepend(c: QLatin1Char('/'));
92 if (!prefix.endsWith(c: QLatin1Char('/')))
93 prefix.append(c: QLatin1Char('/'));
94 } else if (reader.name() == QStringLiteral("file")) {
95 if (state != InResource) {
96 fprintf(stderr, format: "Unexpected file tag in line %d\n", int(reader.lineNumber()));
97 return EXIT_FAILURE;
98 }
99 state = InFile;
100 fileAttributes = reader.attributes();
101 continue;
102 }
103 writer.writeStartElement(qualifiedName: reader.name().toString());
104 writer.writeAttributes(attributes: reader.attributes());
105 continue;
106
107 case QXmlStreamReader::EndElement:
108 if (reader.name() == QStringLiteral("file")) {
109 if (state != InFile) {
110 fprintf(stderr, format: "Unexpected end of file tag in line %d\n", int(reader.lineNumber()));
111 return EXIT_FAILURE;
112 }
113 state = InResource;
114 continue;
115 } else if (reader.name() == QStringLiteral("qresource")) {
116 if (state != InResource) {
117 fprintf(stderr, format: "Unexpected end of qresource tag in line %d\n", int(reader.lineNumber()));
118 return EXIT_FAILURE;
119 }
120 state = InRCC;
121 } else if (reader.name() == QStringLiteral("RCC")) {
122 if (state != InRCC) {
123 fprintf(stderr, format: "Unexpected end of RCC tag in line %d\n", int(reader.lineNumber()));
124 return EXIT_FAILURE;
125 }
126 state = InitialState;
127 }
128 writer.writeEndElement();
129 continue;
130
131 case QXmlStreamReader::Characters:
132 if (reader.isWhitespace())
133 break;
134 if (state != InFile)
135 return EXIT_FAILURE;
136 currentFileName = reader.text().toString();
137 if (currentFileName.isEmpty())
138 continue;
139
140 writer.writeStartElement(QStringLiteral("file"));
141
142 if (!fileAttributes.hasAttribute(QStringLiteral("alias")))
143 fileAttributes.append(QStringLiteral("alias"), value: currentFileName);
144
145 currentFileName = inputDirectory.absoluteFilePath(fileName: currentFileName);
146 currentFileName = outputDirectory.relativeFilePath(fileName: currentFileName);
147
148 writer.writeAttributes(attributes: fileAttributes);
149 writer.writeCharacters(text: currentFileName);
150 writer.writeEndElement();
151 continue;
152
153 default: break;
154 }
155 }
156
157 QFile outputFile(output);
158 if (!outputFile.open(flags: QIODevice::WriteOnly | QIODevice::Truncate)) {
159 fprintf(stderr, format: "Cannot open %s for writing.\n", qPrintable(output));
160 return EXIT_FAILURE;
161 }
162 const QByteArray outputStringUtf8 = outputString.toUtf8();
163 if (outputFile.write(data: outputStringUtf8) != outputStringUtf8.size())
164 return EXIT_FAILURE;
165
166 outputFile.close();
167 if (outputFile.error() != QFileDevice::NoError)
168 return EXIT_FAILURE;
169
170
171 return EXIT_SUCCESS;
172}
173

source code of qtdeclarative/tools/qmlcachegen/resourcefilter.cpp