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 2005-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 #ifndef BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED
0009 #define BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED
0010 
0011 #if defined(_MSC_VER)
0012 # pragma once
0013 #endif
0014 
0015 #include <algorithm>                               // min.
0016 #include <boost/assert.hpp>
0017 #include <memory>                                  // allocator.
0018 #include <string>
0019 #include <boost/config.hpp>                        // BOOST_STATIC_CONSTANT.
0020 #include <boost/iostreams/categories.hpp>
0021 #include <boost/iostreams/checked_operations.hpp>
0022 #include <boost/iostreams/detail/ios.hpp>          // openmode, streamsize.
0023 #include <boost/iostreams/read.hpp>                // check_eof 
0024 #include <boost/iostreams/pipeline.hpp>
0025 #include <boost/iostreams/write.hpp>
0026 
0027 // Must come last.
0028 #include <boost/iostreams/detail/config/disable_warnings.hpp> // VC7.1 C4244.
0029 
0030 namespace boost { namespace iostreams {
0031 
0032 //
0033 // Template name: line_filter.
0034 // Template parameters:
0035 //      Ch - The character type.
0036 //      Alloc - The allocator type.
0037 // Description: Filter which processes data one line at a time.
0038 //
0039 template< typename Ch,
0040           typename Alloc = std::allocator<Ch> >
0041 class basic_line_filter {
0042 private:
0043     typedef typename std::basic_string<Ch>::traits_type  string_traits;
0044 public:
0045     typedef Ch                                           char_type;
0046     typedef char_traits<char_type>                       traits_type;
0047     typedef std::basic_string<
0048                 Ch,
0049                 string_traits,
0050                 Alloc
0051             >                                            string_type;
0052     struct category
0053         : dual_use,
0054           filter_tag,
0055           multichar_tag,
0056           closable_tag
0057         { };
0058 protected:
0059     basic_line_filter(bool suppress_newlines = false) 
0060         : pos_(string_type::npos), 
0061           flags_(suppress_newlines ? f_suppress : 0) 
0062         { }
0063 public:
0064     virtual ~basic_line_filter() { }
0065 
0066     template<typename Source>
0067     std::streamsize read(Source& src, char_type* s, std::streamsize n)
0068     {
0069         using namespace std;
0070         BOOST_ASSERT(!(flags_ & f_write));
0071         flags_ |= f_read;
0072 
0073         // Handle unfinished business.
0074         std::streamsize result = 0;
0075         if (!cur_line_.empty() && (result = read_line(s, n)) == n)
0076             return n;
0077 
0078         typename traits_type::int_type status = traits_type::good();
0079         while (result < n && !traits_type::is_eof(status)) {
0080 
0081             // Call next_line() to retrieve a line of filtered text, and
0082             // read_line() to copy it into buffer s.
0083             if (traits_type::would_block(status = next_line(src)))
0084                 return result;
0085             result += read_line(s + result, n - result);
0086         }
0087 
0088         return detail::check_eof(result);
0089     }
0090 
0091     template<typename Sink>
0092     std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
0093     {
0094         using namespace std;
0095         BOOST_ASSERT(!(flags_ & f_read));
0096         flags_ |= f_write;
0097 
0098         // Handle unfinished business.
0099         if (pos_ != string_type::npos && !write_line(snk))
0100             return 0;
0101 
0102         const char_type *cur = s, *next;
0103         while (true) {
0104 
0105             // Search for the next full line in [cur, s + n), filter it
0106             // and write it to snk.
0107             typename string_type::size_type rest = n - (cur - s);
0108             if ((next = traits_type::find(cur, rest, traits_type::newline()))) {
0109                 cur_line_.append(cur, next - cur);
0110                 cur = next + 1;
0111                 if (!write_line(snk))
0112                     return static_cast<std::streamsize>(cur - s);
0113             } else {
0114                 cur_line_.append(cur, rest);
0115                 return n;
0116             }
0117         }
0118     }
0119 
0120     template<typename Sink>
0121     void close(Sink& snk, BOOST_IOS::openmode which)
0122     {
0123         if ((flags_ & f_read) && which == BOOST_IOS::in)
0124             close_impl();
0125 
0126         if ((flags_ & f_write) && which == BOOST_IOS::out) {
0127             try {
0128                 if (!cur_line_.empty())
0129                     write_line(snk);
0130             } catch (...) {
0131                 try {
0132                     close_impl();
0133                 } catch (...) { }
0134                 throw;
0135             }
0136             close_impl();
0137         }
0138     }
0139 private:
0140     virtual string_type do_filter(const string_type& line) = 0;
0141 
0142     // Copies filtered characters fron the current line into
0143     // the given buffer.
0144     std::streamsize read_line(char_type* s, std::streamsize n)
0145     {
0146         using namespace std;
0147         std::streamsize result =
0148             (std::min) (n, static_cast<std::streamsize>(cur_line_.size()));
0149         traits_type::copy(s, cur_line_.data(), result);
0150         cur_line_.erase(0, result);
0151         return result;
0152     }
0153 
0154     // Attempts to retrieve a line of text from the given source; returns
0155     // an int_type as a good/eof/would_block status code.
0156     template<typename Source>
0157     typename traits_type::int_type next_line(Source& src)
0158     {
0159         using namespace std;
0160         typename traits_type::int_type c;
0161         while ( traits_type::is_good(c = iostreams::get(src)) &&
0162                 c != traits_type::newline() )
0163         {
0164             cur_line_ += traits_type::to_int_type(c);
0165         }
0166         if (!traits_type::would_block(c)) {
0167             if (!cur_line_.empty() || c == traits_type::newline())
0168                 cur_line_ = do_filter(cur_line_);
0169             if (c == traits_type::newline() && (flags_ & f_suppress) == 0)
0170                 cur_line_ += c;
0171         }
0172         return c; // status indicator.
0173     }
0174 
0175     // Filters the current line and attemps to write it to the given sink.
0176     // Returns true for success.
0177     template<typename Sink>
0178     bool write_line(Sink& snk)
0179     {
0180         string_type line = do_filter(cur_line_);
0181         if ((flags_ & f_suppress) == 0)
0182             line += traits_type::newline();
0183         std::streamsize amt = static_cast<std::streamsize>(line.size());
0184         bool result = iostreams::write_if(snk, line.data(), amt) == amt;
0185         if (result)
0186             clear();
0187         return result;
0188     }
0189 
0190     void close_impl()
0191     {
0192         clear();
0193         flags_ &= f_suppress;
0194     }
0195 
0196     void clear()
0197     {
0198         cur_line_.erase();
0199         pos_ = string_type::npos;
0200     }
0201 
0202     enum flag_type {
0203         f_read      = 1,
0204         f_write     = f_read << 1,
0205         f_suppress  = f_write << 1
0206     };
0207 
0208     string_type                      cur_line_;
0209     typename string_type::size_type  pos_;
0210     int                              flags_;
0211 };
0212 BOOST_IOSTREAMS_PIPABLE(basic_line_filter, 2)
0213 
0214 typedef basic_line_filter<char>     line_filter;
0215 typedef basic_line_filter<wchar_t>  wline_filter;
0216 
0217 } } // End namespaces iostreams, boost.
0218 
0219 #include <boost/iostreams/detail/config/enable_warnings.hpp>
0220 
0221 #endif // #ifndef BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED