X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=tool%2Fpacker.cpp;h=2e773a21a04a12dd8139bda0bb1c7acee20d0b15;hb=HEAD;hp=51b7d8f2c433e136a53d27ca2ccba3415ca047f9;hpb=57d8b8c6f07808efdd1b9647d12447c177ce1e7d;p=libs%2Fdatafile.git diff --git a/tool/packer.cpp b/tool/packer.cpp index 51b7d8f..2e773a2 100644 --- a/tool/packer.cpp +++ b/tool/packer.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -13,23 +14,25 @@ using namespace Msp; Packer::Packer(DataTool &t): tool(t), tmp_file(tempfile()), - tmp_buf(new IO::Buffered(*tmp_file)), dir_alloc(0) { } -IO::File *Packer::tempfile() +IO::BufferedFile *Packer::tempfile() { + FS::Path tmpdir; + const char *tmp_env = getenv("TMPDIR"); + if(tmp_env) + tmpdir = tmp_env; + else + tmpdir = "/tmp"; + for(unsigned i=0;; ++i) { try { - std::string filename = format("/tmp/mspdatatool.%d", i); - /*filename.reserve(25); - filename.append("/tmp/mspdatatool."); - for(unsigned i=0; i<8; ++i) - filename.append(rand());*/ - IO::File *file = new IO::File(filename, IO::M_RDWR, IO::File::C_NEW); - FS::unlink(filename); + FS::Path filename = tmpdir/format("mspdatatool.%d", i); + IO::BufferedFile *file = new IO::BufferedFile(filename.str(), IO::M_RDWR, IO::File::C_NEW); + FS::unlink(filename.str()); return file; } catch(const IO::file_already_exists &) @@ -41,7 +44,6 @@ IO::File *Packer::tempfile() Packer::~Packer() { - delete tmp_buf; delete tmp_file; } @@ -50,22 +52,70 @@ void Packer::pack_file(const string &fn) if(!tmp_file) throw logic_error("Packer::pack_file"); - unsigned offset = tmp_file->tell(); + IO::SeekOffset offset = tmp_file->tell(); IO::BufferedFile in(fn); + ObjectList objects; + if(detect_data(in)) + transfer_datafile(in, fn, *tmp_file, objects); + else if(detect_raw(in)) + transfer_raw_data(in, fn, *tmp_file); + else + transfer_unknown(in, *tmp_file); + + unsigned length = tmp_file->tell()-offset; + + DataFile::Statement st("file"); + st.append(FS::basename(fn)); + st.sub.push_back((DataFile::Statement("slice"), offset, length)); + for(list::const_iterator i=objects.begin(); i!=objects.end(); ++i) + st.sub.push_back((DataFile::Statement("object"), i->name, i->keyword)); + directory.push_back(st); + dir_alloc += 100+objects.size()*100; +} + +bool Packer::detect_data(IO::Seekable &in) +{ + IO::SeekOffset offset = in.tell(); + bool data = true; + DataFile::Parser parser(in, "-"); + while(data && parser && in.tell()<10240) + { + try + { + parser.parse(); + } + catch(...) + { + data = false; + } + } + in.seek(offset, IO::S_BEG); + return data; +} + +bool Packer::detect_raw(IO::Seekable &in) +{ + char header[4] = { }; + IO::SeekOffset offset = in.tell(); + in.read(header, sizeof(header)); + in.seek(offset, IO::S_BEG); + return DataFile::RawData::detect_signature(string(header, sizeof(header))); +} + +void Packer::transfer_datafile(IO::Base &in, const string &fn, IO::Base &out, ObjectList &objects) +{ DataFile::Parser parser(in, fn); - DataFile::Writer *writer = tool.create_writer(*tmp_buf); + DataFile::Writer *writer = tool.create_writer(out); bool collection = FS::extpart(fn)==".mdc"; - std::list objects; while(parser) { DataFile::Statement st = parser.parse(true); if(st.valid) { - bool sys = !st.keyword.compare(0, 2, "__"); - if(collection && !sys) + if(collection && !st.control) { if(st.get_signature()=="s") { @@ -77,27 +127,32 @@ void Packer::pack_file(const string &fn) else collection = false; } - if(!sys || st.keyword=="__src") + if(!st.control || st.keyword=="__src") writer->write(st); } } writer->write(DataFile::Statement("__end")); delete writer; +} - tmp_buf->flush(); - unsigned length = tmp_file->tell()-offset; +void Packer::transfer_raw_data(IO::Base &in, const string &fn, IO::Base &out) +{ + DataFile::RawData raw; + raw.open_io(in, fn); + raw.load(); + raw.write_io(out, tool.is_compressed()); +} - DataFile::Statement st("file"); - st.append(FS::basename(fn)); - st.sub.push_back((DataFile::Statement("slice"), offset, length)); - if(collection) +void Packer::transfer_unknown(IO::Base &in, IO::Base &out) +{ + while(!in.eof()) { - for(list::const_iterator i=objects.begin(); i!=objects.end(); ++i) - st.sub.push_back((DataFile::Statement("object"), i->name, i->keyword)); - dir_alloc += objects.size()*100; + char buf[4096]; + unsigned len = in.read(buf, sizeof(buf)); + if(len==0) + break; + out.write(buf, len); } - directory.push_back(st); - dir_alloc += 100; } void Packer::create_pack(const string &fn) @@ -129,12 +184,14 @@ void Packer::create_pack(const string &fn) IO::File out(fn, IO::M_WRITE); out.write(&dir_buffer[0], base_offset); tmp_file->seek(0, IO::S_BEG); + unsigned bufsize = 1048576; + char *buf = new char[bufsize]; while(!tmp_file->eof()) { - char buf[16384]; - unsigned len = tmp_file->read(buf, sizeof(buf)); + unsigned len = tmp_file->read(buf, bufsize); if(!len) break; out.write(buf, len); } + delete[] buf; }