Skip to content

Commit

Permalink
Adding commands: extract and pack. Implement pack.
Browse files Browse the repository at this point in the history
  • Loading branch information
myst6re committed Sep 4, 2019
1 parent 14ef306 commit b72a4a0
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 101 deletions.
59 changes: 34 additions & 25 deletions arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@
#include <QTextStream>

Arguments::Arguments() :
_extract(
#ifndef UNZZZ
false
#else
true
#endif
), _help(false), _quiet(false)
_extract(false), _help(false), _quiet(false)
{
parse();
}
Expand All @@ -36,7 +30,7 @@ const QStringList &Arguments::paths() const
return _paths;
}

const QDir &Arguments::destination() const
const QDir &Arguments::directory() const
{
return _directory;
}
Expand All @@ -61,30 +55,47 @@ void Arguments::parse()
QStringList args = qApp->arguments();
args.removeFirst(); // Application path

while (!args.isEmpty()) {
if (!args.isEmpty()) {
const QString &arg = args.takeFirst();

if (arg == "-e" || arg == "--extract") {
if (arg == "extract") {
_extract = true;
} else if (arg == "-h" || arg == "--help") {
_help = true;
} else if (arg == "-q" || arg == "--quiet") {
_quiet = true;
} else if (arg == "pack") {
_extract = false;
} else {
_paths << arg;
_help = true;
}

bool stopOptions = false;

while (!args.isEmpty()) {
const QString &arg = args.takeFirst();

if (!stopOptions) {
if (arg == "-h" || arg == "--help") {
_help = true;
} else if (arg == "-q" || arg == "--quiet") {
_quiet = true;
} else if (arg == "--") {
stopOptions = true;
} else {
_paths << arg;
}
} else {
_paths << arg;
}
}
}

wilcardParse();
wilcardParse();
} else {
_help = true;
}
}

QMap<QString, QString> Arguments::commands() const
{
QMap<QString, QString> options;

#ifndef UNZZZ
options["-e --extract"] = "Extract.";
#endif
options["-h --help"] = "Show this help and quit.";
options["-q --quiet"] = "Suppress all outputs";

Expand All @@ -94,11 +105,9 @@ QMap<QString, QString> Arguments::commands() const
void Arguments::showHelp(int exitCode)
{
QTextStream out(stdout, QIODevice::WriteOnly);
#ifdef UNZZZ
out << "unzzz [files...] [output directory]\n";
#else
out << "zzz [-d] [files...] [output directory]\n";
#endif
out << "zzz extract ZZZ_FILE [ZZZ_FILE2...] OUTPUT_DIR\n";
out << "zzz pack ZZZ_FILE SOURCE_DIR\n";

out << "Options\n";

QMapIterator<QString, QString> it(commands());
Expand Down
2 changes: 1 addition & 1 deletion arguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Arguments
Arguments();
[[ noreturn ]] void showHelp(int exitCode = 0);
const QStringList &paths() const;
const QDir &destination() const;
const QDir &directory() const;
bool extract() const;
bool help() const;
bool quiet() const;
Expand Down
6 changes: 4 additions & 2 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ int main(int argc, char *argv[])
Zzz zzz(path);

if (args.extract()) {
if (!zzz.extractTo(args.destination(), observer)) {
if (!zzz.extractTo(args.directory(), observer)) {
std::cout << "Error " << qPrintable(zzz.lastInErrorString()) << qPrintable(zzz.lastOutErrorString());
}
} else {
std::cout << "Not implemented";
if (!zzz.packFrom(args.directory(), observer)) {
std::cout << "Error " << qPrintable(zzz.lastInErrorString()) << qPrintable(zzz.lastOutErrorString());
}
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion observer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
****************************************************************************/
#include "observer.h"
#include <stdio.h>
#include <QDebug>

Observer::Observer()
{
}

ObserverPercent::ObserverPercent()
ObserverPercent::ObserverPercent() :
_lastPercent(255)
{
}

Expand All @@ -42,4 +44,5 @@ ObserverStdOut::ObserverStdOut()
void ObserverStdOut::setPercent(quint8 percent)
{
printf("[%d%%] %s\r", percent, qPrintable(_filename));
fflush(stdout);
}
138 changes: 134 additions & 4 deletions zzz.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "zzz.h"
#include "zzzfile.h"
#include <QMap>
#include <QDirIterator>
#include <QDebug>

Zzz::Zzz(const QString &fileName) : f(fileName)
{
Expand All @@ -23,17 +26,17 @@ bool Zzz::extractTo(const QDir &dir, Observer *observer)
}

for (quint32 i = 0; i < fileCount; ++i) {
ZzzToc toc;
ZzzTocEntry tocEntry;

if (observer) {
observer->setValue(i);
}

if (!zzzFile.readTocEntry(toc)) {
if (!zzzFile.readTocEntry(tocEntry)) {
return false;
}

QFileInfo fileInfo = toQtSeparators(toc.name());
QFileInfo fileInfo = toQtSeparators(tocEntry.fileName());

if (!dir.mkpath(fileInfo.dir().path())) {
return false;
Expand All @@ -48,7 +51,7 @@ bool Zzz::extractTo(const QDir &dir, Observer *observer)
return false;
}

if (!zzzFile.copyFile(toc, &out)) {
if (!zzzFile.copyFile(tocEntry, &out)) {
_lastOutError = out.error();
_lastOutErrorString = out.errorString();

Expand All @@ -59,6 +62,119 @@ bool Zzz::extractTo(const QDir &dir, Observer *observer)
return true;
}

bool Zzz::packFrom(const QDir &dir, Observer *observer)
{
QString oldFilename = f.fileName();
f.setFileName(f.fileName().append(".tmp"));

if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return false;
}

bool ok = _packFrom(&f, dir, observer);

if (!ok) {
f.remove();
} else {
if (QFile::exists(oldFilename)) {
QFile::remove(oldFilename);
}

if (!f.rename(oldFilename)) {
return false;
}
}

return ok;
}

bool Zzz::_packFrom(QFile *temp, const QDir &dir, Observer *observer)
{
ZzzFile zzzFile(temp);
QStringList files;
QMap<QString, ZzzTocEntry> entries;
quint64 dataPos = 4;
QDirIterator it(dir.path(), QDir::Files, QDirIterator::Subdirectories);

if (observer) {
observer->setValue(0);
}

while (it.hasNext()) {
const QString &path = it.next();
QString fileName = path.mid(dir.path().size() + 1);
QFileInfo fileInfo(path);

if (fileInfo.size() > qint64(quint32(-1))) {
// TODO: error
return false;
}

ZzzTocEntry entry;
entry.setFilePos(0);
entry.setFileSize(quint32(fileInfo.size()));
entry.setFileName(toFF8Separators(fileName).toLatin1());

entries.insert(path, entry);
dataPos += quint64(entry.fileName().size() + 16);
}

int fileCount = entries.size();

if (observer) {
observer->setMaximum(fileCount - 1);
}

if (!zzzFile.writeHeader(quint32(fileCount))) {
return false;
}

quint32 i = 0;
QMutableMapIterator<QString, ZzzTocEntry> it2(entries);

while (it2.hasNext()) {
it2.next();
ZzzTocEntry &entry = it2.value();

entry.setFilePos(dataPos);

if (!zzzFile.writeTocEntry(entry)) {
return false;
}

dataPos += entry.fileSize();
}

QMapIterator<QString, ZzzTocEntry> it3(entries);

while (it3.hasNext()) {
it3.next();
const QString &path = it3.key();

if (observer) {
observer->setValue(i++);
}

QFile in(path);

if (!in.open(QIODevice::ReadOnly)) {
_lastOutError = in.error();
_lastOutErrorString = in.errorString();

return false;
}

if (!zzzFile.writeFile(&in)) {
_lastOutError = in.error();
_lastOutErrorString = in.errorString();

return false;
}
}

return true;
}

QString Zzz::toQtSeparators(const QString &path)
{
QString n(path);
Expand All @@ -72,3 +188,17 @@ QString Zzz::toQtSeparators(const QString &path)

return n;
}

QString Zzz::toFF8Separators(const QString &path)
{
QString n(path);
QChar * const data = n.data();

for (int i = 0; i < n.length(); ++i) {
if (data[i] == QLatin1Char('/')) {
data[i] = QLatin1Char('\\');
}
}

return n;
}
3 changes: 3 additions & 0 deletions zzz.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Zzz
public:
explicit Zzz(const QString &fileName);
bool extractTo(const QDir &dir, Observer *observer);
bool packFrom(const QDir &dir, Observer *observer);

inline const QString &lastOutErrorString() const {
return _lastOutErrorString;
Expand All @@ -20,7 +21,9 @@ class Zzz
return f.errorString();
}
private:
bool _packFrom(QFile *temp, const QDir &dir, Observer *observer);
static QString toQtSeparators(const QString &path);
static QString toFF8Separators(const QString &path);
QFile f;
QFile::FileError _lastOutError;
QString _lastOutErrorString;
Expand Down
9 changes: 2 additions & 7 deletions zzz.pro
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ QT -= gui

TARGET = zzz

configUNZZZ {
TARGET = unzzz
DEFINES += UNZZZ
}

CONFIG += console
CONFIG -= app_bundle

Expand All @@ -18,14 +13,14 @@ SOURCES += main.cpp \
observer.cpp \
zzz.cpp \
zzzfile.cpp \
zzztoc.cpp
zzztocentry.cpp

HEADERS += \
arguments.h \
observer.h \
zzz.h \
zzzfile.h \
zzztoc.h
zzztocentry.h

OTHER_FILES += README.md \
deploy.bat
Loading

0 comments on commit b72a4a0

Please sign in to comment.