12 #ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
13 #define BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
19 #include <boost/config.hpp>
22 #include <boost/assert.hpp>
27 #include <boost/config.hpp>
28 #include <boost/detail/workaround.hpp>
29 #include <boost/cstdint.hpp>
30 #include <boost/iostreams/checked_operations.hpp>
31 #include <boost/iostreams/constants.hpp>
32 #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
33 #include <boost/iostreams/detail/adapter/range_adapter.hpp>
34 #include <boost/iostreams/detail/char_traits.hpp>
35 #include <boost/iostreams/detail/ios.hpp>
36 #include <boost/iostreams/detail/error.hpp>
37 #include <boost/iostreams/operations.hpp>
38 #include <boost/iostreams/device/back_inserter.hpp>
39 #include <boost/iostreams/filter/zlib.hpp>
40 #include <boost/iostreams/pipeline.hpp>
41 #include <boost/iostreams/putback.hpp>
42 #include <boost/throw_exception.hpp>
45 #if defined(BOOST_MSVC)
46 # pragma warning(push)
47 # pragma warning(disable:4244)
48 # pragma warning(disable:4251)
49 # pragma warning(disable:4309)
52 #ifdef BOOST_NO_STDC_NAMESPACE
53 namespace std { using ::time_t; }
56 namespace boost {
namespace iostreams {
62 using namespace boost::iostreams::zlib;
66 const int zlib_error = 1;
67 const int bad_crc = 2;
68 const int bad_length = 3;
69 const int bad_header = 4;
70 const int bad_footer = 5;
71 const int bad_method = 6;
86 const int deflate = 8;
95 const int header_crc = 2;
98 const int comment = 16;
102 namespace extra_flags {
106 const int best_compression = 2;
107 const int best_speed = 4;
113 const int os_fat = 0;
114 const int os_amiga = 1;
115 const int os_vms = 2;
116 const int os_unix = 3;
117 const int os_vm_cms = 4;
118 const int os_atari = 5;
119 const int os_hpfs = 6;
120 const int os_macintosh = 7;
121 const int os_z_system = 8;
122 const int os_cp_m = 9;
123 const int os_tops_20 = 10;
124 const int os_ntfs = 11;
125 const int os_qdos = 12;
126 const int os_acorn = 13;
127 const int os_unknown = 255;
138 struct gzip_params : zlib_params {
141 gzip_params(
int level = gzip::default_compression,
142 int method = gzip::deflated,
143 int window_bits = gzip::default_window_bits,
144 int mem_level = gzip::default_mem_level,
145 int strategy = gzip::default_strategy,
146 std::string file_name_ =
"",
147 std::string comment_ =
"",
148 std::time_t mtime_ = 0 )
149 : zlib_params(level, method, window_bits, mem_level, strategy),
150 file_name(file_name_), comment(comment_), mtime(mtime_)
152 std::string file_name;
164 class gzip_error :
public BOOST_IOSTREAMS_FAILURE {
166 explicit gzip_error(
int error)
167 : BOOST_IOSTREAMS_FAILURE(
"gzip error"),
168 error_(
error), zlib_error_code_(zlib::okay) { }
169 explicit gzip_error(
const zlib_error& e)
170 : BOOST_IOSTREAMS_FAILURE(
"gzip error"),
171 error_(gzip::zlib_error), zlib_error_code_(e.
error())
173 int error()
const {
return error_; }
174 int zlib_error_code()
const {
return zlib_error_code_; }
177 int zlib_error_code_;
187 template<
typename Alloc = std::allocator<
char> >
188 class basic_gzip_compressor : basic_zlib_compressor<Alloc> {
190 typedef basic_zlib_compressor<Alloc> base_type;
192 typedef char char_type;
199 basic_gzip_compressor(
const gzip_params& = gzip::default_compression,
200 std::streamsize buffer_size = default_device_buffer_size );
202 template<
typename Source>
203 std::streamsize read(Source& src, char_type* s, std::streamsize n)
205 std::streamsize result = 0;
208 if (!(flags_ & f_header_done))
209 result += read_string(s, n, header_);
212 if (!(flags_ & f_body_done)) {
215 std::streamsize amt = base_type::read(src, s + result, n - result);
218 if (amt < n - result) {
219 amt = base_type::read(src, s + result, n - result);
229 if ((flags_ & f_body_done) != 0 && result < n)
230 result += read_string(s + result, n - result, footer_);
232 return result != 0 ? result : -1;
235 template<
typename Sink>
236 std::streamsize write(Sink& snk,
const char_type* s, std::streamsize n)
238 if (!(flags_ & f_header_done)) {
239 std::streamsize amt =
240 static_cast<std::streamsize
>(header_.size() - offset_);
241 offset_ += boost::iostreams::write_if(snk, header_.data() + offset_, amt);
242 if (offset_ == header_.size())
243 flags_ |= f_header_done;
247 return base_type::write(snk, s, n);
250 template<
typename Sink>
251 void close(Sink& snk, BOOST_IOS::openmode m)
254 if (m == BOOST_IOS::out && !(flags_ & f_header_done))
255 this->write(snk, 0, 0);
260 if (m == BOOST_IOS::out) {
261 if (flags_ & f_header_done) {
264 write_long(this->crc(), snk);
265 write_long(this->total_in(), snk);
275 static gzip_params normalize_params(gzip_params p);
276 void prepare_footer();
277 std::streamsize read_string(
char* s, std::streamsize n, std::string& str);
279 template<
typename Sink>
280 static void write_long(
long n, Sink& next, boost::mpl::true_)
282 boost::iostreams::put(next,
static_cast<char>(0xFF & n));
283 boost::iostreams::put(next,
static_cast<char>(0xFF & (n >> 8)));
284 boost::iostreams::put(next,
static_cast<char>(0xFF & (n >> 16)));
285 boost::iostreams::put(next,
static_cast<char>(0xFF & (n >> 24)));
287 template<
typename Sink>
288 static void write_long(
long, Sink&, boost::mpl::false_)
291 template<
typename Sink>
292 static void write_long(
long n, Sink& next)
295 typedef is_convertible<category, output> can_write;
296 write_long(n, next, can_write());
308 f_body_done = f_header_done << 1,
309 f_footer_done = f_body_done << 1
316 BOOST_IOSTREAMS_PIPABLE(basic_gzip_compressor, 1)
318 typedef basic_gzip_compressor<> gzip_compressor;
325 class BOOST_IOSTREAMS_DECL gzip_header {
327 gzip_header() { reset(); }
330 void process(
char c);
331 bool done()
const {
return state_ == s_done; }
335 std::string file_name()
const {
return file_name_; }
336 std::string comment()
const {
return comment_; }
337 bool text()
const {
return (flags_ & gzip::flags::text) != 0; }
338 int os()
const {
return os_; }
339 std::time_t mtime()
const {
return mtime_; }
350 s_extra = s_xlen + 1,
351 s_name = s_extra + 1,
352 s_comment = s_name + 1,
353 s_hcrc = s_comment + 1,
356 std::string file_name_;
357 std::string comment_;
367 class BOOST_IOSTREAMS_DECL gzip_footer {
369 gzip_footer() { reset(); }
372 void process(
char c);
373 bool done()
const {
return state_ == s_done; }
377 zlib::ulong crc()
const {
return crc_; }
378 zlib::ulong uncompressed_size()
const {
return isize_; }
400 template<
typename Alloc = std::allocator<
char> >
401 class basic_gzip_decompressor : basic_zlib_decompressor<Alloc> {
403 typedef basic_zlib_decompressor<Alloc> base_type;
404 typedef typename base_type::string_type string_type;
406 typedef char char_type;
413 basic_gzip_decompressor(
int window_bits = gzip::default_window_bits,
414 std::streamsize buffer_size = default_device_buffer_size );
416 template<
typename Sink>
417 std::streamsize write(Sink& snk,
const char_type* s, std::streamsize n)
419 std::streamsize result = 0;
421 if(state_ == s_start) {
426 if (state_ == s_header) {
431 }
else if (state_ == s_body) {
433 std::streamsize amt =
434 base_type::write(snk, s + result, n - result);
441 }
catch (
const zlib_error& e) {
442 boost::throw_exception(gzip_error(e));
445 if (footer_.done()) {
446 if (footer_.crc() != this->crc())
447 boost::throw_exception(gzip_error(gzip::bad_crc));
460 template<
typename Source>
461 std::streamsize read(Source& src, char_type* s, std::streamsize n)
463 typedef char_traits<char> traits_type;
464 std::streamsize result = 0;
465 peekable_source<Source> peek(src, putback_);
466 while (result < n && state_ != s_done) {
467 if (state_ == s_start) {
472 if (state_ == s_header) {
474 if (traits_type::is_eof(c)) {
475 boost::throw_exception(gzip_error(gzip::bad_header));
476 }
else if (traits_type::would_block(c)) {
482 }
else if (state_ == s_body) {
484 std::streamsize amt =
485 base_type::read(peek, s + result, n - result);
488 if (amt < n - result)
491 peek.putback(this->unconsumed_input());
494 }
catch (
const zlib_error& e) {
495 boost::throw_exception(gzip_error(e));
499 if (traits_type::is_eof(c)) {
500 boost::throw_exception(gzip_error(gzip::bad_footer));
501 }
else if (traits_type::would_block(c)) {
505 if (footer_.done()) {
506 if (footer_.crc() != this->crc())
507 boost::throw_exception(gzip_error(gzip::bad_crc));
509 if (traits_type::is_eof(c)) {
521 if (peek.has_unconsumed_input()) {
522 putback_ = peek.unconsumed_input();
526 return result != 0 || state_ != s_done ?
531 template<
typename Source>
532 void close(Source& src, BOOST_IOS::openmode m)
536 }
catch (
const zlib_error& e) {
538 boost::throw_exception(gzip_error(e));
540 if (m == BOOST_IOS::out) {
541 if (state_ == s_start || state_ == s_header)
542 boost::throw_exception(gzip_error(gzip::bad_header));
543 else if (state_ == s_body)
544 boost::throw_exception(gzip_error(gzip::bad_footer));
545 else if (state_ == s_footer) {
547 boost::throw_exception(gzip_error(gzip::bad_footer));
548 else if(footer_.crc() != this->crc())
549 boost::throw_exception(gzip_error(gzip::bad_crc));
551 BOOST_ASSERT(!
"Bad state");
557 std::string file_name()
const {
return header_.file_name(); }
558 std::string comment()
const {
return header_.comment(); }
559 bool text()
const {
return header_.text(); }
560 int os()
const {
return header_.os(); }
561 std::time_t mtime()
const {
return header_.mtime(); }
563 static gzip_params make_params(
int window_bits);
566 template<
typename Source>
567 struct peekable_source {
568 typedef char char_type;
569 struct category : source_tag, peekable_tag { };
570 explicit peekable_source(Source& src,
const string_type& putback =
"")
571 : src_(src), putback_(putback), offset_(0)
573 std::streamsize read(
char* s, std::streamsize n)
575 std::streamsize result = 0;
578 std::streamsize pbsize =
579 static_cast<std::streamsize
>(putback_.size());
580 if (offset_ < pbsize) {
581 result = (std::min)(n, pbsize - offset_);
582 BOOST_IOSTREAMS_CHAR_TRAITS(
char)::copy(
583 s, putback_.data() + offset_, result);
590 std::streamsize amt =
591 boost::iostreams::read(src_, s + result, n - result);
594 result ? result : -1;
599 putback_[--offset_] = c;
601 boost::throw_exception(
602 boost::iostreams::detail::bad_putback());
606 void putback(
const string_type& s)
608 putback_.replace(0, offset_, s);
613 bool has_unconsumed_input()
const
615 return offset_ < static_cast<std::streamsize>(putback_.size());
619 string_type unconsumed_input()
const
621 return string_type(putback_, offset_, putback_.size() - offset_);
624 string_type putback_;
625 std::streamsize offset_;
630 s_header = s_start + 1,
631 s_body = s_header + 1,
632 s_footer = s_body + 1,
633 s_done = s_footer + 1
635 detail::gzip_header header_;
636 detail::gzip_footer footer_;
637 string_type putback_;
640 BOOST_IOSTREAMS_PIPABLE(basic_gzip_decompressor, 1)
642 typedef basic_gzip_decompressor<> gzip_decompressor;
646 template<typename Alloc>
647 basic_gzip_compressor<Alloc>::basic_gzip_compressor
648 (
const gzip_params& p,
std::streamsize buffer_size)
649 : base_type(normalize_params(p), buffer_size),
650 offset_(0), flags_(0)
653 bool has_name = !p.file_name.empty();
654 bool has_comment = !p.comment.empty();
658 (has_name ? p.file_name.size() + 1 : 0) +
659 (has_comment ? p.comment.size() + 1 : 0);
663 (has_name ? gzip::flags::name : 0) +
664 (has_comment ? gzip::flags::comment : 0);
666 ( p.level == zlib::best_compression ?
667 gzip::extra_flags::best_compression :
669 ( p.level == zlib::best_speed ?
670 gzip::extra_flags::best_speed :
672 header_.reserve(length);
673 header_ += gzip::magic::id1;
674 header_ +=
static_cast<char>(gzip::magic::id2);
675 header_ += gzip::method::deflate;
676 header_ +=
static_cast<char>(flags);
677 header_ +=
static_cast<char>(0xFF & p.mtime);
678 header_ +=
static_cast<char>(0xFF & (p.mtime >> 8));
679 header_ +=
static_cast<char>(0xFF & (p.mtime >> 16));
680 header_ +=
static_cast<char>(0xFF & (p.mtime >> 24));
681 header_ +=
static_cast<char>(extra_flags);
682 header_ +=
static_cast<char>(gzip::os_unknown);
684 header_ += p.file_name;
688 header_ += p.comment;
693 template<
typename Alloc>
694 gzip_params basic_gzip_compressor<Alloc>::normalize_params(gzip_params p)
697 p.calculate_crc =
true;
701 template<
typename Alloc>
702 void basic_gzip_compressor<Alloc>::prepare_footer()
704 boost::iostreams::back_insert_device<std::string> out(footer_);
705 write_long(this->crc(), out);
706 write_long(this->total_in(), out);
707 flags_ |= f_body_done;
711 template<
typename Alloc>
712 std::streamsize basic_gzip_compressor<Alloc>::read_string
713 (
char* s, std::streamsize n, std::string& str)
715 std::streamsize avail =
716 static_cast<std::streamsize
>(str.size() - offset_);
717 std::streamsize amt = (std::min)(avail, n);
718 std::copy( str.data() + offset_,
719 str.data() + offset_ + amt,
722 if ( !(flags_ & f_header_done) &&
723 offset_ ==
static_cast<std::size_t
>(str.size()) )
725 flags_ |= f_header_done;
732 template<
typename Alloc>
733 basic_gzip_decompressor<Alloc>::basic_gzip_decompressor
734 (
int window_bits, std::streamsize buffer_size)
735 : base_type(make_params(window_bits), buffer_size),
739 template<
typename Alloc>
740 gzip_params basic_gzip_decompressor<Alloc>::make_params(
int window_bits)
743 p.window_bits = window_bits;
745 p.calculate_crc =
true;
753 #if defined(BOOST_MSVC)
754 # pragma warning(pop)
@ id2
Definition: Typedefs.h:19
@ id1
Definition: Typedefs.h:19
type
The type the bitset is encoded with.
Definition: bitset.hpp:44
CEREAL_SIZE_TYPE size_type
The size type used by cereal.
Definition: helpers.hpp:61
detail namespace with internal helper functions
Definition: json.hpp:260
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:5657
@ error
throw a parse_error exception in case of a tag
Definition: json.hpp:5678
void close(FILE *out)
Definition: Vtk.h:123
#define const
Definition: zconf.h:233