]> git.tdb.fi Git - libs/datafile.git/blobdiff - tool/packer.cpp
Shuffle some names around in the data tool
[libs/datafile.git] / tool / packer.cpp
index 51b7d8f2c433e136a53d27ca2ccba3415ca047f9..fa4d7e236a943ba3361507cb5ff0b2bcf559415a 100644 (file)
@@ -13,23 +13,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 +43,6 @@ IO::File *Packer::tempfile()
 
 Packer::~Packer()
 {
-       delete tmp_buf;
        delete tmp_file;
 }
 
@@ -50,22 +51,59 @@ 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
+               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<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_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;
+}
+
+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")
                                {
@@ -77,27 +115,24 @@ 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;
-
-       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<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)
@@ -129,12 +164,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;
 }