diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
commit | 1a78a62555be32868418fe52f8e330c9d0f95d5a (patch) | |
tree | d3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/iostreams/filter | |
download | boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2 boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip |
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/iostreams/filter')
-rw-r--r-- | boost/iostreams/filter/aggregate.hpp | 168 | ||||
-rw-r--r-- | boost/iostreams/filter/bzip2.hpp | 414 | ||||
-rw-r--r-- | boost/iostreams/filter/counter.hpp | 82 | ||||
-rw-r--r-- | boost/iostreams/filter/grep.hpp | 109 | ||||
-rw-r--r-- | boost/iostreams/filter/gzip.hpp | 757 | ||||
-rw-r--r-- | boost/iostreams/filter/line.hpp | 227 | ||||
-rw-r--r-- | boost/iostreams/filter/newline.hpp | 442 | ||||
-rw-r--r-- | boost/iostreams/filter/regex.hpp | 98 | ||||
-rw-r--r-- | boost/iostreams/filter/stdio.hpp | 84 | ||||
-rw-r--r-- | boost/iostreams/filter/symmetric.hpp | 310 | ||||
-rw-r--r-- | boost/iostreams/filter/test.hpp | 322 | ||||
-rw-r--r-- | boost/iostreams/filter/zlib.hpp | 427 |
12 files changed, 3440 insertions, 0 deletions
diff --git a/boost/iostreams/filter/aggregate.hpp b/boost/iostreams/filter/aggregate.hpp new file mode 100644 index 0000000000..d37e734507 --- /dev/null +++ b/boost/iostreams/filter/aggregate.hpp @@ -0,0 +1,168 @@ +// (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. + +#ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <algorithm> // copy, min. +#include <boost/assert.hpp> +#include <iterator> // back_inserter +#include <vector> +#include <boost/iostreams/constants.hpp> // default_device_buffer_size +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/detail/char_traits.hpp> +#include <boost/iostreams/detail/ios.hpp> // openmode, streamsize. +#include <boost/iostreams/pipeline.hpp> +#include <boost/iostreams/read.hpp> // check_eof +#include <boost/iostreams/write.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/type_traits/is_convertible.hpp> + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC. + +namespace boost { namespace iostreams { + +// +// Template name: aggregate_filter. +// Template paramters: +// Ch - The character type. +// Alloc - The allocator type. +// Description: Utility for defining DualUseFilters which filter an +// entire stream at once. To use, override the protected virtual +// member do_filter. +// Note: This filter should not be copied while it is in use. +// +template<typename Ch, typename Alloc = std::allocator<Ch> > +class aggregate_filter { +public: + typedef Ch char_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; + aggregate_filter() : ptr_(0), state_(0) { } + virtual ~aggregate_filter() { } + + template<typename Source> + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + BOOST_ASSERT(!(state_ & f_write)); + state_ |= f_read; + if (!(state_ & f_eof)) + do_read(src); + std::streamsize amt = + (std::min)(n, static_cast<std::streamsize>(data_.size() - ptr_)); + if (amt) { + BOOST_IOSTREAMS_CHAR_TRAITS(char_type)::copy(s, &data_[ptr_], amt); + ptr_ += amt; + } + return detail::check_eof(amt); + } + + template<typename Sink> + std::streamsize write(Sink&, const char_type* s, std::streamsize n) + { + BOOST_ASSERT(!(state_ & f_read)); + state_ |= f_write; + data_.insert(data_.end(), s, s + n); + return n; + } + + template<typename Sink> + void close(Sink& sink, BOOST_IOS::openmode which) + { + if ((state_ & f_read) != 0 && which == BOOST_IOS::in) + close_impl(); + if ((state_ & f_write) != 0 && which == BOOST_IOS::out) { + try { + vector_type filtered; + do_filter(data_, filtered); + do_write( + sink, &filtered[0], + static_cast<std::streamsize>(filtered.size()) + ); + } catch (...) { + close_impl(); + throw; + } + close_impl(); + } + } + +protected: + typedef std::vector<Ch, Alloc> vector_type; + typedef typename vector_type::size_type size_type; +private: + virtual void do_filter(const vector_type& src, vector_type& dest) = 0; + virtual void do_close() { } + + template<typename Source> + void do_read(Source& src) + { + using std::streamsize; + vector_type data; + while (true) { + const std::streamsize size = default_device_buffer_size; + Ch buf[size]; + std::streamsize amt; + if ((amt = boost::iostreams::read(src, buf, size)) == -1) + break; + data.insert(data.end(), buf, buf + amt); + } + do_filter(data, data_); + state_ |= f_eof; + } + + template<typename Sink> + void do_write(Sink& sink, const char_type* s, std::streamsize n) + { + typedef typename iostreams::category_of<Sink>::type category; + typedef is_convertible<category, output> can_write; + do_write(sink, s, n, can_write()); + } + + template<typename Sink> + void do_write(Sink& sink, const char_type* s, std::streamsize n, mpl::true_) + { iostreams::write(sink, s, n); } + + template<typename Sink> + void do_write(Sink&, const char_type*, std::streamsize, mpl::false_) { } + + void close_impl() + { + data_.clear(); + ptr_ = 0; + state_ = 0; + do_close(); + } + + enum flag_type { + f_read = 1, + f_write = f_read << 1, + f_eof = f_write << 1 + }; + + // Note: typically will not be copied while vector contains data. + vector_type data_; + size_type ptr_; + int state_; +}; +BOOST_IOSTREAMS_PIPABLE(aggregate_filter, 1) + +} } // End namespaces iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/bzip2.hpp b/boost/iostreams/filter/bzip2.hpp new file mode 100644 index 0000000000..bc4b18f04a --- /dev/null +++ b/boost/iostreams/filter/bzip2.hpp @@ -0,0 +1,414 @@ +// (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 <cassert> +#include <memory> // allocator. +#include <new> // bad_alloc. +#include <boost/config.hpp> // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM. +#include <boost/detail/workaround.hpp> +#include <boost/iostreams/constants.hpp> // buffer size. +#include <boost/iostreams/detail/config/auto_link.hpp> +#include <boost/iostreams/detail/config/bzip2.hpp> +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/detail/config/wide_streams.hpp> +#include <boost/iostreams/detail/ios.hpp> // failure, streamsize. +#include <boost/iostreams/filter/symmetric.hpp> +#include <boost/iostreams/pipeline.hpp> +#include <boost/type_traits/is_same.hpp> + +// Must come last. +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4251 4231 4660) +#endif +#include <boost/config/abi_prefix.hpp> + +// 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<typename Alloc> +struct bzip2_allocator_traits { +#ifndef BOOST_NO_STD_ALLOCATOR + typedef typename Alloc::template rebind<char>::other type; +#else + typedef std::allocator<char> type; +#endif +}; + +template< typename Alloc, + typename Base = // VC6 workaround (C2516) + BOOST_DEDUCED_TYPENAME bzip2_allocator_traits<Alloc>::type > +struct bzip2_allocator : private Base { +private: + typedef typename Base::size_type size_type; +public: + BOOST_STATIC_CONSTANT(bool, custom = + (!is_same<std::allocator<char>, Base>::value)); + typedef typename bzip2_allocator_traits<Alloc>::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<typename Alloc> + void init( bool compress, + bzip2_allocator<Alloc>& alloc ) + { + bool custom = bzip2_allocator<Alloc>::custom; + do_init( compress, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + custom ? bzip2_allocator<Alloc>::allocate : 0, + custom ? bzip2_allocator<Alloc>::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<typename Alloc = std::allocator<char> > +class bzip2_compressor_impl + : public bzip2_base, + #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) + public + #endif + bzip2_allocator<Alloc> +{ +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<typename Alloc = std::allocator<char> > +class bzip2_decompressor_impl + : public bzip2_base, + #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) + public + #endif + bzip2_allocator<Alloc> +{ +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<typename Alloc = std::allocator<char> > +struct basic_bzip2_compressor + : symmetric_filter<detail::bzip2_compressor_impl<Alloc>, Alloc> +{ +private: + typedef detail::bzip2_compressor_impl<Alloc> impl_type; + typedef symmetric_filter<impl_type, Alloc> 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<typename Alloc = std::allocator<char> > +struct basic_bzip2_decompressor + : symmetric_filter<detail::bzip2_decompressor_impl<Alloc>, Alloc> +{ +private: + typedef detail::bzip2_decompressor_impl<Alloc> impl_type; + typedef symmetric_filter<impl_type, Alloc> 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<typename Alloc, typename Base> +void* bzip2_allocator<Alloc, Base>::allocate(void* self, int items, int size) +{ + size_type len = items * size; + char* ptr = + static_cast<allocator_type*>(self)->allocate + (len + sizeof(size_type) + #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) + , (char*)0 + #endif + ); + *reinterpret_cast<size_type*>(ptr) = len; + return ptr + sizeof(size_type); +} + +template<typename Alloc, typename Base> +void bzip2_allocator<Alloc, Base>::deallocate(void* self, void* address) +{ + char* ptr = reinterpret_cast<char*>(address) - sizeof(size_type); + size_type len = *reinterpret_cast<size_type*>(ptr) + sizeof(size_type); + static_cast<allocator_type*>(self)->deallocate(ptr, len); +} + +//------------------Implementation of bzip2_compressor_impl-------------------// + +template<typename Alloc> +bzip2_compressor_impl<Alloc>::bzip2_compressor_impl(const bzip2_params& p) + : bzip2_base(p), eof_(false) { } + +template<typename Alloc> +bool bzip2_compressor_impl<Alloc>::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<typename Alloc> +void bzip2_compressor_impl<Alloc>::close() +{ + try { + end(true); + } catch (...) { + eof_ = false; + throw; + } + eof_ = false; +} + +template<typename Alloc> +inline void bzip2_compressor_impl<Alloc>::init() +{ bzip2_base::init(true, static_cast<bzip2_allocator<Alloc>&>(*this)); } + +//------------------Implementation of bzip2_decompressor_impl-----------------// + +template<typename Alloc> +bzip2_decompressor_impl<Alloc>::bzip2_decompressor_impl(bool small) + : bzip2_base(bzip2_params(small)), eof_(false) { } + +template<typename Alloc> +bool bzip2_decompressor_impl<Alloc>::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<typename Alloc> +void bzip2_decompressor_impl<Alloc>::close() +{ + try { + end(false); + } catch (...) { + eof_ = false; + throw; + } + eof_ = false; +} + +template<typename Alloc> +inline void bzip2_decompressor_impl<Alloc>::init() +{ bzip2_base::init(false, static_cast<bzip2_allocator<Alloc>&>(*this)); } +} // End namespace detail. + +//------------------Implementation of bzip2_decompressor----------------------// + +template<typename Alloc> +basic_bzip2_compressor<Alloc>::basic_bzip2_compressor + (const bzip2_params& p, int buffer_size) + : base_type(buffer_size, p) + { } + +//------------------Implementation of bzip2_decompressor----------------------// + +template<typename Alloc> +basic_bzip2_decompressor<Alloc>::basic_bzip2_decompressor + (bool small, int buffer_size) + : base_type(buffer_size, small) + { } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include <boost/config/abi_suffix.hpp> // Pops abi_suffix.hpp pragmas. +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED diff --git a/boost/iostreams/filter/counter.hpp b/boost/iostreams/filter/counter.hpp new file mode 100644 index 0000000000..e47cba9417 --- /dev/null +++ b/boost/iostreams/filter/counter.hpp @@ -0,0 +1,82 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-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. + +#ifndef BOOST_IOSTREAMS_COUNTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_COUNTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <algorithm> // count. +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/char_traits.hpp> +#include <boost/iostreams/operations.hpp> +#include <boost/iostreams/pipeline.hpp> + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> // VC7.1 C4244. + +namespace boost { namespace iostreams { + +// +// Template name: basic_counter. +// Template paramters: +// Ch - The character type. +// Description: Filter which counts lines and characters. +// +template<typename Ch> +class basic_counter { +public: + typedef Ch char_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + optimally_buffered_tag + { }; + explicit basic_counter(int first_line = 0, int first_char = 0) + : lines_(first_line), chars_(first_char) + { } + int lines() const { return lines_; } + int characters() const { return chars_; } + std::streamsize optimal_buffer_size() const { return 0; } + + template<typename Source> + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + std::streamsize result = iostreams::read(src, s, n); + if (result == -1) + return -1; + lines_ += std::count(s, s + result, char_traits<Ch>::newline()); + chars_ += result; + return result; + } + + template<typename Sink> + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + std::streamsize result = iostreams::write(snk, s, n); + lines_ += std::count(s, s + result, char_traits<Ch>::newline()); + chars_ += result; + return result; + } +private: + int lines_; + int chars_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_counter, 1) + + +typedef basic_counter<char> counter; +typedef basic_counter<wchar_t> wcounter; + +} } // End namespaces iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> + +#endif // #ifndef BOOST_IOSTREAMS_COUNTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/grep.hpp b/boost/iostreams/filter/grep.hpp new file mode 100644 index 0000000000..a41da5b992 --- /dev/null +++ b/boost/iostreams/filter/grep.hpp @@ -0,0 +1,109 @@ +/* + * 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. + + * File: boost/iostreams/filter/grep.hpp + * Date: Mon May 26 17:48:45 MDT 2008 + * Copyright: 2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Defines the class template basic_grep_filter and its specializations + * grep_filter and wgrep_filter. + */ + +#ifndef BOOST_IOSTREAMS_GREP_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_GREP_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <iostream> + +#include <memory> // allocator. +#include <boost/iostreams/char_traits.hpp> +#include <boost/iostreams/filter/line.hpp> +#include <boost/iostreams/pipeline.hpp> +#include <boost/regex.hpp> + +namespace boost { namespace iostreams { + +namespace grep { + +const int invert = 1; +const int whole_line = invert << 1; + +} // End namespace grep. + +template< typename Ch, + typename Tr = regex_traits<Ch>, + typename Alloc = std::allocator<Ch> > +class basic_grep_filter : public basic_line_filter<Ch, Alloc> { +private: + typedef basic_line_filter<Ch, Alloc> base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + typedef char_traits<char_type> traits_type; + typedef typename base_type::string_type string_type; + typedef basic_regex<Ch, Tr> regex_type; + typedef regex_constants::match_flag_type match_flag_type; + basic_grep_filter( const regex_type& re, + match_flag_type match_flags = + regex_constants::match_default, + int options = 0 ); + int count() const { return count_; } + + template<typename Sink> + void close(Sink& snk, BOOST_IOS::openmode which) + { + base_type::close(snk, which); + options_ &= ~f_initialized; + } +private: + virtual string_type do_filter(const string_type& line) + { + if ((options_ & f_initialized) == 0) { + options_ |= f_initialized; + count_ = 0; + } + bool matches = (options_ & grep::whole_line) ? + regex_match(line, re_, match_flags_) : + regex_search(line, re_, match_flags_); + if (options_ & grep::invert) + matches = !matches; + if (matches) + ++count_; + return matches ? line + traits_type::newline() : string_type(); + } + + // Private flags bitwise OR'd with constants from namespace grep + enum flags_ { + f_initialized = 65536 + }; + + regex_type re_; + match_flag_type match_flags_; + int options_; + int count_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_grep_filter, 3) + +typedef basic_grep_filter<char> grep_filter; +typedef basic_grep_filter<wchar_t> wgrep_filter; + +//------------------Implementation of basic_grep_filter-----------------------// + +template<typename Ch, typename Tr, typename Alloc> +basic_grep_filter<Ch, Tr, Alloc>::basic_grep_filter + (const regex_type& re, match_flag_type match_flags, int options) + : base_type(true), re_(re), match_flags_(match_flags), + options_(options), count_(0) + { } + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_REGEX_FILTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/gzip.hpp b/boost/iostreams/filter/gzip.hpp new file mode 100644 index 0000000000..0f483b4463 --- /dev/null +++ b/boost/iostreams/filter/gzip.hpp @@ -0,0 +1,757 @@ +// (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. + +// 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 <boost/assert.hpp> +#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/detail/error.hpp> +#include <boost/iostreams/operations.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filter/zlib.hpp> +#include <boost/iostreams/pipeline.hpp> +#include <boost/iostreams/putback.hpp> +#include <boost/throw_exception.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 { + +//------------------Definitions of constants----------------------------------// + +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. +const int bad_method = 6; // Unsupported compression method. + +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. + +//------------------Definition of gzip_params---------------------------------// + +// +// 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), comment(comment), mtime(mtime) + { } + std::string file_name; + std::string comment; + std::time_t mtime; +}; + +//------------------Definition of gzip_error----------------------------------// + +// +// 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_; +}; + +//------------------Definition of gzip_compressor-----------------------------// + +// +// 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) + { + 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. + std::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) + { + try { + // Close zlib compressor. + base_type::close(snk, m); + + if (m == 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); + } + } + } catch(...) { + close_impl(); + throw; + } + close_impl(); + } +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::mpl::true_) + { + 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))); + } + template<typename Sink> + static void write_long(long n, Sink& next, boost::mpl::false_) + { + } + template<typename Sink> + static void write_long(long n, Sink& next) + { + typedef typename category_of<Sink>::type category; + typedef is_convertible<category, output> can_write; + write_long(n, next, can_write()); + } + + void close_impl() + { + #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; + } + + enum state_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; + +//------------------Definition of helper templates for decompression----------// + +namespace detail { + +// Processes gzip headers +class BOOST_IOSTREAMS_DECL gzip_header { +public: + gzip_header() { reset(); } + + // Members for processing header data + void process(char c); + bool done() const { return state_ == s_done; } + void reset(); + + // Members for accessing header data + std::string file_name() const { return file_name_; } + std::string comment() const { return comment_; } + bool text() const { return (flags_ & gzip::flags::text) != 0; } + int os() const { return os_; } + std::time_t mtime() const { return mtime_; } +private: + enum state_type { + s_id1 = 1, + s_id2 = s_id1 + 1, + s_cm = s_id2 + 1, + s_flg = s_cm + 1, + s_mtime = s_flg + 1, + s_xfl = s_mtime + 1, + s_os = s_xfl + 1, + s_xlen = s_os + 1, + s_extra = s_xlen + 1, + s_name = s_extra + 1, + s_comment = s_name + 1, + s_hcrc = s_comment + 1, + s_done = s_hcrc + 1 + }; + std::string file_name_; + std::string comment_; + int os_; + std::time_t mtime_; + int flags_; + int state_; + int offset_; // Offset within fixed-length region. + int xlen_; // Bytes remaining in extra field. +}; + +// Processes gzip footers +class BOOST_IOSTREAMS_DECL gzip_footer { +public: + gzip_footer() { reset(); } + + // Members for processing footer data + void process(char c); + bool done() const { return state_ == s_done; } + void reset(); + + // Members for accessing footer data + zlib::ulong crc() const { return crc_; } + zlib::ulong uncompressed_size() const { return isize_; } +private: + enum state_type { + s_crc = 1, + s_isize = s_crc + 1, + s_done = s_isize + 1 + }; + zlib::ulong crc_; + zlib::ulong isize_; + int state_; + int offset_; +}; + +} // End namespace boost::iostreams::detail. + +//------------------Definition of basic_gzip_decompressor---------------------// + +// +// 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> { +private: + typedef basic_zlib_decompressor<Alloc> base_type; + typedef typename base_type::string_type string_type; +public: + typedef char char_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; + basic_gzip_decompressor( int window_bits = gzip::default_window_bits, + int buffer_size = default_device_buffer_size ); + + template<typename Sink> + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + std::streamsize result = 0; + while(result < n) { + if(state_ == s_start) { + state_ = s_header; + header_.reset(); + footer_.reset(); + } + if (state_ == s_header) { + int c = s[result++]; + header_.process(c); + if (header_.done()) + state_ = s_body; + } else if (state_ == s_body) { + try { + std::streamsize amt = + base_type::write(snk, s + result, n - result); + result += amt; + if (!this->eof()) { + break; + } else { + state_ = s_footer; + } + } catch (const zlib_error& e) { + boost::throw_exception(gzip_error(e)); + } + } else { // state_ == s_footer + if (footer_.done()) { + if (footer_.crc() != this->crc()) + boost::throw_exception(gzip_error(gzip::bad_crc)); + + base_type::close(snk, BOOST_IOS::out); + state_ = s_start; + } else { + int c = s[result++]; + footer_.process(c); + } + } + } + return result; + } + + template<typename Source> + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + typedef char_traits<char> traits_type; + std::streamsize result = 0; + peekable_source<Source> peek(src, putback_); + while (result < n && state_ != s_done) { + if (state_ == s_start) { + state_ = s_header; + header_.reset(); + footer_.reset(); + } + if (state_ == s_header) { + int c = boost::iostreams::get(peek); + if (traits_type::is_eof(c)) { + boost::throw_exception(gzip_error(gzip::bad_header)); + } else if (traits_type::would_block(c)) { + break; + } + header_.process(c); + if (header_.done()) + state_ = s_body; + } else if (state_ == s_body) { + try { + std::streamsize amt = + base_type::read(peek, s + result, n - result); + if (amt != -1) { + result += amt; + if (amt < n - result) + break; + } else { + peek.putback(this->unconsumed_input()); + state_ = s_footer; + } + } catch (const zlib_error& e) { + boost::throw_exception(gzip_error(e)); + } + } else { // state_ == s_footer + int c = boost::iostreams::get(peek); + if (traits_type::is_eof(c)) { + boost::throw_exception(gzip_error(gzip::bad_footer)); + } else if (traits_type::would_block(c)) { + break; + } + footer_.process(c); + if (footer_.done()) { + if (footer_.crc() != this->crc()) + boost::throw_exception(gzip_error(gzip::bad_crc)); + int c = boost::iostreams::get(peek); + if (traits_type::is_eof(c)) { + state_ = s_done; + } else { + peek.putback(c); + base_type::close(peek, BOOST_IOS::in); + state_ = s_start; + header_.reset(); + footer_.reset(); + } + } + } + } + if (peek.has_unconsumed_input()) { + putback_ = peek.unconsumed_input(); + } else { + putback_.clear(); + } + return result != 0 || state_ != s_done ? + result : + -1; + } + + template<typename Source> + void close(Source& src, BOOST_IOS::openmode m) + { + try { + base_type::close(src, m); + } catch (const zlib_error& e) { + state_ = s_start; + boost::throw_exception(gzip_error(e)); + } + if (m == BOOST_IOS::out) { + if (state_ == s_start || state_ == s_header) + boost::throw_exception(gzip_error(gzip::bad_header)); + else if (state_ == s_body) + boost::throw_exception(gzip_error(gzip::bad_footer)); + else if (state_ == s_footer) { + if (!footer_.done()) + boost::throw_exception(gzip_error(gzip::bad_footer)); + else if(footer_.crc() != this->crc()) + boost::throw_exception(gzip_error(gzip::bad_crc)); + } else { + BOOST_ASSERT(!"Bad state"); + } + } + state_ = s_start; + } + + std::string file_name() const { return header_.file_name(); } + std::string comment() const { return header_.comment(); } + bool text() const { return header_.text(); } + int os() const { return header_.os(); } + std::time_t mtime() const { return header_.mtime(); } +private: + static gzip_params make_params(int window_bits); + + // Source adapter allowing an arbitrary character sequence to be put back. + template<typename Source> + struct peekable_source { + typedef char char_type; + struct category : source_tag, peekable_tag { }; + explicit peekable_source(Source& src, const string_type& putback = "") + : src_(src), putback_(putback), offset_(0) + { } + std::streamsize read(char* s, std::streamsize n) + { + std::streamsize result = 0; + + // Copy characters from putback buffer + std::streamsize pbsize = + static_cast<std::streamsize>(putback_.size()); + if (offset_ < pbsize) { + result = (std::min)(n, pbsize - offset_); + BOOST_IOSTREAMS_CHAR_TRAITS(char)::copy( + s, putback_.data() + offset_, result); + offset_ += result; + if (result == n) + return result; + } + + // Read characters from src_ + std::streamsize amt = + boost::iostreams::read(src_, s + result, n - result); + return amt != -1 ? + result + amt : + result ? result : -1; + } + bool putback(char c) + { + if (offset_) { + putback_[--offset_] = c; + } else { + boost::throw_exception( + boost::iostreams::detail::bad_putback()); + } + return true; + } + void putback(const string_type& s) + { + putback_.replace(0, offset_, s); + offset_ = 0; + } + + // Returns true if some characters have been putback but not re-read. + bool has_unconsumed_input() const + { + return offset_ < static_cast<std::streamsize>(putback_.size()); + } + + // Returns the sequence of characters that have been put back but not re-read. + string_type unconsumed_input() const + { + return string_type(putback_, offset_, putback_.size() - offset_); + } + Source& src_; + string_type putback_; + std::streamsize offset_; + }; + + enum state_type { + s_start = 1, + s_header = s_start + 1, + s_body = s_header + 1, + s_footer = s_body + 1, + s_done = s_footer + 1 + }; + detail::gzip_header header_; + detail::gzip_footer footer_; + string_type putback_; + int state_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_gzip_decompressor, 1) + +typedef basic_gzip_decompressor<> gzip_decompressor; + +//------------------Implementation of gzip_compressor-------------------------// + +template<typename Alloc> +basic_gzip_compressor<Alloc>::basic_gzip_compressor + (const gzip_params& p, int buffer_size) + : base_type(normalize_params(p), buffer_size), + offset_(0), flags_(0) +{ + // Calculate gzip header. + bool has_name = !p.file_name.empty(); + bool has_comment = !p.comment.empty(); + + std::string::size_type length = + 10 + + (has_name ? p.file_name.size() + 1 : 0) + + (has_comment ? p.comment.size() + 1 : 0); + // + 2; // Header crc confuses gunzip. + int flags = + //gzip::flags::header_crc + + (has_name ? gzip::flags::name : 0) + + (has_comment ? gzip::flags::comment : 0); + int extra_flags = + ( p.level == zlib::best_compression ? + gzip::extra_flags::best_compression : + 0 ) + + ( p.level == zlib::best_speed ? + gzip::extra_flags::best_speed : + 0 ); + header_.reserve(length); + header_ += gzip::magic::id1; // ID1. + header_ += gzip::magic::id2; // ID2. + header_ += gzip::method::deflate; // CM. + header_ += static_cast<char>(flags); // FLG. + header_ += static_cast<char>(0xFF & p.mtime); // MTIME. + header_ += static_cast<char>(0xFF & (p.mtime >> 8)); + header_ += static_cast<char>(0xFF & (p.mtime >> 16)); + header_ += static_cast<char>(0xFF & (p.mtime >> 24)); + header_ += static_cast<char>(extra_flags); // XFL. + header_ += static_cast<char>(gzip::os_unknown); // OS. + if (has_name) { + header_ += p.file_name; + header_ += '\0'; + } + if (has_comment) { + header_ += p.comment; + header_ += '\0'; + } +} + +template<typename Alloc> +gzip_params basic_gzip_compressor<Alloc>::normalize_params(gzip_params p) +{ + p.noheader = true; + p.calculate_crc = true; + return p; +} + +template<typename Alloc> +void basic_gzip_compressor<Alloc>::prepare_footer() +{ + boost::iostreams::back_insert_device<std::string> out(footer_); + write_long(this->crc(), out); + write_long(this->total_in(), out); + flags_ |= f_body_done; + offset_ = 0; +} + +template<typename Alloc> +std::streamsize basic_gzip_compressor<Alloc>::read_string + (char* s, std::streamsize n, std::string& str) +{ + std::streamsize avail = + static_cast<std::streamsize>(str.size() - offset_); + std::streamsize amt = (std::min)(avail, n); + std::copy( str.data() + offset_, + str.data() + offset_ + amt, + s ); + offset_ += amt; + if ( !(flags_ & f_header_done) && + offset_ == static_cast<std::size_t>(str.size()) ) + { + flags_ |= f_header_done; + } + return amt; +} + +//------------------Implementation of gzip_decompressor-----------------------// + +template<typename Alloc> +basic_gzip_decompressor<Alloc>::basic_gzip_decompressor + (int window_bits, int buffer_size) + : base_type(make_params(window_bits), buffer_size), + state_(s_start) + { } + +template<typename Alloc> +gzip_params basic_gzip_decompressor<Alloc>::make_params(int window_bits) +{ + gzip_params p; + p.window_bits = window_bits; + p.noheader = true; + p.calculate_crc = true; + return p; +} + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED diff --git a/boost/iostreams/filter/line.hpp b/boost/iostreams/filter/line.hpp new file mode 100644 index 0000000000..9cdf7f7ee2 --- /dev/null +++ b/boost/iostreams/filter/line.hpp @@ -0,0 +1,227 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-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. + +#ifndef BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <algorithm> // min. +#include <boost/assert.hpp> +#include <memory> // allocator. +#include <string> +#include <boost/config.hpp> // BOOST_STATIC_CONSTANT. +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/checked_operations.hpp> +#include <boost/iostreams/detail/ios.hpp> // openmode, streamsize. +#include <boost/iostreams/read.hpp> // check_eof +#include <boost/iostreams/pipeline.hpp> +#include <boost/iostreams/write.hpp> + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> // VC7.1 C4244. + +namespace boost { namespace iostreams { + +// +// Template name: line_filter. +// Template paramters: +// Ch - The character type. +// Alloc - The allocator type. +// Description: Filter which processes data one line at a time. +// +template< typename Ch, + typename Alloc = + #if BOOST_WORKAROUND(__GNUC__, < 3) + typename std::basic_string<Ch>::allocator_type + #else + std::allocator<Ch> + #endif + > +class basic_line_filter { +private: + typedef typename std::basic_string<Ch>::traits_type string_traits; +public: + typedef Ch char_type; + typedef char_traits<char_type> traits_type; + typedef std::basic_string< + Ch, + string_traits, + Alloc + > string_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; +protected: + basic_line_filter(bool suppress_newlines = false) + : pos_(string_type::npos), + flags_(suppress_newlines ? f_suppress : 0) + { } +public: + virtual ~basic_line_filter() { } + + template<typename Source> + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + BOOST_ASSERT(!(flags_ & f_write)); + flags_ |= f_read; + + // Handle unfinished business. + std::streamsize result = 0; + if (!cur_line_.empty() && (result = read_line(s, n)) == n) + return n; + + typename traits_type::int_type status = traits_type::good(); + while (result < n && !traits_type::is_eof(status)) { + + // Call next_line() to retrieve a line of filtered text, and + // read_line() to copy it into buffer s. + if (traits_type::would_block(status = next_line(src))) + return result; + result += read_line(s + result, n - result); + } + + return detail::check_eof(result); + } + + template<typename Sink> + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + using namespace std; + BOOST_ASSERT(!(flags_ & f_read)); + flags_ |= f_write; + + // Handle unfinished business. + if (pos_ != string_type::npos && !write_line(snk)) + return 0; + + const char_type *cur = s, *next; + while (true) { + + // Search for the next full line in [cur, s + n), filter it + // and write it to snk. + typename string_type::size_type rest = n - (cur - s); + if ((next = traits_type::find(cur, rest, traits_type::newline()))) { + cur_line_.append(cur, next - cur); + cur = next + 1; + if (!write_line(snk)) + return static_cast<std::streamsize>(cur - s); + } else { + cur_line_.append(cur, rest); + return n; + } + } + } + + template<typename Sink> + void close(Sink& snk, BOOST_IOS::openmode which) + { + if ((flags_ & f_read) && which == BOOST_IOS::in) + close_impl(); + + if ((flags_ & f_write) && which == BOOST_IOS::out) { + try { + if (!cur_line_.empty()) + write_line(snk); + } catch (...) { + try { + close_impl(); + } catch (...) { } + throw; + } + close_impl(); + } + } +private: + virtual string_type do_filter(const string_type& line) = 0; + + // Copies filtered characters fron the current line into + // the given buffer. + std::streamsize read_line(char_type* s, std::streamsize n) + { + using namespace std; + std::streamsize result = + (std::min) (n, static_cast<std::streamsize>(cur_line_.size())); + traits_type::copy(s, cur_line_.data(), result); + cur_line_.erase(0, result); + return result; + } + + // Attempts to retrieve a line of text from the given source; returns + // an int_type as a good/eof/would_block status code. + template<typename Source> + typename traits_type::int_type next_line(Source& src) + { + using namespace std; + typename traits_type::int_type c; + while ( traits_type::is_good(c = iostreams::get(src)) && + c != traits_type::newline() ) + { + cur_line_ += traits_type::to_int_type(c); + } + if (!traits_type::would_block(c)) { + if (!cur_line_.empty() || c == traits_type::newline()) + cur_line_ = do_filter(cur_line_); + if (c == traits_type::newline() && (flags_ & f_suppress) == 0) + cur_line_ += c; + } + return c; // status indicator. + } + + // Filters the current line and attemps to write it to the given sink. + // Returns true for success. + template<typename Sink> + bool write_line(Sink& snk) + { + string_type line = do_filter(cur_line_); + if ((flags_ & f_suppress) == 0) + line += traits_type::newline(); + std::streamsize amt = static_cast<std::streamsize>(line.size()); + bool result = iostreams::write_if(snk, line.data(), amt) == amt; + if (result) + clear(); + return result; + } + + void close_impl() + { + clear(); + flags_ &= f_suppress; + } + + void clear() + { + cur_line_.erase(); + pos_ = string_type::npos; + } + + enum flag_type { + f_read = 1, + f_write = f_read << 1, + f_suppress = f_write << 1 + }; + + string_type cur_line_; + typename string_type::size_type pos_; + int flags_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_line_filter, 2) + +typedef basic_line_filter<char> line_filter; +typedef basic_line_filter<wchar_t> wline_filter; + +} } // End namespaces iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> + +#endif // #ifndef BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/newline.hpp b/boost/iostreams/filter/newline.hpp new file mode 100644 index 0000000000..ac064b716f --- /dev/null +++ b/boost/iostreams/filter/newline.hpp @@ -0,0 +1,442 @@ +// (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: I hope to replace the current implementation with a much simpler +// one. + +#ifndef BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/assert.hpp> +#include <cstdio> +#include <stdexcept> // logic_error. +#include <boost/config.hpp> // BOOST_STATIC_CONSTANT. +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/detail/char_traits.hpp> +#include <boost/iostreams/detail/ios.hpp> // BOOST_IOSTREAMS_FAILURE +#include <boost/iostreams/read.hpp> // get +#include <boost/iostreams/write.hpp> // put +#include <boost/iostreams/pipeline.hpp> +#include <boost/iostreams/putback.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/throw_exception.hpp> +#include <boost/type_traits/is_convertible.hpp> + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> + +#define BOOST_IOSTREAMS_ASSERT_UNREACHABLE(val) \ + (BOOST_ASSERT("unreachable code" == 0), val) \ + /**/ + +namespace boost { namespace iostreams { + +namespace newline { + +const char CR = 0x0D; +const char LF = 0x0A; + + // Flags for configuring newline_filter. + +// Exactly one of the following three flags must be present. + +const int posix = 1; // Use CR as line separator. +const int mac = 2; // Use LF as line separator. +const int dos = 4; // Use CRLF as line separator. +const int mixed = 8; // Mixed line endings. +const int final_newline = 16; +const int platform_mask = posix | dos | mac; + +} // End namespace newline. + +namespace detail { + +class newline_base { +public: + bool is_posix() const + { + return !is_mixed() && (flags_ & newline::posix) != 0; + } + bool is_dos() const + { + return !is_mixed() && (flags_ & newline::dos) != 0; + } + bool is_mac() const + { + return !is_mixed() && (flags_ & newline::mac) != 0; + } + bool is_mixed_posix() const { return (flags_ & newline::posix) != 0; } + bool is_mixed_dos() const { return (flags_ & newline::dos) != 0; } + bool is_mixed_mac() const { return (flags_ & newline::mac) != 0; } + bool is_mixed() const + { + int platform = + (flags_ & newline::posix) != 0 ? + newline::posix : + (flags_ & newline::dos) != 0 ? + newline::dos : + (flags_ & newline::mac) != 0 ? + newline::mac : + 0; + return (flags_ & ~platform & newline::platform_mask) != 0; + } + bool has_final_newline() const + { + return (flags_ & newline::final_newline) != 0; + } +protected: + newline_base(int flags) : flags_(flags) { } + int flags_; +}; + +} // End namespace detail. + +class newline_error + : public BOOST_IOSTREAMS_FAILURE, public detail::newline_base +{ +private: + friend class newline_checker; + newline_error(int flags) + : BOOST_IOSTREAMS_FAILURE("bad line endings"), + detail::newline_base(flags) + { } +}; + +class newline_filter { +public: + typedef char char_type; + struct category + : dual_use, + filter_tag, + closable_tag + { }; + + explicit newline_filter(int target) : flags_(target) + { + if ( target != iostreams::newline::posix && + target != iostreams::newline::dos && + target != iostreams::newline::mac ) + { + boost::throw_exception(std::logic_error("bad flags")); + } + } + + template<typename Source> + int get(Source& src) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + BOOST_ASSERT((flags_ & f_write) == 0); + flags_ |= f_read; + + if (flags_ & (f_has_LF | f_has_EOF)) { + if (flags_ & f_has_LF) + return newline(); + else + return EOF; + } + + int c = + (flags_ & f_has_CR) == 0 ? + iostreams::get(src) : + CR; + + if (c == WOULD_BLOCK ) + return WOULD_BLOCK; + + if (c == CR) { + flags_ |= f_has_CR; + + int d; + if ((d = iostreams::get(src)) == WOULD_BLOCK) + return WOULD_BLOCK; + + if (d == LF) { + flags_ &= ~f_has_CR; + return newline(); + } + + if (d == EOF) { + flags_ |= f_has_EOF; + } else { + iostreams::putback(src, d); + } + + flags_ &= ~f_has_CR; + return newline(); + } + + if (c == LF) + return newline(); + + return c; + } + + template<typename Sink> + bool put(Sink& dest, char c) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + BOOST_ASSERT((flags_ & f_read) == 0); + flags_ |= f_write; + + if ((flags_ & f_has_LF) != 0) + return c == LF ? + newline(dest) : + newline(dest) && this->put(dest, c); + + if (c == LF) + return newline(dest); + + if ((flags_ & f_has_CR) != 0) + return newline(dest) ? + this->put(dest, c) : + false; + + if (c == CR) { + flags_ |= f_has_CR; + return true; + } + + return iostreams::put(dest, c); + } + + template<typename Sink> + void close(Sink& dest, BOOST_IOS::openmode) + { + typedef typename iostreams::category_of<Sink>::type category; + if ((flags_ & f_write) != 0 && (flags_ & f_has_CR) != 0) + newline_if_sink(dest); + flags_ &= ~f_has_LF; // Restore original flags. + } +private: + + // Returns the appropriate element of a newline sequence. + int newline() + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + switch (flags_ & iostreams::newline::platform_mask) { + case iostreams::newline::posix: + return LF; + case iostreams::newline::mac: + return CR; + case iostreams::newline::dos: + if (flags_ & f_has_LF) { + flags_ &= ~f_has_LF; + return LF; + } else { + flags_ |= f_has_LF; + return CR; + } + } + return BOOST_IOSTREAMS_ASSERT_UNREACHABLE(0); + } + + // Writes a newline sequence. + template<typename Sink> + bool newline(Sink& dest) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + bool success = false; + switch (flags_ & iostreams::newline::platform_mask) { + case iostreams::newline::posix: + success = boost::iostreams::put(dest, LF); + break; + case iostreams::newline::mac: + success = boost::iostreams::put(dest, CR); + break; + case iostreams::newline::dos: + if ((flags_ & f_has_LF) != 0) { + if ((success = boost::iostreams::put(dest, LF))) + flags_ &= ~f_has_LF; + } else if (boost::iostreams::put(dest, CR)) { + if (!(success = boost::iostreams::put(dest, LF))) + flags_ |= f_has_LF; + } + break; + } + if (success) + flags_ &= ~f_has_CR; + return success; + } + + // Writes a newline sequence if the given device is a Sink. + template<typename Device> + void newline_if_sink(Device& dest) + { + typedef typename iostreams::category_of<Device>::type category; + newline_if_sink(dest, is_convertible<category, output>()); + } + + template<typename Sink> + void newline_if_sink(Sink& dest, mpl::true_) { newline(dest); } + + template<typename Source> + void newline_if_sink(Source&, mpl::false_) { } + + enum flags { + f_has_LF = 32768, + f_has_CR = f_has_LF << 1, + f_has_newline = f_has_CR << 1, + f_has_EOF = f_has_newline << 1, + f_read = f_has_EOF << 1, + f_write = f_read << 1 + }; + int flags_; +}; +BOOST_IOSTREAMS_PIPABLE(newline_filter, 0) + +class newline_checker : public detail::newline_base { +public: + typedef char char_type; + struct category + : dual_use_filter_tag, + closable_tag + { }; + explicit newline_checker(int target = newline::mixed) + : detail::newline_base(0), target_(target), open_(false) + { } + template<typename Source> + int get(Source& src) + { + using newline::CR; + using newline::LF; + + if (!open_) { + open_ = true; + source() = 0; + } + + int c; + if ((c = iostreams::get(src)) == WOULD_BLOCK) + return WOULD_BLOCK; + + // Update source flags. + if (c != EOF) + source() &= ~f_line_complete; + if ((source() & f_has_CR) != 0) { + if (c == LF) { + source() |= newline::dos; + source() |= f_line_complete; + } else { + source() |= newline::mac; + if (c == EOF) + source() |= f_line_complete; + } + } else if (c == LF) { + source() |= newline::posix; + source() |= f_line_complete; + } + source() = (source() & ~f_has_CR) | (c == CR ? f_has_CR : 0); + + // Check for errors. + if ( c == EOF && + (target_ & newline::final_newline) != 0 && + (source() & f_line_complete) == 0 ) + { + fail(); + } + if ( (target_ & newline::platform_mask) != 0 && + (source() & ~target_ & newline::platform_mask) != 0 ) + { + fail(); + } + + return c; + } + + template<typename Sink> + bool put(Sink& dest, int c) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + if (!open_) { + open_ = true; + source() = 0; + } + + if (!iostreams::put(dest, c)) + return false; + + // Update source flags. + source() &= ~f_line_complete; + if ((source() & f_has_CR) != 0) { + if (c == LF) { + source() |= newline::dos; + source() |= f_line_complete; + } else { + source() |= newline::mac; + } + } else if (c == LF) { + source() |= newline::posix; + source() |= f_line_complete; + } + source() = (source() & ~f_has_CR) | (c == CR ? f_has_CR : 0); + + // Check for errors. + if ( (target_ & newline::platform_mask) != 0 && + (source() & ~target_ & newline::platform_mask) != 0 ) + { + fail(); + } + + return true; + } + + template<typename Sink> + void close(Sink&, BOOST_IOS::openmode) + { + using iostreams::newline::final_newline; + + // Update final_newline flag. + if ( (source() & f_has_CR) != 0 || + (source() & f_line_complete) != 0 ) + { + source() |= final_newline; + } + + // Clear non-sticky flags. + source() &= ~(f_has_CR | f_line_complete); + + // Check for errors. + if ( (target_ & final_newline) != 0 && + (source() & final_newline) == 0 ) + { + fail(); + } + } +private: + void fail() { boost::throw_exception(newline_error(source())); } + int& source() { return flags_; } + int source() const { return flags_; } + + enum flags { + f_has_CR = 32768, + f_line_complete = f_has_CR << 1 + }; + + int target_; // Represents expected input. + bool open_; +}; +BOOST_IOSTREAMS_PIPABLE(newline_checker, 0) + +} } // End namespaces iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> + +#endif // #ifndef BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/regex.hpp b/boost/iostreams/filter/regex.hpp new file mode 100644 index 0000000000..e6efd6d8ae --- /dev/null +++ b/boost/iostreams/filter/regex.hpp @@ -0,0 +1,98 @@ +// (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. + +#ifndef BOOST_IOSTREAMS_REGEX_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_REGEX_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <memory> // allocator. +#include <boost/function.hpp> +#include <boost/iostreams/filter/aggregate.hpp> +#include <boost/iostreams/pipeline.hpp> +#include <boost/regex.hpp> + +namespace boost { namespace iostreams { + +template< typename Ch, + typename Tr = regex_traits<Ch>, + typename Alloc = std::allocator<Ch> > +class basic_regex_filter : public aggregate_filter<Ch, Alloc> { +private: + typedef aggregate_filter<Ch, Alloc> base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + typedef std::basic_string<Ch> string_type; + typedef basic_regex<Ch, Tr> regex_type; + typedef regex_constants::match_flag_type flag_type; + typedef match_results<const Ch*> match_type; + typedef function1<string_type, const match_type&> formatter; + + basic_regex_filter( const regex_type& re, + const formatter& replace, + flag_type flags = regex_constants::match_default ) + : re_(re), replace_(replace), flags_(flags) { } + basic_regex_filter( const regex_type& re, + const string_type& fmt, + flag_type flags = regex_constants::match_default, + flag_type fmt_flags = regex_constants::format_default ) + : re_(re), replace_(simple_formatter(fmt, fmt_flags)), flags_(flags) { } + basic_regex_filter( const regex_type& re, + const char_type* fmt, + flag_type flags = regex_constants::match_default, + flag_type fmt_flags = regex_constants::format_default ) + : re_(re), replace_(simple_formatter(fmt, fmt_flags)), flags_(flags) { } +private: + typedef typename base_type::vector_type vector_type; + void do_filter(const vector_type& src, vector_type& dest) + { + typedef regex_iterator<const Ch*, Ch, Tr> iterator; + if (src.empty()) + return; + iterator first(&src[0], &src[0] + src.size(), re_, flags_); + iterator last; + const Ch* suffix = 0; + for (; first != last; ++first) { + dest.insert( dest.end(), + first->prefix().first, + first->prefix().second ); + string_type replacement = replace_(*first); + dest.insert( dest.end(), + replacement.begin(), + replacement.end() ); + suffix = first->suffix().first; + } + if (suffix) { + dest.insert(dest.end(), suffix, &src[0] + src.size()); + } else { + dest.insert(dest.end(), &src[0], &src[0] + src.size()); + } + } + struct simple_formatter { + simple_formatter(const string_type& fmt, flag_type fmt_flags) + : fmt_(fmt), fmt_flags_(fmt_flags) { } + string_type operator() (const match_type& match) const + { return match.format(fmt_, fmt_flags_); } + string_type fmt_; + flag_type fmt_flags_; + }; + regex_type re_; + formatter replace_; + flag_type flags_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_regex_filter, 3) + +typedef basic_regex_filter<char> regex_filter; +typedef basic_regex_filter<wchar_t> wregex_filter; + + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_REGEX_FILTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/stdio.hpp b/boost/iostreams/filter/stdio.hpp new file mode 100644 index 0000000000..e2addf569c --- /dev/null +++ b/boost/iostreams/filter/stdio.hpp @@ -0,0 +1,84 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-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. + +// Based on the work of Christopher Diggins. + +#ifndef BOOST_IOSTREAMS_STDIO_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_STDIO_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <iostream> +#include <memory> // allocator. +#include <vector> +#include <boost/iostreams/detail/config/wide_streams.hpp> +#include <boost/iostreams/detail/char_traits.hpp> +#include <boost/iostreams/detail/ios.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filter/aggregate.hpp> +#include <boost/iostreams/pipeline.hpp> +#include <boost/iostreams/stream_buffer.hpp> + +namespace boost { namespace iostreams { + +namespace detail { + +} // End namespace detail. + +template<typename Ch, typename Alloc = std::allocator<Ch> > +class basic_stdio_filter : public aggregate_filter<Ch, Alloc> { +private: + typedef aggregate_filter<Ch, Alloc> base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + typedef typename base_type::vector_type vector_type; +private: + static std::istream& standard_input(char*) { return std::cin; } + static std::ostream& standard_output(char*) { return std::cout; } +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + static std::wistream& standard_input(wchar_t*) { return std::wcin; } + static std::wostream& standard_output(wchar_t*) { return std::wcout; } +#endif // BOOST_IOSTREAMS_NO_WIDE_STREAMS + + struct scoped_redirector { // Thanks to Maxim Egorushkin. + typedef BOOST_IOSTREAMS_CHAR_TRAITS(Ch) traits_type; + typedef BOOST_IOSTREAMS_BASIC_IOS(Ch, traits_type) ios_type; + typedef BOOST_IOSTREAMS_BASIC_STREAMBUF(Ch, traits_type) streambuf_type; + scoped_redirector( ios_type& ios, + streambuf_type* newbuf ) + : ios_(ios), old_(ios.rdbuf(newbuf)) + { } + ~scoped_redirector() { ios_.rdbuf(old_); } + scoped_redirector& operator=(const scoped_redirector&); + ios_type& ios_; + streambuf_type* old_; + }; + + virtual void do_filter() = 0; + virtual void do_filter(const vector_type& src, vector_type& dest) + { + stream_buffer< basic_array_source<Ch> > + srcbuf(&src[0], &src[0] + src.size()); + stream_buffer< back_insert_device<vector_type> > + destbuf(iostreams::back_inserter(dest)); + scoped_redirector redirect_input(standard_input((Ch*)0), &srcbuf); + scoped_redirector redirect_output(standard_output((Ch*)0), &destbuf); + do_filter(); + } +}; +BOOST_IOSTREAMS_PIPABLE(basic_stdio_filter, 2) + +typedef basic_stdio_filter<char> stdio_filter; +typedef basic_stdio_filter<wchar_t> wstdio_wfilter; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_STDIO_FILTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/symmetric.hpp b/boost/iostreams/filter/symmetric.hpp new file mode 100644 index 0000000000..cc92b0cfa8 --- /dev/null +++ b/boost/iostreams/filter/symmetric.hpp @@ -0,0 +1,310 @@ +// (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. + +// Contains the definitions of the class templates symmetric_filter, +// which models DualUseFilter based on a model of the Symmetric Filter. + +// +// Roughly, a Symmetric Filter is a class type with the following interface: +// +// struct symmetric_filter { +// typedef xxx char_type; +// +// bool filter( const char*& begin_in, const char* end_in, +// char*& begin_out, char* end_out, bool flush ) +// { +// // Consume as many characters as possible from the interval +// // [begin_in, end_in), without exhausting the output range +// // [begin_out, end_out). If flush is true, write as mush output +// // as possible. +// // A return value of true indicates that filter should be called +// // again. More precisely, if flush is false, a return value of +// // false indicates that the natural end of stream has been reached +// // and that all filtered data has been forwarded; if flush is +// // true, a return value of false indicates that all filtered data +// // has been forwarded. +// } +// void close() { /* Reset filter's state. */ } +// }; +// +// Symmetric Filter filters need not be CopyConstructable. +// + +#ifndef BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/assert.hpp> +#include <memory> // allocator, auto_ptr. +#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME. +#include <boost/iostreams/char_traits.hpp> +#include <boost/iostreams/constants.hpp> // buffer size. +#include <boost/iostreams/detail/buffer.hpp> +#include <boost/iostreams/detail/char_traits.hpp> +#include <boost/iostreams/detail/config/limits.hpp> +#include <boost/iostreams/detail/template_params.hpp> +#include <boost/iostreams/traits.hpp> +#include <boost/iostreams/operations.hpp> // read, write. +#include <boost/iostreams/pipeline.hpp> +#include <boost/preprocessor/iteration/local.hpp> +#include <boost/preprocessor/punctuation/comma_if.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/shared_ptr.hpp> + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC. + +namespace boost { namespace iostreams { + +template< typename SymmetricFilter, + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME char_type_of<SymmetricFilter>::type + > > +class symmetric_filter { +public: + typedef typename char_type_of<SymmetricFilter>::type char_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type; + typedef std::basic_string<char_type, traits_type, Alloc> string_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; + + // Expands to a sequence of ctors which forward to impl. + #define BOOST_PP_LOCAL_MACRO(n) \ + BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \ + explicit symmetric_filter( \ + int buffer_size BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \ + : pimpl_(new impl(buffer_size BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_PARAMS(n, t))) \ + { BOOST_ASSERT(buffer_size > 0); } \ + /**/ + #define BOOST_PP_LOCAL_LIMITS (0, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) + #include BOOST_PP_LOCAL_ITERATE() + #undef BOOST_PP_LOCAL_MACRO + + template<typename Source> + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + if (!(state() & f_read)) + begin_read(); + + buffer_type& buf = pimpl_->buf_; + int status = (state() & f_eof) != 0 ? f_eof : f_good; + char_type *next_s = s, + *end_s = s + n; + while (true) + { + // Invoke filter if there are unconsumed characters in buffer or if + // filter must be flushed. + bool flush = status == f_eof; + if (buf.ptr() != buf.eptr() || flush) { + const char_type* next = buf.ptr(); + bool done = + !filter().filter(next, buf.eptr(), next_s, end_s, flush); + buf.ptr() = buf.data() + (next - buf.data()); + if (done) + return detail::check_eof( + static_cast<std::streamsize>(next_s - s) + ); + } + + // If no more characters are available without blocking, or + // if read request has been satisfied, return. + if ( (status == f_would_block && buf.ptr() == buf.eptr()) || + next_s == end_s ) + { + return static_cast<std::streamsize>(next_s - s); + } + + // Fill buffer. + if (status == f_good) + status = fill(src); + } + } + + template<typename Sink> + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + if (!(state() & f_write)) + begin_write(); + + buffer_type& buf = pimpl_->buf_; + const char_type *next_s, *end_s; + for (next_s = s, end_s = s + n; next_s != end_s; ) { + if (buf.ptr() == buf.eptr() && !flush(snk)) + break; + if(!filter().filter(next_s, end_s, buf.ptr(), buf.eptr(), false)) { + flush(snk); + break; + } + } + return static_cast<std::streamsize>(next_s - s); + } + + template<typename Sink> + void close(Sink& snk, BOOST_IOS::openmode mode) + { + if (mode == BOOST_IOS::out) { + + if (!(state() & f_write)) + begin_write(); + + // Repeatedly invoke filter() with no input. + try { + buffer_type& buf = pimpl_->buf_; + char_type dummy; + const char_type* end = &dummy; + bool again = true; + while (again) { + if (buf.ptr() != buf.eptr()) + again = filter().filter( end, end, buf.ptr(), + buf.eptr(), true ); + flush(snk); + } + } catch (...) { + try { close_impl(); } catch (...) { } + throw; + } + close_impl(); + } else { + close_impl(); + } + } + SymmetricFilter& filter() { return *pimpl_; } + string_type unconsumed_input() const; + +// Give impl access to buffer_type on Tru64 +#if !BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + private: +#endif + typedef detail::buffer<char_type, Alloc> buffer_type; +private: + buffer_type& buf() { return pimpl_->buf_; } + const buffer_type& buf() const { return pimpl_->buf_; } + int& state() { return pimpl_->state_; } + void begin_read(); + void begin_write(); + + template<typename Source> + int fill(Source& src) + { + std::streamsize amt = iostreams::read(src, buf().data(), buf().size()); + if (amt == -1) { + state() |= f_eof; + return f_eof; + } + buf().set(0, amt); + return amt != 0 ? f_good : f_would_block; + } + + // Attempts to write the contents of the buffer the given Sink. + // Returns true if at least on character was written. + template<typename Sink> + bool flush(Sink& snk) + { + typedef typename iostreams::category_of<Sink>::type category; + typedef is_convertible<category, output> can_write; + return flush(snk, can_write()); + } + + template<typename Sink> + bool flush(Sink& snk, mpl::true_) + { + std::streamsize amt = + static_cast<std::streamsize>(buf().ptr() - buf().data()); + std::streamsize result = + boost::iostreams::write(snk, buf().data(), amt); + if (result < amt && result > 0) + traits_type::move(buf().data(), buf().data() + result, amt - result); + buf().set(amt - result, buf().size()); + return result != 0; + } + + template<typename Sink> + bool flush(Sink&, mpl::false_) { return true;} + + void close_impl(); + + enum flag_type { + f_read = 1, + f_write = f_read << 1, + f_eof = f_write << 1, + f_good, + f_would_block + }; + + struct impl : SymmetricFilter { + + // Expands to a sequence of ctors which forward to SymmetricFilter. + #define BOOST_PP_LOCAL_MACRO(n) \ + BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \ + impl( int buffer_size BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \ + : SymmetricFilter(BOOST_PP_ENUM_PARAMS(n, t)), \ + buf_(buffer_size), state_(0) \ + { } \ + /**/ + #define BOOST_PP_LOCAL_LIMITS (0, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) + #include BOOST_PP_LOCAL_ITERATE() + #undef BOOST_PP_LOCAL_MACRO + + buffer_type buf_; + int state_; + }; + + shared_ptr<impl> pimpl_; +}; +BOOST_IOSTREAMS_PIPABLE(symmetric_filter, 2) + +//------------------Implementation of symmetric_filter----------------// + +template<typename SymmetricFilter, typename Alloc> +void symmetric_filter<SymmetricFilter, Alloc>::begin_read() +{ + BOOST_ASSERT(!(state() & f_write)); + state() |= f_read; + buf().set(0, 0); +} + +template<typename SymmetricFilter, typename Alloc> +void symmetric_filter<SymmetricFilter, Alloc>::begin_write() +{ + BOOST_ASSERT(!(state() & f_read)); + state() |= f_write; + buf().set(0, buf().size()); +} + +template<typename SymmetricFilter, typename Alloc> +void symmetric_filter<SymmetricFilter, Alloc>::close_impl() +{ + state() = 0; + buf().set(0, 0); + filter().close(); +} + +template<typename SymmetricFilter, typename Alloc> +typename symmetric_filter<SymmetricFilter, Alloc>::string_type +symmetric_filter<SymmetricFilter, Alloc>::unconsumed_input() const +{ return string_type(buf().ptr(), buf().eptr()); } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED diff --git a/boost/iostreams/filter/test.hpp b/boost/iostreams/filter/test.hpp new file mode 100644 index 0000000000..ea2fd601ca --- /dev/null +++ b/boost/iostreams/filter/test.hpp @@ -0,0 +1,322 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-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. + +#ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/config.hpp> // BOOST_MSVC,put size_t in std. +#include <boost/detail/workaround.hpp> +#include <algorithm> // min. +#include <cstddef> // size_t. +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \ + BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ +# include <cstdlib> // rand. +#endif +#include <cstring> // memcpy, strlen. +#include <iterator> +#include <string> +#include <vector> +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ + !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ +# include <boost/random/linear_congruential.hpp> +# include <boost/random/uniform_smallint.hpp> +#endif +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/compose.hpp> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/detail/bool_trait_def.hpp> +#include <boost/iostreams/detail/ios.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/operations.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/type_traits/is_array.hpp> +#include <boost/type_traits/is_same.hpp> + +#undef memcpy +#undef rand +#undef strlen + +#if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__) +namespace std { + using ::memcpy; + using ::strlen; + #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \ + BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ + using ::rand; + #endif +} +#endif + +namespace boost { namespace iostreams { + +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3) + +const std::streamsize default_increment = 5; + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ + !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ + std::streamsize rand(int inc) + { + static rand48 random_gen; + static uniform_smallint<int> random_dist(0, inc); + return random_dist(random_gen); + } +#else + std::streamsize rand(int inc) + { + return (std::rand() * inc + 1) / RAND_MAX; + } +#endif + +class non_blocking_source { +public: + typedef char char_type; + struct category + : source_tag, + peekable_tag + { }; + explicit non_blocking_source( const std::string& data, + std::streamsize inc = default_increment ) + : data_(data), inc_(inc), pos_(0) + { } + std::streamsize read(char* s, std::streamsize n) + { + if (pos_ == static_cast<std::streamsize>(data_.size())) + return -1; + std::streamsize avail = + (std::min) (n, static_cast<std::streamsize>(data_.size() - pos_)); + std::streamsize amt = (std::min) (rand(inc_), avail); + if (amt) + std::memcpy(s, data_.c_str() + pos_, amt); + pos_ += amt; + return amt; + } + + bool putback(char c) + { + if (pos_ > 0) { + data_[--pos_] = c; + return true; + } + return false; + } +private: + std::string data_; + std::streamsize inc_, pos_; +}; + +class non_blocking_sink : public sink { +public: + non_blocking_sink( std::string& dest, + std::streamsize inc = default_increment ) + : dest_(dest), inc_(inc) + { } + std::streamsize write(const char* s, std::streamsize n) + { + std::streamsize amt = (std::min) (rand(inc_), n); + dest_.insert(dest_.end(), s, s + amt); + return amt; + } +private: + non_blocking_sink& operator=(const non_blocking_sink&); + std::string& dest_; + std::streamsize inc_; +}; + +//--------------Definition of test_input_filter-------------------------------// + +template<typename Filter> +bool test_input_filter( Filter filter, + const std::string& input, + const std::string& output, + mpl::true_ ) +{ + for ( int inc = default_increment; + inc < default_increment * 40; + inc += default_increment ) + { + non_blocking_source src(input, inc); + std::string dest; + iostreams::copy(compose(filter, src), iostreams::back_inserter(dest)); + if (dest != output) + return false; + } + return true; +} + +template<typename Filter, typename Source1, typename Source2> +bool test_input_filter( Filter filter, + const Source1& input, + const Source2& output, + mpl::false_ ) +{ + std::string in; + std::string out; + iostreams::copy(input, iostreams::back_inserter(in)); + iostreams::copy(output, iostreams::back_inserter(out)); + return test_input_filter(filter, in, out); +} + +template<typename Filter, typename Source1, typename Source2> +bool test_input_filter( Filter filter, + const Source1& input, + const Source2& output ) +{ + // Use tag dispatch to compensate for bad overload resolution. + return test_input_filter( filter, input, output, + is_string<Source1>() ); +} + +//--------------Definition of test_output_filter------------------------------// + +template<typename Filter> +bool test_output_filter( Filter filter, + const std::string& input, + const std::string& output, + mpl::true_ ) +{ + for ( int inc = default_increment; + inc < default_increment * 40; + inc += default_increment ) + { + array_source src(input.data(), input.data() + input.size()); + std::string dest; + iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc))); + if (dest != output ) + return false; + } + return true; +} + +template<typename Filter, typename Source1, typename Source2> +bool test_output_filter( Filter filter, + const Source1& input, + const Source2& output, + mpl::false_ ) +{ + std::string in; + std::string out; + iostreams::copy(input, iostreams::back_inserter(in)); + iostreams::copy(output, iostreams::back_inserter(out)); + return test_output_filter(filter, in, out); +} + +template<typename Filter, typename Source1, typename Source2> +bool test_output_filter( Filter filter, + const Source1& input, + const Source2& output ) +{ + // Use tag dispatch to compensate for bad overload resolution. + return test_output_filter( filter, input, output, + is_string<Source1>() ); +} + +//--------------Definition of test_filter_pair--------------------------------// + +template<typename OutputFilter, typename InputFilter> +bool test_filter_pair( OutputFilter out, + InputFilter in, + const std::string& data, + mpl::true_ ) +{ + for ( int inc = default_increment; + inc <= default_increment * 40; + inc += default_increment ) + { + { + array_source src(data.data(), data.data() + data.size()); + std::string temp; + std::string dest; + iostreams::copy(src, compose(out, non_blocking_sink(temp, inc))); + iostreams::copy( + compose(in, non_blocking_source(temp, inc)), + iostreams::back_inserter(dest) + ); + if (dest != data) + return false; + } + { + array_source src(data.data(), data.data() + data.size()); + std::string temp; + std::string dest; + iostreams::copy(src, compose(out, non_blocking_sink(temp, inc))); + // truncate the file, this should not loop, it may throw + // std::ios_base::failure, which we swallow. + try { + temp.resize(temp.size() / 2); + iostreams::copy( + compose(in, non_blocking_source(temp, inc)), + iostreams::back_inserter(dest) + ); + } catch(std::ios_base::failure&) {} + } + { + array_source src(data.data(), data.data() + data.size()); + std::string temp; + std::string dest; + iostreams::copy(compose(out, src), non_blocking_sink(temp, inc)); + iostreams::copy( + non_blocking_source(temp, inc), + compose(in, iostreams::back_inserter(dest)) + ); + if (dest != data) + return false; + } + { + array_source src(data.data(), data.data() + data.size()); + std::string temp; + std::string dest; + iostreams::copy(compose(out, src), non_blocking_sink(temp, inc)); + // truncate the file, this should not loop, it may throw + // std::ios_base::failure, which we swallow. + try { + temp.resize(temp.size() / 2); + iostreams::copy( + non_blocking_source(temp, inc), + compose(in, iostreams::back_inserter(dest)) + ); + } catch(std::ios_base::failure&) {} + } + } + return true; +} + +template<typename OutputFilter, typename InputFilter, typename Source> +bool test_filter_pair( OutputFilter out, + InputFilter in, + const Source& data, + mpl::false_ ) +{ + std::string str; + iostreams::copy(data, iostreams::back_inserter(str)); + return test_filter_pair(out, in, str); +} + +template<typename OutputFilter, typename InputFilter, typename Source> +bool test_filter_pair( OutputFilter out, + InputFilter in, + const Source& data ) +{ + // Use tag dispatch to compensate for bad overload resolution. + return test_filter_pair(out, in, data, is_string<Source>()); +} + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED diff --git a/boost/iostreams/filter/zlib.hpp b/boost/iostreams/filter/zlib.hpp new file mode 100644 index 0000000000..b0327f3cb8 --- /dev/null +++ b/boost/iostreams/filter/zlib.hpp @@ -0,0 +1,427 @@ +// (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_ZLIB_HPP_INCLUDED +#define BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <cassert> +#include <iosfwd> // streamsize. +#include <memory> // allocator, bad_alloc. +#include <new> +#include <boost/config.hpp> // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM. +#include <boost/cstdint.hpp> // uint*_t +#include <boost/detail/workaround.hpp> +#include <boost/iostreams/constants.hpp> // buffer size. +#include <boost/iostreams/detail/config/auto_link.hpp> +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/detail/config/wide_streams.hpp> +#include <boost/iostreams/detail/config/zlib.hpp> +#include <boost/iostreams/detail/ios.hpp> // failure, streamsize. +#include <boost/iostreams/filter/symmetric.hpp> +#include <boost/iostreams/pipeline.hpp> +#include <boost/type_traits/is_same.hpp> + +// Must come last. +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4251 4231 4660) // Dependencies not exported. +#endif +#include <boost/config/abi_prefix.hpp> + +namespace boost { namespace iostreams { + +namespace zlib { + // Typedefs + +typedef uint32_t uint; +typedef uint8_t byte; +typedef uint32_t ulong; + +// Prefix 'x' prevents symbols from being redefined when Z_PREFIX is defined +typedef void* (*xalloc_func)(void*, zlib::uint, zlib::uint); +typedef void (*xfree_func)(void*, void*); + + // Compression levels + +BOOST_IOSTREAMS_DECL extern const int no_compression; +BOOST_IOSTREAMS_DECL extern const int best_speed; +BOOST_IOSTREAMS_DECL extern const int best_compression; +BOOST_IOSTREAMS_DECL extern const int default_compression; + + // Compression methods + +BOOST_IOSTREAMS_DECL extern const int deflated; + + // Compression strategies + +BOOST_IOSTREAMS_DECL extern const int default_strategy; +BOOST_IOSTREAMS_DECL extern const int filtered; +BOOST_IOSTREAMS_DECL extern const int huffman_only; + + // Status codes + +BOOST_IOSTREAMS_DECL extern const int okay; +BOOST_IOSTREAMS_DECL extern const int stream_end; +BOOST_IOSTREAMS_DECL extern const int stream_error; +BOOST_IOSTREAMS_DECL extern const int version_error; +BOOST_IOSTREAMS_DECL extern const int data_error; +BOOST_IOSTREAMS_DECL extern const int mem_error; +BOOST_IOSTREAMS_DECL extern const int buf_error; + + // Flush codes + +BOOST_IOSTREAMS_DECL extern const int finish; +BOOST_IOSTREAMS_DECL extern const int no_flush; +BOOST_IOSTREAMS_DECL extern const int sync_flush; + + // Code for current OS + +//BOOST_IOSTREAMS_DECL extern const int os_code; + + // Null pointer constant. + +const int null = 0; + + // Default values + +const int default_window_bits = 15; +const int default_mem_level = 8; +const bool default_crc = false; +const bool default_noheader = false; + +} // End namespace zlib. + +// +// Class name: zlib_params. +// Description: Encapsulates the parameters passed to deflateInit2 +// and inflateInit2 to customize compression and decompression. +// +struct zlib_params { + + // Non-explicit constructor. + zlib_params( int level = zlib::default_compression, + int method = zlib::deflated, + int window_bits = zlib::default_window_bits, + int mem_level = zlib::default_mem_level, + int strategy = zlib::default_strategy, + bool noheader = zlib::default_noheader, + bool calculate_crc = zlib::default_crc ) + : level(level), method(method), window_bits(window_bits), + mem_level(mem_level), strategy(strategy), + noheader(noheader), calculate_crc(calculate_crc) + { } + int level; + int method; + int window_bits; + int mem_level; + int strategy; + bool noheader; + bool calculate_crc; +}; + +// +// Class name: zlib_error. +// Description: Subclass of std::ios::failure thrown to indicate +// zlib errors other than out-of-memory conditions. +// +class BOOST_IOSTREAMS_DECL zlib_error : public BOOST_IOSTREAMS_FAILURE { +public: + explicit zlib_error(int error); + int error() const { return error_; } + static void check BOOST_PREVENT_MACRO_SUBSTITUTION(int error); +private: + int error_; +}; + +namespace detail { + +template<typename Alloc> +struct zlib_allocator_traits { +#ifndef BOOST_NO_STD_ALLOCATOR + typedef typename Alloc::template rebind<char>::other type; +#else + typedef std::allocator<char> type; +#endif +}; + +template< typename Alloc, + typename Base = // VC6 workaround (C2516) + BOOST_DEDUCED_TYPENAME zlib_allocator_traits<Alloc>::type > +struct zlib_allocator : private Base { +private: + typedef typename Base::size_type size_type; +public: + BOOST_STATIC_CONSTANT(bool, custom = + (!is_same<std::allocator<char>, Base>::value)); + typedef typename zlib_allocator_traits<Alloc>::type allocator_type; + static void* allocate(void* self, zlib::uint items, zlib::uint size); + static void deallocate(void* self, void* address); +}; + +class BOOST_IOSTREAMS_DECL zlib_base { +public: + typedef char char_type; +protected: + zlib_base(); + ~zlib_base(); + void* stream() { return stream_; } + template<typename Alloc> + void init( const zlib_params& p, + bool compress, + zlib_allocator<Alloc>& zalloc ) + { + bool custom = zlib_allocator<Alloc>::custom; + do_init( p, compress, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + custom ? zlib_allocator<Alloc>::allocate : 0, + custom ? zlib_allocator<Alloc>::deallocate : 0, + #endif + &zalloc ); + } + 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, + bool compress ); + int xdeflate(int flush); // Prefix 'x' prevents symbols from being + int xinflate(int flush); // redefined when Z_PREFIX is defined + void reset(bool compress, bool realloc); +public: + zlib::ulong crc() const { return crc_; } + int total_in() const { return total_in_; } + int total_out() const { return total_out_; } +private: + void do_init( const zlib_params& p, bool compress, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + zlib::xalloc_func, + zlib::xfree_func, + #endif + void* derived ); + void* stream_; // Actual type: z_stream*. + bool calculate_crc_; + zlib::ulong crc_; + zlib::ulong crc_imp_; + int total_in_; + int total_out_; +}; + +// +// Template name: zlib_compressor_impl +// Description: Model of C-Style Filte implementing compression by +// delegating to the zlib function deflate. +// +template<typename Alloc = std::allocator<char> > +class zlib_compressor_impl : public zlib_base, public zlib_allocator<Alloc> { +public: + zlib_compressor_impl(const zlib_params& = zlib::default_compression); + ~zlib_compressor_impl(); + bool filter( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool flush ); + void close(); +}; + +// +// Template name: zlib_compressor +// Description: Model of C-Style Filte implementing decompression by +// delegating to the zlib function inflate. +// +template<typename Alloc = std::allocator<char> > +class zlib_decompressor_impl : public zlib_base, public zlib_allocator<Alloc> { +public: + zlib_decompressor_impl(const zlib_params&); + zlib_decompressor_impl(int window_bits = zlib::default_window_bits); + ~zlib_decompressor_impl(); + bool filter( const char*& begin_in, const char* end_in, + char*& begin_out, char* end_out, bool flush ); + void close(); + bool eof() const { return eof_; } +private: + bool eof_; +}; + +} // End namespace detail. + +// +// Template name: zlib_compressor +// Description: Model of InputFilter and OutputFilter implementing +// compression using zlib. +// +template<typename Alloc = std::allocator<char> > +struct basic_zlib_compressor + : symmetric_filter<detail::zlib_compressor_impl<Alloc>, Alloc> +{ +private: + typedef detail::zlib_compressor_impl<Alloc> impl_type; + typedef symmetric_filter<impl_type, Alloc> base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + basic_zlib_compressor( const zlib_params& = zlib::default_compression, + int buffer_size = default_device_buffer_size ); + zlib::ulong crc() { return this->filter().crc(); } + int total_in() { return this->filter().total_in(); } +}; +BOOST_IOSTREAMS_PIPABLE(basic_zlib_compressor, 1) + +typedef basic_zlib_compressor<> zlib_compressor; + +// +// Template name: zlib_decompressor +// Description: Model of InputFilter and OutputFilter implementing +// decompression using zlib. +// +template<typename Alloc = std::allocator<char> > +struct basic_zlib_decompressor + : symmetric_filter<detail::zlib_decompressor_impl<Alloc>, Alloc> +{ +private: + typedef detail::zlib_decompressor_impl<Alloc> impl_type; + typedef symmetric_filter<impl_type, Alloc> base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + basic_zlib_decompressor( int window_bits = zlib::default_window_bits, + int buffer_size = default_device_buffer_size ); + basic_zlib_decompressor( const zlib_params& p, + int buffer_size = default_device_buffer_size ); + zlib::ulong crc() { return this->filter().crc(); } + int total_out() { return this->filter().total_out(); } + bool eof() { return this->filter().eof(); } +}; +BOOST_IOSTREAMS_PIPABLE(basic_zlib_decompressor, 1) + +typedef basic_zlib_decompressor<> zlib_decompressor; + +//----------------------------------------------------------------------------// + +//------------------Implementation of zlib_allocator--------------------------// + +namespace detail { + +template<typename Alloc, typename Base> +void* zlib_allocator<Alloc, Base>::allocate + (void* self, zlib::uint items, zlib::uint size) +{ + size_type len = items * size; + char* ptr = + static_cast<allocator_type*>(self)->allocate + (len + sizeof(size_type) + #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) + , (char*)0 + #endif + ); + *reinterpret_cast<size_type*>(ptr) = len; + return ptr + sizeof(size_type); +} + +template<typename Alloc, typename Base> +void zlib_allocator<Alloc, Base>::deallocate(void* self, void* address) +{ + char* ptr = reinterpret_cast<char*>(address) - sizeof(size_type); + size_type len = *reinterpret_cast<size_type*>(ptr) + sizeof(size_type); + static_cast<allocator_type*>(self)->deallocate(ptr, len); +} + +//------------------Implementation of zlib_compressor_impl--------------------// + +template<typename Alloc> +zlib_compressor_impl<Alloc>::zlib_compressor_impl(const zlib_params& p) +{ init(p, true, static_cast<zlib_allocator<Alloc>&>(*this)); } + +template<typename Alloc> +zlib_compressor_impl<Alloc>::~zlib_compressor_impl() +{ reset(true, false); } + +template<typename Alloc> +bool zlib_compressor_impl<Alloc>::filter + ( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool flush ) +{ + before(src_begin, src_end, dest_begin, dest_end); + int result = xdeflate(flush ? zlib::finish : zlib::no_flush); + after(src_begin, dest_begin, true); + zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); + return result != zlib::stream_end; +} + +template<typename Alloc> +void zlib_compressor_impl<Alloc>::close() { reset(true, true); } + +//------------------Implementation of zlib_decompressor_impl------------------// + +template<typename Alloc> +zlib_decompressor_impl<Alloc>::zlib_decompressor_impl(const zlib_params& p) + : eof_(false) +{ init(p, false, static_cast<zlib_allocator<Alloc>&>(*this)); } + +template<typename Alloc> +zlib_decompressor_impl<Alloc>::~zlib_decompressor_impl() +{ reset(false, false); } + +template<typename Alloc> +zlib_decompressor_impl<Alloc>::zlib_decompressor_impl(int window_bits) +{ + zlib_params p; + p.window_bits = window_bits; + init(p, false, static_cast<zlib_allocator<Alloc>&>(*this)); +} + +template<typename Alloc> +bool zlib_decompressor_impl<Alloc>::filter + ( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool /* flush */ ) +{ + before(src_begin, src_end, dest_begin, dest_end); + int result = xinflate(zlib::sync_flush); + after(src_begin, dest_begin, false); + zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); + return !(eof_ = result == zlib::stream_end); +} + +template<typename Alloc> +void zlib_decompressor_impl<Alloc>::close() { + eof_ = false; + reset(false, true); +} + +} // End namespace detail. + +//------------------Implementation of zlib_decompressor-----------------------// + +template<typename Alloc> +basic_zlib_compressor<Alloc>::basic_zlib_compressor + (const zlib_params& p, int buffer_size) + : base_type(buffer_size, p) { } + +//------------------Implementation of zlib_decompressor-----------------------// + +template<typename Alloc> +basic_zlib_decompressor<Alloc>::basic_zlib_decompressor + (int window_bits, int buffer_size) + : base_type(buffer_size, window_bits) { } + +template<typename Alloc> +basic_zlib_decompressor<Alloc>::basic_zlib_decompressor + (const zlib_params& p, int buffer_size) + : base_type(buffer_size, p) { } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include <boost/config/abi_suffix.hpp> // Pops abi_suffix.hpp pragmas. +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED |