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 stream_compressor_lzma
: public stream_compressor_base
28 stream_compressor_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");
48 ~stream_compressor_lzma()
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 stream_compressor_base::do_register("lzma", [](const std::string
& v
) ->
83 stream_compressor_base
* {
85 auto a
= stream_compressor_parse_attributes(v
);
88 if(a
.count("level")) level
= parse_value
<unsigned>(a
["level"]);
89 if(level
> 9) level
= 9;
90 if(a
.count("extreme")) extreme
= parse_value
<bool>(a
["level"]);
92 lzma_lzma_preset(&opts
.lzmaopts
, level
| (extreme
? LZMA_PRESET_EXTREME
: 0));
93 return new stream_compressor_lzma(opts
);
95 stream_compressor_base::do_register("xz", [](const std::string
& v
) ->
96 stream_compressor_base
* {
98 auto a
= stream_compressor_parse_attributes(v
);
100 bool extreme
= false;
101 lzma_options_lzma opt_lzma2
;
102 if(a
.count("level")) level
= parse_value
<unsigned>(a
["level"]);
103 if(level
> 9) level
= 9;
104 if(a
.count("extreme")) extreme
= parse_value
<bool>(a
["level"]);
105 lzma_lzma_preset(&opt_lzma2
, level
| (extreme
? LZMA_PRESET_EXTREME
: 0));
106 lzma_filter filterchain
[] = {
107 { LZMA_FILTER_LZMA2
, &opt_lzma2
},
110 opts
.fchain
= filterchain
;
111 opts
.check
= LZMA_CHECK_CRC64
;
113 return new stream_compressor_lzma(opts
);
117 stream_compressor_base::do_unregister("lzma");
118 stream_compressor_base::do_unregister("xz");
125 typedef char char_type
;
126 typedef boost::iostreams::source_tag category
;
136 std::streamsize
read(char* s
, std::streamsize x
)
139 if(!std::cin
.gcount() && !std::cin
) return -1;
140 return std::cin
.gcount();
147 stdin_input
& operator=(const stdin_input
& f
);
152 #ifdef STREAMCOMPRESS_LZMA_TEST
155 std::vector
<char> out
;
156 stream_compressor_base
* X
= stream_compressor_base::create_compressor("xz", "level=7,extreme=true");
157 boost::iostreams::filtering_istream
* s
= new boost::iostreams::filtering_istream();
158 s
->push(iostream_compressor(X
));
159 s
->push(stdin_input());
160 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
161 boost::iostreams::copy(*s
, rd
);
165 std::cout
.write(&out
[0], out
.size());