Some tweaks to Lua docs
[lsnes.git] / src / library / streamcompress-xz.cpp
blob6569ed834999bedd1a96764b8d14df1573bae175
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"
12 #include "string.hpp"
13 #include <lzma.h>
14 #include <stdexcept>
16 namespace
18 struct lzma_options
20 bool xz;
21 lzma_filter* fchain;
22 lzma_check check;
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));
31 lzma_ret r;
32 if(opts.xz) {
33 r = lzma_stream_encoder(&strm, opts.fchain, opts.check);
34 } else {
35 r = lzma_alone_encoder(&strm, &opts.lzmaopts);
37 if(r >= 5) {
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()
50 lzma_end(&strm);
52 bool process(uint8_t*& in, size_t& insize, uint8_t*& out, size_t& outsize, bool final)
54 strm.next_in = in;
55 strm.avail_in = insize;
56 strm.next_out = out;
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;
61 out = strm.next_out;
62 outsize = strm.avail_out;
63 if(r == LZMA_STREAM_END) return true;
64 if(r >= 5) {
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");
74 return false;
76 private:
77 lzma_stream strm;
80 struct foo {
81 foo() {
82 stream_compressor_base::do_register("lzma", [](const std::string& v) ->
83 stream_compressor_base* {
84 lzma_options opts;
85 auto a = stream_compressor_parse_attributes(v);
86 unsigned level = 7;
87 bool extreme = false;
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"]);
91 opts.xz = false;
92 lzma_lzma_preset(&opts.lzmaopts, level | (extreme ? LZMA_PRESET_EXTREME : 0));
93 return new stream_compressor_lzma(opts);
94 });
95 stream_compressor_base::do_register("xz", [](const std::string& v) ->
96 stream_compressor_base* {
97 lzma_options opts;
98 auto a = stream_compressor_parse_attributes(v);
99 unsigned level = 7;
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 },
108 { LZMA_VLI_UNKNOWN }
110 opts.fchain = filterchain;
111 opts.check = LZMA_CHECK_CRC64;
112 opts.xz = true;
113 return new stream_compressor_lzma(opts);
116 ~foo() {
117 stream_compressor_base::do_unregister("lzma");
118 stream_compressor_base::do_unregister("xz");
120 } _foo;
122 class stdin_input
124 public:
125 typedef char char_type;
126 typedef boost::iostreams::source_tag category;
128 stdin_input()
132 void close()
136 std::streamsize read(char* s, std::streamsize x)
138 std::cin.read(s, x);
139 if(!std::cin.gcount() && !std::cin) return -1;
140 return std::cin.gcount();
143 ~stdin_input()
146 private:
147 stdin_input& operator=(const stdin_input& f);
152 #ifdef STREAMCOMPRESS_LZMA_TEST
153 int main()
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);
162 delete s;
163 delete X;
165 std::cout.write(&out[0], out.size());
166 return 0;
168 #endif
169 #endif