1 #ifdef LIBLZMA_AVAILABLE
2 #include <boost/iostreams/categories.hpp>
3 #include <boost/iostreams/copy.hpp>
4 #include <boost/iostreams/stream.hpp>
5 #include <boost/iostreams/stream_buffer.hpp>
6 #include <boost/iostreams/filter/symmetric.hpp>
7 #include <boost/iostreams/filter/zlib.hpp>
8 #include <boost/iostreams/filtering_stream.hpp>
9 #include <boost/iostreams/device/back_inserter.hpp>
10 #include "streamcompress.hpp"
11 #include "serialization.hpp"
23 lzma_options_lzma lzmaopts
;
26 struct lzma
: public streamcompress::base
28 lzma(lzma_options
& opts
)
30 memset(&strm
, 0, sizeof(strm
));
33 r
= lzma_stream_encoder(&strm
, opts
.fchain
, opts
.check
);
35 r
= lzma_alone_encoder(&strm
, &opts
.lzmaopts
);
38 if(r
== LZMA_MEM_ERROR
) throw std::runtime_error("Memory error");
39 if(r
== LZMA_MEMLIMIT_ERROR
) throw std::runtime_error("Memory limit exceeded");
40 if(r
== LZMA_FORMAT_ERROR
) throw std::runtime_error("File format error");
41 if(r
== LZMA_OPTIONS_ERROR
) throw std::runtime_error("Options error");
42 if(r
== LZMA_DATA_ERROR
) throw std::runtime_error("Data error");
43 if(r
== LZMA_BUF_ERROR
) throw std::runtime_error("Buffer error");
44 if(r
== LZMA_PROG_ERROR
) throw std::runtime_error("Programming error");
45 throw std::runtime_error("Unknown error");
52 bool process(uint8_t*& in
, size_t& insize
, uint8_t*& out
, size_t& outsize
, bool final
)
55 strm
.avail_in
= insize
;
57 strm
.avail_out
= outsize
;
58 lzma_ret r
= lzma_code(&strm
, final
? LZMA_FINISH
: LZMA_RUN
);
59 in
= (uint8_t*)strm
.next_in
;
60 insize
= strm
.avail_in
;
62 outsize
= strm
.avail_out
;
63 if(r
== LZMA_STREAM_END
) return true;
65 if(r
== LZMA_MEM_ERROR
) throw std::runtime_error("Memory error");
66 if(r
== LZMA_MEMLIMIT_ERROR
) throw std::runtime_error("Memory limit exceeded");
67 if(r
== LZMA_FORMAT_ERROR
) throw std::runtime_error("File format error");
68 if(r
== LZMA_OPTIONS_ERROR
) throw std::runtime_error("Options error");
69 if(r
== LZMA_DATA_ERROR
) throw std::runtime_error("Data error");
70 if(r
== LZMA_BUF_ERROR
) throw std::runtime_error("Buffer error");
71 if(r
== LZMA_PROG_ERROR
) throw std::runtime_error("Programming error");
72 throw std::runtime_error("Unknown error");
82 streamcompress::base::do_register("lzma", [](const std::string
& v
) -> streamcompress::base
* {
84 auto a
= streamcompress::parse_attributes(v
);
87 if(a
.count("level")) level
= parse_value
<unsigned>(a
["level"]);
88 if(level
> 9) level
= 9;
89 if(a
.count("extreme")) extreme
= parse_value
<bool>(a
["level"]);
91 lzma_lzma_preset(&opts
.lzmaopts
, level
| (extreme
? LZMA_PRESET_EXTREME
: 0));
92 return new lzma(opts
);
94 streamcompress::base::do_register("xz", [](const std::string
& v
) -> streamcompress::base
* {
96 auto a
= streamcompress::parse_attributes(v
);
99 lzma_options_lzma opt_lzma2
;
100 if(a
.count("level")) level
= parse_value
<unsigned>(a
["level"]);
101 if(level
> 9) level
= 9;
102 if(a
.count("extreme")) extreme
= parse_value
<bool>(a
["level"]);
103 lzma_lzma_preset(&opt_lzma2
, level
| (extreme
? LZMA_PRESET_EXTREME
: 0));
104 lzma_filter filterchain
[] = {
105 { LZMA_FILTER_LZMA2
, &opt_lzma2
},
108 opts
.fchain
= filterchain
;
109 opts
.check
= LZMA_CHECK_CRC64
;
111 return new lzma(opts
);
115 streamcompress::base::do_unregister("lzma");
116 streamcompress::base::do_unregister("xz");
123 typedef char char_type
;
124 typedef boost::iostreams::source_tag category
;
134 std::streamsize
read(char* s
, std::streamsize x
)
137 if(!std::cin
.gcount() && !std::cin
) return -1;
138 return std::cin
.gcount();
145 stdin_input
& operator=(const stdin_input
& f
);
150 #ifdef STREAMCOMPRESS_LZMA_TEST
153 std::vector
<char> out
;
154 streamcompress::base
* X
= streamcompress::base::create_compressor("xz", "level=7,extreme=true");
155 boost::iostreams::filtering_istream
* s
= new boost::iostreams::filtering_istream();
156 s
->push(streamcompress::iostream(X
));
157 s
->push(stdin_input());
158 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
159 boost::iostreams::copy(*s
, rd
);
163 std::cout
.write(&out
[0], out
.size());