Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / iostreams / filter / zlib.hpp
1 // (C) Copyright Jonathan Turkanis 2003.
2 // Distributed under the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4
5 // See http://www.boost.org/libs/iostreams for documentation.
6
7 // Note: custom allocators are not supported on VC6, since that compiler
8 // had trouble finding the function zlib_base::do_init.
9
10 #ifndef BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED
11 #define BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED
12
13 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
14 # pragma once
15 #endif              
16
17 #include <cassert>                            
18 #include <iosfwd>            // streamsize.                 
19 #include <memory>            // allocator, bad_alloc.
20 #include <new>          
21 #include <boost/config.hpp>  // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM.
22 #include <boost/detail/workaround.hpp>
23 #include <boost/iostreams/constants.hpp>   // buffer size.
24 #include <boost/iostreams/detail/config/auto_link.hpp>
25 #include <boost/iostreams/detail/config/dyn_link.hpp>
26 #include <boost/iostreams/detail/config/wide_streams.hpp>
27 #include <boost/iostreams/detail/config/zlib.hpp>
28 #include <boost/iostreams/detail/ios.hpp>  // failure, streamsize.
29 #include <boost/iostreams/filter/symmetric.hpp>                
30 #include <boost/iostreams/pipeline.hpp>                
31 #include <boost/type_traits/is_same.hpp>
32
33 // Must come last.
34 #ifdef BOOST_MSVC
35 # pragma warning(push)
36 # pragma warning(disable:4251 4231 4660)         // Dependencies not exported.
37 #endif
38 #include <boost/config/abi_prefix.hpp>           
39
40 namespace boost { namespace iostreams {
41
42 namespace zlib {
43                     // Typedefs
44
45 typedef unsigned int uint;
46 typedef unsigned char byte;
47 typedef unsigned long ulong;
48
49 typedef void* (*alloc_func)(void*, zlib::uint, zlib::uint);
50 typedef void (*free_func)(void*, void*);
51
52                     // Compression levels
53
54 BOOST_IOSTREAMS_DECL extern const int no_compression;
55 BOOST_IOSTREAMS_DECL extern const int best_speed;
56 BOOST_IOSTREAMS_DECL extern const int best_compression;
57 BOOST_IOSTREAMS_DECL extern const int default_compression;
58
59                     // Compression methods
60
61 BOOST_IOSTREAMS_DECL extern const int deflated;
62
63                     // Compression strategies
64
65 BOOST_IOSTREAMS_DECL extern const int default_strategy;
66 BOOST_IOSTREAMS_DECL extern const int filtered;
67 BOOST_IOSTREAMS_DECL extern const int huffman_only;
68
69                     // Status codes
70
71 BOOST_IOSTREAMS_DECL extern const int okay;
72 BOOST_IOSTREAMS_DECL extern const int stream_end;
73 BOOST_IOSTREAMS_DECL extern const int stream_error;
74 BOOST_IOSTREAMS_DECL extern const int version_error;
75 BOOST_IOSTREAMS_DECL extern const int data_error;
76 BOOST_IOSTREAMS_DECL extern const int mem_error;
77 BOOST_IOSTREAMS_DECL extern const int buf_error;
78
79                     // Flush codes
80
81 BOOST_IOSTREAMS_DECL extern const int finish;
82 BOOST_IOSTREAMS_DECL extern const int no_flush;
83 BOOST_IOSTREAMS_DECL extern const int sync_flush;
84
85                     // Code for current OS
86
87 //BOOST_IOSTREAMS_DECL extern const int os_code;
88
89                     // Null pointer constant.
90
91 const int null                               = 0;
92
93                     // Default values
94
95 const int default_window_bits                = 15;
96 const int default_mem_level                  = 8;
97 const bool default_crc                       = false;
98 const bool default_noheader                  = false;
99
100 } // End namespace zlib. 
101
102 //
103 // Class name: zlib_params.
104 // Description: Encapsulates the parameters passed to deflateInit2
105 //      and inflateInit2 to customize compression and decompression.
106 //
107 struct zlib_params {
108
109     // Non-explicit constructor.
110     zlib_params( int level           = zlib::default_compression,
111                  int method          = zlib::deflated,
112                  int window_bits     = zlib::default_window_bits, 
113                  int mem_level       = zlib::default_mem_level, 
114                  int strategy        = zlib::default_strategy,
115                  bool noheader       = zlib::default_noheader,
116                  bool calculate_crc  = zlib::default_crc )
117         : level(level), method(method), window_bits(window_bits),
118           mem_level(mem_level), strategy(strategy),  
119           noheader(noheader), calculate_crc(calculate_crc)
120         { }
121     int level;
122     int method;
123     int window_bits;
124     int mem_level;
125     int strategy;
126     bool noheader;
127     bool calculate_crc;
128 };
129
130 //
131 // Class name: zlib_error.
132 // Description: Subclass of std::ios::failure thrown to indicate
133 //     zlib errors other than out-of-memory conditions.
134 //
135 class BOOST_IOSTREAMS_DECL zlib_error : public BOOST_IOSTREAMS_FAILURE {
136 public:
137     explicit zlib_error(int error);
138     int error() const { return error_; }
139     static void check(int error);
140 private:
141     int error_;
142 };
143
144 namespace detail {
145
146 template<typename Alloc>
147 struct zlib_allocator_traits {
148 #ifndef BOOST_NO_STD_ALLOCATOR
149     typedef typename Alloc::template rebind<char>::other type;
150 #else
151     typedef std::allocator<char> type;
152 #endif
153 };
154
155 template< typename Alloc,
156           typename Base = // VC6 workaround (C2516)
157               BOOST_DEDUCED_TYPENAME zlib_allocator_traits<Alloc>::type >
158 struct zlib_allocator : private Base {
159 private:
160     typedef typename Base::size_type size_type;
161 public:
162     BOOST_STATIC_CONSTANT(bool, custom = 
163         (!is_same<std::allocator<char>, Base>::value));
164     typedef typename zlib_allocator_traits<Alloc>::type allocator_type;
165     static void* allocate(void* self, zlib::uint items, zlib::uint size);
166     static void deallocate(void* self, void* address);
167 };
168
169 class BOOST_IOSTREAMS_DECL zlib_base { 
170 public:
171     typedef char char_type;
172 protected:
173     zlib_base();
174     ~zlib_base();
175     void* stream() { return stream_; }
176     template<typename Alloc> 
177     void init( const zlib_params& p, 
178                bool compress,
179                zlib_allocator<Alloc>& zalloc )
180         {
181             bool custom = zlib_allocator<Alloc>::custom;
182             do_init( p, compress,
183                      #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
184                          custom ? zlib_allocator<Alloc>::allocate : 0,
185                          custom ? zlib_allocator<Alloc>::deallocate : 0,
186                      #endif
187                      &zalloc );
188         }
189     void before( const char*& src_begin, const char* src_end,
190                  char*& dest_begin, char* dest_end );
191     void after( const char*& src_begin, char*& dest_begin, 
192                 bool compress );
193     int deflate(int flush);
194     int inflate(int flush);
195     void reset(bool compress, bool realloc);
196 public:
197     zlib::ulong crc() const { return crc_; }
198     int total_in() const { return total_in_; }
199     int total_out() const { return total_out_; }
200 private:
201     void do_init( const zlib_params& p, bool compress, 
202                   #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
203                       zlib::alloc_func, 
204                       zlib::free_func, 
205                   #endif
206                   void* derived );
207     void*        stream_;         // Actual type: z_stream*.
208     bool         calculate_crc_;
209     zlib::ulong  crc_;
210     int          total_in_;
211     int          total_out_;
212 };
213
214 //
215 // Template name: zlib_compressor_impl
216 // Description: Model of C-Style Filte implementing compression by
217 //      delegating to the zlib function deflate.
218 //
219 template<typename Alloc = std::allocator<char> >
220 class zlib_compressor_impl : public zlib_base, public zlib_allocator<Alloc> { 
221 public: 
222     zlib_compressor_impl(const zlib_params& = zlib::default_compression);
223     ~zlib_compressor_impl();
224     bool filter( const char*& src_begin, const char* src_end,
225                  char*& dest_begin, char* dest_end, bool flush );
226     void close();
227 };
228
229 //
230 // Template name: zlib_compressor
231 // Description: Model of C-Style Filte implementing decompression by
232 //      delegating to the zlib function inflate.
233 //
234 template<typename Alloc = std::allocator<char> >
235 class zlib_decompressor_impl : public zlib_base, public zlib_allocator<Alloc> {
236 public:
237     zlib_decompressor_impl(const zlib_params&);
238     zlib_decompressor_impl(int window_bits = zlib::default_window_bits);
239     ~zlib_decompressor_impl();
240     bool filter( const char*& begin_in, const char* end_in,
241                  char*& begin_out, char* end_out, bool flush );
242     void close();
243 };
244
245 } // End namespace detail.
246
247 //
248 // Template name: zlib_compressor
249 // Description: Model of InputFilter and OutputFilter implementing
250 //      compression using zlib.
251 //
252 template<typename Alloc = std::allocator<char> >
253 struct basic_zlib_compressor 
254     : symmetric_filter<detail::zlib_compressor_impl<Alloc>, Alloc> 
255 {
256 private:
257     typedef detail::zlib_compressor_impl<Alloc>         impl_type;
258     typedef symmetric_filter<impl_type, Alloc>  base_type;
259 public:
260     typedef typename base_type::char_type               char_type;
261     typedef typename base_type::category                category;
262     basic_zlib_compressor( const zlib_params& = zlib::default_compression, 
263                            int buffer_size = default_device_buffer_size );
264     zlib::ulong crc() { return this->filter().crc(); }
265     int total_in() {  return this->filter().total_in(); }
266 };
267 BOOST_IOSTREAMS_PIPABLE(basic_zlib_compressor, 1)
268
269 typedef basic_zlib_compressor<> zlib_compressor;
270
271 //
272 // Template name: zlib_decompressor
273 // Description: Model of InputFilter and OutputFilter implementing
274 //      decompression using zlib.
275 //
276 template<typename Alloc = std::allocator<char> >
277 struct basic_zlib_decompressor 
278     : symmetric_filter<detail::zlib_decompressor_impl<Alloc>, Alloc> 
279 {
280 private:
281     typedef detail::zlib_decompressor_impl<Alloc>       impl_type;
282     typedef symmetric_filter<impl_type, Alloc>  base_type;
283 public:
284     typedef typename base_type::char_type               char_type;
285     typedef typename base_type::category                category;
286     basic_zlib_decompressor( int window_bits = zlib::default_window_bits,
287                              int buffer_size = default_device_buffer_size );
288     basic_zlib_decompressor( const zlib_params& p,
289                              int buffer_size = default_device_buffer_size );
290     zlib::ulong crc() { return this->filter().crc(); }
291     int total_out() {  return this->filter().total_out(); }
292 };
293 BOOST_IOSTREAMS_PIPABLE(basic_zlib_decompressor, 1)
294
295 typedef basic_zlib_decompressor<> zlib_decompressor;
296
297 //----------------------------------------------------------------------------//
298
299 //------------------Implementation of zlib_allocator--------------------------//
300
301 namespace detail {
302
303 template<typename Alloc, typename Base>
304 void* zlib_allocator<Alloc, Base>::allocate
305     (void* self, zlib::uint items, zlib::uint size)
306
307     size_type len = items * size;
308     char* ptr = 
309         static_cast<allocator_type*>(self)->allocate
310             (len + sizeof(size_type)
311             #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
312                 , (char*)0
313             #endif
314             );
315     *reinterpret_cast<size_type*>(ptr) = len;
316     return ptr + sizeof(size_type);
317 }
318
319 template<typename Alloc, typename Base>
320 void zlib_allocator<Alloc, Base>::deallocate(void* self, void* address)
321
322     char* ptr = reinterpret_cast<char*>(address) - sizeof(size_type);
323     size_type len = *reinterpret_cast<size_type*>(ptr) + sizeof(size_type);
324     static_cast<allocator_type*>(self)->deallocate(ptr, len); 
325 }
326
327 //------------------Implementation of zlib_compressor_impl--------------------//
328
329 template<typename Alloc>
330 zlib_compressor_impl<Alloc>::zlib_compressor_impl(const zlib_params& p)
331 { init(p, true, static_cast<zlib_allocator<Alloc>&>(*this)); }
332
333 template<typename Alloc>
334 zlib_compressor_impl<Alloc>::~zlib_compressor_impl()
335 { reset(true, false); }
336
337 template<typename Alloc>
338 bool zlib_compressor_impl<Alloc>::filter
339     ( const char*& src_begin, const char* src_end,
340       char*& dest_begin, char* dest_end, bool flush )
341 {
342     before(src_begin, src_end, dest_begin, dest_end);
343     int result = deflate(flush ? zlib::finish : zlib::no_flush);
344     after(src_begin, dest_begin, true);
345     zlib_error::check(result);
346     return result != zlib::stream_end; 
347 }
348
349 template<typename Alloc>
350 void zlib_compressor_impl<Alloc>::close() { reset(true, true); }
351
352 //------------------Implementation of zlib_decompressor_impl------------------//
353
354 template<typename Alloc>
355 zlib_decompressor_impl<Alloc>::zlib_decompressor_impl(const zlib_params& p)
356 { init(p, false, static_cast<zlib_allocator<Alloc>&>(*this)); }
357
358 template<typename Alloc>
359 zlib_decompressor_impl<Alloc>::~zlib_decompressor_impl()
360 { reset(false, false); }
361
362 template<typename Alloc>
363 zlib_decompressor_impl<Alloc>::zlib_decompressor_impl(int window_bits)
364
365     zlib_params p;
366     p.window_bits = window_bits;
367     init(p, false, static_cast<zlib_allocator<Alloc>&>(*this)); 
368 }
369
370 template<typename Alloc>
371 bool zlib_decompressor_impl<Alloc>::filter
372     ( const char*& src_begin, const char* src_end,
373       char*& dest_begin, char* dest_end, bool /* flush */ )
374 {
375     before(src_begin, src_end, dest_begin, dest_end);
376     int result = inflate(zlib::sync_flush);
377     after(src_begin, dest_begin, false);
378     zlib_error::check(result);
379     return result != zlib::stream_end;
380 }
381
382 template<typename Alloc>
383 void zlib_decompressor_impl<Alloc>::close() { reset(false, true); }
384
385 } // End namespace detail.
386
387 //------------------Implementation of zlib_decompressor-----------------------//
388
389 template<typename Alloc>
390 basic_zlib_compressor<Alloc>::basic_zlib_compressor
391     (const zlib_params& p, int buffer_size) 
392     : base_type(buffer_size, p) { }
393
394 //------------------Implementation of zlib_decompressor-----------------------//
395
396 template<typename Alloc>
397 basic_zlib_decompressor<Alloc>::basic_zlib_decompressor
398     (int window_bits, int buffer_size) 
399     : base_type(buffer_size, window_bits) { }
400
401 template<typename Alloc>
402 basic_zlib_decompressor<Alloc>::basic_zlib_decompressor
403     (const zlib_params& p, int buffer_size) 
404     : base_type(buffer_size, p) { }
405
406 //----------------------------------------------------------------------------//
407
408 } } // End namespaces iostreams, boost.
409
410 #include <boost/config/abi_suffix.hpp> // Pops abi_suffix.hpp pragmas.
411 #ifdef BOOST_MSVC
412 # pragma warning(pop)
413 #endif
414
415 #endif // #ifndef BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED