summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/paq.cpp116
1 files changed, 116 insertions, 0 deletions
diff --git a/contrib/paq.cpp b/contrib/paq.cpp
new file mode 100644
index 0000000..cd4fb0d
--- /dev/null
+++ b/contrib/paq.cpp
@@ -0,0 +1,116 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <list>
+#include <exception>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/iostreams/filtering_streambuf.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
+#include <boost/iostreams/copy.hpp>
+
+using namespace std;
+
+class my_exception : public exception
+{
+private:
+ string cause;
+
+public:
+ my_exception(const string& cause) : cause(cause) { }
+ virtual const char* what() const { return cause.c_str(); }
+};
+
+class paq_builder
+{
+private:
+ struct index_entry
+ {
+ index_entry(const string& file_name, bool is_dir) : file_name(file_name), is_dir(is_dir) { }
+
+ string file_name;
+ bool is_dir;
+ };
+
+ list<index_entry> index;
+ list<vector<char> > files;
+
+ void process(string path)
+ {
+ boost::filesystem::directory_iterator end;
+ for (boost::filesystem::directory_iterator itr(path.c_str()); itr != end ; ++itr)
+ {
+ index.push_back(index_entry(itr->filename(), boost::filesystem::is_directory(itr->status())));
+ if (index.back().is_dir)
+ process(path + "/" + itr->filename());
+ else
+ {
+ ifstream in(itr->string().c_str(), ios::binary);
+ if (!in) throw my_exception(string("Can't open ") + itr->string());
+ vector<char> v(4);
+ *reinterpret_cast<unsigned int*>(&v[0]) = boost::filesystem::file_size(itr->path());
+ boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
+ out.push(boost::iostreams::gzip_compressor());
+ out.push(boost::iostreams::back_inserter(v));
+ boost::iostreams::copy(in, out);
+ files.push_back(v);
+ }
+ }
+ index.push_back(index_entry(string(""), 0));
+ }
+
+public:
+ paq_builder(const char* path)
+ {
+ if (!boost::filesystem::exists(path) || !boost::filesystem::is_directory(path))
+ throw my_exception(string(path) + " doesn't exist or isn't a directory!");
+
+ process(string(path));
+ }
+
+ void write_to_file(const char* path)
+ {
+ ofstream paq(path, ios::binary);
+ if (!paq) throw my_exception(string("Can't open ") + path);
+
+ paq.write("NPAQ", 4);
+
+ list<vector<char> >::iterator f_it = files.begin();
+ for (list<index_entry>::iterator i_it = index.begin(); i_it != index.end(); i_it++)
+ {
+ paq << static_cast<char>(i_it->file_name.size());
+ if (i_it->file_name.size())
+ {
+ paq.write(i_it->file_name.c_str(), i_it->file_name.size());
+ unsigned int file_size = i_it->is_dir ? 0 : f_it++->size();
+ paq.write(reinterpret_cast<char*>(&file_size), 4);
+ paq << static_cast<char>(file_size ? 0 : 1);
+ }
+ }
+
+ for(f_it = files.begin(); f_it != files.end(); f_it++)
+ paq.write(&(*f_it)[0], f_it->size());
+ }
+};
+
+int main(int argc, char** argv)
+{
+ if (argc < 3)
+ {
+ cout << "Usage: " << argv[0] << " <in-directory> <out-paq>" << endl;
+ return 0;
+ }
+
+ try
+ {
+ paq_builder(argv[1]).write_to_file(argv[2]);
+ }
+ catch (const exception& e)
+ {
+ cerr << e.what() << endl;
+ return -1;
+ }
+
+ return 0;
+} \ No newline at end of file