📄 gzip.hpp
字号:
// (C) Copyright Jonathan Turkanis 2003.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
// See http://www.boost.org/libs/iostreams for documentation.
// Contains the definitions of the class templates gzip_compressor and
// gzip_decompressor for reading and writing files in the gzip file format
// (RFC 1952). Based in part on work of Jonathan de Halleux; see [...]
#ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
#define BOOST_IOSTREAMS_GZIP_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp> // STATIC_CONSTANT, STDC_NAMESPACE,
// DINKUMWARE_STDLIB, __STL_CONFIG_H.
#include <algorithm> // min.
#include <cstdio> // EOF.
#include <cstddef> // size_t.
#include <ctime> // std::time_t.
#include <memory> // allocator.
#include <boost/config.hpp> // Put size_t in std.
#include <boost/detail/workaround.hpp>
#include <boost/cstdint.hpp> // uint8_t, uint32_t.
#include <boost/iostreams/constants.hpp> // buffer size.
#include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
#include <boost/iostreams/detail/adapter/range_adapter.hpp>
#include <boost/iostreams/detail/char_traits.hpp>
#include <boost/iostreams/detail/ios.hpp> // failure.
#include <boost/iostreams/operations.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/pipeline.hpp>
// Must come last.
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4309) // Truncation of constant value.
#endif
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::time_t; }
#endif
namespace boost { namespace iostreams {
namespace gzip {
using namespace boost::iostreams::zlib;
// Error codes used by gzip_error.
const int zlib_error = 1;
const int bad_crc = 2; // Recorded crc doesn't match data.
const int bad_length = 3; // Recorded length doesn't match data.
const int bad_header = 4; // Malformed header.
const int bad_footer = 5; // Malformed footer.
namespace magic {
// Magic numbers used by gzip header.
const int id1 = 0x1f;
const int id2 = 0x8b;
} // End namespace magic.
namespace method {
// Codes used for the 'CM' byte of the gzip header.
const int deflate = 8;
} // End namespace method.
namespace flags {
// Codes used for the 'FLG' byte of the gzip header.
const int text = 1;
const int header_crc = 2;
const int extra = 4;
const int name = 8;
const int comment = 16;
} // End namespace flags.
namespace extra_flags {
// Codes used for the 'XFL' byte of the gzip header.
const int best_compression = 2;
const int best_speed = 4;
} // End namespace extra_flags.
// Codes used for the 'OS' byte of the gzip header.
const int os_fat = 0;
const int os_amiga = 1;
const int os_vms = 2;
const int os_unix = 3;
const int os_vm_cms = 4;
const int os_atari = 5;
const int os_hpfs = 6;
const int os_macintosh = 7;
const int os_z_system = 8;
const int os_cp_m = 9;
const int os_tops_20 = 10;
const int os_ntfs = 11;
const int os_qdos = 12;
const int os_acorn = 13;
const int os_unknown = 255;
} // End namespace gzip.
//
// Class name: gzip_params.
// Description: Subclass of zlib_params with an additional field
// representing a file name.
//
struct gzip_params : zlib_params {
// Non-explicit constructor.
gzip_params( int level = gzip::default_compression,
int method = gzip::deflated,
int window_bits = gzip::default_window_bits,
int mem_level = gzip::default_mem_level,
int strategy = gzip::default_strategy,
std::string file_name = "",
std::string comment = "",
std::time_t mtime = 0 )
: zlib_params(level, method, window_bits, mem_level, strategy),
file_name(file_name), mtime(mtime)
{ }
std::string file_name;
std::string comment;
std::time_t mtime;
};
//
// Class name: gzip_error.
// Description: Subclass of std::ios_base::failure thrown to indicate
// zlib errors other than out-of-memory conditions.
//
class gzip_error : public BOOST_IOSTREAMS_FAILURE {
public:
explicit gzip_error(int error)
: BOOST_IOSTREAMS_FAILURE("gzip error"),
error_(error), zlib_error_code_(zlib::okay) { }
explicit gzip_error(const zlib_error& e)
: BOOST_IOSTREAMS_FAILURE("gzip error"),
error_(gzip::zlib_error), zlib_error_code_(e.error())
{ }
int error() const { return error_; }
int zlib_error_code() const { return zlib_error_code_; }
private:
int error_;
int zlib_error_code_;
};
//
// Template name: gzip_compressor
// Description: Model of OutputFilter implementing compression in the
// gzip format.
//
template<typename Alloc = std::allocator<char> >
class basic_gzip_compressor : basic_zlib_compressor<Alloc> {
private:
typedef basic_zlib_compressor<Alloc> base_type;
public:
typedef char char_type;
struct category
: dual_use,
filter_tag,
multichar_tag,
closable_tag
{ };
basic_gzip_compressor( const gzip_params& = gzip::default_compression,
int buffer_size = default_device_buffer_size );
template<typename Source>
std::streamsize read(Source& src, char_type* s, std::streamsize n)
{
using namespace std;
streamsize result = 0;
// Read header.
if (!(flags_ & f_header_done))
result += read_string(s, n, header_);
// Read body.
if (!(flags_ & f_body_done)) {
// Read from basic_zlib_filter.
streamsize amt = base_type::read(src, s + result, n - result);
if (amt != -1) {
result += amt;
if (amt < n - result) { // Double-check for EOF.
amt = base_type::read(src, s + result, n - result);
if (amt != -1)
result += amt;
}
}
if (amt == -1)
prepare_footer();
}
// Read footer.
if ((flags_ & f_body_done) != 0 && result < n)
result += read_string(s + result, n - result, footer_);
return result != 0 ? result : -1;
}
template<typename Sink>
std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
{
if (!(flags_ & f_header_done)) {
std::streamsize amt =
static_cast<std::streamsize>(header_.size() - offset_);
offset_ += boost::iostreams::write(snk, header_.data() + offset_, amt);
if (offset_ == header_.size())
flags_ |= f_header_done;
else
return 0;
}
return base_type::write(snk, s, n);
}
template<typename Sink>
void close(Sink& snk, BOOST_IOS::openmode m)
{
namespace io = boost::iostreams;
if (m & BOOST_IOS::out) {
// Close zlib compressor.
base_type::close(snk, BOOST_IOS::out);
if (flags_ & f_header_done) {
// Write final fields of gzip file format.
write_long(this->crc(), snk);
write_long(this->total_in(), snk);
}
}
#if BOOST_WORKAROUND(__GNUC__, == 2) && defined(__STL_CONFIG_H) || \
BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) \
/**/
footer_.erase(0, std::string::npos);
#else
footer_.clear();
#endif
offset_ = 0;
flags_ = 0;
}
private:
static gzip_params normalize_params(gzip_params p);
void prepare_footer();
std::streamsize read_string(char* s, std::streamsize n, std::string& str);
template<typename Sink>
static void write_long(long n, Sink& next)
{
boost::iostreams::put(next, static_cast<char>(0xFF & n));
boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 8)));
boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 16)));
boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 24)));
}
enum flag_type {
f_header_done = 1,
f_body_done = f_header_done << 1,
f_footer_done = f_body_done << 1
};
std::string header_;
std::string footer_;
std::size_t offset_;
int flags_;
};
BOOST_IOSTREAMS_PIPABLE(basic_gzip_compressor, 1)
typedef basic_gzip_compressor<> gzip_compressor;
//
// Template name: basic_gzip_decompressor
// Description: Model of InputFilter implementing compression in the
// gzip format.
//
template<typename Alloc = std::allocator<char> >
class basic_gzip_decompressor : basic_zlib_decompressor<Alloc> {
public:
typedef char char_type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -