⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 output_iterator.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
字号:
//  Copyright (c) 2001-2008 Hartmut Kaiser// //  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)#if !defined(BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM)#define BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM#if defined(_MSC_VER) && (_MSC_VER >= 1020)#pragma once      // MS compatible compilers support #pragma once#endif#include <iterator>#include <vector>#include <algorithm>#include <boost/noncopyable.hpp>#include <boost/spirit/home/karma/detail/ostream_iterator.hpp>namespace boost { namespace spirit { namespace karma { namespace detail {    ///////////////////////////////////////////////////////////////////////////    //  This class is used to keep track of the current position in the output.    ///////////////////////////////////////////////////////////////////////////    class position_sink     {    public:        position_sink() : count(0), line(1), column(0) {}        void tidy() { count = 0; line = 1; column = 0; }                template <typename T>        void output(T const& value)         {            ++count;             if (value == '\n') {                ++line;                column = 1;            }            else {                ++column;            }        }        std::size_t get_count() const { return count; }        std::size_t get_line() const { return line; }        std::size_t get_column() const { return column; }    private:        std::size_t count;        std::size_t line;        std::size_t column;    };    ///////////////////////////////////////////////////////////////////////////    //  This class is used to count the umber of characters streamed into the     //  output.    ///////////////////////////////////////////////////////////////////////////    class counting_sink     {    public:        counting_sink() : count(0) {}                void init(std::size_t count_) { count = count_; }        void tidy() { count = 0; }                void output() { ++count; }        std::size_t get_count() const { return count; }    private:        std::size_t count;    };    ///////////////////////////////////////////////////////////////////////////    //  The following classes are used to intercept the output into a buffer    //  allowing to do things like alignment, character escaping etc.    //    //  We need to use virtual functions because output_iterators do not have    //  an associated value_type. The type of the buffer elements is available    //  at insertion time only (and not at buffer creation time).    ///////////////////////////////////////////////////////////////////////////    template <typename OutputIterator>    struct abstract_container    {        virtual ~abstract_container() {}        virtual void output(void const *item) = 0;        virtual void copy(OutputIterator& sink) = 0;        virtual std::size_t buffer_size() = 0;    };        template <typename OutputIterator, typename T>    class concrete_container : public abstract_container<OutputIterator>    {    public:        concrete_container(std::size_t size)        {             buffer.reserve(size);         }        ~concrete_container() {}        void output(void const *item)        {            buffer.push_back(*static_cast<T const*>(item));        }        void copy(OutputIterator& sink)        {            std::copy(buffer.begin(), buffer.end(), sink);        }        std::size_t buffer_size()        {            return buffer.size();        }        private:        std::vector<T> buffer;    };        ///////////////////////////////////////////////////////////////////////////    template <typename OutputIterator>    class buffer_sink : boost::noncopyable    {    public:        buffer_sink()          : width(0), buffer(0)         {}                ~buffer_sink()         {             delete buffer;         }                void init(std::size_t width_) { width = width_; }        void tidy() { delete buffer; buffer = 0; width = 0; }                template <typename T>        void output(T const& value)        {            if (0 == buffer)            {                typedef concrete_container<OutputIterator, T> container;                buffer = new container(width);            }            buffer->output(&value);        }                void copy(OutputIterator& sink) const         {             if (buffer)                 buffer->copy(sink);         }                std::size_t buffer_size() const         {             return buffer ? buffer->buffer_size() : 0;         }    private:        std::size_t width;        abstract_container<OutputIterator> *buffer;    };    ///////////////////////////////////////////////////////////////////////////    //  forward declaration only    ///////////////////////////////////////////////////////////////////////////    template <typename OutputIterator> struct enable_counting;    template <typename OutputIterator> struct enable_buffering;    ///////////////////////////////////////////////////////////////////////////    //  Karma uses a output iterator wrapper for all output operations. This    //  is necessary to avoid the dreaded 'scanner business' problem, i.e. the    //  dependency of rules and grammars on the used output iterator.     //    //  By default the user supplied output iterator is wrapped inside an     //  instance of this internal output_iterator class.     //    //  This output_iterator class normally just forwards to the embedded user    //  supplied iterator. But it is possible to enable additional functionality    //  on demand, such as counting, buffering, and position tracking.    ///////////////////////////////////////////////////////////////////////////    template <typename OutputIterator, typename Enable = void>    class output_iterator : boost::noncopyable    {    private:        enum output_mode         {            output_characters = 0,    // just hand through character            count_characters = 1,     // additionally count characters            buffer_characters = 2     // buffer all characters, no output        };                struct output_proxy         {            output_proxy(output_iterator& parent)               : parent(parent)             {}                        template <typename T>             output_proxy& operator=(T const& value)             {                parent.output(value);                return *this;             }        private:            output_iterator& parent;            // suppress warning about assignment operator not being generated            output_proxy& operator=(output_proxy const&);        };        #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)private:        friend struct enable_counting<output_iterator>;        friend struct enable_buffering<output_iterator>;#elsepublic:#endif        // functions related to counting        void enable_counting(std::size_t count = 0)        {            count_data.init(count);            mode = output_mode(mode | count_characters);        }        void disable_counting()        {            mode = output_mode(mode & ~count_characters);        }        void reset_counting()        {            count_data.tidy();        }                // functions related to buffering        void enable_buffering(std::size_t width = 0)        {            buffer_data.init(width);            mode = output_mode(mode | buffer_characters);        }        void disable_buffering()        {            mode = output_mode(mode & ~buffer_characters);        }        void reset_buffering()        {            buffer_data.tidy();        }            public:        typedef std::output_iterator_tag iterator_category;        typedef void value_type;        typedef void difference_type;        typedef void pointer;        typedef void reference;        output_iterator(OutputIterator& sink_)          : sink(sink_), mode(output_characters)        {}        output_proxy operator*() { return output_proxy(*this); }        output_iterator& operator++() { ++sink; return *this; }         output_iterator& operator++(int) { sink++; return *this; }        template <typename T>         void output(T const& value)         {             if (mode & count_characters)    // count characters, if appropriate                count_data.output();            // always track position in the output (this is needed by different             // generators, such as indent, pad, etc.)            track_position_data.output(value);            if (mode & buffer_characters)   // buffer output, if appropriate                buffer_data.output(value);            else                *sink = value;         }        // functions related to counting        std::size_t count() const        {            return count_data.get_count();        }                // functions related to buffering        std::size_t buffer_size() const        {            return buffer_data.buffer_size();        }        void buffer_copy()        {            buffer_data.copy(sink);        }                // return the current count in the output        std::size_t get_out_count() const        {            return track_position_data.get_count();        }            protected:        // this is the wrapped user supplied output iterator        OutputIterator& sink;    private:        // these are the hooks providing optional functionality        counting_sink count_data;                   // for counting        buffer_sink<OutputIterator> buffer_data;    // for buffering        position_sink track_position_data;          // for position tracking        int mode;                // suppress warning about assignment operator not being generated        output_iterator& operator=(output_iterator const&);    };    ///////////////////////////////////////////////////////////////////////////    template <typename T, typename Elem, typename Traits>    class output_iterator<ostream_iterator<T, Elem, Traits> >      : public output_iterator<ostream_iterator<T, Elem, Traits>, int>    {    private:        typedef             output_iterator<ostream_iterator<T, Elem, Traits>, int>         base_type;        typedef ostream_iterator<T, Elem, Traits> base_iterator_type;        typedef std::basic_ostream<Elem, Traits> ostream_type;    public:        output_iterator(base_iterator_type& sink)          : base_type(sink)        {}        ostream_type& get_ostream() { return this->sink.get_ostream(); }    };    ///////////////////////////////////////////////////////////////////////////    //  Helper class for exception safe enabling of character counting in the    //  output iterator    ///////////////////////////////////////////////////////////////////////////    template <typename OutputIterator>    struct enable_counting    {        enable_counting(OutputIterator& sink_, std::size_t count = 0)          : sink(sink_)        {            sink.enable_counting(count);        }        ~enable_counting()        {            sink.disable_counting();            sink.reset_counting();        }                void disable()        {            sink.disable_counting();        }        OutputIterator& sink;    };        ///////////////////////////////////////////////////////////////////////////    //  Helper class for exception safe enabling of character buffering in the    //  output iterator    ///////////////////////////////////////////////////////////////////////////    template <typename OutputIterator>    struct enable_buffering    {        enable_buffering(OutputIterator& sink_, std::size_t width = 0)          : sink(sink_)        {            sink.enable_buffering(width);        }        ~enable_buffering()        {            sink.disable_buffering();            sink.reset_buffering();        }                void disable()        {            sink.disable_buffering();        }                OutputIterator& sink;    };    }}}}#endif 

⌨️ 快捷键说明

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