Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:44:31

0001 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
0002 // (C) Copyright 2003-2007 Jonathan Turkanis
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
0005 
0006 // See http://www.boost.org/libs/iostreams for documentation.
0007 
0008 // Contains the definitions of the class templates symmetric_filter,
0009 // which models DualUseFilter based on a model of the Symmetric Filter.
0010 
0011 //
0012 // Roughly, a Symmetric Filter is a class type with the following interface:
0013 //
0014 //   struct symmetric_filter {
0015 //       typedef xxx char_type;
0016 //
0017 //       bool filter( const char*& begin_in, const char* end_in,
0018 //                    char*& begin_out, char* end_out, bool flush )
0019 //       {
0020 //          // Consume as many characters as possible from the interval
0021 //          // [begin_in, end_in), without exhausting the output range
0022 //          // [begin_out, end_out). If flush is true, write as mush output
0023 //          // as possible. 
0024 //          // A return value of true indicates that filter should be called 
0025 //          // again. More precisely, if flush is false, a return value of 
0026 //          // false indicates that the natural end of stream has been reached
0027 //          // and that all filtered data has been forwarded; if flush is
0028 //          // true, a return value of false indicates that all filtered data 
0029 //          // has been forwarded.
0030 //       }
0031 //       void close() { /* Reset filter's state. */ }
0032 //   };
0033 //
0034 // Symmetric Filter filters need not be CopyConstructable.
0035 //
0036 
0037 #ifndef BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED
0038 #define BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED
0039 
0040 #if defined(_MSC_VER)
0041 # pragma once
0042 #endif
0043 
0044 #include <boost/assert.hpp>
0045 #include <memory>                               // allocator.
0046 #include <boost/config.hpp>                     // BOOST_DEDUCED_TYPENAME.
0047 #include <boost/iostreams/char_traits.hpp>
0048 #include <boost/iostreams/constants.hpp>        // buffer size.
0049 #include <boost/iostreams/detail/buffer.hpp>
0050 #include <boost/iostreams/detail/char_traits.hpp>
0051 #include <boost/iostreams/detail/config/limits.hpp>
0052 #include <boost/iostreams/detail/ios.hpp>  // streamsize.
0053 #include <boost/iostreams/detail/template_params.hpp>
0054 #include <boost/iostreams/traits.hpp>
0055 #include <boost/iostreams/operations.hpp>       // read, write.
0056 #include <boost/iostreams/pipeline.hpp>
0057 #include <boost/preprocessor/iteration/local.hpp>
0058 #include <boost/preprocessor/punctuation/comma_if.hpp>
0059 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0060 #include <boost/preprocessor/repetition/enum_params.hpp>
0061 #include <boost/shared_ptr.hpp>
0062 
0063 // Must come last.
0064 #include <boost/iostreams/detail/config/disable_warnings.hpp>  // MSVC.
0065 
0066 namespace boost { namespace iostreams {
0067 
0068 template< typename SymmetricFilter,
0069           typename Alloc =
0070               std::allocator<
0071                   BOOST_DEDUCED_TYPENAME char_type_of<SymmetricFilter>::type
0072               > >
0073 class symmetric_filter {
0074 public:
0075     typedef typename char_type_of<SymmetricFilter>::type      char_type;
0076     typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type)            traits_type;
0077     typedef std::basic_string<char_type, traits_type, Alloc>  string_type;
0078     struct category
0079         : dual_use,
0080           filter_tag,
0081           multichar_tag,
0082           closable_tag
0083         { };
0084 
0085     // Expands to a sequence of ctors which forward to impl.
0086     #define BOOST_PP_LOCAL_MACRO(n) \
0087         BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \
0088         explicit symmetric_filter( \
0089               std::streamsize buffer_size BOOST_PP_COMMA_IF(n) \
0090               BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \
0091             : pimpl_(new impl(buffer_size BOOST_PP_COMMA_IF(n) \
0092                      BOOST_PP_ENUM_PARAMS(n, t))) \
0093             { BOOST_ASSERT(buffer_size > 0); } \
0094         /**/
0095     #define BOOST_PP_LOCAL_LIMITS (0, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY)
0096     #include BOOST_PP_LOCAL_ITERATE()
0097     #undef BOOST_PP_LOCAL_MACRO
0098 
0099     template<typename Source>
0100     std::streamsize read(Source& src, char_type* s, std::streamsize n)
0101     {
0102         using namespace std;
0103         if (!(state() & f_read))
0104             begin_read();
0105 
0106         buffer_type&  buf = pimpl_->buf_;
0107         int           status = (state() & f_eof) != 0 ? f_eof : f_good;
0108         char_type    *next_s = s,
0109                      *end_s = s + n;
0110         while (true)
0111         {
0112             // Invoke filter if there are unconsumed characters in buffer or if
0113             // filter must be flushed.
0114             bool flush = status == f_eof;
0115             if (buf.ptr() != buf.eptr() || flush) {
0116                 const char_type* next = buf.ptr();
0117                 bool done =
0118                     !filter().filter(next, buf.eptr(), next_s, end_s, flush);
0119                 buf.ptr() = buf.data() + (next - buf.data());
0120                 if (done)
0121                     return detail::check_eof(
0122                                static_cast<std::streamsize>(next_s - s)
0123                            );
0124             }
0125 
0126             // If no more characters are available without blocking, or
0127             // if read request has been satisfied, return.
0128             if ( (status == f_would_block && buf.ptr() == buf.eptr()) ||
0129                  next_s == end_s )
0130             {
0131                 return static_cast<std::streamsize>(next_s - s);
0132             }
0133 
0134             // Fill buffer.
0135             if (status == f_good)
0136                 status = fill(src);
0137         }
0138     }
0139 
0140     template<typename Sink>
0141     std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
0142     {
0143         if (!(state() & f_write))
0144             begin_write();
0145 
0146         buffer_type&     buf = pimpl_->buf_;
0147         const char_type *next_s, *end_s;
0148         for (next_s = s, end_s = s + n; next_s != end_s; ) {
0149             if (buf.ptr() == buf.eptr() && !flush(snk))
0150                 break;
0151             if(!filter().filter(next_s, end_s, buf.ptr(), buf.eptr(), false)) {
0152                 flush(snk);
0153                 break;
0154             }
0155         }
0156         return static_cast<std::streamsize>(next_s - s);
0157     }
0158 
0159     template<typename Sink>
0160     void close(Sink& snk, BOOST_IOS::openmode mode)
0161     {
0162         if (mode == BOOST_IOS::out) {
0163 
0164             if (!(state() & f_write))
0165                 begin_write();
0166 
0167             // Repeatedly invoke filter() with no input.
0168             try {
0169                 buffer_type&     buf = pimpl_->buf_;
0170                 char_type        dummy;
0171                 const char_type* end = &dummy;
0172                 bool             again = true;
0173                 while (again) {
0174                     if (buf.ptr() != buf.eptr())
0175                         again = filter().filter( end, end, buf.ptr(),
0176                                                  buf.eptr(), true );
0177                     flush(snk);
0178                 }
0179             } catch (...) {
0180                 try { close_impl(); } catch (...) { }
0181                 throw;
0182             }
0183             close_impl();
0184         } else {
0185             close_impl();
0186         }
0187     }
0188     SymmetricFilter& filter() { return *pimpl_; }
0189     string_type unconsumed_input() const;
0190 
0191 // Give impl access to buffer_type on Tru64
0192 #if !BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) 
0193     private:
0194 #endif
0195     typedef detail::buffer<char_type, Alloc> buffer_type;
0196 private:
0197     buffer_type& buf() { return pimpl_->buf_; }
0198     const buffer_type& buf() const { return pimpl_->buf_; }
0199     int& state() { return pimpl_->state_; }
0200     void begin_read();
0201     void begin_write();
0202 
0203     template<typename Source>
0204     int fill(Source& src)
0205     {
0206         std::streamsize amt = iostreams::read(src, buf().data(), buf().size());
0207         if (amt == -1) {
0208             state() |= f_eof;
0209             return f_eof;
0210         }
0211         buf().set(0, amt);
0212         return amt != 0 ? f_good : f_would_block;
0213     }
0214 
0215     // Attempts to write the contents of the buffer the given Sink.
0216     // Returns true if at least on character was written.
0217     template<typename Sink>
0218     bool flush(Sink& snk)
0219     {
0220         typedef typename iostreams::category_of<Sink>::type  category;
0221         typedef is_convertible<category, output>             can_write;
0222         return flush(snk, can_write());
0223     }
0224 
0225     template<typename Sink>
0226     bool flush(Sink& snk, mpl::true_)
0227     {
0228         std::streamsize amt =
0229             static_cast<std::streamsize>(buf().ptr() - buf().data());
0230         std::streamsize result =
0231             boost::iostreams::write(snk, buf().data(), amt);
0232         if (result < amt && result > 0)
0233             traits_type::move(buf().data(), buf().data() + result, amt - result);
0234         buf().set(amt - result, buf().size());
0235         return result != 0;
0236     }
0237 
0238     template<typename Sink>
0239     bool flush(Sink&, mpl::false_) { return true;}
0240 
0241     void close_impl();
0242 
0243     enum flag_type {
0244         f_read   = 1,
0245         f_write  = f_read << 1,
0246         f_eof    = f_write << 1,
0247         f_good,
0248         f_would_block
0249     };
0250 
0251     struct impl : SymmetricFilter {
0252 
0253     // Expands to a sequence of ctors which forward to SymmetricFilter.
0254     #define BOOST_PP_LOCAL_MACRO(n) \
0255         BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \
0256         impl( std::streamsize buffer_size BOOST_PP_COMMA_IF(n) \
0257               BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \
0258             : SymmetricFilter(BOOST_PP_ENUM_PARAMS(n, t)), \
0259               buf_(buffer_size), state_(0) \
0260             { } \
0261         /**/
0262     #define BOOST_PP_LOCAL_LIMITS (0, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY)
0263     #include BOOST_PP_LOCAL_ITERATE()
0264     #undef BOOST_PP_LOCAL_MACRO
0265 
0266         buffer_type  buf_;
0267         int          state_;
0268     };
0269 
0270     shared_ptr<impl> pimpl_;
0271 };
0272 BOOST_IOSTREAMS_PIPABLE(symmetric_filter, 2)
0273 
0274 //------------------Implementation of symmetric_filter----------------//
0275 
0276 template<typename SymmetricFilter, typename Alloc>
0277 void symmetric_filter<SymmetricFilter, Alloc>::begin_read()
0278 {
0279     BOOST_ASSERT(!(state() & f_write));
0280     state() |= f_read;
0281     buf().set(0, 0);
0282 }
0283 
0284 template<typename SymmetricFilter, typename Alloc>
0285 void symmetric_filter<SymmetricFilter, Alloc>::begin_write()
0286 {
0287     BOOST_ASSERT(!(state() & f_read));
0288     state() |= f_write;
0289     buf().set(0, buf().size());
0290 }
0291 
0292 template<typename SymmetricFilter, typename Alloc>
0293 void symmetric_filter<SymmetricFilter, Alloc>::close_impl()
0294 {
0295     state() = 0;
0296     buf().set(0, 0);
0297     filter().close();
0298 }
0299 
0300 template<typename SymmetricFilter, typename Alloc>
0301 typename symmetric_filter<SymmetricFilter, Alloc>::string_type
0302 symmetric_filter<SymmetricFilter, Alloc>::unconsumed_input() const
0303 { return string_type(buf().ptr(), buf().eptr()); }
0304 
0305 //----------------------------------------------------------------------------//
0306 
0307 } } // End namespaces iostreams, boost.
0308 
0309 #include <boost/iostreams/detail/config/enable_warnings.hpp>  // MSVC.
0310 
0311 #endif // #ifndef BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED