source: trunk/src/tools/rcc/rcc.cpp@ 67

Last change on this file since 67 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 31.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "rcc.h"
43
44#include <QtCore/QByteArray>
45#include <QtCore/QDateTime>
46#include <QtCore/QDebug>
47#include <QtCore/QDir>
48#include <QtCore/QDirIterator>
49#include <QtCore/QFile>
50#include <QtCore/QIODevice>
51#include <QtCore/QLocale>
52#include <QtCore/QStack>
53
54#include <QtXml/QDomDocument>
55
56QT_BEGIN_NAMESPACE
57
58enum {
59 CONSTANT_USENAMESPACE = 1,
60 CONSTANT_COMPRESSLEVEL_DEFAULT = -1,
61 CONSTANT_COMPRESSTHRESHOLD_DEFAULT = 70
62};
63
64
65#define writeString(s) write(s, sizeof(s))
66
67void RCCResourceLibrary::write(const char *str, int len)
68{
69 --len; // trailing \0 on string literals...
70 int n = m_out.size();
71 m_out.resize(n + len);
72 memcpy(m_out.data() + n, str, len);
73}
74
75void RCCResourceLibrary::writeByteArray(const QByteArray &other)
76{
77 m_out.append(other);
78}
79
80static inline QString msgOpenReadFailed(const QString &fname, const QString &why)
81{
82 return QString::fromUtf8("Unable to open %1 for reading: %2\n").arg(fname).arg(why);
83}
84
85
86///////////////////////////////////////////////////////////
87//
88// RCCFileInfo
89//
90///////////////////////////////////////////////////////////
91
92class RCCFileInfo
93{
94public:
95 enum Flags
96 {
97 NoFlags = 0x00,
98 Compressed = 0x01,
99 Directory = 0x02
100 };
101
102 RCCFileInfo(const QString &name = QString(), const QFileInfo &fileInfo = QFileInfo(),
103 QLocale::Language language = QLocale::C,
104 QLocale::Country country = QLocale::AnyCountry,
105 uint flags = NoFlags,
106 int compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT,
107 int compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT);
108 ~RCCFileInfo();
109
110 QString resourceName() const;
111
112public:
113 qint64 writeDataBlob(RCCResourceLibrary &lib, qint64 offset, QString *errorMessage);
114 qint64 writeDataName(RCCResourceLibrary &, qint64 offset);
115 void writeDataInfo(RCCResourceLibrary &lib);
116
117 int m_flags;
118 QString m_name;
119 QLocale::Language m_language;
120 QLocale::Country m_country;
121 QFileInfo m_fileInfo;
122 RCCFileInfo *m_parent;
123 QHash<QString, RCCFileInfo*> m_children;
124 int m_compressLevel;
125 int m_compressThreshold;
126
127 qint64 m_nameOffset;
128 qint64 m_dataOffset;
129 qint64 m_childOffset;
130};
131
132RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo,
133 QLocale::Language language, QLocale::Country country, uint flags,
134 int compressLevel, int compressThreshold)
135{
136 m_name = name;
137 m_fileInfo = fileInfo;
138 m_language = language;
139 m_country = country;
140 m_flags = flags;
141 m_parent = 0;
142 m_nameOffset = 0;
143 m_dataOffset = 0;
144 m_childOffset = 0;
145 m_compressLevel = compressLevel;
146 m_compressThreshold = compressThreshold;
147}
148
149RCCFileInfo::~RCCFileInfo()
150{
151 qDeleteAll(m_children);
152}
153
154QString RCCFileInfo::resourceName() const
155{
156 QString resource = m_name;
157 for (RCCFileInfo *p = m_parent; p; p = p->m_parent)
158 resource = resource.prepend(p->m_name + QLatin1Char('/'));
159 return QLatin1Char(':') + resource;
160}
161
162void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
163{
164 const bool text = (lib.m_format == RCCResourceLibrary::C_Code);
165 //some info
166 if (text) {
167 if (m_language != QLocale::C) {
168 lib.writeString(" // ");
169 lib.writeByteArray(resourceName().toLocal8Bit());
170 lib.writeString(" [");
171 lib.writeByteArray(QByteArray::number(m_country));
172 lib.writeString("::");
173 lib.writeByteArray(QByteArray::number(m_language));
174 lib.writeString("[\n ");
175 } else {
176 lib.writeString(" // ");
177 lib.writeByteArray(resourceName().toLocal8Bit());
178 lib.writeString("\n ");
179 }
180 }
181
182 //pointer data
183 if (m_flags & RCCFileInfo::Directory) {
184 // name offset
185 lib.writeNumber4(m_nameOffset);
186
187 // flags
188 lib.writeNumber2(m_flags);
189
190 // child count
191 lib.writeNumber4(m_children.size());
192
193 // first child offset
194 lib.writeNumber4(m_childOffset);
195 } else {
196 // name offset
197 lib.writeNumber4(m_nameOffset);
198
199 // flags
200 lib.writeNumber2(m_flags);
201
202 // locale
203 lib.writeNumber2(m_country);
204 lib.writeNumber2(m_language);
205
206 //data offset
207 lib.writeNumber4(m_dataOffset);
208 }
209 if (text)
210 lib.writeChar('\n');