Files
wc3re/iffexplore.cc

113 lines
2.6 KiB
C++

#include <cstdio>
#include <cstring>
#include <cerrno>
#include <cstdint>
#include <vector>
#include <unistd.h>
#include "common.hh"
#include "util.hh"
#include "IffFile.hh"
void blobDump(Resource const& obj, std::string const& filename)
{
FILEUPtr file{fopen(filename.c_str(), "wb")};
if (!file)
throw POSIXException{errno, "Could not open file: " + filename};
if (fwrite(obj.data(), obj.size(), 1, file.get()) != 1)
throw POSIXException{errno, "Could not write"};
}
void iffDumper(IffFile::Object const& obj, bool dumpBlobs, std::string dumpPath, unsigned& blobCount, unsigned level = 0)
{
for (unsigned i = 0;i < level;++i)
putchar('\t');
printf("%s Length %lu (0x%.lx)", obj.getType().c_str(), obj.size(), obj.size());
if (obj.isForm()) {
auto& form = dynamic_cast<IffFile::Form const&>(obj);
printf(", Subtype %s\n", form.getSubtype().c_str());
for(auto it = form.childrenBegin();it != form.childrenEnd();++it)
iffDumper(*it, dumpBlobs, dumpPath, blobCount, level+1);
} else {
try {
printf(" = \"%s\"\n", static_cast<std::string>(obj).c_str());
} catch(FormatException &ex) {
if (dumpBlobs) {
std::string filename{dumpPath};
filename += obj.getType() + "-" + std::to_string(blobCount++);
printf(" dump to %s\n", filename.c_str());
blobDump(obj, filename);
} else
printf("\n");
}
}
}
void usage(char *argv0) {
fprintf(stderr, "Usage: %s [-sh] [-d dest] iff-file\n", argv0);
fprintf(stderr, "\t-s\tPrint the iff-file's structure\n");
fprintf(stderr, "\t-d dest\tDump BLOBs as files to dest/\n");
fprintf(stderr, "\t-h\tPrint this help\n");
}
int main(int argc, char *argv[])
{
bool printStructure = false, dumpBlobs = false;
std::string dumpPath, iffFile;
{
int opt;
while ((opt = getopt(argc, argv, "hsd:")) != -1) {
switch (opt) {
case 'h':
usage(argv[0]);
return 0;
case 's':
printStructure = true;
break;
case 'd':
dumpPath = optarg;
dumpBlobs = true;
break;
default:
usage(argv[0]);
return 1;
}
}
if (optind >= argc) {
usage(argv[0]);
return 1;
}
iffFile = argv[optind];
}
try {
MmapFile mmap{iffFile};
IffFile iff{mmap};
if (printStructure) {
unsigned blobCount = 0, subdoc = 0;
for (auto& root : iff) {
printf("Subdocument %u:\n", subdoc++);
iffDumper(root, dumpBlobs, dumpPath, blobCount);
}
}
} catch (POSIXException &ex) {
fflush(stdout);
fprintf(stderr, "%s\n", ex.toString().c_str());
return 2;
} catch (FormatException &ex) {
fflush(stdout);
fprintf(stderr, "%s\n", ex.toString().c_str());
return 3;
}
return 0;
}