From 41a6cc09743cd3bb304bc79a2e8c7b1c9d49ccfc Mon Sep 17 00:00:00 2001 From: Pixel Date: Tue, 3 Nov 2009 16:34:36 -0800 Subject: Adding paq.cpp from Jes. --- contrib/paq.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 contrib/paq.cpp 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + list > 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 v(4); + *reinterpret_cast(&v[0]) = boost::filesystem::file_size(itr->path()); + boost::iostreams::filtering_streambuf 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 >::iterator f_it = files.begin(); + for (list::iterator i_it = index.begin(); i_it != index.end(); i_it++) + { + paq << static_cast(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(&file_size), 4); + paq << static_cast(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] << " " << 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 -- cgit v1.2.3