treexplore: Add nested IFF parsing

Use IffFile to add an option to treexplore to show the structure of contained
IFF files
This commit is contained in:
2015-04-22 17:19:42 +02:00
parent c87836468d
commit 89688c5fba
4 changed files with 172 additions and 14 deletions

View File

@@ -5,7 +5,7 @@ LDOPTS=
IFFEXPLORE_CXXSRCS=iffexplore.cc IffFile.cc
IFFEXPLORE_OBJS=$(addprefix objs/,$(IFFEXPLORE_CXXSRCS:.cc=.o))
TREEXPLORE_CXXSRCS=treexplore.cc TreFile.cc
TREEXPLORE_CXXSRCS=treexplore.cc TreFile.cc IffFile.cc
TREEXPLORE_OBJS=$(addprefix objs/,$(TREEXPLORE_CXXSRCS:.cc=.o))
FONT2PNG_CXXSRCS=font2png.cc

View File

@@ -73,33 +73,68 @@ TreFile::~TreFile()
}
}
std::vector<std::string> TreFile::getNames() const
{
std::vector<std::string> ret;
for (auto ent : table2_) {
ret.push_back(ent.first);
}
return ret;
}
std::vector<uint32_t> TreFile::getCRCs() const
{
std::vector<uint32_t> ret;
for (auto ent : table1_) {
ret.push_back(ent.first);
}
return ret;
}
TreFile::File TreFile::openName(std::string const& name) const
{
return openIdx_(findName_(name));
}
TreFile::File TreFile::openCRC(uint32_t crc) const
{
return openIdx_(findCRC_(crc));
}
TreFile::Stat TreFile::statName(std::string const& name) const
{
return statIdx_(findName_(name));
}
TreFile::Stat TreFile::statCRC(uint32_t crc) const
{
return statIdx_(findCRC_(crc));
}
void TreFile::dumpName(std::string path, std::string const& name)
{
auto it = table2_.find(name);
if (it == table2_.end())
throw Exception{name + " not found"};
auto idx = findName_(name);
if (path.back() != '/')
path.push_back('/');
path.append(name);
dumpIdx_(path, it->second);
dumpIdx_(path, idx);
}
void TreFile::dumpCRC(std::string path, uint32_t crc)
{
auto idx = findCRC_(crc);
char crcStr[9];
snprintf(crcStr, 9, "%.8X", crc);
auto it = table1_.find(crc);
if (it == table1_.end())
throw Exception{"CRC "s + crcStr + " not found"s};
if (path.back() != '/')
path.push_back('/');
path.append(crcStr);
dumpIdx_(path, it->second);
dumpIdx_(path, idx);
}
void TreFile::dumpAll(std::string path)
@@ -302,6 +337,27 @@ void TreFile::construct_()
}
}
size_t TreFile::findName_(std::string const& name) const
{
auto it = table2_.find(name);
if (it == table2_.end())
throw Exception{name + " not found"};
return it->second;
}
size_t TreFile::findCRC_(uint32_t crc) const
{
auto it = table1_.find(crc);
if (it == table1_.end()) {
char crcStr[9];
snprintf(crcStr, 9, "%.8X", crc);
throw Exception{"CRC "s + crcStr + " not found"s};
}
return it->second;
}
void TreFile::dumpIdx_(std::string const& name, size_t table3Idx)
{
uint32_t ofs, len;
@@ -327,3 +383,31 @@ void TreFile::dumpIdx_(std::string const& name, size_t table3Idx)
if (fwrite(buf.data(), len, 1, outFile.get()) != 1)
throw POSIXException{errno, "Could not write"};
}
TreFile::File TreFile::openIdx_(size_t table3Idx) const
{
uint32_t ofs, len;
uint8_t flags;
std::tie(ofs, len, flags) = table3_[table3Idx];
if(flags&0x80)
throw Exception{"Compressed TRE objects NYI"};
std::vector<char> buf(len);
if (fseeko(file_, start_+ofs, SEEK_SET) != 0)
throw POSIXException{errno, "Could not seek"};
if (fread(buf.data(), len, 1, file_) != 1)
throw POSIXException{errno, "Could not read data"};
return File{buf};
}
TreFile::Stat TreFile::statIdx_(size_t table3Idx) const
{
Stat ret;
std::tie(std::ignore, ret.size, ret.flags) = table3_[table3Idx];
return ret;
}

View File

@@ -16,6 +16,9 @@ public:
TreFile(TreFile const& copy) = delete;
TreFile& operator=(TreFile const& copy) = delete;
std::vector<std::string> getNames() const;
std::vector<uint32_t> getCRCs() const;
void dumpName(std::string path, std::string const& name);
void dumpCRC(std::string path, uint32_t crc);
@@ -23,15 +26,51 @@ public:
void printStructure();
class File {
public:
char const* data() const {
return data_.data();
}
size_t size() const {
return data_.size();
}
private:
std::vector<char> data_;
File(std::vector<char> data)
: data_(std::move(data)) {
}
friend class TreFile;
};
File openName(std::string const& name) const;
File openCRC(uint32_t crc) const;
struct Stat {
uint32_t size;
uint8_t flags;
};
Stat statName(std::string const& name) const;
Stat statCRC(uint32_t crc) const;
private:
void construct_();
size_t findName_(std::string const& name) const;
size_t findCRC_(uint32_t crc) const;
void dumpIdx_(std::string const& name, size_t table3Idx);
File openIdx_(size_t table3Idx) const;
Stat statIdx_(size_t table3Idx) const;
std::map<uint32_t, size_t> table1_;
std::map<std::string, size_t> table2_;
std::vector<std::tuple<uint32_t, uint32_t, uint8_t> > table3_;
FILE* file_;
mutable FILE* file_;
off_t start_;
size_t length_;
};

View File

@@ -12,23 +12,25 @@
#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;
bool printStructure = false, dumpFiles = false, dumpIff = false;
std::string dumpPath, treFile;
std::vector<std::string> fileSpecs;
{
int opt;
while ((opt = getopt(argc, argv, "hsd:")) != -1) {
while ((opt = getopt(argc, argv, "hsd:i")) != -1) {
switch (opt) {
case 'h':
usage(argv[0]);
@@ -36,6 +38,9 @@ int main(int argc, char *argv[]) {
case 's':
printStructure = true;
break;
case 'i':
dumpIff = true;
break;
case 'd':
dumpPath = optarg;
dumpFiles = true;
@@ -62,6 +67,36 @@ int main(int argc, char *argv[]) {
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);
@@ -83,7 +118,7 @@ int main(int argc, char *argv[]) {
} catch (POSIXException &ex) {
fprintf(stderr, "%s\n", ex.toString().c_str());
return 2;
} catch (FormatException &ex) {
} catch (Exception &ex) {
fprintf(stderr, "%s\n", ex.toString().c_str());
return 3;
}