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 libbz2, 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/bzip2.hpp>
20 #include "bzlib.h"  // Julian Seward's "bzip.h" header.
21                     // To configure Boost to work with libbz2, 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 bzip2 {
28 
29                     // Status codes
30 
31 const int ok                   = BZ_OK;
32 const int run_ok               = BZ_RUN_OK;
33 const int flush_ok             = BZ_FLUSH_OK;
34 const int finish_ok            = BZ_FINISH_OK;
35 const int stream_end           = BZ_STREAM_END;
36 const int sequence_error       = BZ_SEQUENCE_ERROR;
37 const int param_error          = BZ_PARAM_ERROR;
38 const int mem_error            = BZ_MEM_ERROR;
39 const int data_error           = BZ_DATA_ERROR;
40 const int data_error_magic     = BZ_DATA_ERROR_MAGIC;
41 const int io_error             = BZ_IO_ERROR;
42 const int unexpected_eof       = BZ_UNEXPECTED_EOF;
43 const int outbuff_full         = BZ_OUTBUFF_FULL;
44 const int config_error         = BZ_CONFIG_ERROR;
45 
46                     // Action codes
47 
48 const int finish               = BZ_FINISH;
49 const int run                  = BZ_RUN;
50 
51 } // End namespace bzip2.
52 
53 //------------------Implementation of bzip2_error-----------------------------//
54 
bzip2_error(int error)55 bzip2_error::bzip2_error(int error)
56     : BOOST_IOSTREAMS_FAILURE("bzip2 error"), error_(error)
57     { }
58 
BOOST_PREVENT_MACRO_SUBSTITUTION(int error)59 void bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
60 {
61     switch (error) {
62     case BZ_OK:
63     case BZ_RUN_OK:
64     case BZ_FLUSH_OK:
65     case BZ_FINISH_OK:
66     case BZ_STREAM_END:
67         return;
68     case BZ_MEM_ERROR:
69         boost::throw_exception(std::bad_alloc());
70     default:
71         boost::throw_exception(bzip2_error(error));
72     }
73 }
74 
75 //------------------Implementation of bzip2_base------------------------------//
76 
77 namespace detail {
78 
bzip2_base(const bzip2_params & params)79 bzip2_base::bzip2_base(const bzip2_params& params)
80     : params_(params), stream_(new bz_stream), ready_(false)
81     { }
82 
~bzip2_base()83 bzip2_base::~bzip2_base() { delete static_cast<bz_stream*>(stream_); }
84 
before(const char * & src_begin,const char * src_end,char * & dest_begin,char * dest_end)85 void bzip2_base::before( const char*& src_begin, const char* src_end,
86                          char*& dest_begin, char* dest_end )
87 {
88     bz_stream* s = static_cast<bz_stream*>(stream_);
89     s->next_in = const_cast<char*>(src_begin);
90     s->avail_in = static_cast<unsigned>(src_end - src_begin);
91     s->next_out = reinterpret_cast<char*>(dest_begin);
92     s->avail_out= static_cast<unsigned>(dest_end - dest_begin);
93 }
94 
after(const char * & src_begin,char * & dest_begin)95 void bzip2_base::after(const char*& src_begin, char*& dest_begin)
96 {
97     bz_stream* s = static_cast<bz_stream*>(stream_);
98     src_begin = const_cast<char*>(s->next_in);
99     dest_begin = s->next_out;
100 }
101 
check_end(const char * src_begin,const char * dest_begin)102 int bzip2_base::check_end(const char* src_begin, const char* dest_begin)
103 {
104     bz_stream* s = static_cast<bz_stream*>(stream_);
105     if( src_begin == s->next_in &&
106         s->avail_in == 0 &&
107         dest_begin == s->next_out) {
108         return bzip2::unexpected_eof;
109     } else {
110         return bzip2::ok;
111     }
112 }
113 
end(bool compress,std::nothrow_t)114 int bzip2_base::end(bool compress, std::nothrow_t)
115 {
116     if (!ready_) return bzip2::ok;
117     ready_ = false;
118     bz_stream* s = static_cast<bz_stream*>(stream_);
119     return compress ? BZ2_bzCompressEnd(s) :  BZ2_bzDecompressEnd(s);
120 }
121 
end(bool compress)122 void bzip2_base::end(bool compress)
123 {
124     bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
125         end(compress, std::nothrow)
126     );
127 }
128 
compress(int action)129 int bzip2_base::compress(int action)
130 {
131     return BZ2_bzCompress(static_cast<bz_stream*>(stream_), action);
132 }
133 
decompress()134 int bzip2_base::decompress()
135 {
136     return BZ2_bzDecompress(static_cast<bz_stream*>(stream_));
137 }
138 
do_init(bool compress,bzip2::alloc_func,bzip2::free_func,void * derived)139 void bzip2_base::do_init
140     ( bool compress,
141       bzip2::alloc_func /* alloc */,
142       bzip2::free_func /* free */,
143       void* derived )
144 {
145     bz_stream* s = static_cast<bz_stream*>(stream_);
146 
147     // Current interface for customizing memory management
148     // is non-conforming and has been disabled:
149     //    s->bzalloc = alloc;
150     //    s->bzfree = free;
151         s->bzalloc = 0;
152         s->bzfree = 0;
153     s->opaque = derived;
154     bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
155         compress ?
156             BZ2_bzCompressInit( s,
157                                 params_.block_size,
158                                 0,
159                                 params_.work_factor ) :
160             BZ2_bzDecompressInit( s,
161                                   0,
162                                   params_.small )
163     );
164     ready_ = true;
165 }
166 
167 } // End namespace detail.
168 
169 //----------------------------------------------------------------------------//
170 
171 } } // End namespaces iostreams, boost.
172