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 // NOTE: I hope to replace the current implementation with a much simpler
0009 // one.
0010 
0011 #ifndef BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED
0012 #define BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED
0013 
0014 #if defined(_MSC_VER)
0015 # pragma once
0016 #endif
0017 
0018 #include <boost/assert.hpp>
0019 #include <cstdio>
0020 #include <stdexcept>                       // logic_error.
0021 #include <boost/config.hpp>                // BOOST_STATIC_CONSTANT.
0022 #include <boost/iostreams/categories.hpp>
0023 #include <boost/iostreams/detail/char_traits.hpp>
0024 #include <boost/iostreams/detail/ios.hpp>  // BOOST_IOSTREAMS_FAILURE 
0025 #include <boost/iostreams/read.hpp>        // get 
0026 #include <boost/iostreams/write.hpp>       // put 
0027 #include <boost/iostreams/pipeline.hpp>
0028 #include <boost/iostreams/putback.hpp>
0029 #include <boost/mpl/bool.hpp>
0030 #include <boost/throw_exception.hpp>
0031 #include <boost/type_traits/is_convertible.hpp>
0032 
0033 // Must come last.
0034 #include <boost/iostreams/detail/config/disable_warnings.hpp>
0035 
0036 #define BOOST_IOSTREAMS_ASSERT_UNREACHABLE(val) \
0037     (BOOST_ASSERT("unreachable code" == 0), val) \
0038     /**/
0039 
0040 namespace boost { namespace iostreams {
0041 
0042 namespace newline {
0043 
0044 const char CR                   = 0x0D;
0045 const char LF                   = 0x0A;
0046 
0047     // Flags for configuring newline_filter.
0048 
0049 // Exactly one of the following three flags must be present.
0050 
0051 const int posix             = 1;    // Use LF as line separator.
0052 const int mac               = 2;    // Use CR as line separator.
0053 const int dos               = 4;    // Use CRLF as line separator.
0054 const int mixed             = 8;    // Mixed line endings.
0055 const int final_newline     = 16;
0056 const int platform_mask     = posix | dos | mac;
0057 
0058 } // End namespace newline.
0059 
0060 namespace detail {
0061 
0062 class newline_base {
0063 public:
0064     bool is_posix() const
0065     {
0066         return !is_mixed() && (flags_ & newline::posix) != 0;
0067     }
0068     bool is_dos() const
0069     {
0070         return !is_mixed() && (flags_ & newline::dos) != 0;
0071     }
0072     bool is_mac() const
0073     {
0074         return !is_mixed() && (flags_ & newline::mac) != 0;
0075     }
0076     bool is_mixed_posix() const { return (flags_ & newline::posix) != 0; }
0077     bool is_mixed_dos() const { return (flags_ & newline::dos) != 0; }
0078     bool is_mixed_mac() const { return (flags_ & newline::mac) != 0; }
0079     bool is_mixed() const
0080     {
0081         int platform =
0082             (flags_ & newline::posix) != 0 ?
0083                 newline::posix :
0084                 (flags_ & newline::dos) != 0 ?
0085                     newline::dos :
0086                     (flags_ & newline::mac) != 0 ?
0087                         newline::mac :
0088                         0;
0089         return (flags_ & ~platform & newline::platform_mask) != 0;
0090     }
0091     bool has_final_newline() const
0092     {
0093         return (flags_ & newline::final_newline) != 0;
0094     }
0095 protected:
0096     newline_base(int flags) : flags_(flags) { }
0097     int flags_;
0098 };
0099 
0100 } // End namespace detail.
0101 
0102 class newline_error
0103     : public BOOST_IOSTREAMS_FAILURE, public detail::newline_base
0104 {
0105 private:
0106     friend class newline_checker;
0107     newline_error(int flags)
0108         : BOOST_IOSTREAMS_FAILURE("bad line endings"),
0109           detail::newline_base(flags)
0110         { }
0111 };
0112 
0113 class newline_filter {
0114 public:
0115     typedef char char_type;
0116     struct category
0117         : dual_use,
0118           filter_tag,
0119           closable_tag
0120         { };
0121 
0122     explicit newline_filter(int target) : flags_(target)
0123     {
0124         if ( target != iostreams::newline::posix &&
0125              target != iostreams::newline::dos &&
0126              target != iostreams::newline::mac )
0127         {
0128             boost::throw_exception(std::logic_error("bad flags"));
0129         }
0130     }
0131 
0132     template<typename Source>
0133     int get(Source& src)
0134     {
0135         using iostreams::newline::CR;
0136         using iostreams::newline::LF;
0137 
0138         BOOST_ASSERT((flags_ & f_write) == 0);
0139         flags_ |= f_read;
0140 
0141         if (flags_ & (f_has_LF | f_has_EOF)) {
0142             if (flags_ & f_has_LF)
0143                 return newline();
0144             else
0145                 return EOF;
0146         }
0147 
0148         int c =
0149             (flags_ & f_has_CR) == 0 ?
0150                 iostreams::get(src) :
0151                 CR;
0152 
0153         if (c == WOULD_BLOCK )
0154             return WOULD_BLOCK;
0155 
0156         if (c == CR) {
0157             flags_ |= f_has_CR;
0158 
0159             int d = iostreams::get(src);
0160             if (d == WOULD_BLOCK)
0161                 return WOULD_BLOCK;
0162 
0163             if (d == LF) {
0164                 flags_ &= ~f_has_CR;
0165                 return newline();
0166             }
0167 
0168             if (d == EOF) {
0169                 flags_ |= f_has_EOF;
0170             } else {
0171                 iostreams::putback(src, d);
0172             }
0173 
0174             flags_ &= ~f_has_CR;
0175             return newline();
0176         }
0177 
0178         if (c == LF)
0179             return newline();
0180 
0181         return c;
0182     }
0183 
0184     template<typename Sink>
0185     bool put(Sink& dest, char c)
0186     {
0187         using iostreams::newline::CR;
0188         using iostreams::newline::LF;
0189 
0190         BOOST_ASSERT((flags_ & f_read) == 0);
0191         flags_ |= f_write;
0192 
0193         if ((flags_ & f_has_LF) != 0)
0194             return c == LF ?
0195                 newline(dest) :
0196                 newline(dest) && this->put(dest, c);
0197 
0198         if (c == LF)
0199            return newline(dest);
0200 
0201         if ((flags_ & f_has_CR) != 0)
0202             return newline(dest) ?
0203                 this->put(dest, c) :
0204                 false;
0205 
0206         if (c == CR) {
0207             flags_ |= f_has_CR;
0208             return true;
0209         }
0210 
0211         return iostreams::put(dest, c);
0212     }
0213 
0214     template<typename Sink>
0215     void close(Sink& dest, BOOST_IOS::openmode)
0216     {
0217         if ((flags_ & f_write) != 0 && (flags_ & f_has_CR) != 0)
0218             newline_if_sink(dest);
0219         flags_ &= ~f_has_LF; // Restore original flags.
0220     }
0221 private:
0222 
0223     // Returns the appropriate element of a newline sequence.
0224     int newline()
0225     {
0226         using iostreams::newline::CR;
0227         using iostreams::newline::LF;
0228 
0229         switch (flags_ & iostreams::newline::platform_mask) {
0230         case iostreams::newline::posix:
0231             return LF;
0232         case iostreams::newline::mac:
0233             return CR;
0234         case iostreams::newline::dos:
0235             if (flags_ & f_has_LF) {
0236                 flags_ &= ~f_has_LF;
0237                 return LF;
0238             } else {
0239                 flags_ |= f_has_LF;
0240                 return CR;
0241             }
0242         }
0243         return BOOST_IOSTREAMS_ASSERT_UNREACHABLE(0);
0244     }
0245 
0246     // Writes a newline sequence.
0247     template<typename Sink>
0248     bool newline(Sink& dest)
0249     {
0250         using iostreams::newline::CR;
0251         using iostreams::newline::LF;
0252 
0253         bool success = false;
0254         switch (flags_ & iostreams::newline::platform_mask) {
0255         case iostreams::newline::posix:
0256             success = boost::iostreams::put(dest, LF);
0257             break;
0258         case iostreams::newline::mac:
0259             success = boost::iostreams::put(dest, CR);
0260             break;
0261         case iostreams::newline::dos:
0262             if ((flags_ & f_has_LF) != 0) {
0263                 success = boost::iostreams::put(dest, LF);
0264                 if (success)
0265                     flags_ &= ~f_has_LF;
0266             } else if (boost::iostreams::put(dest, CR)) {
0267                 success = boost::iostreams::put(dest, LF);
0268                 if (!success)
0269                     flags_ |= f_has_LF;
0270             }
0271             break;
0272         }
0273         if (success)
0274             flags_ &= ~f_has_CR;
0275         return success;
0276     }
0277 
0278     // Writes a newline sequence if the given device is a Sink.
0279     template<typename Device>
0280     void newline_if_sink(Device& dest) 
0281     { 
0282         typedef typename iostreams::category_of<Device>::type category;
0283         newline_if_sink(dest, is_convertible<category, output>()); 
0284     }
0285 
0286     template<typename Sink>
0287     void newline_if_sink(Sink& dest, mpl::true_) { newline(dest); }
0288 
0289     template<typename Source>
0290     void newline_if_sink(Source&, mpl::false_) { }
0291 
0292     enum flags {
0293         f_has_LF         = 32768,
0294         f_has_CR         = f_has_LF << 1,
0295         f_has_newline    = f_has_CR << 1,
0296         f_has_EOF        = f_has_newline << 1,
0297         f_read           = f_has_EOF << 1,
0298         f_write          = f_read << 1
0299     };
0300     int       flags_;
0301 };
0302 BOOST_IOSTREAMS_PIPABLE(newline_filter, 0)
0303 
0304 class newline_checker : public detail::newline_base {
0305 public:
0306     typedef char                 char_type;
0307     struct category
0308         : dual_use_filter_tag,
0309           closable_tag
0310         { };
0311     explicit newline_checker(int target = newline::mixed)
0312         : detail::newline_base(0), target_(target), open_(false)
0313         { }
0314     template<typename Source>
0315     int get(Source& src)
0316     {
0317         using newline::CR;
0318         using newline::LF;
0319 
0320         if (!open_) {
0321             open_ = true;
0322             source() = 0;
0323         }
0324 
0325         int c;
0326         if ((c = iostreams::get(src)) == WOULD_BLOCK)
0327             return WOULD_BLOCK;
0328 
0329         // Update source flags.
0330         if (c != EOF)
0331             source() &= ~f_line_complete;
0332         if ((source() & f_has_CR) != 0) {
0333             if (c == LF) {
0334                 source() |= newline::dos;
0335                 source() |= f_line_complete;
0336             } else {
0337                 source() |= newline::mac;
0338                 if (c == EOF)
0339                     source() |= f_line_complete;
0340             }
0341         } else if (c == LF) {
0342             source() |= newline::posix;
0343             source() |= f_line_complete;
0344         }
0345         source() = (source() & ~f_has_CR) | (c == CR ? f_has_CR : 0);
0346 
0347         // Check for errors.
0348         if ( c == EOF &&
0349             (target_ & newline::final_newline) != 0 &&
0350             (source() & f_line_complete) == 0 )
0351         {
0352             fail();
0353         }
0354         if ( (target_ & newline::platform_mask) != 0 &&
0355              (source() & ~target_ & newline::platform_mask) != 0 )
0356         {
0357             fail();
0358         }
0359 
0360         return c;
0361     }
0362 
0363     template<typename Sink>
0364     bool put(Sink& dest, int c)
0365     {
0366         using iostreams::newline::CR;
0367         using iostreams::newline::LF;
0368 
0369         if (!open_) {
0370             open_ = true;
0371             source() = 0;
0372         }
0373 
0374         if (!iostreams::put(dest, c))
0375             return false;
0376 
0377          // Update source flags.
0378         source() &= ~f_line_complete;
0379         if ((source() & f_has_CR) != 0) {
0380             if (c == LF) {
0381                 source() |= newline::dos;
0382                 source() |= f_line_complete;
0383             } else {
0384                 source() |= newline::mac;
0385             }
0386         } else if (c == LF) {
0387             source() |= newline::posix;
0388             source() |= f_line_complete;
0389         }
0390         source() = (source() & ~f_has_CR) | (c == CR ? f_has_CR : 0);
0391 
0392         // Check for errors.
0393         if ( (target_ & newline::platform_mask) != 0 &&
0394              (source() & ~target_ & newline::platform_mask) != 0 )
0395         {
0396             fail();
0397         }
0398 
0399         return true;
0400     }
0401 
0402     template<typename Sink>
0403     void close(Sink&, BOOST_IOS::openmode)
0404     {
0405         using iostreams::newline::final_newline;
0406 
0407         // Update final_newline flag.
0408         if ( (source() & f_has_CR) != 0 ||
0409              (source() & f_line_complete) != 0 )
0410         {
0411             source() |= final_newline;
0412         }
0413 
0414         // Clear non-sticky flags.
0415         source() &= ~(f_has_CR | f_line_complete);
0416 
0417         // Check for errors.
0418         if ( (target_ & final_newline) != 0 &&
0419              (source() & final_newline) == 0 )
0420         {
0421             fail();
0422         }
0423     }
0424 private:
0425     void fail() { boost::throw_exception(newline_error(source())); }
0426     int& source() { return flags_; }
0427     int source() const { return flags_; }
0428 
0429     enum flags {
0430         f_has_CR = 32768,
0431         f_line_complete = f_has_CR << 1
0432     };
0433 
0434     int   target_;  // Represents expected input.
0435     bool  open_;
0436 };
0437 BOOST_IOSTREAMS_PIPABLE(newline_checker, 0)
0438 
0439 } } // End namespaces iostreams, boost.
0440 
0441 #include <boost/iostreams/detail/config/enable_warnings.hpp>
0442 
0443 #endif // #ifndef BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED