]> git.tdb.fi Git - libs/datafile.git/commitdiff
Add ability to put raw files in a pack
authorMikko Rasa <tdb@tdb.fi>
Sat, 13 Apr 2013 12:57:11 +0000 (15:57 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 13 Apr 2013 12:57:11 +0000 (15:57 +0300)
tool/packer.cpp
tool/packer.h

index 51b7d8f2c433e136a53d27ca2ccba3415ca047f9..44be7243e86e45df093e8fdf38270f8bcdfbbd45 100644 (file)
@@ -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<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);
@@ -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<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)
index 351b45d3109c59bea04fd790e1825e4ac055a839..913d7d6825bc30fd6ba58cf94c2e463d8efb880b 100644 (file)
@@ -17,6 +17,8 @@ private:
                std::string keyword;
        };
 
+       typedef std::list<Object> 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 &);
 };