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 + -
显示快捷键?