// (C) Copyright Reimar Döffinger 2018. // Based on zstd.cpp by: // (C) Copyright Milan Svoboda 2008. // (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. // Define BOOST_IOSTREAMS_SOURCE so that // knows that we are building the library (possibly exporting code), rather // than using it (possibly importing code). #define BOOST_IOSTREAMS_SOURCE #include #include #include #include namespace boost { namespace iostreams { namespace zstd { // Compression levels const uint32_t best_speed = 1; const uint32_t best_compression = 19; const uint32_t default_compression = 3; // Status codes const int okay = 0; const int stream_end = 1; // Flush codes const int finish = 0; const int flush = 1; const int run = 2; } // End namespace zstd. //------------------Implementation of zstd_error------------------------------// zstd_error::zstd_error(size_t error) : BOOST_IOSTREAMS_FAILURE(ZSTD_getErrorName(error)), error_(error) { } void zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(size_t error) { if (ZSTD_isError(error)) boost::throw_exception(zstd_error(error)); } //------------------Implementation of zstd_base-------------------------------// namespace detail { zstd_base::zstd_base() : cstream_(ZSTD_createCStream()), dstream_(ZSTD_createDStream()), in_(new ZSTD_inBuffer), out_(new ZSTD_outBuffer), eof_(0) { } zstd_base::~zstd_base() { ZSTD_freeCStream(static_cast(cstream_)); ZSTD_freeDStream(static_cast(dstream_)); delete static_cast(in_); delete static_cast(out_); } void zstd_base::before( const char*& src_begin, const char* src_end, char*& dest_begin, char* dest_end ) { ZSTD_inBuffer *in = static_cast(in_); ZSTD_outBuffer *out = static_cast(out_); in->src = src_begin; in->size = static_cast(src_end - src_begin); in->pos = 0; out->dst = dest_begin; out->size = static_cast(dest_end - dest_begin); out->pos = 0; } void zstd_base::after(const char*& src_begin, char*& dest_begin, bool) { ZSTD_inBuffer *in = static_cast(in_); ZSTD_outBuffer *out = static_cast(out_); src_begin = reinterpret_cast(in->src) + in->pos; dest_begin = reinterpret_cast(out->dst) + out->pos; } int zstd_base::deflate(int action) { ZSTD_CStream *s = static_cast(cstream_); ZSTD_inBuffer *in = static_cast(in_); ZSTD_outBuffer *out = static_cast(out_); // Ignore spurious extra calls. // Note size > 0 will trigger an error in this case. if (eof_ && in->size == 0) return zstd::stream_end; size_t result = ZSTD_compressStream(s, out, in); zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); if (action != zstd::run) { result = action == zstd::finish ? ZSTD_endStream(s, out) : ZSTD_flushStream(s, out); zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); eof_ = action == zstd::finish && result == 0; return result == 0 ? zstd::stream_end : zstd::okay; } return zstd::okay; } int zstd_base::inflate(int action) { ZSTD_DStream *s = static_cast(dstream_); ZSTD_inBuffer *in = static_cast(in_); ZSTD_outBuffer *out = static_cast(out_); // need loop since iostream code cannot handle short reads do { size_t result = ZSTD_decompressStream(s, out, in); zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); } while (in->pos < in->size && out->pos < out->size); return action == zstd::finish && in->size == 0 && out->pos == 0 ? zstd::stream_end : zstd::okay; } void zstd_base::reset(bool compress, bool realloc) { ZSTD_inBuffer *in = static_cast(in_); ZSTD_outBuffer *out = static_cast(out_); if (realloc) { memset(in, 0, sizeof(*in)); memset(out, 0, sizeof(*out)); eof_ = 0; zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( compress ? ZSTD_initCStream(static_cast(cstream_), level) : ZSTD_initDStream(static_cast(dstream_)) ); } } void zstd_base::do_init ( const zstd_params& p, bool compress, zstd::alloc_func, zstd::free_func, void* ) { ZSTD_inBuffer *in = static_cast(in_); ZSTD_outBuffer *out = static_cast(out_); memset(in, 0, sizeof(*in)); memset(out, 0, sizeof(*out)); eof_ = 0; level = p.level; zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( compress ? ZSTD_initCStream(static_cast(cstream_), level) : ZSTD_initDStream(static_cast(dstream_)) ); } } // End namespace detail. //----------------------------------------------------------------------------// } } // End namespaces iostreams, boost.