File indexing completed on 2024-05-19 16:46:34
0001 // (C) Copyright Reimar Döffinger 2018. 0002 // Based on zstd.hpp by: 0003 // (C) Copyright Milan Svoboda 2008. 0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 0006 0007 // See http://www.boost.org/libs/iostreams for documentation. 0008 0009 #ifndef BOOST_IOSTREAMS_ZSTD_HPP_INCLUDED 0010 #define BOOST_IOSTREAMS_ZSTD_HPP_INCLUDED 0011 0012 #if defined(_MSC_VER) 0013 # pragma once 0014 #endif 0015 0016 #include <cassert> 0017 #include <iosfwd> // streamsize. 0018 #include <memory> // allocator, bad_alloc. 0019 #include <new> 0020 #include <boost/config.hpp> // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM. 0021 #include <boost/detail/workaround.hpp> 0022 #include <boost/iostreams/constants.hpp> // buffer size. 0023 #include <boost/iostreams/detail/config/auto_link.hpp> 0024 #include <boost/iostreams/detail/config/dyn_link.hpp> 0025 #include <boost/iostreams/detail/config/wide_streams.hpp> 0026 #include <boost/iostreams/detail/ios.hpp> // failure, streamsize. 0027 #include <boost/iostreams/filter/symmetric.hpp> 0028 #include <boost/iostreams/pipeline.hpp> 0029 #include <boost/type_traits/is_same.hpp> 0030 0031 // Must come last. 0032 #ifdef BOOST_MSVC 0033 # pragma warning(push) 0034 # pragma warning(disable:4251 4231 4660) // Dependencies not exported. 0035 #endif 0036 #include <boost/config/abi_prefix.hpp> 0037 0038 namespace boost { namespace iostreams { 0039 0040 namespace zstd { 0041 0042 typedef void* (*alloc_func)(void*, size_t, size_t); 0043 typedef void (*free_func)(void*, void*); 0044 0045 // Compression levels 0046 0047 BOOST_IOSTREAMS_DECL extern const uint32_t best_speed; 0048 BOOST_IOSTREAMS_DECL extern const uint32_t best_compression; 0049 BOOST_IOSTREAMS_DECL extern const uint32_t default_compression; 0050 0051 // Status codes 0052 0053 BOOST_IOSTREAMS_DECL extern const int okay; 0054 BOOST_IOSTREAMS_DECL extern const int stream_end; 0055 0056 // Flush codes 0057 0058 BOOST_IOSTREAMS_DECL extern const int finish; 0059 BOOST_IOSTREAMS_DECL extern const int flush; 0060 BOOST_IOSTREAMS_DECL extern const int run; 0061 0062 // Code for current OS 0063 0064 // Null pointer constant. 0065 0066 const int null = 0; 0067 0068 // Default values 0069 0070 } // End namespace zstd. 0071 0072 // 0073 // Class name: zstd_params. 0074 // Description: Encapsulates the parameters passed to zstddec_init 0075 // to customize compression and decompression. 0076 // 0077 struct zstd_params { 0078 0079 // Non-explicit constructor. 0080 zstd_params( uint32_t level = zstd::default_compression ) 0081 : level(level) 0082 { } 0083 uint32_t level; 0084 }; 0085 0086 // 0087 // Class name: zstd_error. 0088 // Description: Subclass of std::ios::failure thrown to indicate 0089 // zstd errors other than out-of-memory conditions. 0090 // 0091 class BOOST_IOSTREAMS_DECL zstd_error : public BOOST_IOSTREAMS_FAILURE { 0092 public: 0093 explicit zstd_error(size_t error); 0094 int error() const { return error_; } 0095 static void check BOOST_PREVENT_MACRO_SUBSTITUTION(size_t error); 0096 private: 0097 size_t error_; 0098 }; 0099 0100 namespace detail { 0101 0102 template<typename Alloc> 0103 struct zstd_allocator_traits { 0104 #ifndef BOOST_NO_STD_ALLOCATOR 0105 #if defined(BOOST_NO_CXX11_ALLOCATOR) 0106 typedef typename Alloc::template rebind<char>::other type; 0107 #else 0108 typedef typename std::allocator_traits<Alloc>::template rebind_alloc<char> type; 0109 #endif 0110 #else 0111 typedef std::allocator<char> type; 0112 #endif 0113 }; 0114 0115 template< typename Alloc, 0116 typename Base = // VC6 workaround (C2516) 0117 BOOST_DEDUCED_TYPENAME zstd_allocator_traits<Alloc>::type > 0118 struct zstd_allocator : private Base { 0119 private: 0120 #if defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_STD_ALLOCATOR) 0121 typedef typename Base::size_type size_type; 0122 #else 0123 typedef typename std::allocator_traits<Base>::size_type size_type; 0124 #endif 0125 public: 0126 BOOST_STATIC_CONSTANT(bool, custom = 0127 (!is_same<std::allocator<char>, Base>::value)); 0128 typedef typename zstd_allocator_traits<Alloc>::type allocator_type; 0129 static void* allocate(void* self, size_t items, size_t size); 0130 static void deallocate(void* self, void* address); 0131 }; 0132 0133 class BOOST_IOSTREAMS_DECL zstd_base { 0134 public: 0135 typedef char char_type; 0136 protected: 0137 zstd_base(); 0138 ~zstd_base(); 0139 template<typename Alloc> 0140 void init( const zstd_params& p, 0141 bool compress, 0142 zstd_allocator<Alloc>& zalloc ) 0143 { 0144 bool custom = zstd_allocator<Alloc>::custom; 0145 do_init( p, compress, 0146 custom ? zstd_allocator<Alloc>::allocate : 0, 0147 custom ? zstd_allocator<Alloc>::deallocate : 0, 0148 &zalloc ); 0149 } 0150 void before( const char*& src_begin, const char* src_end, 0151 char*& dest_begin, char* dest_end ); 0152 void after( const char*& src_begin, char*& dest_begin, 0153 bool compress ); 0154 int deflate(int action); 0155 int inflate(int action); 0156 void reset(bool compress, bool realloc); 0157 private: 0158 void do_init( const zstd_params& p, bool compress, 0159 zstd::alloc_func, 0160 zstd::free_func, 0161 void* derived ); 0162 void* cstream_; // Actual type: ZSTD_CStream * 0163 void* dstream_; // Actual type: ZSTD_DStream * 0164 void* in_; // Actual type: ZSTD_inBuffer * 0165 void* out_; // Actual type: ZSTD_outBuffer * 0166 int eof_; 0167 uint32_t level; 0168 }; 0169 0170 // 0171 // Template name: zstd_compressor_impl 0172 // Description: Model of C-Style Filter implementing compression by 0173 // delegating to the zstd function deflate. 0174 // 0175 template<typename Alloc = std::allocator<char> > 0176 class zstd_compressor_impl : public zstd_base, public zstd_allocator<Alloc> { 0177 public: 0178 zstd_compressor_impl(const zstd_params& = zstd::default_compression); 0179 ~zstd_compressor_impl(); 0180 bool filter( const char*& src_begin, const char* src_end, 0181 char*& dest_begin, char* dest_end, bool flush ); 0182 void close(); 0183 }; 0184 0185 // 0186 // Template name: zstd_compressor_impl 0187 // Description: Model of C-Style Filte implementing decompression by 0188 // delegating to the zstd function inflate. 0189 // 0190 template<typename Alloc = std::allocator<char> > 0191 class zstd_decompressor_impl : public zstd_base, public zstd_allocator<Alloc> { 0192 public: 0193 zstd_decompressor_impl(const zstd_params&); 0194 zstd_decompressor_impl(); 0195 ~zstd_decompressor_impl(); 0196 bool filter( const char*& begin_in, const char* end_in, 0197 char*& begin_out, char* end_out, bool flush ); 0198 void close(); 0199 }; 0200 0201 } // End namespace detail. 0202 0203 // 0204 // Template name: zstd_compressor 0205 // Description: Model of InputFilter and OutputFilter implementing 0206 // compression using zstd. 0207 // 0208 template<typename Alloc = std::allocator<char> > 0209 struct basic_zstd_compressor 0210 : symmetric_filter<detail::zstd_compressor_impl<Alloc>, Alloc> 0211 { 0212 private: 0213 typedef detail::zstd_compressor_impl<Alloc> impl_type; 0214 typedef symmetric_filter<impl_type, Alloc> base_type; 0215 public: 0216 typedef typename base_type::char_type char_type; 0217 typedef typename base_type::category category; 0218 basic_zstd_compressor( const zstd_params& = zstd::default_compression, 0219 std::streamsize buffer_size = default_device_buffer_size ); 0220 }; 0221 BOOST_IOSTREAMS_PIPABLE(basic_zstd_compressor, 1) 0222 0223 typedef basic_zstd_compressor<> zstd_compressor; 0224 0225 // 0226 // Template name: zstd_decompressor 0227 // Description: Model of InputFilter and OutputFilter implementing 0228 // decompression using zstd. 0229 // 0230 template<typename Alloc = std::allocator<char> > 0231 struct basic_zstd_decompressor 0232 : symmetric_filter<detail::zstd_decompressor_impl<Alloc>, Alloc> 0233 { 0234 private: 0235 typedef detail::zstd_decompressor_impl<Alloc> impl_type; 0236 typedef symmetric_filter<impl_type, Alloc> base_type; 0237 public: 0238 typedef typename base_type::char_type char_type; 0239 typedef typename base_type::category category; 0240 basic_zstd_decompressor( std::streamsize buffer_size = default_device_buffer_size ); 0241 basic_zstd_decompressor( const zstd_params& p, 0242 std::streamsize buffer_size = default_device_buffer_size ); 0243 }; 0244 BOOST_IOSTREAMS_PIPABLE(basic_zstd_decompressor, 1) 0245 0246 typedef basic_zstd_decompressor<> zstd_decompressor; 0247 0248 //----------------------------------------------------------------------------// 0249 0250 //------------------Implementation of zstd_allocator--------------------------// 0251 0252 namespace detail { 0253 0254 template<typename Alloc, typename Base> 0255 void* zstd_allocator<Alloc, Base>::allocate 0256 (void* self, size_t items, size_t size) 0257 { 0258 size_type len = items * size; 0259 char* ptr = 0260 static_cast<allocator_type*>(self)->allocate 0261 (len + sizeof(size_type) 0262 #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) 0263 , (char*)0 0264 #endif 0265 ); 0266 *reinterpret_cast<size_type*>(ptr) = len; 0267 return ptr + sizeof(size_type); 0268 } 0269 0270 template<typename Alloc, typename Base> 0271 void zstd_allocator<Alloc, Base>::deallocate(void* self, void* address) 0272 { 0273 char* ptr = reinterpret_cast<char*>(address) - sizeof(size_type); 0274 size_type len = *reinterpret_cast<size_type*>(ptr) + sizeof(size_type); 0275 static_cast<allocator_type*>(self)->deallocate(ptr, len); 0276 } 0277 0278 //------------------Implementation of zstd_compressor_impl--------------------// 0279 0280 template<typename Alloc> 0281 zstd_compressor_impl<Alloc>::zstd_compressor_impl(const zstd_params& p) 0282 { init(p, true, static_cast<zstd_allocator<Alloc>&>(*this)); } 0283 0284 template<typename Alloc> 0285 zstd_compressor_impl<Alloc>::~zstd_compressor_impl() 0286 { reset(true, false); } 0287 0288 template<typename Alloc> 0289 bool zstd_compressor_impl<Alloc>::filter 0290 ( const char*& src_begin, const char* src_end, 0291 char*& dest_begin, char* dest_end, bool flush ) 0292 { 0293 before(src_begin, src_end, dest_begin, dest_end); 0294 int result = deflate(flush ? zstd::finish : zstd::run); 0295 after(src_begin, dest_begin, true); 0296 return result != zstd::stream_end; 0297 } 0298 0299 template<typename Alloc> 0300 void zstd_compressor_impl<Alloc>::close() { reset(true, true); } 0301 0302 //------------------Implementation of zstd_decompressor_impl------------------// 0303 0304 template<typename Alloc> 0305 zstd_decompressor_impl<Alloc>::zstd_decompressor_impl(const zstd_params& p) 0306 { init(p, false, static_cast<zstd_allocator<Alloc>&>(*this)); } 0307 0308 template<typename Alloc> 0309 zstd_decompressor_impl<Alloc>::~zstd_decompressor_impl() 0310 { reset(false, false); } 0311 0312 template<typename Alloc> 0313 zstd_decompressor_impl<Alloc>::zstd_decompressor_impl() 0314 { 0315 zstd_params p; 0316 init(p, false, static_cast<zstd_allocator<Alloc>&>(*this)); 0317 } 0318 0319 template<typename Alloc> 0320 bool zstd_decompressor_impl<Alloc>::filter 0321 ( const char*& src_begin, const char* src_end, 0322 char*& dest_begin, char* dest_end, bool flush ) 0323 { 0324 before(src_begin, src_end, dest_begin, dest_end); 0325 int result = inflate(flush ? zstd::finish : zstd::run); 0326 after(src_begin, dest_begin, false); 0327 return result != zstd::stream_end; 0328 } 0329 0330 template<typename Alloc> 0331 void zstd_decompressor_impl<Alloc>::close() { reset(false, true); } 0332 0333 } // End namespace detail. 0334 0335 //------------------Implementation of zstd_compressor-----------------------// 0336 0337 template<typename Alloc> 0338 basic_zstd_compressor<Alloc>::basic_zstd_compressor 0339 (const zstd_params& p, std::streamsize buffer_size) 0340 : base_type(buffer_size, p) { } 0341 0342 //------------------Implementation of zstd_decompressor-----------------------// 0343 0344 template<typename Alloc> 0345 basic_zstd_decompressor<Alloc>::basic_zstd_decompressor 0346 (std::streamsize buffer_size) 0347 : base_type(buffer_size) { } 0348 0349 template<typename Alloc> 0350 basic_zstd_decompressor<Alloc>::basic_zstd_decompressor 0351 (const zstd_params& p, std::streamsize buffer_size) 0352 : base_type(buffer_size, p) { } 0353 0354 //----------------------------------------------------------------------------// 0355 0356 } } // End namespaces iostreams, boost. 0357 0358 #include <boost/config/abi_suffix.hpp> // Pops abi_suffix.hpp pragmas. 0359 #ifdef BOOST_MSVC 0360 # pragma warning(pop) 0361 #endif 0362 0363 #endif // #ifndef BOOST_IOSTREAMS_ZSTD_HPP_INCLUDED