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 &)
Packer::~Packer()
{
- delete tmp_buf;
delete tmp_file;
}
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_file, objects);
+
+ 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 && parser && 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);
if(st.valid)
{
- bool sys = !st.keyword.compare(0, 2, "__");
- if(collection && !sys)
+ if(collection && !st.control)
{
if(st.get_signature()=="s")
{
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;
-
- 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)
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;
}