File indexing completed on 2024-05-05 05:44:03
0001 // (C) Copyright Reimar Döffinger 2018. 0002 // Based on zstd.cpp by: 0003 // (C) Copyright Milan Svoboda 2008. 0004 // (C) Copyright Jonathan Turkanis 2003. 0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 0007 0008 // See http://www.boost.org/libs/iostreams for documentation. 0009 0010 // Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> 0011 // knows that we are building the library (possibly exporting code), rather 0012 // than using it (possibly importing code). 0013 #define BOOST_IOSTREAMS_SOURCE 0014 0015 #include <zstd.h> 0016 0017 #include <boost/throw_exception.hpp> 0018 #include <boost/iostreams/detail/config/dyn_link.hpp> 0019 //#include <boost/iostreams/filter/zstd.hpp> 0020 #include "zstd.hpp" 0021 0022 namespace boost { namespace iostreams { 0023 0024 namespace zstd { 0025 // Compression levels 0026 0027 const uint32_t best_speed = 1; 0028 const uint32_t best_compression = 19; 0029 const uint32_t default_compression = 3; 0030 0031 // Status codes 0032 0033 const int okay = 0; 0034 const int stream_end = 1; 0035 0036 // Flush codes 0037 0038 const int finish = 0; 0039 const int flush = 1; 0040 const int run = 2; 0041 } // End namespace zstd. 0042 0043 //------------------Implementation of zstd_error------------------------------// 0044 0045 zstd_error::zstd_error(size_t error) 0046 : BOOST_IOSTREAMS_FAILURE(ZSTD_getErrorName(error)), error_(error) 0047 { } 0048 0049 void zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(size_t error) 0050 { 0051 if (ZSTD_isError(error)) 0052 boost::throw_exception(zstd_error(error)); 0053 } 0054 0055 //------------------Implementation of zstd_base-------------------------------// 0056 0057 namespace detail { 0058 0059 zstd_base::zstd_base() 0060 : cstream_(ZSTD_createCStream()), dstream_(ZSTD_createDStream()), in_(new ZSTD_inBuffer), out_(new ZSTD_outBuffer), eof_(0) 0061 { } 0062 0063 zstd_base::~zstd_base() 0064 { 0065 ZSTD_freeCStream(static_cast<ZSTD_CStream *>(cstream_)); 0066 ZSTD_freeDStream(static_cast<ZSTD_DStream *>(dstream_)); 0067 delete static_cast<ZSTD_inBuffer*>(in_); 0068 delete static_cast<ZSTD_outBuffer*>(out_); 0069 } 0070 0071 void zstd_base::before( const char*& src_begin, const char* src_end, 0072 char*& dest_begin, char* dest_end ) 0073 { 0074 ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); 0075 ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); 0076 in->src = src_begin; 0077 in->size = static_cast<size_t>(src_end - src_begin); 0078 in->pos = 0; 0079 out->dst = dest_begin; 0080 out->size = static_cast<size_t>(dest_end - dest_begin); 0081 out->pos = 0; 0082 } 0083 0084 void zstd_base::after(const char*& src_begin, char*& dest_begin, bool) 0085 { 0086 ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); 0087 ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); 0088 src_begin = reinterpret_cast<const char*>(in->src) + in->pos; 0089 dest_begin = reinterpret_cast<char*>(out->dst) + out->pos; 0090 } 0091 0092 int zstd_base::deflate(int action) 0093 { 0094 ZSTD_CStream *s = static_cast<ZSTD_CStream *>(cstream_); 0095 ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); 0096 ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); 0097 // Ignore spurious extra calls. 0098 // Note size > 0 will trigger an error in this case. 0099 if (eof_ && in->size == 0) return zstd::stream_end; 0100 size_t result = ZSTD_compressStream(s, out, in); 0101 zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); 0102 if (action != zstd::run) 0103 { 0104 result = action == zstd::finish ? ZSTD_endStream(s, out) : ZSTD_flushStream(s, out); 0105 zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); 0106 eof_ = action == zstd::finish && result == 0; 0107 return result == 0 ? zstd::stream_end : zstd::okay; 0108 } 0109 return zstd::okay; 0110 } 0111 0112 int zstd_base::inflate(int action) 0113 { 0114 ZSTD_DStream *s = static_cast<ZSTD_DStream *>(dstream_); 0115 ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); 0116 ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); 0117 // need loop since iostream code cannot handle short reads 0118 do { 0119 size_t result = ZSTD_decompressStream(s, out, in); 0120 zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); 0121 } while (in->pos < in->size && out->pos < out->size); 0122 return action == zstd::finish && in->size == 0 && out->pos == 0 ? zstd::stream_end : zstd::okay; 0123 } 0124 0125 void zstd_base::reset(bool compress, bool realloc) 0126 { 0127 ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); 0128 ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); 0129 if (realloc) 0130 { 0131 memset(in, 0, sizeof(*in)); 0132 memset(out, 0, sizeof(*out)); 0133 eof_ = 0; 0134 0135 zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( 0136 compress ? 0137 ZSTD_initCStream(static_cast<ZSTD_CStream *>(cstream_), level) : 0138 ZSTD_initDStream(static_cast<ZSTD_DStream *>(dstream_)) 0139 ); 0140 } 0141 } 0142 0143 void zstd_base::do_init 0144 ( const zstd_params& p, bool compress, 0145 zstd::alloc_func, zstd::free_func, 0146 void* ) 0147 { 0148 ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); 0149 ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); 0150 0151 memset(in, 0, sizeof(*in)); 0152 memset(out, 0, sizeof(*out)); 0153 eof_ = 0; 0154 0155 level = p.level; 0156 zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( 0157 compress ? 0158 ZSTD_initCStream(static_cast<ZSTD_CStream *>(cstream_), level) : 0159 ZSTD_initDStream(static_cast<ZSTD_DStream *>(dstream_)) 0160 ); 0161 } 0162 0163 } // End namespace detail. 0164 0165 //----------------------------------------------------------------------------// 0166 0167 } } // End namespaces iostreams, boost.