Files
wc3re/treexplore.cc
Matthias Blankertz 89688c5fba treexplore: Add nested IFF parsing
Use IffFile to add an option to treexplore to show the structure of contained
IFF files
2015-04-22 17:19:42 +02:00

128 lines
2.8 KiB
C++

#include <cstdio>
#include <cstring>
#include <cerrno>
#include <cstdint>
#include <vector>
#include <limits>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "common.hh"
#include "TreFile.hh"
#include "IffFile.hh"
void usage(char *argv0) {
fprintf(stderr, "Usage: %s [-sh] [-d dest] tre-file [filenames/crcs...]\n", argv0);
fprintf(stderr, "\t-s\tPrint the tre-file's structure\n");
fprintf(stderr, "\t-d dest\tDump files to dest/\n");
fprintf(stderr, "\t\tif dilenames/crcs are supplied, dump those object, else dump all\n");
fprintf(stderr, "\t-i\tAttempt to print iff-file's structures\n");
fprintf(stderr, "\t-h\tPrint this help\n");
}
int main(int argc, char *argv[]) {
bool printStructure = false, dumpFiles = false, dumpIff = false;
std::string dumpPath, treFile;
std::vector<std::string> fileSpecs;
{
int opt;
while ((opt = getopt(argc, argv, "hsd:i")) != -1) {
switch (opt) {
case 'h':
usage(argv[0]);
return 0;
case 's':
printStructure = true;
break;
case 'i':
dumpIff = true;
break;
case 'd':
dumpPath = optarg;
dumpFiles = true;
break;
default:
usage(argv[0]);
return 1;
}
}
if (optind >= argc) {
usage(argv[0]);
return 1;
}
treFile = argv[optind];
for (int i = optind+1;i < argc;++i)
fileSpecs.push_back(argv[i]);
}
try {
TreFile file{treFile};
if (printStructure)
file.printStructure();
if (dumpIff) {
for(auto name : file.getNames()) {
auto s = file.statName(name);
if (s.flags&0x80)
continue;
auto f = file.openName(name);
try {
IffFile iff{f.data(), f.size()};
printf("%s:\n", name.c_str());
iff.printStructure(1);
} catch(FormatException &ex) {
printf("%s: Not an IFF\n", name.c_str());
}
}
for(auto crc : file.getCRCs()) {
auto s = file.statCRC(crc);
if (s.flags&0x80)
continue;
auto f = file.openCRC(crc);
try {
IffFile iff{f.data(), f.size()};
printf("%.8x:\n", crc);
iff.printStructure(1);
} catch(FormatException &ex) {
printf("%.8x: Not an IFF\n", crc);
}
}
}
if (dumpFiles) {
if (fileSpecs.empty())
file.dumpAll(dumpPath);
else {
for (auto spec : fileSpecs) {
try {
unsigned long fileCRC = std::stoul(spec, nullptr, 16);
if (fileCRC <= std::numeric_limits<uint32_t>::max()) {
file.dumpCRC(dumpPath, fileCRC);
continue;
}
} catch (std::invalid_argument &ex) {
} catch (std::out_of_range &ex) {
}
file.dumpName(dumpPath, spec);
}
}
}
} catch (POSIXException &ex) {
fprintf(stderr, "%s\n", ex.toString().c_str());
return 2;
} catch (Exception &ex) {
fprintf(stderr, "%s\n", ex.toString().c_str());
return 3;
}
return 0;
}