source: NonGTP/Boost/boost/iostreams/filter/bzip2.hpp @ 857

Revision 857, 12.7 KB checked in by igarcia, 18 years ago (diff)
Line 
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_BZIP2_HPP_INCLUDED
11#define BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED
12
13#if defined(_MSC_VER) && (_MSC_VER >= 1020)
14# pragma once
15#endif
16                   
17#include <cassert>                           
18#include <memory>            // allocator.
19#include <new>               // bad_alloc.
20#include <boost/config.hpp>  // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM.
21#include <boost/detail/workaround.hpp>
22#include <boost/iostreams/constants.hpp>   // buffer size.
23#include <boost/iostreams/detail/config/auto_link.hpp>
24#include <boost/iostreams/detail/config/bzip2.hpp>
25#include <boost/iostreams/detail/config/dyn_link.hpp>
26#include <boost/iostreams/detail/config/wide_streams.hpp>
27#include <boost/iostreams/detail/ios.hpp>  // failure, streamsize.
28#include <boost/iostreams/filter/symmetric.hpp>               
29#include <boost/iostreams/pipeline.hpp>       
30#include <boost/type_traits/is_same.hpp>     
31
32// Must come last.
33#ifdef BOOST_MSVC
34# pragma warning(push)
35# pragma warning(disable:4251 4231 4660)
36#endif
37#include <boost/config/abi_prefix.hpp>           
38
39// Temporary fix.
40#undef small
41
42namespace boost { namespace iostreams {
43
44namespace bzip2 {
45
46                    // Typedefs.
47
48typedef void* (*alloc_func)(void*, int, int);
49typedef void (*free_func)(void*, void*);
50
51                    // Status codes
52
53BOOST_IOSTREAMS_DECL extern const int ok;
54BOOST_IOSTREAMS_DECL extern const int run_ok;
55BOOST_IOSTREAMS_DECL extern const int flush_ok;
56BOOST_IOSTREAMS_DECL extern const int finish_ok;
57BOOST_IOSTREAMS_DECL extern const int stream_end;   
58BOOST_IOSTREAMS_DECL extern const int sequence_error;
59BOOST_IOSTREAMS_DECL extern const int param_error;
60BOOST_IOSTREAMS_DECL extern const int mem_error;
61BOOST_IOSTREAMS_DECL extern const int data_error;
62BOOST_IOSTREAMS_DECL extern const int data_error_magic;
63BOOST_IOSTREAMS_DECL extern const int io_error;
64BOOST_IOSTREAMS_DECL extern const int unexpected_eof;
65BOOST_IOSTREAMS_DECL extern const int outbuff_full;
66BOOST_IOSTREAMS_DECL extern const int config_error;
67
68                    // Action codes
69
70BOOST_IOSTREAMS_DECL extern const int finish;
71BOOST_IOSTREAMS_DECL extern const int run;
72
73                    // Default values
74
75const int default_block_size   = 9;
76const int default_work_factor  = 30;
77const bool default_small       = false;
78
79} // End namespace bzip2.
80
81//
82// Class name: bzip2_params.
83// Description: Encapsulates the parameters passed to deflateInit2
84//      to customize compression.
85//
86struct bzip2_params {
87
88    // Non-explicit constructor for compression.
89    bzip2_params( int block_size   = bzip2::default_block_size,
90                  int work_factor  = bzip2::default_work_factor )
91        : block_size(block_size), work_factor(work_factor)
92        { }
93
94    // Constructor for decompression.
95    bzip2_params(bool small)
96        : small(small), work_factor(0)
97        { }
98
99    union {
100        int   block_size;    // For compression.
101        bool  small;         // For decompression.
102    };
103    int       work_factor;
104};
105
106//
107// Class name: bzip2_error.
108// Description: Subclass of std::ios_base::failure thrown to indicate
109//     bzip2 errors other than out-of-memory conditions.
110//
111class BOOST_IOSTREAMS_DECL bzip2_error : public BOOST_IOSTREAMS_FAILURE {
112public:
113    explicit bzip2_error(int error);
114    int error() const { return error_; }
115    static void check(int error);
116private:
117    int error_;
118};
119
120namespace detail {
121
122template<typename Alloc>
123struct bzip2_allocator_traits {
124#ifndef BOOST_NO_STD_ALLOCATOR
125    typedef typename Alloc::template rebind<char>::other type;
126#else
127    typedef std::allocator<char> type;
128#endif
129};
130
131template< typename Alloc,
132          typename Base = // VC6 workaround (C2516)
133              BOOST_DEDUCED_TYPENAME bzip2_allocator_traits<Alloc>::type >
134struct bzip2_allocator : private Base {
135private:
136    typedef typename Base::size_type size_type;
137public:
138    BOOST_STATIC_CONSTANT(bool, custom =
139        (!is_same<std::allocator<char>, Base>::value));
140    typedef typename bzip2_allocator_traits<Alloc>::type allocator_type;
141    static void* allocate(void* self, int items, int size);
142    static void deallocate(void* self, void* address);
143};
144
145class BOOST_IOSTREAMS_DECL bzip2_base  {
146public:
147    typedef char char_type;
148protected:
149    bzip2_base(const bzip2_params& params);
150    ~bzip2_base();
151    bzip2_params& params() { return params_; }
152    bool& ready() { return ready_; }
153    template<typename Alloc>
154    void init( bool compress,
155               bzip2_allocator<Alloc>& alloc )
156        {
157            bool custom = bzip2_allocator<Alloc>::custom;
158            do_init( compress,
159                     #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
160                         custom ? bzip2_allocator<Alloc>::allocate : 0,
161                         custom ? bzip2_allocator<Alloc>::deallocate : 0,
162                     #endif
163                     custom ? &alloc : 0 );
164        }
165    void before( const char*& src_begin, const char* src_end,
166                 char*& dest_begin, char* dest_end );
167    void after(const char*& src_begin, char*& dest_begin);
168    int compress(int action);
169    int decompress();
170    void end(bool compress);
171private:
172    void do_init( bool compress,
173                  #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
174                      bzip2::alloc_func,
175                      bzip2::free_func,
176                  #endif
177                  void* derived );
178    bzip2_params  params_;
179    void*         stream_; // Actual type: bz_stream*.
180    bool          ready_;
181};
182
183//
184// Template name: bzip2_compressor_impl
185// Description: Model of SymmetricFilter implementing compression by
186//      delegating to the libbzip2 function BZ_bzCompress.
187//
188template<typename Alloc = std::allocator<char> >
189class bzip2_compressor_impl
190    : public bzip2_base,
191      #if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
192          public
193      #endif
194      bzip2_allocator<Alloc>
195{
196public:
197    bzip2_compressor_impl(const bzip2_params&);
198    bool filter( const char*& src_begin, const char* src_end,
199                 char*& dest_begin, char* dest_end, bool flush );
200    void close();
201private:
202    void init();
203};
204
205//
206// Template name: bzip2_compressor
207// Description: Model of SymmetricFilter implementing decompression by
208//      delegating to the libbzip2 function BZ_bzDecompress.
209//
210template<typename Alloc = std::allocator<char> >
211class bzip2_decompressor_impl
212    : public bzip2_base,
213      #if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
214          public
215      #endif
216      bzip2_allocator<Alloc>
217{
218public:
219    bzip2_decompressor_impl(bool small = bzip2::default_small);
220    bool filter( const char*& begin_in, const char* end_in,
221                 char*& begin_out, char* end_out, bool flush );
222    void close();
223private:
224    void init();
225    bool eof_; // Guard to make sure filter() isn't called after it returns false.
226};
227
228} // End namespace detail.
229
230//
231// Template name: bzip2_compressor
232// Description: Model of InputFilter and OutputFilter implementing
233//      compression using libbzip2.
234//
235template<typename Alloc = std::allocator<char> >
236struct basic_bzip2_compressor
237    : symmetric_filter<detail::bzip2_compressor_impl<Alloc>, Alloc>
238{
239private:
240    typedef detail::bzip2_compressor_impl<Alloc>        impl_type;
241    typedef symmetric_filter<impl_type, Alloc>  base_type;
242public:
243    typedef typename base_type::char_type               char_type;
244    typedef typename base_type::category                category;
245    basic_bzip2_compressor( const bzip2_params& = bzip2::default_block_size,
246                            int buffer_size =  default_device_buffer_size );
247};
248BOOST_IOSTREAMS_PIPABLE(basic_bzip2_compressor, 1)
249
250typedef basic_bzip2_compressor<> bzip2_compressor;
251
252//
253// Template name: bzip2_decompressor
254// Description: Model of InputFilter and OutputFilter implementing
255//      decompression using libbzip2.
256//
257template<typename Alloc = std::allocator<char> >
258struct basic_bzip2_decompressor
259    : symmetric_filter<detail::bzip2_decompressor_impl<Alloc>, Alloc>
260{
261private:
262    typedef detail::bzip2_decompressor_impl<Alloc>      impl_type;
263    typedef symmetric_filter<impl_type, Alloc>  base_type;
264public:
265    typedef typename base_type::char_type               char_type;
266    typedef typename base_type::category                category;
267    basic_bzip2_decompressor( bool small = bzip2::default_small,
268                              int buffer_size = default_device_buffer_size );
269};
270BOOST_IOSTREAMS_PIPABLE(basic_bzip2_decompressor, 1)
271
272typedef basic_bzip2_decompressor<> bzip2_decompressor;
273
274//----------------------------------------------------------------------------//
275
276//------------------Implementation of bzip2_allocator-------------------------//
277
278namespace detail {
279
280template<typename Alloc, typename Base>
281void* bzip2_allocator<Alloc, Base>::allocate(void* self, int items, int size)
282{
283    size_type len = items * size;
284    char* ptr =
285        static_cast<allocator_type*>(self)->allocate
286            (len + sizeof(size_type)
287            #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
288                , (char*)0
289            #endif
290            );
291    *reinterpret_cast<size_type*>(ptr) = len;
292    return ptr + sizeof(size_type);
293}
294
295template<typename Alloc, typename Base>
296void bzip2_allocator<Alloc, Base>::deallocate(void* self, void* address)
297{
298    char* ptr = reinterpret_cast<char*>(address) - sizeof(size_type);
299    size_type len = *reinterpret_cast<size_type*>(ptr) + sizeof(size_type);
300    static_cast<allocator_type*>(self)->deallocate(ptr, len);
301}
302
303//------------------Implementation of bzip2_compressor_impl-------------------//
304
305template<typename Alloc>
306bzip2_compressor_impl<Alloc>::bzip2_compressor_impl(const bzip2_params& p)
307    : bzip2_base(p) { }
308
309template<typename Alloc>
310bool bzip2_compressor_impl<Alloc>::filter
311    ( const char*& src_begin, const char* src_end,
312      char*& dest_begin, char* dest_end, bool flush )
313{
314    if (!ready()) init();
315    before(src_begin, src_end, dest_begin, dest_end);
316    int result = compress(flush ? bzip2::finish : bzip2::run);
317    after(src_begin, dest_begin);
318    bzip2_error::check(result);
319    return result != bzip2::stream_end;
320}
321
322template<typename Alloc>
323void bzip2_compressor_impl<Alloc>::close()
324{
325    end(true);
326}
327
328template<typename Alloc>
329inline void bzip2_compressor_impl<Alloc>::init()
330{ bzip2_base::init(true, static_cast<bzip2_allocator<Alloc>&>(*this)); }
331
332//------------------Implementation of bzip2_decompressor_impl-----------------//
333
334template<typename Alloc>
335bzip2_decompressor_impl<Alloc>::bzip2_decompressor_impl(bool small)
336    : bzip2_base(bzip2_params(small)), eof_(false) { }
337
338template<typename Alloc>
339bool bzip2_decompressor_impl<Alloc>::filter
340    ( const char*& src_begin, const char* src_end,
341      char*& dest_begin, char* dest_end, bool /* flush */ )
342{
343    if (!ready())
344        init();
345    if (eof_)
346        return false;
347    before(src_begin, src_end, dest_begin, dest_end);
348    int result = decompress();
349    after(src_begin, dest_begin);
350    bzip2_error::check(result);
351    return !(eof_ = result == bzip2::stream_end);
352}
353
354template<typename Alloc>
355void bzip2_decompressor_impl<Alloc>::close() { end(false); eof_ = false; }
356
357template<typename Alloc>
358inline void bzip2_decompressor_impl<Alloc>::init()
359{ bzip2_base::init(false, static_cast<bzip2_allocator<Alloc>&>(*this)); }
360} // End namespace detail.
361
362//------------------Implementation of bzip2_decompressor----------------------//
363
364template<typename Alloc>
365basic_bzip2_compressor<Alloc>::basic_bzip2_compressor
366        (const bzip2_params& p, int buffer_size)
367    : base_type(buffer_size, p)
368    { }
369
370//------------------Implementation of bzip2_decompressor----------------------//
371
372template<typename Alloc>
373basic_bzip2_decompressor<Alloc>::basic_bzip2_decompressor
374        (bool small, int buffer_size)
375    : base_type(buffer_size, small)
376    { }
377
378//----------------------------------------------------------------------------//
379
380} } // End namespaces iostreams, boost.
381
382#include <boost/config/abi_suffix.hpp> // Pops abi_suffix.hpp pragmas.
383#ifdef BOOST_MSVC
384# pragma warning(pop)
385#endif
386
387#endif // #ifndef BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.