• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // (C) Copyright Milan Svoboda 2008.
2 // Originally developed under the fusecompress project.
3 // Based on bzip2.cpp by:
4 // (C) Copyright Jonathan Turkanis 2003.
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
7 
8 // See http://www.boost.org/libs/iostreams for documentation.
9 
10 // Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
11 // knows that we are building the library (possibly exporting code), rather
12 // than using it (possibly importing code).
13 #define BOOST_IOSTREAMS_SOURCE
14 
15 #include <lzma.h>
16 
17 #include <boost/throw_exception.hpp>
18 #include <boost/iostreams/detail/config/dyn_link.hpp>
19 #include <boost/iostreams/filter/lzma.hpp>
20 
21 
22 #ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
23     #if LZMA_VERSION < 50020002
24         #define BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
25     #endif
26 #endif
27 
28 namespace boost { namespace iostreams {
29 
30 namespace lzma {
31 
32                     // Compression levels
33 
34 const uint32_t no_compression       = 0;
35 const uint32_t best_speed           = 1;
36 const uint32_t best_compression     = 9;
37 const uint32_t default_compression  = 2;
38 
39                     // Status codes
40 
41 const int okay                 = LZMA_OK;
42 const int stream_end           = LZMA_STREAM_END;
43 const int unsupported_check    = LZMA_UNSUPPORTED_CHECK;
44 const int mem_error            = LZMA_MEM_ERROR;
45 const int options_error        = LZMA_OPTIONS_ERROR;
46 const int data_error           = LZMA_DATA_ERROR;
47 const int buf_error            = LZMA_BUF_ERROR;
48 const int prog_error           = LZMA_PROG_ERROR;
49 
50                     // Flush codes
51 
52 const int finish               = LZMA_FINISH;
53 const int full_flush           = LZMA_FULL_FLUSH;
54 const int sync_flush           = LZMA_SYNC_FLUSH;
55 const int run                  = LZMA_RUN;
56 
57                     // Code for current OS
58 
59 } // End namespace lzma.
60 
61 //------------------Implementation of lzma_error------------------------------//
62 
lzma_error(int error)63 lzma_error::lzma_error(int error)
64     : BOOST_IOSTREAMS_FAILURE("lzma error"), error_(error)
65     { }
66 
BOOST_PREVENT_MACRO_SUBSTITUTION(int error)67 void lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
68 {
69     switch (error) {
70     case LZMA_OK:
71     case LZMA_STREAM_END:
72         return;
73     case LZMA_MEM_ERROR:
74         boost::throw_exception(std::bad_alloc());
75     default:
76         boost::throw_exception(lzma_error(error));
77     }
78 }
79 
80 //------------------Implementation of lzma_base-------------------------------//
81 
82 namespace detail {
83 
lzma_base()84 lzma_base::lzma_base()
85     : stream_(new lzma_stream), level_(lzma::default_compression), threads_(1)
86     { }
87 
~lzma_base()88 lzma_base::~lzma_base() { delete static_cast<lzma_stream*>(stream_); }
89 
before(const char * & src_begin,const char * src_end,char * & dest_begin,char * dest_end)90 void lzma_base::before( const char*& src_begin, const char* src_end,
91                         char*& dest_begin, char* dest_end )
92 {
93     lzma_stream* s = static_cast<lzma_stream*>(stream_);
94     s->next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(src_begin));
95     s->avail_in = static_cast<size_t>(src_end - src_begin);
96     s->next_out = reinterpret_cast<uint8_t*>(dest_begin);
97     s->avail_out= static_cast<size_t>(dest_end - dest_begin);
98 }
99 
after(const char * & src_begin,char * & dest_begin,bool)100 void lzma_base::after(const char*& src_begin, char*& dest_begin, bool)
101 {
102     lzma_stream* s = static_cast<lzma_stream*>(stream_);
103     src_begin = const_cast<const char*>(reinterpret_cast<const char*>(s->next_in));
104     dest_begin = reinterpret_cast<char*>(s->next_out);
105 }
106 
deflate(int action)107 int lzma_base::deflate(int action)
108 {
109     return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action));
110 }
111 
inflate(int action)112 int lzma_base::inflate(int action)
113 {
114     return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action));
115 }
116 
reset(bool compress,bool realloc)117 void lzma_base::reset(bool compress, bool realloc)
118 {
119     lzma_stream* s = static_cast<lzma_stream*>(stream_);
120     lzma_end(s);
121     if (realloc)
122     {
123         init_stream(compress);
124     }
125 }
126 
do_init(const lzma_params & p,bool compress,lzma::alloc_func,lzma::free_func,void *)127 void lzma_base::do_init
128     ( const lzma_params& p, bool compress,
129       lzma::alloc_func, lzma::free_func,
130       void* )
131 {
132 
133     level_ = p.level;
134     threads_ = p.threads;
135 
136 #ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
137     if (threads_ == 0) {
138         threads_ = lzma_cputhreads();
139     }
140 #endif
141 
142     init_stream(compress);
143 }
144 
init_stream(bool compress)145 void lzma_base::init_stream(bool compress)
146 {
147     lzma_stream* s = static_cast<lzma_stream*>(stream_);
148 
149     memset(s, 0, sizeof(*s));
150 
151 #ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
152     const lzma_mt opt = { 0, threads_, 0, 1000, level_, NULL, LZMA_CHECK_CRC32 };
153 #endif
154 
155     lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
156         compress ?
157 #ifdef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
158             lzma_easy_encoder(s, level_, LZMA_CHECK_CRC32) :
159 #else
160             lzma_stream_encoder_mt(s, &opt) :
161 #endif
162             lzma_stream_decoder(s, 100 * 1024 * 1024, LZMA_CONCATENATED)
163     );
164 }
165 
166 
167 } // End namespace detail.
168 
169 //----------------------------------------------------------------------------//
170 
171 } } // End namespaces iostreams, boost.
172