PageRenderTime 750ms CodeModel.GetById 18ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 670ms

/Src/Dependencies/Boost/boost/iostreams/filter/gzip.hpp

http://hadesmem.googlecode.com/
C++ Header | 757 lines | 601 code | 89 blank | 67 comment | 103 complexity | 02a8335b257da6bf49b5e38da710d579 MD5 | raw file
  1// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  2// (C) Copyright 2003-2007 Jonathan Turkanis
  3// Distributed under the Boost Software License, Version 1.0. (See accompanying
  4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
  5
  6// See http://www.boost.org/libs/iostreams for documentation.
  7
  8// Contains the definitions of the class templates gzip_compressor and
  9// gzip_decompressor for reading and writing files in the gzip file format
 10// (RFC 1952). Based in part on work of Jonathan de Halleux; see [...]
 11
 12#ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
 13#define BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
 14
 15#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 16# pragma once
 17#endif
 18
 19#include <boost/config.hpp> // STATIC_CONSTANT, STDC_NAMESPACE, 
 20                            // DINKUMWARE_STDLIB, __STL_CONFIG_H.
 21#include <algorithm>                      // min.
 22#include <boost/assert.hpp>
 23#include <cstdio>                         // EOF.
 24#include <cstddef>                        // size_t.
 25#include <ctime>                          // std::time_t.
 26#include <memory>                         // allocator.
 27#include <boost/config.hpp>               // Put size_t in std.
 28#include <boost/detail/workaround.hpp>
 29#include <boost/cstdint.hpp>              // uint8_t, uint32_t.
 30#include <boost/iostreams/constants.hpp>  // buffer size.
 31#include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
 32#include <boost/iostreams/detail/adapter/range_adapter.hpp>
 33#include <boost/iostreams/detail/char_traits.hpp>
 34#include <boost/iostreams/detail/ios.hpp> // failure.
 35#include <boost/iostreams/detail/error.hpp>
 36#include <boost/iostreams/operations.hpp>
 37#include <boost/iostreams/device/back_inserter.hpp>
 38#include <boost/iostreams/filter/zlib.hpp>
 39#include <boost/iostreams/pipeline.hpp>     
 40#include <boost/iostreams/putback.hpp>
 41#include <boost/throw_exception.hpp>
 42
 43// Must come last.
 44#if defined(BOOST_MSVC)
 45# pragma warning(push)
 46# pragma warning(disable: 4309)    // Truncation of constant value.
 47#endif
 48
 49#ifdef BOOST_NO_STDC_NAMESPACE
 50namespace std { using ::time_t; }
 51#endif
 52
 53namespace boost { namespace iostreams {
 54                    
 55//------------------Definitions of constants----------------------------------//
 56
 57namespace gzip {
 58
 59using namespace boost::iostreams::zlib;
 60
 61    // Error codes used by gzip_error.
 62
 63const int zlib_error        = 1;
 64const int bad_crc           = 2; // Recorded crc doesn't match data.
 65const int bad_length        = 3; // Recorded length doesn't match data.
 66const int bad_header        = 4; // Malformed header.
 67const int bad_footer        = 5; // Malformed footer.
 68const int bad_method        = 6; // Unsupported compression method.
 69
 70namespace magic {
 71
 72    // Magic numbers used by gzip header.
 73
 74const int id1               = 0x1f;
 75const int id2               = 0x8b;
 76
 77} // End namespace magic.
 78
 79namespace method {
 80
 81    // Codes used for the 'CM' byte of the gzip header.
 82
 83const int deflate           = 8;
 84
 85} // End namespace method.
 86
 87namespace flags {
 88
 89    // Codes used for the 'FLG' byte of the gzip header.
 90
 91const int text              = 1;
 92const int header_crc        = 2;
 93const int extra             = 4;
 94const int name              = 8;
 95const int comment           = 16;
 96
 97} // End namespace flags.
 98
 99namespace extra_flags {
100
101    // Codes used for the 'XFL' byte of the gzip header.
102
103const int best_compression  = 2;
104const int best_speed        = 4;
105
106} // End namespace extra_flags.
107
108    // Codes used for the 'OS' byte of the gzip header.
109
110const int os_fat            = 0;
111const int os_amiga          = 1;
112const int os_vms            = 2;
113const int os_unix           = 3;
114const int os_vm_cms         = 4;
115const int os_atari          = 5;
116const int os_hpfs           = 6;
117const int os_macintosh      = 7;
118const int os_z_system       = 8;
119const int os_cp_m           = 9;
120const int os_tops_20        = 10;
121const int os_ntfs           = 11;
122const int os_qdos           = 12;
123const int os_acorn          = 13;
124const int os_unknown        = 255;
125
126} // End namespace gzip.
127
128//------------------Definition of gzip_params---------------------------------//
129
130//
131// Class name: gzip_params.
132// Description: Subclass of zlib_params with an additional field
133//      representing a file name.
134//
135struct gzip_params : zlib_params {
136
137    // Non-explicit constructor.
138    gzip_params( int level              = gzip::default_compression,
139                 int method             = gzip::deflated,
140                 int window_bits        = gzip::default_window_bits,
141                 int mem_level          = gzip::default_mem_level,
142                 int strategy           = gzip::default_strategy,
143                 std::string file_name  = "",
144                 std::string comment    = "",
145                 std::time_t mtime      = 0 )
146        : zlib_params(level, method, window_bits, mem_level, strategy),
147          file_name(file_name), comment(comment), mtime(mtime)
148        { }
149    std::string  file_name;
150    std::string  comment;
151    std::time_t  mtime;
152};
153
154//------------------Definition of gzip_error----------------------------------//
155
156//
157// Class name: gzip_error.
158// Description: Subclass of std::ios_base::failure thrown to indicate
159//     zlib errors other than out-of-memory conditions.
160//
161class gzip_error : public BOOST_IOSTREAMS_FAILURE {
162public:
163    explicit gzip_error(int error)
164        : BOOST_IOSTREAMS_FAILURE("gzip error"),
165          error_(error), zlib_error_code_(zlib::okay) { }
166    explicit gzip_error(const zlib_error& e)
167        : BOOST_IOSTREAMS_FAILURE("gzip error"),
168          error_(gzip::zlib_error), zlib_error_code_(e.error())
169        { }
170    int error() const { return error_; }
171    int zlib_error_code() const { return zlib_error_code_; }
172private:
173    int error_;
174    int zlib_error_code_;
175};
176
177//------------------Definition of gzip_compressor-----------------------------//
178
179//
180// Template name: gzip_compressor
181// Description: Model of OutputFilter implementing compression in the
182//      gzip format.
183//
184template<typename Alloc = std::allocator<char> >
185class basic_gzip_compressor : basic_zlib_compressor<Alloc> {
186private:
187    typedef basic_zlib_compressor<Alloc>  base_type;
188public:
189    typedef char char_type;
190    struct category
191        : dual_use,
192          filter_tag,
193          multichar_tag,
194          closable_tag
195        { };
196    basic_gzip_compressor( const gzip_params& = gzip::default_compression,
197                           int buffer_size = default_device_buffer_size );
198
199    template<typename Source>
200    std::streamsize read(Source& src, char_type* s, std::streamsize n)
201    {
202        std::streamsize result = 0;
203
204        // Read header.
205        if (!(flags_ & f_header_done))
206            result += read_string(s, n, header_);
207
208        // Read body.
209        if (!(flags_ & f_body_done)) {
210
211            // Read from basic_zlib_filter.
212            std::streamsize amt = base_type::read(src, s + result, n - result);
213            if (amt != -1) {
214                result += amt;
215                if (amt < n - result) { // Double-check for EOF.
216                    amt = base_type::read(src, s + result, n - result);
217                    if (amt != -1)
218                        result += amt;
219                }
220            }
221            if (amt == -1)
222                prepare_footer();
223        }
224
225        // Read footer.
226        if ((flags_ & f_body_done) != 0 && result < n)
227            result += read_string(s + result, n - result, footer_);
228
229        return result != 0 ? result : -1;
230    }
231
232    template<typename Sink>
233    std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
234    {
235        if (!(flags_ & f_header_done)) {
236            std::streamsize amt = 
237                static_cast<std::streamsize>(header_.size() - offset_);
238            offset_ += boost::iostreams::write(snk, header_.data() + offset_, amt);
239            if (offset_ == header_.size())
240                flags_ |= f_header_done;
241            else
242                return 0;
243        }
244        return base_type::write(snk, s, n);
245    }
246
247    template<typename Sink>
248    void close(Sink& snk, BOOST_IOS::openmode m)
249    {
250        try {
251            // Close zlib compressor.
252            base_type::close(snk, m);
253
254            if (m == BOOST_IOS::out) {
255                if (flags_ & f_header_done) {
256
257                    // Write final fields of gzip file format.
258                    write_long(this->crc(), snk);
259                    write_long(this->total_in(), snk);
260                }
261            }
262        } catch(...) {
263            close_impl();
264            throw;
265        }
266        close_impl();
267    }
268private:
269    static gzip_params normalize_params(gzip_params p);
270    void prepare_footer();
271    std::streamsize read_string(char* s, std::streamsize n, std::string& str);
272
273    template<typename Sink>
274    static void write_long(long n, Sink& next, boost::mpl::true_)
275    {
276        boost::iostreams::put(next, static_cast<char>(0xFF & n));
277        boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 8)));
278        boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 16)));
279        boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 24)));
280    }
281    template<typename Sink>
282    static void write_long(long n, Sink& next, boost::mpl::false_)
283    {
284    }
285    template<typename Sink>
286    static void write_long(long n, Sink& next)
287    {
288        typedef typename category_of<Sink>::type category;
289        typedef is_convertible<category, output> can_write;
290        write_long(n, next, can_write());
291    }
292
293    void close_impl()
294    {
295        #if BOOST_WORKAROUND(__GNUC__, == 2) && defined(__STL_CONFIG_H) || \
296            BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) \
297            /**/
298            footer_.erase(0, std::string::npos);
299        #else
300            footer_.clear();
301        #endif
302        offset_ = 0;
303        flags_ = 0;
304    }
305
306    enum state_type {
307        f_header_done = 1,
308        f_body_done = f_header_done << 1,
309        f_footer_done = f_body_done << 1
310    };
311    std::string  header_;
312    std::string  footer_;
313    std::size_t  offset_;
314    int          flags_;
315};
316BOOST_IOSTREAMS_PIPABLE(basic_gzip_compressor, 1)
317
318typedef basic_gzip_compressor<> gzip_compressor;
319
320//------------------Definition of helper templates for decompression----------//
321
322namespace detail {
323
324// Processes gzip headers
325class BOOST_IOSTREAMS_DECL gzip_header {
326public:
327    gzip_header() { reset(); }
328
329    // Members for processing header data
330    void process(char c);
331    bool done() const { return state_ == s_done; }
332    void reset();
333
334    // Members for accessing header data
335    std::string file_name() const { return file_name_; }
336    std::string comment() const { return comment_; }
337    bool text() const { return (flags_ & gzip::flags::text) != 0; }
338    int os() const { return os_; }
339    std::time_t mtime() const { return mtime_; }
340private:
341    enum state_type {
342        s_id1       = 1,
343        s_id2       = s_id1 + 1,
344        s_cm        = s_id2 + 1,
345        s_flg       = s_cm + 1,
346        s_mtime     = s_flg + 1,
347        s_xfl       = s_mtime + 1,
348        s_os        = s_xfl + 1,
349        s_xlen      = s_os + 1,
350        s_extra     = s_xlen + 1,
351        s_name      = s_extra + 1,
352        s_comment   = s_name + 1,
353        s_hcrc      = s_comment + 1,
354        s_done      = s_hcrc + 1
355    };
356    std::string  file_name_;
357    std::string  comment_;
358    int          os_;
359    std::time_t  mtime_;
360    int          flags_;
361    int          state_;
362    int          offset_;  // Offset within fixed-length region.
363    int          xlen_;    // Bytes remaining in extra field.
364};
365
366// Processes gzip footers
367class BOOST_IOSTREAMS_DECL gzip_footer {
368public:
369    gzip_footer() { reset(); }
370    
371    // Members for processing footer data
372    void process(char c);
373    bool done() const { return state_ == s_done; }
374    void reset();
375    
376    // Members for accessing footer data
377    zlib::ulong crc() const { return crc_; }
378    zlib::ulong uncompressed_size() const { return isize_; }
379private:
380    enum state_type {
381        s_crc     = 1,
382        s_isize   = s_crc + 1,
383        s_done    = s_isize + 1
384    };
385    zlib::ulong  crc_;
386    zlib::ulong  isize_;
387    int          state_;
388    int          offset_; 
389};
390
391} // End namespace boost::iostreams::detail.
392
393//------------------Definition of basic_gzip_decompressor---------------------//
394
395//
396// Template name: basic_gzip_decompressor
397// Description: Model of InputFilter implementing compression in the
398//      gzip format.
399//
400template<typename Alloc = std::allocator<char> >
401class basic_gzip_decompressor : basic_zlib_decompressor<Alloc> {
402private:
403    typedef basic_zlib_decompressor<Alloc>   base_type;
404    typedef typename base_type::string_type  string_type;
405public:
406    typedef char char_type;
407    struct category
408        : dual_use,
409          filter_tag,
410          multichar_tag,
411          closable_tag
412        { };
413    basic_gzip_decompressor( int window_bits = gzip::default_window_bits,
414                             int buffer_size = default_device_buffer_size );
415
416    template<typename Sink>
417    std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
418    {
419        std::streamsize result = 0;
420        while(result < n) {
421            if(state_ == s_start) {
422                state_ = s_header;
423                header_.reset();
424                footer_.reset();
425            }
426            if (state_ == s_header) {
427                int c = s[result++];
428                header_.process(c);
429                if (header_.done())
430                    state_ = s_body;
431            } else if (state_ == s_body) {
432                try {
433                    std::streamsize amt = 
434                        base_type::write(snk, s + result, n - result);
435                    result += amt;
436                    if (!this->eof()) {
437                        break;
438                    } else {
439                        state_ = s_footer;
440                    }
441                } catch (const zlib_error& e) {
442                    boost::throw_exception(gzip_error(e));
443                }
444            } else { // state_ == s_footer
445                if (footer_.done()) {
446                    if (footer_.crc() != this->crc())
447                        boost::throw_exception(gzip_error(gzip::bad_crc));
448
449                    base_type::close(snk, BOOST_IOS::out);
450                    state_ = s_start;
451                } else {
452                    int c = s[result++];
453                    footer_.process(c);
454                }
455            }
456        }
457        return result;
458    }
459
460    template<typename Source>
461    std::streamsize read(Source& src, char_type* s, std::streamsize n)
462    {
463        typedef char_traits<char>  traits_type;
464        std::streamsize            result = 0;
465        peekable_source<Source>    peek(src, putback_);
466        while (result < n && state_ != s_done) {
467            if (state_ == s_start) {
468                state_ = s_header;
469                header_.reset();
470                footer_.reset();
471            }
472            if (state_ == s_header) {
473                int c = boost::iostreams::get(peek);
474                if (traits_type::is_eof(c)) {
475                    boost::throw_exception(gzip_error(gzip::bad_header));
476                } else if (traits_type::would_block(c)) {
477                    break;
478                }
479                header_.process(c);
480                if (header_.done())
481                    state_ = s_body;
482            } else if (state_ == s_body) {
483                try {
484                    std::streamsize amt = 
485                        base_type::read(peek, s + result, n - result);
486                    if (amt != -1) {
487                        result += amt;
488                        if (amt < n - result)
489                            break;
490                    } else {
491                        peek.putback(this->unconsumed_input());
492                        state_ = s_footer;
493                    }
494                } catch (const zlib_error& e) {
495                    boost::throw_exception(gzip_error(e));
496                }
497            } else { // state_ == s_footer
498                int c = boost::iostreams::get(peek);
499                if (traits_type::is_eof(c)) {
500                    boost::throw_exception(gzip_error(gzip::bad_footer));
501                } else if (traits_type::would_block(c)) {
502                    break;
503                }
504                footer_.process(c);
505                if (footer_.done()) {
506                    if (footer_.crc() != this->crc())
507                        boost::throw_exception(gzip_error(gzip::bad_crc));
508                    int c = boost::iostreams::get(peek);
509                    if (traits_type::is_eof(c)) {
510                        state_ = s_done;
511                    } else {
512                        peek.putback(c);
513                        base_type::close(peek, BOOST_IOS::in);
514                        state_ = s_start;
515                        header_.reset();
516                        footer_.reset();
517                    }
518                }
519            }
520        }
521        if (peek.has_unconsumed_input()) {
522            putback_ = peek.unconsumed_input();
523        } else {
524            putback_.clear();
525        }
526        return result != 0 || state_ != s_done ?
527            result :
528            -1;
529    }
530
531    template<typename Source>
532    void close(Source& src, BOOST_IOS::openmode m)
533    {
534        try {
535            base_type::close(src, m);
536        } catch (const zlib_error& e) {
537            state_ = s_start;
538            boost::throw_exception(gzip_error(e));
539        }
540        if (m == BOOST_IOS::out) {
541            if (state_ == s_start || state_ == s_header)
542                boost::throw_exception(gzip_error(gzip::bad_header));
543            else if (state_ == s_body)
544                boost::throw_exception(gzip_error(gzip::bad_footer));
545            else if (state_ == s_footer) {
546                if (!footer_.done())
547                    boost::throw_exception(gzip_error(gzip::bad_footer));
548                else if(footer_.crc() != this->crc())
549                    boost::throw_exception(gzip_error(gzip::bad_crc));
550            } else {
551                BOOST_ASSERT(!"Bad state");
552            }
553        }
554        state_ = s_start;
555    }
556
557    std::string file_name() const { return header_.file_name(); }
558    std::string comment() const { return header_.comment(); }
559    bool text() const { return header_.text(); }
560    int os() const { return header_.os(); }
561    std::time_t mtime() const { return header_.mtime(); }
562private:
563    static gzip_params make_params(int window_bits);
564
565    // Source adapter allowing an arbitrary character sequence to be put back.
566    template<typename Source>
567    struct peekable_source {
568        typedef char char_type;
569        struct category : source_tag, peekable_tag { };
570        explicit peekable_source(Source& src, const string_type& putback = "") 
571            : src_(src), putback_(putback), offset_(0)
572            { }
573        std::streamsize read(char* s, std::streamsize n)
574        {
575            std::streamsize result = 0;
576
577            // Copy characters from putback buffer
578            std::streamsize pbsize = 
579                static_cast<std::streamsize>(putback_.size());
580            if (offset_ < pbsize) {
581                result = (std::min)(n, pbsize - offset_);
582                BOOST_IOSTREAMS_CHAR_TRAITS(char)::copy(
583                    s, putback_.data() + offset_, result);
584                offset_ += result;
585                if (result == n)
586                    return result;
587            }
588
589            // Read characters from src_
590            std::streamsize amt = 
591                boost::iostreams::read(src_, s + result, n - result);
592            return amt != -1 ? 
593                result + amt : 
594                result ? result : -1;
595        }
596        bool putback(char c)
597        {
598            if (offset_) {
599                putback_[--offset_] = c;
600            } else {
601                boost::throw_exception(
602                    boost::iostreams::detail::bad_putback());
603            }
604            return true;
605        }
606        void putback(const string_type& s)
607        {
608            putback_.replace(0, offset_, s);
609            offset_ = 0;
610        }
611
612        // Returns true if some characters have been putback but not re-read.
613        bool has_unconsumed_input() const 
614        {
615            return offset_ < static_cast<std::streamsize>(putback_.size());
616        }
617
618        // Returns the sequence of characters that have been put back but not re-read.
619        string_type unconsumed_input() const
620        {
621            return string_type(putback_, offset_, putback_.size() - offset_);
622        }
623        Source&          src_;
624        string_type      putback_;
625        std::streamsize  offset_;
626    };
627
628    enum state_type {
629        s_start   = 1,
630        s_header  = s_start + 1,
631        s_body    = s_header + 1,
632        s_footer  = s_body + 1,
633        s_done    = s_footer + 1
634    };
635    detail::gzip_header  header_;
636    detail::gzip_footer  footer_;
637    string_type          putback_;
638    int                  state_;
639};
640BOOST_IOSTREAMS_PIPABLE(basic_gzip_decompressor, 1)
641
642typedef basic_gzip_decompressor<> gzip_decompressor;
643
644//------------------Implementation of gzip_compressor-------------------------//
645
646template<typename Alloc>
647basic_gzip_compressor<Alloc>::basic_gzip_compressor
648    (const gzip_params& p, int buffer_size)
649    : base_type(normalize_params(p), buffer_size),
650      offset_(0), flags_(0)
651{
652    // Calculate gzip header.
653    bool has_name = !p.file_name.empty();
654    bool has_comment = !p.comment.empty();
655
656    std::string::size_type length =
657        10 +
658        (has_name ? p.file_name.size() + 1 : 0) +
659        (has_comment ? p.comment.size() + 1 : 0);
660        // + 2; // Header crc confuses gunzip.
661    int flags =
662        //gzip::flags::header_crc +
663        (has_name ? gzip::flags::name : 0) +
664        (has_comment ? gzip::flags::comment : 0);
665    int extra_flags =
666        ( p.level == zlib::best_compression ?
667              gzip::extra_flags::best_compression :
668              0 ) +
669        ( p.level == zlib::best_speed ?
670              gzip::extra_flags::best_speed :
671              0 );
672    header_.reserve(length);
673    header_ += gzip::magic::id1;                         // ID1.
674    header_ += gzip::magic::id2;                         // ID2.
675    header_ += gzip::method::deflate;                    // CM.
676    header_ += static_cast<char>(flags);                 // FLG.
677    header_ += static_cast<char>(0xFF & p.mtime);        // MTIME.
678    header_ += static_cast<char>(0xFF & (p.mtime >> 8));
679    header_ += static_cast<char>(0xFF & (p.mtime >> 16));
680    header_ += static_cast<char>(0xFF & (p.mtime >> 24));
681    header_ += static_cast<char>(extra_flags);           // XFL.
682    header_ += static_cast<char>(gzip::os_unknown);      // OS.
683    if (has_name) {
684        header_ += p.file_name;
685        header_ += '\0';
686    }
687    if (has_comment) {
688        header_ += p.comment;
689        header_ += '\0';
690    }
691}
692
693template<typename Alloc>
694gzip_params basic_gzip_compressor<Alloc>::normalize_params(gzip_params p)
695{
696    p.noheader = true;
697    p.calculate_crc = true;
698    return p;
699}
700
701template<typename Alloc>
702void basic_gzip_compressor<Alloc>::prepare_footer()
703{
704    boost::iostreams::back_insert_device<std::string> out(footer_);
705    write_long(this->crc(), out);
706    write_long(this->total_in(), out);
707    flags_ |= f_body_done;
708    offset_ = 0;
709}
710
711template<typename Alloc>
712std::streamsize basic_gzip_compressor<Alloc>::read_string
713    (char* s, std::streamsize n, std::string& str)
714{
715    std::streamsize avail =
716        static_cast<std::streamsize>(str.size() - offset_);
717    std::streamsize amt = (std::min)(avail, n);
718    std::copy( str.data() + offset_,
719               str.data() + offset_ + amt,
720               s );
721    offset_ += amt;
722    if ( !(flags_ & f_header_done) &&
723         offset_ == static_cast<std::size_t>(str.size()) )
724    {
725        flags_ |= f_header_done;
726    }
727    return amt;
728}
729
730//------------------Implementation of gzip_decompressor-----------------------//
731
732template<typename Alloc>
733basic_gzip_decompressor<Alloc>::basic_gzip_decompressor
734    (int window_bits, int buffer_size)
735    : base_type(make_params(window_bits), buffer_size),
736      state_(s_start)
737    { }
738
739template<typename Alloc>
740gzip_params basic_gzip_decompressor<Alloc>::make_params(int window_bits)
741{
742    gzip_params p;
743    p.window_bits = window_bits;
744    p.noheader = true;
745    p.calculate_crc = true;
746    return p;
747}
748
749//----------------------------------------------------------------------------//
750
751} } // End namespaces iostreams, boost.
752
753#if defined(BOOST_MSVC)
754# pragma warning(pop)
755#endif
756
757#endif // #ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED