1 #include <msp/datafile/parser.h>
2 #include <msp/datafile/rawdata.h>
3 #include <msp/datafile/statement.h>
4 #include <msp/datafile/writer.h>
5 #include <msp/fs/utils.h>
6 #include <msp/io/memory.h>
7 #include <msp/strings/format.h>
14 Packer::Packer(DataTool &t):
20 IO::BufferedFile *Packer::tempfile()
23 const char *tmp_env = getenv("TMPDIR");
29 for(unsigned i=0;; ++i)
33 FS::Path filename = tmpdir/format("mspdatatool.%d", i);
34 IO::BufferedFile *file = new IO::BufferedFile(filename.str(), IO::M_RDWR, IO::File::C_NEW);
35 FS::unlink(filename.str());
38 catch(const IO::file_already_exists &)
50 void Packer::pack_file(const string &fn)
53 throw logic_error("Packer::pack_file");
55 IO::SeekOffset offset = tmp_file->tell();
57 IO::BufferedFile in(fn);
60 transfer_datafile(in, fn, *tmp_file, objects);
61 else if(detect_raw(in))
62 transfer_raw_data(in, fn, *tmp_file);
64 transfer_unknown(in, *tmp_file);
66 unsigned length = tmp_file->tell()-offset;
68 DataFile::Statement st("file");
69 st.append(FS::basename(fn));
70 st.sub.push_back((DataFile::Statement("slice"), offset, length));
71 for(list<Object>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
72 st.sub.push_back((DataFile::Statement("object"), i->name, i->keyword));
73 directory.push_back(st);
74 dir_alloc += 100+objects.size()*100;
77 bool Packer::detect_data(IO::Seekable &in)
79 IO::SeekOffset offset = in.tell();
81 DataFile::Parser parser(in, "-");
82 while(data && parser && in.tell()<10240)
93 in.seek(offset, IO::S_BEG);
97 bool Packer::detect_raw(IO::Seekable &in)
100 IO::SeekOffset offset = in.tell();
101 in.read(header, sizeof(header));
102 in.seek(offset, IO::S_BEG);
103 return DataFile::RawData::detect_signature(string(header, sizeof(header)));
106 void Packer::transfer_datafile(IO::Base &in, const string &fn, IO::Base &out, ObjectList &objects)
108 DataFile::Parser parser(in, fn);
110 DataFile::Writer *writer = tool.create_writer(out);
112 bool collection = FS::extpart(fn)==".mdc";
115 DataFile::Statement st = parser.parse(true);
118 if(collection && !st.control)
120 if(st.get_signature()=="s")
123 obj.name = st.args[0].get<string>();
124 obj.keyword = st.keyword;
125 objects.push_back(obj);
130 if(!st.control || st.keyword=="__src")
134 writer->write(DataFile::Statement("__end"));
138 void Packer::transfer_raw_data(IO::Base &in, const string &fn, IO::Base &out)
140 DataFile::RawData raw;
143 raw.write_io(out, tool.is_compressed());
146 void Packer::transfer_unknown(IO::Base &in, IO::Base &out)
151 unsigned len = in.read(buf, sizeof(buf));
158 void Packer::create_pack(const string &fn)
160 vector<char> dir_buffer(dir_alloc);
161 IO::Memory mem(&dir_buffer[0], dir_buffer.size(), IO::M_WRITE);
163 unsigned base_offset = 0;
166 mem.seek(0, IO::S_BEG);
168 DataFile::Writer *writer = tool.create_writer(mem);
170 for(list<DataFile::Statement>::const_iterator i=directory.begin(); i!=directory.end(); ++i)
173 base_offset = mem.tell();
174 writer->write((DataFile::Statement("base_offset"), base_offset));
175 writer->write(DataFile::Statement("__end"));
178 unsigned dir_size = mem.tell();
179 if(dir_size<=base_offset)
181 base_offset = dir_size;
184 IO::File out(fn, IO::M_WRITE);
185 out.write(&dir_buffer[0], base_offset);
186 tmp_file->seek(0, IO::S_BEG);
187 unsigned bufsize = 1048576;
188 char *buf = new char[bufsize];
189 while(!tmp_file->eof())
191 unsigned len = tmp_file->read(buf, bufsize);