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 // To configure Boost to work with zlib, see the
9 // installation instructions here:
10 // http://boost.org/libs/iostreams/doc/index.html?path=7
11 
12 // Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
13 // knows that we are building the library (possibly exporting code), rather
14 // than using it (possibly importing code).
15 #define BOOST_IOSTREAMS_SOURCE
16 
17 #include <boost/throw_exception.hpp>
18 #include <boost/iostreams/detail/config/dyn_link.hpp>
19 #include <boost/iostreams/filter/zlib.hpp>
20 #include "zlib.h"   // Jean-loup Gailly's and Mark Adler's "zlib.h" header.
21                     // To configure Boost to work with zlib, see the
22                     // installation instructions here:
23                     // http://boost.org/libs/iostreams/doc/index.html?path=7
24 
25 namespace boost { namespace iostreams {
26 
27 namespace zlib {
28 
29                     // Compression levels
30 
31 const int no_compression       = Z_NO_COMPRESSION;
32 const int best_speed           = Z_BEST_SPEED;
33 const int best_compression     = Z_BEST_COMPRESSION;
34 const int default_compression  = Z_DEFAULT_COMPRESSION;
35 
36                     // Compression methods
37 
38 const int deflated             = Z_DEFLATED;
39 
40                     // Compression strategies
41 
42 const int default_strategy     = Z_DEFAULT_STRATEGY;
43 const int filtered             = Z_FILTERED;
44 const int huffman_only         = Z_HUFFMAN_ONLY;
45 
46                     // Status codes
47 
48 const int okay                 = Z_OK;
49 const int stream_end           = Z_STREAM_END;
50 const int stream_error         = Z_STREAM_ERROR;
51 const int version_error        = Z_VERSION_ERROR;
52 const int data_error           = Z_DATA_ERROR;
53 const int mem_error            = Z_MEM_ERROR;
54 const int buf_error            = Z_BUF_ERROR;
55 
56                     // Flush codes
57 
58 const int finish               = Z_FINISH;
59 const int no_flush             = Z_NO_FLUSH;
60 const int sync_flush           = Z_SYNC_FLUSH;
61 
62                     // Code for current OS
63 
64 //const int os_code              = OS_CODE;
65 
66 } // End namespace zlib.
67 
68 //------------------Implementation of zlib_error------------------------------//
69 
zlib_error(int error)70 zlib_error::zlib_error(int error)
71     : BOOST_IOSTREAMS_FAILURE("zlib error"), error_(error)
72     { }
73 
BOOST_PREVENT_MACRO_SUBSTITUTION(int error)74 void zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
75 {
76     switch (error) {
77     case Z_OK:
78     case Z_STREAM_END:
79     //case Z_BUF_ERROR:
80         return;
81     case Z_MEM_ERROR:
82         boost::throw_exception(std::bad_alloc());
83     default:
84         boost::throw_exception(zlib_error(error));
85         ;
86     }
87 }
88 
89 //------------------Implementation of zlib_base-------------------------------//
90 
91 namespace detail {
92 
zlib_base()93 zlib_base::zlib_base()
94     : stream_(new z_stream), calculate_crc_(false), crc_(0), crc_imp_(0),
95       total_in_(0), total_out_(0)
96     { }
97 
~zlib_base()98 zlib_base::~zlib_base() { delete static_cast<z_stream*>(stream_); }
99 
before(const char * & src_begin,const char * src_end,char * & dest_begin,char * dest_end)100 void zlib_base::before( const char*& src_begin, const char* src_end,
101                         char*& dest_begin, char* dest_end )
102 {
103     z_stream* s = static_cast<z_stream*>(stream_);
104     s->next_in = reinterpret_cast<zlib::byte*>(const_cast<char*>(src_begin));
105     s->avail_in = static_cast<zlib::uint>(src_end - src_begin);
106     s->next_out = reinterpret_cast<zlib::byte*>(dest_begin);
107     s->avail_out= static_cast<zlib::uint>(dest_end - dest_begin);
108 }
109 
after(const char * & src_begin,char * & dest_begin,bool compress)110 void zlib_base::after(const char*& src_begin, char*& dest_begin, bool compress)
111 {
112     z_stream* s = static_cast<z_stream*>(stream_);
113     const char* next_in = reinterpret_cast<const char*>(s->next_in);
114     char* next_out = reinterpret_cast<char*>(s->next_out);
115     if (calculate_crc_) {
116         const zlib::byte* buf = compress ?
117             reinterpret_cast<const zlib::byte*>(src_begin) :
118             reinterpret_cast<const zlib::byte*>(
119                 const_cast<const char*>(dest_begin)
120             );
121         zlib::uint length = compress ?
122             static_cast<zlib::uint>(next_in - src_begin) :
123             static_cast<zlib::uint>(next_out - dest_begin);
124         crc_ = crc_imp_ = crc32(crc_imp_, buf, length);
125     }
126     total_in_ = s->total_in;
127     total_out_ = s->total_out;
128     src_begin = next_in;
129     dest_begin = next_out;
130 }
131 
xdeflate(int flush)132 int zlib_base::xdeflate(int flush)
133 {
134     return ::deflate(static_cast<z_stream*>(stream_), flush);
135 }
136 
xinflate(int flush)137 int zlib_base::xinflate(int flush)
138 {
139     return ::inflate(static_cast<z_stream*>(stream_), flush);
140 }
141 
reset(bool compress,bool realloc)142 void zlib_base::reset(bool compress, bool realloc)
143 {
144     z_stream* s = static_cast<z_stream*>(stream_);
145     // Undiagnosed bug:
146     // deflateReset(), etc., return Z_DATA_ERROR
147     //zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
148         realloc ?
149             (compress ? deflateReset(s) : inflateReset(s)) :
150             (compress ? deflateEnd(s) : inflateEnd(s))
151                 ;
152     //);
153     crc_imp_ = 0;
154 }
155 
do_init(const zlib_params & p,bool compress,zlib::xalloc_func,zlib::xfree_func,void * derived)156 void zlib_base::do_init
157     ( const zlib_params& p, bool compress,
158       zlib::xalloc_func /* alloc */, zlib::xfree_func /* free*/,
159       void* derived )
160 {
161     calculate_crc_ = p.calculate_crc;
162     z_stream* s = static_cast<z_stream*>(stream_);
163 
164     // Current interface for customizing memory management
165     // is non-conforming and has been disabled:
166     //    s->zalloc = alloc;
167     //    s->zfree = free;
168         s->zalloc = 0;
169         s->zfree = 0;
170     s->opaque = derived;
171     int window_bits = p.noheader? -p.window_bits : p.window_bits;
172     zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
173         compress ?
174             deflateInit2( s,
175                           p.level,
176                           p.method,
177                           window_bits,
178                           p.mem_level,
179                           p.strategy ) :
180             inflateInit2(s, window_bits)
181     );
182 }
183 
184 } // End namespace detail.
185 
186 //----------------------------------------------------------------------------//
187 
188 } } // End namespaces iostreams, boost.
189