From: Mikko Rasa Date: Sat, 13 Apr 2013 12:57:11 +0000 (+0300) Subject: Add ability to put raw files in a pack X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=a3935faaba6187cbccc5f2b60b065d9180b1cdee;p=libs%2Fdatafile.git Add ability to put raw files in a pack --- diff --git a/tool/packer.cpp b/tool/packer.cpp index 51b7d8f..44be724 100644 --- a/tool/packer.cpp +++ b/tool/packer.cpp @@ -50,15 +50,57 @@ 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; + bool raw = detect_raw(in); + if(raw) + transfer_raw(in, *tmp_file); + else + { + transfer_datafile(in, fn, *tmp_buf, objects); + tmp_buf->flush(); + } + + 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_raw(IO::Seekable &in) +{ + IO::SeekOffset offset = in.tell(); + bool raw = false; + DataFile::Parser parser(in, "-"); + while(!raw && !in.eof() && in.tell()<10240) + { + try + { + parser.parse(); + } + catch(...) + { + raw = true; + } + } + in.seek(offset, IO::S_BEG); + return raw; +} + +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); @@ -83,21 +125,18 @@ void Packer::pack_file(const string &fn) } writer->write(DataFile::Statement("__end")); delete writer; +} - tmp_buf->flush(); - unsigned length = tmp_file->tell()-offset; - - DataFile::Statement st("file"); - st.append(FS::basename(fn)); - st.sub.push_back((DataFile::Statement("slice"), offset, length)); - if(collection) +void Packer::transfer_raw(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) diff --git a/tool/packer.h b/tool/packer.h index 351b45d..913d7d6 100644 --- a/tool/packer.h +++ b/tool/packer.h @@ -17,6 +17,8 @@ private: std::string keyword; }; + typedef std::list ObjectList; + DataTool &tool; Msp::IO::File *tmp_file; Msp::IO::Buffered *tmp_buf; @@ -31,6 +33,11 @@ public: ~Packer(); void pack_file(const std::string &); +private: + bool detect_raw(Msp::IO::Seekable &); + void transfer_datafile(Msp::IO::Base &, const std::string &, Msp::IO::Base &, ObjectList &); + void transfer_raw(Msp::IO::Base &, Msp::IO::Base &); +public: void create_pack(const std::string &); };