ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/s10k/CommonLibs/quazip-0.7.2/quazip/quazipdir.cpp
Revision: 1096
Committed: Sat Dec 30 14:40:33 2017 UTC (7 years, 9 months ago) by s10k
Content type: text/x-c++src
File size: 16881 byte(s)
Log Message:
Added zlib, quazip, basicxmlsyntaxhighlighter, conditionalsemaphore and linenumberdisplay libraries. zlib and quazip are pre-compiled, but you can compile them yourself, just delete the dll files (or equivalent binary files to your OS)

File Contents

# Content
1 /*
2 Copyright (C) 2005-2014 Sergey A. Tachenov
3
4 This file is part of QuaZIP.
5
6 QuaZIP is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10
11 QuaZIP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with QuaZIP. If not, see <http://www.gnu.org/licenses/>.
18
19 See COPYING file for the full LGPL text.
20
21 Original ZIP package is copyrighted by Gilles Vollant and contributors,
22 see quazip/(un)zip.h files for details. Basically it's the zlib license.
23 */
24
25 #include "quazipdir.h"
26
27 #include <QSet>
28 #include <QSharedData>
29
30 /// \cond internal
31 class QuaZipDirPrivate: public QSharedData {
32 friend class QuaZipDir;
33 private:
34 QuaZipDirPrivate(QuaZip *zip, const QString &dir = QString()):
35 zip(zip), dir(dir), caseSensitivity(QuaZip::csDefault),
36 filter(QDir::NoFilter), sorting(QDir::NoSort) {}
37 QuaZip *zip;
38 QString dir;
39 QuaZip::CaseSensitivity caseSensitivity;
40 QDir::Filters filter;
41 QStringList nameFilters;
42 QDir::SortFlags sorting;
43 template<typename TFileInfoList>
44 bool entryInfoList(QStringList nameFilters, QDir::Filters filter,
45 QDir::SortFlags sort, TFileInfoList &result) const;
46 inline QString simplePath() const {return QDir::cleanPath(dir);}
47 };
48 /// \endcond
49
50 QuaZipDir::QuaZipDir(const QuaZipDir &that):
51 d(that.d)
52 {
53 }
54
55 QuaZipDir::QuaZipDir(QuaZip *zip, const QString &dir):
56 d(new QuaZipDirPrivate(zip, dir))
57 {
58 if (d->dir.startsWith('/'))
59 d->dir = d->dir.mid(1);
60 }
61
62 QuaZipDir::~QuaZipDir()
63 {
64 }
65
66 bool QuaZipDir::operator==(const QuaZipDir &that)
67 {
68 return d->zip == that.d->zip && d->dir == that.d->dir;
69 }
70
71 QuaZipDir& QuaZipDir::operator=(const QuaZipDir &that)
72 {
73 this->d = that.d;
74 return *this;
75 }
76
77 QString QuaZipDir::operator[](int pos) const
78 {
79 return entryList().at(pos);
80 }
81
82 QuaZip::CaseSensitivity QuaZipDir::caseSensitivity() const
83 {
84 return d->caseSensitivity;
85 }
86
87 bool QuaZipDir::cd(const QString &directoryName)
88 {
89 if (directoryName == "/") {
90 d->dir = "";
91 return true;
92 }
93 QString dirName = directoryName;
94 if (dirName.endsWith('/'))
95 dirName.chop(1);
96 if (dirName.contains('/')) {
97 QuaZipDir dir(*this);
98 if (dirName.startsWith('/')) {
99 #ifdef QUAZIP_QUAZIPDIR_DEBUG
100 qDebug("QuaZipDir::cd(%s): going to /",
101 dirName.toUtf8().constData());
102 #endif
103 if (!dir.cd("/"))
104 return false;
105 }
106 QStringList path = dirName.split('/', QString::SkipEmptyParts);
107 for (QStringList::const_iterator i = path.constBegin();
108 i != path.end();
109 ++i) {
110 const QString &step = *i;
111 #ifdef QUAZIP_QUAZIPDIR_DEBUG
112 qDebug("QuaZipDir::cd(%s): going to %s",
113 dirName.toUtf8().constData(),
114 step.toUtf8().constData());
115 #endif
116 if (!dir.cd(step))
117 return false;
118 }
119 d->dir = dir.path();
120 return true;
121 } else { // no '/'
122 if (dirName == ".") {
123 return true;
124 } else if (dirName == "..") {
125 if (isRoot()) {
126 return false;
127 } else {
128 int slashPos = d->dir.lastIndexOf('/');
129 if (slashPos == -1) {
130 d->dir = "";
131 } else {
132 d->dir = d->dir.left(slashPos);
133 }
134 return true;
135 }
136 } else { // a simple subdirectory
137 if (exists(dirName)) {
138 if (isRoot())
139 d->dir = dirName;
140 else
141 d->dir += "/" + dirName;
142 return true;
143 } else {
144 return false;
145 }
146 }
147 }
148 }
149
150 bool QuaZipDir::cdUp()
151 {
152 return cd("..");
153 }
154
155 uint QuaZipDir::count() const
156 {
157 return entryList().count();
158 }
159
160 QString QuaZipDir::dirName() const
161 {
162 return QDir(d->dir).dirName();
163 }
164
165 QuaZipFileInfo64 QuaZipDir_getFileInfo(QuaZip *zip, bool *ok,
166 const QString &relativeName,
167 bool isReal)
168 {
169 QuaZipFileInfo64 info;
170 if (isReal) {
171 *ok = zip->getCurrentFileInfo(&info);
172 } else {
173 *ok = true;
174 info.compressedSize = 0;
175 info.crc = 0;
176 info.diskNumberStart = 0;
177 info.externalAttr = 0;
178 info.flags = 0;
179 info.internalAttr = 0;
180 info.method = 0;
181 info.uncompressedSize = 0;
182 info.versionCreated = info.versionNeeded = 0;
183 }
184 info.name = relativeName;
185 return info;
186 }
187
188 static void QuaZipDir_convertInfoList(const QList<QuaZipFileInfo64> &from,
189 QList<QuaZipFileInfo64> &to)
190 {
191 to = from;
192 }
193
194 static void QuaZipDir_convertInfoList(const QList<QuaZipFileInfo64> &from,
195 QStringList &to)
196 {
197 to.clear();
198 for (QList<QuaZipFileInfo64>::const_iterator i = from.constBegin();
199 i != from.constEnd();
200 ++i) {
201 to.append(i->name);
202 }
203 }
204
205 static void QuaZipDir_convertInfoList(const QList<QuaZipFileInfo64> &from,
206 QList<QuaZipFileInfo> &to)
207 {
208 to.clear();
209 for (QList<QuaZipFileInfo64>::const_iterator i = from.constBegin();
210 i != from.constEnd();
211 ++i) {
212 QuaZipFileInfo info32;
213 i->toQuaZipFileInfo(info32);
214 to.append(info32);
215 }
216 }
217
218 /// \cond internal
219 /**
220 An utility class to restore the current file.
221 */
222 class QuaZipDirRestoreCurrent {
223 public:
224 inline QuaZipDirRestoreCurrent(QuaZip *zip):
225 zip(zip), currentFile(zip->getCurrentFileName()) {}
226 inline ~QuaZipDirRestoreCurrent()
227 {
228 zip->setCurrentFile(currentFile);
229 }
230 private:
231 QuaZip *zip;
232 QString currentFile;
233 };
234 /// \endcond
235
236 /// \cond internal
237 class QuaZipDirComparator
238 {
239 private:
240 QDir::SortFlags sort;
241 static QString getExtension(const QString &name);
242 int compareStrings(const QString &string1, const QString &string2);
243 public:
244 inline QuaZipDirComparator(QDir::SortFlags sort): sort(sort) {}
245 bool operator()(const QuaZipFileInfo64 &info1, const QuaZipFileInfo64 &info2);
246 };
247
248 QString QuaZipDirComparator::getExtension(const QString &name)
249 {
250 if (name.endsWith('.') || name.indexOf('.', 1) == -1) {
251 return "";
252 } else {
253 return name.mid(name.lastIndexOf('.') + 1);
254 }
255
256 }
257
258 int QuaZipDirComparator::compareStrings(const QString &string1,
259 const QString &string2)
260 {
261 if (sort & QDir::LocaleAware) {
262 if (sort & QDir::IgnoreCase) {
263 return string1.toLower().localeAwareCompare(string2.toLower());
264 } else {
265 return string1.localeAwareCompare(string2);
266 }
267 } else {
268 return string1.compare(string2, (sort & QDir::IgnoreCase)
269 ? Qt::CaseInsensitive : Qt::CaseSensitive);
270 }
271 }
272
273 bool QuaZipDirComparator::operator()(const QuaZipFileInfo64 &info1,
274 const QuaZipFileInfo64 &info2)
275 {
276 QDir::SortFlags order = sort
277 & (QDir::Name | QDir::Time | QDir::Size | QDir::Type);
278 if ((sort & QDir::DirsFirst) == QDir::DirsFirst
279 || (sort & QDir::DirsLast) == QDir::DirsLast) {
280 if (info1.name.endsWith('/') && !info2.name.endsWith('/'))
281 return (sort & QDir::DirsFirst) == QDir::DirsFirst;
282 else if (!info1.name.endsWith('/') && info2.name.endsWith('/'))
283 return (sort & QDir::DirsLast) == QDir::DirsLast;
284 }
285 bool result;
286 int extDiff;
287 switch (order) {
288 case QDir::Name:
289 result = compareStrings(info1.name, info2.name) < 0;
290 break;
291 case QDir::Type:
292 extDiff = compareStrings(getExtension(info1.name),
293 getExtension(info2.name));
294 if (extDiff == 0) {
295 result = compareStrings(info1.name, info2.name) < 0;
296 } else {
297 result = extDiff < 0;
298 }
299 break;
300 case QDir::Size:
301 if (info1.uncompressedSize == info2.uncompressedSize) {
302 result = compareStrings(info1.name, info2.name) < 0;
303 } else {
304 result = info1.uncompressedSize < info2.uncompressedSize;
305 }
306 break;
307 case QDir::Time:
308 if (info1.dateTime == info2.dateTime) {
309 result = compareStrings(info1.name, info2.name) < 0;
310 } else {
311 result = info1.dateTime < info2.dateTime;
312 }
313 break;
314 default:
315 qWarning("QuaZipDirComparator(): Invalid sort mode 0x%2X",
316 static_cast<unsigned>(sort));
317 return false;
318 }
319 return (sort & QDir::Reversed) ? !result : result;
320 }
321
322 template<typename TFileInfoList>
323 bool QuaZipDirPrivate::entryInfoList(QStringList nameFilters,
324 QDir::Filters filter, QDir::SortFlags sort, TFileInfoList &result) const
325 {
326 QString basePath = simplePath();
327 if (!basePath.isEmpty())
328 basePath += "/";
329 int baseLength = basePath.length();
330 result.clear();
331 QuaZipDirRestoreCurrent saveCurrent(zip);
332 if (!zip->goToFirstFile()) {
333 return zip->getZipError() == UNZ_OK;
334 }
335 QDir::Filters fltr = filter;
336 if (fltr == QDir::NoFilter)
337 fltr = this->filter;
338 if (fltr == QDir::NoFilter)
339 fltr = QDir::AllEntries;
340 QStringList nmfltr = nameFilters;
341 if (nmfltr.isEmpty())
342 nmfltr = this->nameFilters;
343 QSet<QString> dirsFound;
344 QList<QuaZipFileInfo64> list;
345 do {
346 QString name = zip->getCurrentFileName();
347 if (!name.startsWith(basePath))
348 continue;
349 QString relativeName = name.mid(baseLength);
350 if (relativeName.isEmpty())
351 continue;
352 bool isDir = false;
353 bool isReal = true;
354 if (relativeName.contains('/')) {
355 int indexOfSlash = relativeName.indexOf('/');
356 // something like "subdir/"
357 isReal = indexOfSlash == relativeName.length() - 1;
358 relativeName = relativeName.left(indexOfSlash + 1);
359 if (dirsFound.contains(relativeName))
360 continue;
361 isDir = true;
362 }
363 dirsFound.insert(relativeName);
364 if ((fltr & QDir::Dirs) == 0 && isDir)
365 continue;
366 if ((fltr & QDir::Files) == 0 && !isDir)
367 continue;
368 if (!nmfltr.isEmpty() && !QDir::match(nmfltr, relativeName))
369 continue;
370 bool ok;
371 QuaZipFileInfo64 info = QuaZipDir_getFileInfo(zip, &ok, relativeName,
372 isReal);
373 if (!ok) {
374 return false;
375 }
376 list.append(info);
377 } while (zip->goToNextFile());
378 QDir::SortFlags srt = sort;
379 if (srt == QDir::NoSort)
380 srt = sorting;
381 #ifdef QUAZIP_QUAZIPDIR_DEBUG
382 qDebug("QuaZipDirPrivate::entryInfoList(): before sort:");
383 foreach (QuaZipFileInfo64 info, list) {
384 qDebug("%s\t%s", info.name.toUtf8().constData(),
385 info.dateTime.toString(Qt::ISODate).toUtf8().constData());
386 }
387 #endif
388 if (srt != QDir::NoSort && (srt & QDir::Unsorted) != QDir::Unsorted) {
389 if (QuaZip::convertCaseSensitivity(caseSensitivity)
390 == Qt::CaseInsensitive)
391 srt |= QDir::IgnoreCase;
392 QuaZipDirComparator lessThan(srt);
393 qSort(list.begin(), list.end(), lessThan);
394 }
395 QuaZipDir_convertInfoList(list, result);
396 return true;
397 }
398
399 /// \endcond
400
401 QList<QuaZipFileInfo> QuaZipDir::entryInfoList(const QStringList &nameFilters,
402 QDir::Filters filters, QDir::SortFlags sort) const
403 {
404 QList<QuaZipFileInfo> result;
405 if (d->entryInfoList(nameFilters, filters, sort, result))
406 return result;
407 else
408 return QList<QuaZipFileInfo>();
409 }
410
411 QList<QuaZipFileInfo> QuaZipDir::entryInfoList(QDir::Filters filters,
412 QDir::SortFlags sort) const
413 {
414 return entryInfoList(QStringList(), filters, sort);
415 }
416
417 QList<QuaZipFileInfo64> QuaZipDir::entryInfoList64(const QStringList &nameFilters,
418 QDir::Filters filters, QDir::SortFlags sort) const
419 {
420 QList<QuaZipFileInfo64> result;
421 if (d->entryInfoList(nameFilters, filters, sort, result))
422 return result;
423 else
424 return QList<QuaZipFileInfo64>();
425 }
426
427 QList<QuaZipFileInfo64> QuaZipDir::entryInfoList64(QDir::Filters filters,
428 QDir::SortFlags sort) const
429 {
430 return entryInfoList64(QStringList(), filters, sort);
431 }
432
433 QStringList QuaZipDir::entryList(const QStringList &nameFilters,
434 QDir::Filters filters, QDir::SortFlags sort) const
435 {
436 QStringList result;
437 if (d->entryInfoList(nameFilters, filters, sort, result))
438 return result;
439 else
440 return QStringList();
441 }
442
443 QStringList QuaZipDir::entryList(QDir::Filters filters,
444 QDir::SortFlags sort) const
445 {
446 return entryList(QStringList(), filters, sort);
447 }
448
449 bool QuaZipDir::exists(const QString &filePath) const
450 {
451 if (filePath == "/" || filePath.isEmpty())
452 return true;
453 QString fileName = filePath;
454 if (fileName.endsWith('/'))
455 fileName.chop(1);
456 if (fileName.contains('/')) {
457 QFileInfo fileInfo(fileName);
458 #ifdef QUAZIP_QUAZIPDIR_DEBUG
459 qDebug("QuaZipDir::exists(): fileName=%s, fileInfo.fileName()=%s, "
460 "fileInfo.path()=%s", fileName.toUtf8().constData(),
461 fileInfo.fileName().toUtf8().constData(),
462 fileInfo.path().toUtf8().constData());
463 #endif
464 QuaZipDir dir(*this);
465 return dir.cd(fileInfo.path()) && dir.exists(fileInfo.fileName());
466 } else {
467 if (fileName == "..") {
468 return !isRoot();
469 } else if (fileName == ".") {
470 return true;
471 } else {
472 QStringList entries = entryList(QDir::AllEntries, QDir::NoSort);
473 #ifdef QUAZIP_QUAZIPDIR_DEBUG
474 qDebug("QuaZipDir::exists(): looking for %s",
475 fileName.toUtf8().constData());
476 for (QStringList::const_iterator i = entries.constBegin();
477 i != entries.constEnd();
478 ++i) {
479 qDebug("QuaZipDir::exists(): entry: %s",
480 i->toUtf8().constData());
481 }
482 #endif
483 Qt::CaseSensitivity cs = QuaZip::convertCaseSensitivity(
484 d->caseSensitivity);
485 if (filePath.endsWith('/')) {
486 return entries.contains(filePath, cs);
487 } else {
488 return entries.contains(fileName, cs)
489 || entries.contains(fileName + "/", cs);
490 }
491 }
492 }
493 }
494
495 bool QuaZipDir::exists() const
496 {
497 return QuaZipDir(d->zip).exists(d->dir);
498 }
499
500 QString QuaZipDir::filePath(const QString &fileName) const
501 {
502 return QDir(d->dir).filePath(fileName);
503 }
504
505 QDir::Filters QuaZipDir::filter()
506 {
507 return d->filter;
508 }
509
510 bool QuaZipDir::isRoot() const
511 {
512 return d->simplePath().isEmpty();
513 }
514
515 QStringList QuaZipDir::nameFilters() const
516 {
517 return d->nameFilters;
518 }
519
520 QString QuaZipDir::path() const
521 {
522 return d->dir;
523 }
524
525 QString QuaZipDir::relativeFilePath(const QString &fileName) const
526 {
527 return QDir("/" + d->dir).relativeFilePath(fileName);
528 }
529
530 void QuaZipDir::setCaseSensitivity(QuaZip::CaseSensitivity caseSensitivity)
531 {
532 d->caseSensitivity = caseSensitivity;
533 }
534
535 void QuaZipDir::setFilter(QDir::Filters filters)
536 {
537 d->filter = filters;
538 }
539
540 void QuaZipDir::setNameFilters(const QStringList &nameFilters)
541 {
542 d->nameFilters = nameFilters;
543 }
544
545 void QuaZipDir::setPath(const QString &path)
546 {
547 QString newDir = path;
548 if (newDir == "/") {
549 d->dir = "";
550 } else {
551 if (newDir.endsWith('/'))
552 newDir.chop(1);
553 if (newDir.startsWith('/'))
554 newDir = newDir.mid(1);
555 d->dir = newDir;
556 }
557 }
558
559 void QuaZipDir::setSorting(QDir::SortFlags sort)
560 {
561 d->sorting = sort;
562 }
563
564 QDir::SortFlags QuaZipDir::sorting() const
565 {
566 return d->sorting;
567 }