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<Object>::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<Object> objects;
while(parser)
{
DataFile::Statement st = parser.parse(true);
}
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<Object>::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)
std::string keyword;
};
+ typedef std::list<Object> ObjectList;
+
DataTool &tool;
Msp::IO::File *tmp_file;
Msp::IO::Buffered *tmp_buf;
~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 &);
};