gzip.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 605 行 · 第 1/2 页
HPP
605 行
//template<typename Alloc = std::allocator<char> >class basic_gzip_decompressor : basic_zlib_decompressor<Alloc> {public: typedef char char_type; struct category : multichar_input_filter_tag, closable_tag { }; basic_gzip_decompressor( int window_bits = gzip::default_window_bits, int buffer_size = default_device_buffer_size ); template<typename Source> std::streamsize read(Source& src, char_type* s, std::streamsize n) { if ((flags_ & f_header_read) == 0) { non_blocking_adapter<Source> nb(src); read_header(nb); flags_ |= f_header_read; } if ((flags_ & f_footer_read) != 0) return -1; try { std::streamsize result = 0; std::streamsize amt; if ((amt = base_type::read(src, s, n)) != -1) { result += amt; if (amt < n) { // Double check for EOF. amt = base_type::read(src, s + result, n - result); if (amt != -1) result += amt; } } if (amt == -1) { non_blocking_adapter<Source> nb(src); read_footer(nb); flags_ |= f_footer_read; } return result; } catch (const zlib_error& e) { throw gzip_error(e); } } template<typename Source> void close(Source& src) { try { base_type::close(src, BOOST_IOS::in); } catch (const zlib_error& e) { flags_ = 0; throw gzip_error(e); } flags_ = 0; } std::string file_name() const { return file_name_; } std::string comment() const { return comment_; } bool text() const { return (flags_ & gzip::flags::text) != 0; } int os() const { return os_; } std::time_t mtime() const { return mtime_; }private: typedef basic_zlib_decompressor<Alloc> base_type; typedef BOOST_IOSTREAMS_CHAR_TRAITS(char) traits_type; static bool is_eof(int c) { return traits_type::eq_int_type(c, EOF); } static gzip_params make_params(int window_bits); template<typename Source> static uint8_t read_uint8(Source& src, int error) { int c; if ((c = boost::iostreams::get(src)) == EOF || c == WOULD_BLOCK) throw gzip_error(error); return static_cast<uint8_t>(traits_type::to_char_type(c)); } template<typename Source> static uint32_t read_uint32(Source& src, int error) { uint8_t b1 = read_uint8(src, error); uint8_t b2 = read_uint8(src, error); uint8_t b3 = read_uint8(src, error); uint8_t b4 = read_uint8(src, error); return b1 + (b2 << 8) + (b3 << 16) + (b4 << 24); } template<typename Source> std::string read_string(Source& src) { std::string result; while (true) { int c; if (is_eof(c = boost::iostreams::get(src))) throw gzip_error(gzip::bad_header); else if (c == 0) return result; else result += static_cast<char>(c); } } template<typename Source> void read_header(Source& src) // Source is non-blocking. { // Reset saved values. #if BOOST_WORKAROUND(__GNUC__, == 2) && defined(__STL_CONFIG_H) || \ BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) \ /**/ file_name_.erase(0, std::string::npos); comment_.erase(0, std::string::npos); #else file_name_.clear(); comment_.clear(); #endif os_ = gzip::os_unknown; mtime_ = 0; int flags; // Read header, without checking header crc. if ( boost::iostreams::get(src) != gzip::magic::id1 || // ID1. boost::iostreams::get(src) != gzip::magic::id2 || // ID2. is_eof(boost::iostreams::get(src)) || // CM. is_eof(flags = boost::iostreams::get(src)) ) // FLG. { throw gzip_error(gzip::bad_header); } mtime_ = read_uint32(src, gzip::bad_header); // MTIME. read_uint8(src, gzip::bad_header); // XFL. os_ = read_uint8(src, gzip::bad_header); // OS. if (flags & boost::iostreams::gzip::flags::text) flags_ |= f_text; // Skip extra field. (From J. Halleaux; see note at top.) if (flags & gzip::flags::extra) { int length = static_cast<int>( read_uint8(src, gzip::bad_header) + (read_uint8(src, gzip::bad_header) << 8) ); // length is garbage if EOF but the loop below will quit anyway. do { } while (length-- != 0 && !is_eof(boost::iostreams::get(src))); } if (flags & gzip::flags::name) // Read file name. file_name_ = read_string(src); if (flags & gzip::flags::comment) // Read comment. comment_ = read_string(src); if (flags & gzip::flags::header_crc) { // Skip header crc. read_uint8(src, gzip::bad_header); read_uint8(src, gzip::bad_header); } } template<typename Source> void read_footer(Source& src) { typename base_type::string_type footer = this->unconsumed_input(); int c; while (!is_eof(c = boost::iostreams::get(src))) footer += c; detail::range_adapter<input, std::string> rng(footer.begin(), footer.end()); if (read_uint32(rng, gzip::bad_footer) != this->crc()) throw gzip_error(gzip::bad_crc); if (static_cast<int>(read_uint32(rng, gzip::bad_footer)) != this->total_out()) throw gzip_error(gzip::bad_length); } enum flag_type { f_header_read = 1, f_footer_read = f_header_read << 1, f_text = f_footer_read << 1 }; std::string file_name_; std::string comment_; int os_; std::time_t mtime_; int flags_;};BOOST_IOSTREAMS_PIPABLE(basic_gzip_decompressor, 1)typedef basic_gzip_decompressor<> gzip_decompressor;//------------------Implementation of gzip_compressor-------------------------//template<typename Alloc>basic_gzip_compressor<Alloc>::basic_gzip_compressor (const gzip_params& p, int buffer_size) : base_type(normalize_params(p), buffer_size), offset_(0), flags_(0){ // Calculate gzip header. bool has_name = !p.file_name.empty(); bool has_comment = !p.comment.empty(); std::string::size_type length = 10 + (has_name ? p.file_name.size() + 1 : 0) + (has_comment ? p.comment.size() + 1 : 0); // + 2; // Header crc confuses gunzip. int flags = //gzip::flags::header_crc + (has_name ? gzip::flags::name : 0) + (has_comment ? gzip::flags::comment : 0); int extra_flags = ( p.level == zlib::best_compression ? gzip::extra_flags::best_compression : 0 ) + ( p.level == zlib::best_speed ? gzip::extra_flags::best_speed : 0 ); header_.reserve(length); header_ += gzip::magic::id1; // ID1. header_ += gzip::magic::id2; // ID2. header_ += gzip::method::deflate; // CM. header_ += static_cast<char>(flags); // FLG. header_ += static_cast<char>(0xFF & p.mtime); // MTIME. header_ += static_cast<char>(0xFF & (p.mtime >> 8)); header_ += static_cast<char>(0xFF & (p.mtime >> 16)); header_ += static_cast<char>(0xFF & (p.mtime >> 24)); header_ += static_cast<char>(extra_flags); // XFL. header_ += static_cast<char>(gzip::os_unknown); // OS. if (has_name) { header_ += p.file_name; header_ += '\0'; } if (has_comment) { header_ += p.comment; header_ += '\0'; }}template<typename Alloc>gzip_params basic_gzip_compressor<Alloc>::normalize_params(gzip_params p){ p.noheader = true; p.calculate_crc = true; return p;}template<typename Alloc>void basic_gzip_compressor<Alloc>::prepare_footer(){ boost::iostreams::back_insert_device<std::string> out(footer_); write_long(this->crc(), out); write_long(this->total_in(), out); flags_ |= f_body_done; offset_ = 0;}template<typename Alloc>std::streamsize basic_gzip_compressor<Alloc>::read_string (char* s, std::streamsize n, std::string& str){ std::streamsize avail = static_cast<std::streamsize>(str.size() - offset_); std::streamsize amt = (std::min)(avail, n); std::copy( str.data() + offset_, str.data() + offset_ + amt, s ); offset_ += amt; if ( !(flags_ & f_header_done) && offset_ == static_cast<std::size_t>(str.size()) ) { flags_ |= f_header_done; } return amt;}//------------------Implementation of gzip_decompressor-----------------------//template<typename Alloc>basic_gzip_decompressor<Alloc>::basic_gzip_decompressor (int window_bits, int buffer_size) : base_type(make_params(window_bits), buffer_size), os_(gzip::os_unknown), mtime_(0), flags_(0) { }template<typename Alloc>gzip_params basic_gzip_decompressor<Alloc>::make_params(int window_bits){ gzip_params p; p.window_bits = window_bits; p.noheader = true; p.calculate_crc = true; return p;}//----------------------------------------------------------------------------//} } // End namespaces iostreams, boost.#if defined(BOOST_MSVC)# pragma warning(pop)#endif#endif // #ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?