// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) // (C) Copyright 2003-2007 Jonathan Turkanis // 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. // Note: custom allocators are not supported on VC6, since that compiler // had trouble finding the function zlib_base::do_init. #ifndef BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED #define BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include #include // allocator. #include // bad_alloc. #include // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM. #include #include // buffer size. #include #include #include #include #include // failure, streamsize. #include #include #include // Must come last. #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable:4251 4231 4660) #endif #include // Temporary fix. #undef small namespace boost { namespace iostreams { namespace bzip2 { // Typedefs. typedef void* (*alloc_func)(void*, int, int); typedef void (*free_func)(void*, void*); // Status codes BOOST_IOSTREAMS_DECL extern const int ok; BOOST_IOSTREAMS_DECL extern const int run_ok; BOOST_IOSTREAMS_DECL extern const int flush_ok; BOOST_IOSTREAMS_DECL extern const int finish_ok; BOOST_IOSTREAMS_DECL extern const int stream_end; BOOST_IOSTREAMS_DECL extern const int sequence_error; BOOST_IOSTREAMS_DECL extern const int param_error; BOOST_IOSTREAMS_DECL extern const int mem_error; BOOST_IOSTREAMS_DECL extern const int data_error; BOOST_IOSTREAMS_DECL extern const int data_error_magic; BOOST_IOSTREAMS_DECL extern const int io_error; BOOST_IOSTREAMS_DECL extern const int unexpected_eof; BOOST_IOSTREAMS_DECL extern const int outbuff_full; BOOST_IOSTREAMS_DECL extern const int config_error; // Action codes BOOST_IOSTREAMS_DECL extern const int finish; BOOST_IOSTREAMS_DECL extern const int run; // Default values const int default_block_size = 9; const int default_work_factor = 30; const bool default_small = false; } // End namespace bzip2. // // Class name: bzip2_params. // Description: Encapsulates the parameters passed to deflateInit2 // to customize compression. // struct bzip2_params { // Non-explicit constructor for compression. bzip2_params( int block_size = bzip2::default_block_size, int work_factor = bzip2::default_work_factor ) : block_size(block_size), work_factor(work_factor) { } // Constructor for decompression. bzip2_params(bool small) : small(small), work_factor(0) { } union { int block_size; // For compression. bool small; // For decompression. }; int work_factor; }; // // Class name: bzip2_error. // Description: Subclass of std::ios_base::failure thrown to indicate // bzip2 errors other than out-of-memory conditions. // class BOOST_IOSTREAMS_DECL bzip2_error : public BOOST_IOSTREAMS_FAILURE { public: explicit bzip2_error(int error); int error() const { return error_; } static void check BOOST_PREVENT_MACRO_SUBSTITUTION(int error); private: int error_; }; namespace detail { template struct bzip2_allocator_traits { #ifndef BOOST_NO_STD_ALLOCATOR typedef typename Alloc::template rebind::other type; #else typedef std::allocator type; #endif }; template< typename Alloc, typename Base = // VC6 workaround (C2516) BOOST_DEDUCED_TYPENAME bzip2_allocator_traits::type > struct bzip2_allocator : private Base { private: typedef typename Base::size_type size_type; public: BOOST_STATIC_CONSTANT(bool, custom = (!is_same, Base>::value)); typedef typename bzip2_allocator_traits::type allocator_type; static void* allocate(void* self, int items, int size); static void deallocate(void* self, void* address); }; class BOOST_IOSTREAMS_DECL bzip2_base { public: typedef char char_type; protected: bzip2_base(const bzip2_params& params); ~bzip2_base(); bzip2_params& params() { return params_; } bool& ready() { return ready_; } template void init( bool compress, bzip2_allocator& alloc ) { bool custom = bzip2_allocator::custom; do_init( compress, #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) custom ? bzip2_allocator::allocate : 0, custom ? bzip2_allocator::deallocate : 0, #endif custom ? &alloc : 0 ); } void before( const char*& src_begin, const char* src_end, char*& dest_begin, char* dest_end ); void after(const char*& src_begin, char*& dest_begin); int check_end(const char* src_begin, const char* dest_begin); int compress(int action); int decompress(); void end(bool compress); private: void do_init( bool compress, #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) bzip2::alloc_func, bzip2::free_func, #endif void* derived ); bzip2_params params_; void* stream_; // Actual type: bz_stream*. bool ready_; }; // // Template name: bzip2_compressor_impl // Description: Model of SymmetricFilter implementing compression by // delegating to the libbzip2 function BZ_bzCompress. // template > class bzip2_compressor_impl : public bzip2_base, #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) public #endif bzip2_allocator { public: bzip2_compressor_impl(const bzip2_params&); bool filter( const char*& src_begin, const char* src_end, char*& dest_begin, char* dest_end, bool flush ); void close(); private: void init(); bool eof_; // Guard to make sure filter() isn't called after it returns false. }; // // Template name: bzip2_compressor // Description: Model of SymmetricFilter implementing decompression by // delegating to the libbzip2 function BZ_bzDecompress. // template > class bzip2_decompressor_impl : public bzip2_base, #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) public #endif bzip2_allocator { public: bzip2_decompressor_impl(bool small = bzip2::default_small); bool filter( const char*& begin_in, const char* end_in, char*& begin_out, char* end_out, bool flush ); void close(); private: void init(); bool eof_; // Guard to make sure filter() isn't called after it returns false. }; } // End namespace detail. // // Template name: bzip2_compressor // Description: Model of InputFilter and OutputFilter implementing // compression using libbzip2. // template > struct basic_bzip2_compressor : symmetric_filter, Alloc> { private: typedef detail::bzip2_compressor_impl impl_type; typedef symmetric_filter base_type; public: typedef typename base_type::char_type char_type; typedef typename base_type::category category; basic_bzip2_compressor( const bzip2_params& = bzip2::default_block_size, int buffer_size = default_device_buffer_size ); }; BOOST_IOSTREAMS_PIPABLE(basic_bzip2_compressor, 1) typedef basic_bzip2_compressor<> bzip2_compressor; // // Template name: bzip2_decompressor // Description: Model of InputFilter and OutputFilter implementing // decompression using libbzip2. // template > struct basic_bzip2_decompressor : symmetric_filter, Alloc> { private: typedef detail::bzip2_decompressor_impl impl_type; typedef symmetric_filter base_type; public: typedef typename base_type::char_type char_type; typedef typename base_type::category category; basic_bzip2_decompressor( bool small = bzip2::default_small, int buffer_size = default_device_buffer_size ); }; BOOST_IOSTREAMS_PIPABLE(basic_bzip2_decompressor, 1) typedef basic_bzip2_decompressor<> bzip2_decompressor; //----------------------------------------------------------------------------// //------------------Implementation of bzip2_allocator-------------------------// namespace detail { template void* bzip2_allocator::allocate(void* self, int items, int size) { size_type len = items * size; char* ptr = static_cast(self)->allocate (len + sizeof(size_type) #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) , (char*)0 #endif ); *reinterpret_cast(ptr) = len; return ptr + sizeof(size_type); } template void bzip2_allocator::deallocate(void* self, void* address) { char* ptr = reinterpret_cast(address) - sizeof(size_type); size_type len = *reinterpret_cast(ptr) + sizeof(size_type); static_cast(self)->deallocate(ptr, len); } //------------------Implementation of bzip2_compressor_impl-------------------// template bzip2_compressor_impl::bzip2_compressor_impl(const bzip2_params& p) : bzip2_base(p), eof_(false) { } template bool bzip2_compressor_impl::filter ( const char*& src_begin, const char* src_end, char*& dest_begin, char* dest_end, bool flush ) { if (!ready()) init(); if (eof_) return false; before(src_begin, src_end, dest_begin, dest_end); int result = compress(flush ? bzip2::finish : bzip2::run); after(src_begin, dest_begin); bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); return !(eof_ = result == bzip2::stream_end); } template void bzip2_compressor_impl::close() { try { end(true); } catch (...) { eof_ = false; throw; } eof_ = false; } template inline void bzip2_compressor_impl::init() { bzip2_base::init(true, static_cast&>(*this)); } //------------------Implementation of bzip2_decompressor_impl-----------------// template bzip2_decompressor_impl::bzip2_decompressor_impl(bool small) : bzip2_base(bzip2_params(small)), eof_(false) { } template bool bzip2_decompressor_impl::filter ( const char*& src_begin, const char* src_end, char*& dest_begin, char* dest_end, bool flush ) { if (eof_) { // reset the stream if there are more characters if(src_begin == src_end) return false; else close(); } if (!ready()) init(); before(src_begin, src_end, dest_begin, dest_end); int result = decompress(); if(result == bzip2::ok && flush) result = check_end(src_begin, dest_begin); after(src_begin, dest_begin); bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); eof_ = result == bzip2::stream_end; return true; } template void bzip2_decompressor_impl::close() { try { end(false); } catch (...) { eof_ = false; throw; } eof_ = false; } template inline void bzip2_decompressor_impl::init() { bzip2_base::init(false, static_cast&>(*this)); } } // End namespace detail. //------------------Implementation of bzip2_decompressor----------------------// template basic_bzip2_compressor::basic_bzip2_compressor (const bzip2_params& p, int buffer_size) : base_type(buffer_size, p) { } //------------------Implementation of bzip2_decompressor----------------------// template basic_bzip2_decompressor::basic_bzip2_decompressor (bool small, int buffer_size) : base_type(buffer_size, small) { } //----------------------------------------------------------------------------// } } // End namespaces iostreams, boost. #include // Pops abi_suffix.hpp pragmas. #ifdef BOOST_MSVC # pragma warning(pop) #endif #endif // #ifndef BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED