newline.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 442 行

HPP
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 <cassert>#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/type_traits/is_convertible.hpp>// Must come last.#include <boost/iostreams/detail/config/disable_warnings.hpp>#define BOOST_IOSTREAMS_ASSERT_UNREACHABLE(val) \    (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 != newline::posix &&             target != newline::dos &&             target != newline::mac )        {            throw std::logic_error("bad flags");        }    }    template<typename Source>    int get(Source& src)    {        using iostreams::newline::CR;        using iostreams::newline::LF;        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;        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 which)    {        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_ & newline::platform_mask) {        case newline::posix:            return LF;        case newline::mac:            return CR;        case 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_ & newline::platform_mask) {        case newline::posix:            success = boost::iostreams::put(dest, LF);            break;        case newline::mac:            success = boost::iostreams::put(dest, CR);            break;        case 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 which)    {        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() { throw 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

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?