1 #include <boost/iostreams/categories.hpp>
2 #include <boost/iostreams/copy.hpp>
3 #include <boost/iostreams/stream.hpp>
4 #include <boost/iostreams/stream_buffer.hpp>
5 #include <boost/iostreams/filter/symmetric.hpp>
6 #include <boost/iostreams/filter/zlib.hpp>
7 #include <boost/iostreams/filtering_stream.hpp>
8 #include <boost/iostreams/device/back_inserter.hpp>
9 #include "streamcompress.hpp"
10 #include "serialization.hpp"
17 void* zalloc(void* opaque
, unsigned items
, unsigned size
)
19 return calloc(items
, size
);
22 void zfree(void* opaque
, void* ptr
)
27 struct gzip
: public streamcompress::base
31 memset(&strm
, 0, sizeof(z_stream
));
34 if(level
> 9) level
= 9;
35 deflateInit2(&strm
, level
, Z_DEFLATED
, -15, 8, Z_DEFAULT_STRATEGY
);
36 crc
= crc32(0, NULL
, 0);
46 bool process(uint8_t*& in
, size_t& insize
, uint8_t*& out
, size_t& outsize
, bool final
)
48 uint8_t header
[] = {31, 139, 8, 0, 0, 0, 0, 0, 0, 255};
50 serialization::u32l(trailer
+ 0, crc
);
51 serialization::u32l(trailer
+ 4, size
);
53 if(!outsize
) return false;
54 *(out
++) = header
[hdr
++];
59 if(!outsize
) return false;
60 *(out
++) = trailer
[trl
++];
66 strm
.avail_in
= insize
;
68 strm
.avail_out
= outsize
;
69 int r
= deflate(&strm
, final
? Z_FINISH
: 0);
70 size
+= (insize
- strm
.avail_in
);
71 crc
= crc32(crc
, in
, insize
- strm
.avail_in
);
73 insize
= strm
.avail_in
;
75 outsize
= strm
.avail_out
;
76 if(r
== Z_STREAM_END
) data_output
= true;
78 if(r
== Z_ERRNO
) throw std::runtime_error("OS error");
79 if(r
== Z_STREAM_ERROR
) throw std::runtime_error("Streams error");
80 if(r
== Z_DATA_ERROR
) throw std::runtime_error("Data error");
81 if(r
== Z_MEM_ERROR
) throw std::runtime_error("Memory error");
82 if(r
== Z_BUF_ERROR
) throw std::runtime_error("Buffer error");
83 if(r
== Z_VERSION_ERROR
) throw std::runtime_error("Version error");
84 throw std::runtime_error("Unknown error");
99 streamcompress::base::do_register("gzip", [](const std::string
& v
) ->
100 streamcompress::base
* {
101 auto a
= streamcompress::parse_attributes(v
);
102 unsigned compression
= 7;
103 if(a
.count("level")) compression
= parse_value
<unsigned>(a
["level"]);
104 return new gzip(compression
);
108 streamcompress::base::do_unregister("gzip");
115 typedef char char_type
;
116 typedef boost::iostreams::source_tag category
;
126 std::streamsize
read(char* s
, std::streamsize x
)
129 if(!std::cin
.gcount() && !std::cin
) return -1;
130 return std::cin
.gcount();
137 stdin_input
& operator=(const stdin_input
& f
);
142 #ifdef STREAMCOMPRESS_GZIP_TEST
145 std::vector
<char> out
;
146 streamcompress::base
* X
= streamcompress::base::create_compressor("gzip", "level=7");
147 boost::iostreams::filtering_istream
* s
= new boost::iostreams::filtering_istream();
148 s
->push(streamcompress::iostream(X
));
149 s
->push(stdin_input());
150 boost::iostreams::back_insert_device
<std::vector
<char>> rd(out
);
151 boost::iostreams::copy(*s
, rd
);
155 std::cout
.write(&out
[0], out
.size());