summaryrefslogtreecommitdiff
path: root/boost/iostreams/filter
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/iostreams/filter
downloadboost-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.hpp168
-rw-r--r--boost/iostreams/filter/bzip2.hpp414
-rw-r--r--boost/iostreams/filter/counter.hpp82
-rw-r--r--boost/iostreams/filter/grep.hpp109
-rw-r--r--boost/iostreams/filter/gzip.hpp757
-rw-r--r--boost/iostreams/filter/line.hpp227
-rw-r--r--boost/iostreams/filter/newline.hpp442
-rw-r--r--boost/iostreams/filter/regex.hpp98
-rw-r--r--boost/iostreams/filter/stdio.hpp84
-rw-r--r--boost/iostreams/filter/symmetric.hpp310
-rw-r--r--boost/iostreams/filter/test.hpp322
-rw-r--r--boost/iostreams/filter/zlib.hpp427
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