| // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) |
| // (C) Copyright 2003-2007 Jonathan Turkanis |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) |
| |
| // See http://www.boost.org/libs/iostreams for documentation. |
| |
| // Contains the definitions of the class templates gzip_compressor and |
| // gzip_decompressor for reading and writing files in the gzip file format |
| // (RFC 1952). Based in part on work of Jonathan de Halleux; see [...] |
| |
| #ifndef NDNBOOST_IOSTREAMS_GZIP_HPP_INCLUDED |
| #define NDNBOOST_IOSTREAMS_GZIP_HPP_INCLUDED |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| #endif |
| |
| #include <ndnboost/config.hpp> // STATIC_CONSTANT, STDC_NAMESPACE, |
| // DINKUMWARE_STDLIB, __STL_CONFIG_H. |
| #include <algorithm> // min. |
| #include <ndnboost/assert.hpp> |
| #include <cstdio> // EOF. |
| #include <cstddef> // size_t. |
| #include <ctime> // std::time_t. |
| #include <memory> // allocator. |
| #include <ndnboost/config.hpp> // Put size_t in std. |
| #include <ndnboost/detail/workaround.hpp> |
| #include <ndnboost/cstdint.hpp> // uint8_t, uint32_t. |
| #include <ndnboost/iostreams/constants.hpp> // buffer size. |
| #include <ndnboost/iostreams/detail/adapter/non_blocking_adapter.hpp> |
| #include <ndnboost/iostreams/detail/adapter/range_adapter.hpp> |
| #include <ndnboost/iostreams/detail/char_traits.hpp> |
| #include <ndnboost/iostreams/detail/ios.hpp> // failure. |
| #include <ndnboost/iostreams/detail/error.hpp> |
| #include <ndnboost/iostreams/operations.hpp> |
| #include <ndnboost/iostreams/device/back_inserter.hpp> |
| #include <ndnboost/iostreams/filter/zlib.hpp> |
| #include <ndnboost/iostreams/pipeline.hpp> |
| #include <ndnboost/iostreams/putback.hpp> |
| #include <ndnboost/throw_exception.hpp> |
| |
| // Must come last. |
| #if defined(NDNBOOST_MSVC) |
| # pragma warning(push) |
| # pragma warning(disable: 4309) // Truncation of constant value. |
| #endif |
| |
| #ifdef NDNBOOST_NO_STDC_NAMESPACE |
| namespace std { using ::time_t; } |
| #endif |
| |
| namespace ndnboost { namespace iostreams { |
| |
| //------------------Definitions of constants----------------------------------// |
| |
| namespace gzip { |
| |
| using namespace ndnboost::iostreams::zlib; |
| |
| // Error codes used by gzip_error. |
| |
| const int zlib_error = 1; |
| const int bad_crc = 2; // Recorded crc doesn't match data. |
| const int bad_length = 3; // Recorded length doesn't match data. |
| const int bad_header = 4; // Malformed header. |
| const int bad_footer = 5; // Malformed footer. |
| const int bad_method = 6; // Unsupported compression method. |
| |
| namespace magic { |
| |
| // Magic numbers used by gzip header. |
| |
| const int id1 = 0x1f; |
| const int id2 = 0x8b; |
| |
| } // End namespace magic. |
| |
| namespace method { |
| |
| // Codes used for the 'CM' byte of the gzip header. |
| |
| const int deflate = 8; |
| |
| } // End namespace method. |
| |
| namespace flags { |
| |
| // Codes used for the 'FLG' byte of the gzip header. |
| |
| const int text = 1; |
| const int header_crc = 2; |
| const int extra = 4; |
| const int name = 8; |
| const int comment = 16; |
| |
| } // End namespace flags. |
| |
| namespace extra_flags { |
| |
| // Codes used for the 'XFL' byte of the gzip header. |
| |
| const int best_compression = 2; |
| const int best_speed = 4; |
| |
| } // End namespace extra_flags. |
| |
| // Codes used for the 'OS' byte of the gzip header. |
| |
| const int os_fat = 0; |
| const int os_amiga = 1; |
| const int os_vms = 2; |
| const int os_unix = 3; |
| const int os_vm_cms = 4; |
| const int os_atari = 5; |
| const int os_hpfs = 6; |
| const int os_macintosh = 7; |
| const int os_z_system = 8; |
| const int os_cp_m = 9; |
| const int os_tops_20 = 10; |
| const int os_ntfs = 11; |
| const int os_qdos = 12; |
| const int os_acorn = 13; |
| const int os_unknown = 255; |
| |
| } // End namespace gzip. |
| |
| //------------------Definition of gzip_params---------------------------------// |
| |
| // |
| // Class name: gzip_params. |
| // Description: Subclass of zlib_params with an additional field |
| // representing a file name. |
| // |
| struct gzip_params : zlib_params { |
| |
| // Non-explicit constructor. |
| gzip_params( int level = gzip::default_compression, |
| int method = gzip::deflated, |
| int window_bits = gzip::default_window_bits, |
| int mem_level = gzip::default_mem_level, |
| int strategy = gzip::default_strategy, |
| std::string file_name = "", |
| std::string comment = "", |
| std::time_t mtime = 0 ) |
| : zlib_params(level, method, window_bits, mem_level, strategy), |
| file_name(file_name), comment(comment), mtime(mtime) |
| { } |
| std::string file_name; |
| std::string comment; |
| std::time_t mtime; |
| }; |
| |
| //------------------Definition of gzip_error----------------------------------// |
| |
| // |
| // Class name: gzip_error. |
| // Description: Subclass of std::ios_base::failure thrown to indicate |
| // zlib errors other than out-of-memory conditions. |
| // |
| class gzip_error : public NDNBOOST_IOSTREAMS_FAILURE { |
| public: |
| explicit gzip_error(int error) |
| : NDNBOOST_IOSTREAMS_FAILURE("gzip error"), |
| error_(error), zlib_error_code_(zlib::okay) { } |
| explicit gzip_error(const zlib_error& e) |
| : NDNBOOST_IOSTREAMS_FAILURE("gzip error"), |
| error_(gzip::zlib_error), zlib_error_code_(e.error()) |
| { } |
| int error() const { return error_; } |
| int zlib_error_code() const { return zlib_error_code_; } |
| private: |
| int error_; |
| int zlib_error_code_; |
| }; |
| |
| //------------------Definition of gzip_compressor-----------------------------// |
| |
| // |
| // Template name: gzip_compressor |
| // Description: Model of OutputFilter implementing compression in the |
| // gzip format. |
| // |
| template<typename Alloc = std::allocator<char> > |
| class basic_gzip_compressor : basic_zlib_compressor<Alloc> { |
| private: |
| typedef basic_zlib_compressor<Alloc> base_type; |
| public: |
| typedef char char_type; |
| struct category |
| : dual_use, |
| filter_tag, |
| multichar_tag, |
| closable_tag |
| { }; |
| basic_gzip_compressor( const gzip_params& = gzip::default_compression, |
| int buffer_size = default_device_buffer_size ); |
| |
| template<typename Source> |
| std::streamsize read(Source& src, char_type* s, std::streamsize n) |
| { |
| std::streamsize result = 0; |
| |
| // Read header. |
| if (!(flags_ & f_header_done)) |
| result += read_string(s, n, header_); |
| |
| // Read body. |
| if (!(flags_ & f_body_done)) { |
| |
| // Read from basic_zlib_filter. |
| std::streamsize amt = base_type::read(src, s + result, n - result); |
| if (amt != -1) { |
| result += amt; |
| if (amt < n - result) { // Double-check for EOF. |
| amt = base_type::read(src, s + result, n - result); |
| if (amt != -1) |
| result += amt; |
| } |
| } |
| if (amt == -1) |
| prepare_footer(); |
| } |
| |
| // Read footer. |
| if ((flags_ & f_body_done) != 0 && result < n) |
| result += read_string(s + result, n - result, footer_); |
| |
| return result != 0 ? result : -1; |
| } |
| |
| template<typename Sink> |
| std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) |
| { |
| if (!(flags_ & f_header_done)) { |
| std::streamsize amt = |
| static_cast<std::streamsize>(header_.size() - offset_); |
| offset_ += ndnboost::iostreams::write(snk, header_.data() + offset_, amt); |
| if (offset_ == header_.size()) |
| flags_ |= f_header_done; |
| else |
| return 0; |
| } |
| return base_type::write(snk, s, n); |
| } |
| |
| template<typename Sink> |
| void close(Sink& snk, NDNBOOST_IOS::openmode m) |
| { |
| try { |
| // Close zlib compressor. |
| base_type::close(snk, m); |
| |
| if (m == NDNBOOST_IOS::out) { |
| if (flags_ & f_header_done) { |
| |
| // Write final fields of gzip file format. |
| write_long(this->crc(), snk); |
| write_long(this->total_in(), snk); |
| } |
| } |
| } catch(...) { |
| close_impl(); |
| throw; |
| } |
| close_impl(); |
| } |
| private: |
| static gzip_params normalize_params(gzip_params p); |
| void prepare_footer(); |
| std::streamsize read_string(char* s, std::streamsize n, std::string& str); |
| |
| template<typename Sink> |
| static void write_long(long n, Sink& next, ndnboost::mpl::true_) |
| { |
| ndnboost::iostreams::put(next, static_cast<char>(0xFF & n)); |
| ndnboost::iostreams::put(next, static_cast<char>(0xFF & (n >> 8))); |
| ndnboost::iostreams::put(next, static_cast<char>(0xFF & (n >> 16))); |
| ndnboost::iostreams::put(next, static_cast<char>(0xFF & (n >> 24))); |
| } |
| template<typename Sink> |
| static void write_long(long n, Sink& next, ndnboost::mpl::false_) |
| { |
| } |
| template<typename Sink> |
| static void write_long(long n, Sink& next) |
| { |
| typedef typename category_of<Sink>::type category; |
| typedef is_convertible<category, output> can_write; |
| write_long(n, next, can_write()); |
| } |
| |
| void close_impl() |
| { |
| #if NDNBOOST_WORKAROUND(__GNUC__, == 2) && defined(__STL_CONFIG_H) || \ |
| NDNBOOST_WORKAROUND(NDNBOOST_DINKUMWARE_STDLIB, == 1) \ |
| /**/ |
| footer_.erase(0, std::string::npos); |
| #else |
| footer_.clear(); |
| #endif |
| offset_ = 0; |
| flags_ = 0; |
| } |
| |
| enum state_type { |
| f_header_done = 1, |
| f_body_done = f_header_done << 1, |
| f_footer_done = f_body_done << 1 |
| }; |
| std::string header_; |
| std::string footer_; |
| std::size_t offset_; |
| int flags_; |
| }; |
| NDNBOOST_IOSTREAMS_PIPABLE(basic_gzip_compressor, 1) |
| |
| typedef basic_gzip_compressor<> gzip_compressor; |
| |
| //------------------Definition of helper templates for decompression----------// |
| |
| namespace detail { |
| |
| // Processes gzip headers |
| class NDNBOOST_IOSTREAMS_DECL gzip_header { |
| public: |
| gzip_header() { reset(); } |
| |
| // Members for processing header data |
| void process(char c); |
| bool done() const { return state_ == s_done; } |
| void reset(); |
| |
| // Members for accessing header data |
| 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: |
| enum state_type { |
| s_id1 = 1, |
| s_id2 = s_id1 + 1, |
| s_cm = s_id2 + 1, |
| s_flg = s_cm + 1, |
| s_mtime = s_flg + 1, |
| s_xfl = s_mtime + 1, |
| s_os = s_xfl + 1, |
| s_xlen = s_os + 1, |
| s_extra = s_xlen + 1, |
| s_name = s_extra + 1, |
| s_comment = s_name + 1, |
| s_hcrc = s_comment + 1, |
| s_done = s_hcrc + 1 |
| }; |
| std::string file_name_; |
| std::string comment_; |
| int os_; |
| std::time_t mtime_; |
| int flags_; |
| int state_; |
| int offset_; // Offset within fixed-length region. |
| int xlen_; // Bytes remaining in extra field. |
| }; |
| |
| // Processes gzip footers |
| class NDNBOOST_IOSTREAMS_DECL gzip_footer { |
| public: |
| gzip_footer() { reset(); } |
| |
| // Members for processing footer data |
| void process(char c); |
| bool done() const { return state_ == s_done; } |
| void reset(); |
| |
| // Members for accessing footer data |
| zlib::ulong crc() const { return crc_; } |
| zlib::ulong uncompressed_size() const { return isize_; } |
| private: |
| enum state_type { |
| s_crc = 1, |
| s_isize = s_crc + 1, |
| s_done = s_isize + 1 |
| }; |
| zlib::ulong crc_; |
| zlib::ulong isize_; |
| int state_; |
| int offset_; |
| }; |
| |
| } // End namespace ndnboost::iostreams::detail. |
| |
| //------------------Definition of basic_gzip_decompressor---------------------// |
| |
| // |
| // Template name: basic_gzip_decompressor |
| // Description: Model of InputFilter implementing compression in the |
| // gzip format. |
| // |
| template<typename Alloc = std::allocator<char> > |
| class basic_gzip_decompressor : basic_zlib_decompressor<Alloc> { |
| private: |
| typedef basic_zlib_decompressor<Alloc> base_type; |
| typedef typename base_type::string_type string_type; |
| public: |
| typedef char char_type; |
| struct category |
| : dual_use, |
| filter_tag, |
| multichar_tag, |
| closable_tag |
| { }; |
| basic_gzip_decompressor( int window_bits = gzip::default_window_bits, |
| int buffer_size = default_device_buffer_size ); |
| |
| template<typename Sink> |
| std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) |
| { |
| std::streamsize result = 0; |
| while(result < n) { |
| if(state_ == s_start) { |
| state_ = s_header; |
| header_.reset(); |
| footer_.reset(); |
| } |
| if (state_ == s_header) { |
| int c = s[result++]; |
| header_.process(c); |
| if (header_.done()) |
| state_ = s_body; |
| } else if (state_ == s_body) { |
| try { |
| std::streamsize amt = |
| base_type::write(snk, s + result, n - result); |
| result += amt; |
| if (!this->eof()) { |
| break; |
| } else { |
| state_ = s_footer; |
| } |
| } catch (const zlib_error& e) { |
| ndnboost::throw_exception(gzip_error(e)); |
| } |
| } else { // state_ == s_footer |
| if (footer_.done()) { |
| if (footer_.crc() != this->crc()) |
| ndnboost::throw_exception(gzip_error(gzip::bad_crc)); |
| |
| base_type::close(snk, NDNBOOST_IOS::out); |
| state_ = s_start; |
| } else { |
| int c = s[result++]; |
| footer_.process(c); |
| } |
| } |
| } |
| return result; |
| } |
| |
| template<typename Source> |
| std::streamsize read(Source& src, char_type* s, std::streamsize n) |
| { |
| typedef char_traits<char> traits_type; |
| std::streamsize result = 0; |
| peekable_source<Source> peek(src, putback_); |
| while (result < n && state_ != s_done) { |
| if (state_ == s_start) { |
| state_ = s_header; |
| header_.reset(); |
| footer_.reset(); |
| } |
| if (state_ == s_header) { |
| int c = ndnboost::iostreams::get(peek); |
| if (traits_type::is_eof(c)) { |
| ndnboost::throw_exception(gzip_error(gzip::bad_header)); |
| } else if (traits_type::would_block(c)) { |
| break; |
| } |
| header_.process(c); |
| if (header_.done()) |
| state_ = s_body; |
| } else if (state_ == s_body) { |
| try { |
| std::streamsize amt = |
| base_type::read(peek, s + result, n - result); |
| if (amt != -1) { |
| result += amt; |
| if (amt < n - result) |
| break; |
| } else { |
| peek.putback(this->unconsumed_input()); |
| state_ = s_footer; |
| } |
| } catch (const zlib_error& e) { |
| ndnboost::throw_exception(gzip_error(e)); |
| } |
| } else { // state_ == s_footer |
| int c = ndnboost::iostreams::get(peek); |
| if (traits_type::is_eof(c)) { |
| ndnboost::throw_exception(gzip_error(gzip::bad_footer)); |
| } else if (traits_type::would_block(c)) { |
| break; |
| } |
| footer_.process(c); |
| if (footer_.done()) { |
| if (footer_.crc() != this->crc()) |
| ndnboost::throw_exception(gzip_error(gzip::bad_crc)); |
| int c = ndnboost::iostreams::get(peek); |
| if (traits_type::is_eof(c)) { |
| state_ = s_done; |
| } else { |
| peek.putback(c); |
| base_type::close(peek, NDNBOOST_IOS::in); |
| state_ = s_start; |
| header_.reset(); |
| footer_.reset(); |
| } |
| } |
| } |
| } |
| if (peek.has_unconsumed_input()) { |
| putback_ = peek.unconsumed_input(); |
| } else { |
| putback_.clear(); |
| } |
| return result != 0 || state_ != s_done ? |
| result : |
| -1; |
| } |
| |
| template<typename Source> |
| void close(Source& src, NDNBOOST_IOS::openmode m) |
| { |
| try { |
| base_type::close(src, m); |
| } catch (const zlib_error& e) { |
| state_ = s_start; |
| ndnboost::throw_exception(gzip_error(e)); |
| } |
| if (m == NDNBOOST_IOS::out) { |
| if (state_ == s_start || state_ == s_header) |
| ndnboost::throw_exception(gzip_error(gzip::bad_header)); |
| else if (state_ == s_body) |
| ndnboost::throw_exception(gzip_error(gzip::bad_footer)); |
| else if (state_ == s_footer) { |
| if (!footer_.done()) |
| ndnboost::throw_exception(gzip_error(gzip::bad_footer)); |
| else if(footer_.crc() != this->crc()) |
| ndnboost::throw_exception(gzip_error(gzip::bad_crc)); |
| } else { |
| NDNBOOST_ASSERT(!"Bad state"); |
| } |
| } |
| state_ = s_start; |
| } |
| |
| std::string file_name() const { return header_.file_name(); } |
| std::string comment() const { return header_.comment(); } |
| bool text() const { return header_.text(); } |
| int os() const { return header_.os(); } |
| std::time_t mtime() const { return header_.mtime(); } |
| private: |
| static gzip_params make_params(int window_bits); |
| |
| // Source adapter allowing an arbitrary character sequence to be put back. |
| template<typename Source> |
| struct peekable_source { |
| typedef char char_type; |
| struct category : source_tag, peekable_tag { }; |
| explicit peekable_source(Source& src, const string_type& putback = "") |
| : src_(src), putback_(putback), offset_(0) |
| { } |
| std::streamsize read(char* s, std::streamsize n) |
| { |
| std::streamsize result = 0; |
| |
| // Copy characters from putback buffer |
| std::streamsize pbsize = |
| static_cast<std::streamsize>(putback_.size()); |
| if (offset_ < pbsize) { |
| result = (std::min)(n, pbsize - offset_); |
| NDNBOOST_IOSTREAMS_CHAR_TRAITS(char)::copy( |
| s, putback_.data() + offset_, result); |
| offset_ += result; |
| if (result == n) |
| return result; |
| } |
| |
| // Read characters from src_ |
| std::streamsize amt = |
| ndnboost::iostreams::read(src_, s + result, n - result); |
| return amt != -1 ? |
| result + amt : |
| result ? result : -1; |
| } |
| bool putback(char c) |
| { |
| if (offset_) { |
| putback_[--offset_] = c; |
| } else { |
| ndnboost::throw_exception( |
| ndnboost::iostreams::detail::bad_putback()); |
| } |
| return true; |
| } |
| void putback(const string_type& s) |
| { |
| putback_.replace(0, offset_, s); |
| offset_ = 0; |
| } |
| |
| // Returns true if some characters have been putback but not re-read. |
| bool has_unconsumed_input() const |
| { |
| return offset_ < static_cast<std::streamsize>(putback_.size()); |
| } |
| |
| // Returns the sequence of characters that have been put back but not re-read. |
| string_type unconsumed_input() const |
| { |
| return string_type(putback_, offset_, putback_.size() - offset_); |
| } |
| Source& src_; |
| string_type putback_; |
| std::streamsize offset_; |
| }; |
| |
| enum state_type { |
| s_start = 1, |
| s_header = s_start + 1, |
| s_body = s_header + 1, |
| s_footer = s_body + 1, |
| s_done = s_footer + 1 |
| }; |
| detail::gzip_header header_; |
| detail::gzip_footer footer_; |
| string_type putback_; |
| int state_; |
| }; |
| NDNBOOST_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() |
| { |
| ndnboost::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), |
| state_(s_start) |
| { } |
| |
| 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(NDNBOOST_MSVC) |
| # pragma warning(pop) |
| #endif |
| |
| #endif // #ifndef NDNBOOST_IOSTREAMS_GZIP_HPP_INCLUDED |