$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r55034 - in trunk/boost/spirit/home/karma: . detail directive operator
From: hartmut.kaiser_at_[hidden]
Date: 2009-07-19 22:38:29
Author: hkaiser
Date: 2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
New Revision: 55034
URL: http://svn.boost.org/trac/boost/changeset/55034
Log:
Spirit: improving overall performance
Text files modified: 
   trunk/boost/spirit/home/karma/detail/output_iterator.hpp     |    97 ++++++++++++++++++++++++++++++--------- 
   trunk/boost/spirit/home/karma/directive/center_alignment.hpp |     1                                         
   trunk/boost/spirit/home/karma/directive/left_alignment.hpp   |     1                                         
   trunk/boost/spirit/home/karma/directive/maxwidth.hpp         |     5 +                                       
   trunk/boost/spirit/home/karma/directive/repeat.hpp           |    22 +++++---                                
   trunk/boost/spirit/home/karma/directive/right_alignment.hpp  |     1                                         
   trunk/boost/spirit/home/karma/generate.hpp                   |    12 ++++                                    
   trunk/boost/spirit/home/karma/generator.hpp                  |     7 ++                                      
   trunk/boost/spirit/home/karma/operator/alternative.hpp       |     2                                         
   trunk/boost/spirit/home/karma/operator/and_predicate.hpp     |     1                                         
   trunk/boost/spirit/home/karma/operator/not_predicate.hpp     |     1                                         
   trunk/boost/spirit/home/karma/operator/sequence.hpp          |    23 +++++++++                               
   12 files changed, 139 insertions(+), 34 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/output_iterator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/output_iterator.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/output_iterator.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -236,25 +236,6 @@
     class output_iterator : boost::noncopyable
     {
     private:
-        struct output_proxy 
-        {
-            output_proxy(output_iterator& parent) 
-              : parent(parent) 
-            {}
-
-            template <typename T> 
-            void operator=(T const& value) 
-            {
-                parent.output(value);
-            }
-
-        private:
-            output_iterator& parent;
-
-            // suppress warning about assignment operator not being generated
-            output_proxy& operator=(output_proxy const&);
-        };
-
         // get the most derived type of this class
         typedef typename mpl::if_<
             traits::is_not_unused<Derived>, Derived, output_iterator
@@ -296,7 +277,7 @@
           , track_position_data(rhs.track_position_data)
         {}
 
-        output_proxy operator*() { return output_proxy(*this); }
+        output_iterator& operator*() { return *this; }
         output_iterator& operator++() 
         { 
             if (NULL == buffer)
@@ -313,8 +294,8 @@
             return *this;
         }
 
-        template <typename T> 
-        void output(T const& value) 
+        template <typename T>
+        output_iterator& operator=(T const& value) 
         { 
             if (NULL != count)          // count characters, if appropriate
                 count->output();
@@ -327,6 +308,8 @@
                 buffer->output(value);
             else
                 *sink = value; 
+
+            return *this;
         }
 
         // return the current count in the output
@@ -376,6 +359,76 @@
         bool good() const { return this->sink.get_ostream().good(); }
     };
 
+//     ///////////////////////////////////////////////////////////////////////////
+//     template <typename OutputIterator, typename Derived = unused_type>
+//     class plain_output_iterator : boost::noncopyable
+//     {
+//     private:
+//         // get the most derived type of this class
+//         typedef typename mpl::if_<
+//             traits::is_not_unused<Derived>, Derived, plain_output_iterator
+//         >::type most_derived_type;
+// 
+//     public:
+//         typedef std::output_iterator_tag iterator_category;
+//         typedef void value_type;
+//         typedef void difference_type;
+//         typedef void pointer;
+//         typedef void reference;
+// 
+//         explicit plain_output_iterator(OutputIterator& sink_)
+//           : sink(sink_)
+//         {}
+//         plain_output_iterator(plain_output_iterator const& rhs)
+//           : sink(rhs.sink)
+//           , track_position_data(rhs.track_position_data)
+//         {}
+// 
+//         plain_output_iterator& operator*() { return *this; }
+// 
+//         template <typename T>
+//         plain_output_iterator& operator=(T const& value) 
+//         { 
+//             // always track position in the output (this is needed by different 
+//             // generators, such as indent, pad, etc.)
+//             track_position_data.output(value);
+// 
+//             // output value by forwarding to the underlying iterator
+//             *sink = value; 
+//             return *this; 
+//         }
+//         plain_output_iterator& operator++() 
+//         { 
+//             ++sink;
+//             return *this; 
+//         } 
+//         plain_output_iterator operator++(int) 
+//         {
+//             plain_output_iterator t(*this);
+//             ++sink; 
+//             return t; 
+//         }
+// 
+//         // return the current count in the output
+//         std::size_t get_out_count() const
+//         {
+//             return track_position_data.get_count();
+//         }
+// 
+//         // plain output iterators are considered to be good all the time
+//         bool good() const { return true; }
+// 
+//     protected:
+//         // this is the wrapped user supplied output iterator
+//         OutputIterator& sink;
+// 
+//     private:
+//         position_sink track_position_data;            // for position tracking
+// 
+//         // suppress warning about assignment operator not being generated
+//         plain_output_iterator& operator=(plain_output_iterator const&);
+//     };
+
     ///////////////////////////////////////////////////////////////////////////
     //  Helper class for exception safe enabling of character counting in the
     //  output iterator
Modified: trunk/boost/spirit/home/karma/directive/center_alignment.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/center_alignment.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/center_alignment.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -128,6 +128,7 @@
     struct simple_center_alignment
       : unary_generator<simple_center_alignment<Subject, Width> >
     {
+        typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
         template <typename Context, typename Unused>
Modified: trunk/boost/spirit/home/karma/directive/left_alignment.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/left_alignment.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/left_alignment.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -111,6 +111,7 @@
     struct simple_left_alignment 
       : unary_generator<simple_left_alignment<Subject, Width> >
     {
+        typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
         template <typename Context, typename Unused>
Modified: trunk/boost/spirit/home/karma/directive/maxwidth.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/maxwidth.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/maxwidth.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -110,11 +110,11 @@
             // maxwidth
             bool r = false;
 
-            {            
+            {
                 detail::disable_counting<OutputIterator> nocounting(sink);
                 r = e.generate(sink, ctx, d, attr);
             }   // re-enable counting
-            
+
             return r && buffering.buffer_copy(maxwidth) &&
                    buffer_copy_rest(buffering, maxwidth, restdest);
         }
@@ -133,6 +133,7 @@
     struct maxwidth_width
       : unary_generator<maxwidth_width<Subject, Width, Rest> >
     {
+        typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
         template <typename Context, typename Unused>
Modified: trunk/boost/spirit/home/karma/directive/repeat.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/repeat.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/repeat.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -124,6 +124,7 @@
     struct repeat_generator 
       : unary_generator<repeat_generator<Subject, LoopIter> >
     {
+        typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
         template <typename Context, typename Unused>
@@ -158,19 +159,22 @@
             {
                 // inhibit (redirect) output, disable counting while buffering
                 detail::enable_buffering<OutputIterator> buffering(sink);
-                detail::disable_counting<OutputIterator> nocounting(sink);
 
-                // generate the minimal required amount of output
-                for (/**/; !iter.got_min(i); ++i, traits::next(it))
                 {
-                    if (traits::compare(it, end) ||
-                        !subject.generate(sink, ctx, d, traits::deref(it)))
+                    detail::disable_counting<OutputIterator> nocounting(sink);
+
+                    // generate the minimal required amount of output
+                    for (/**/; !iter.got_min(i); ++i, traits::next(it))
                     {
-                        // if we fail before reaching the minimum iteration
-                        // required, do not output anything and return false
-                        return false;
+                        if (traits::compare(it, end) ||
+                            !subject.generate(sink, ctx, d, traits::deref(it)))
+                        {
+                            // if we fail before reaching the minimum iteration
+                            // required, do not output anything and return false
+                            return false;
+                        }
                     }
-                }
+                }   // re-enable counting
 
                 // copy the output generated so far to the target output iterator
                 buffering.buffer_copy();
Modified: trunk/boost/spirit/home/karma/directive/right_alignment.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/right_alignment.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/right_alignment.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -121,6 +121,7 @@
     struct simple_right_alignment 
       : unary_generator<simple_right_alignment<Subject, Width> >
     {
+        typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
         template <typename Context, typename Unused>
Modified: trunk/boost/spirit/home/karma/generate.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/generate.hpp	(original)
+++ trunk/boost/spirit/home/karma/generate.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -40,7 +40,17 @@
         // then the expression (expr) is not a valid spirit karma expression.
         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
 
-        // wrap user supplied iterator into our own output iterator
+//         typedef typename result_of::compile<
+//             karma::domain, Expr, unused_type
+//         >::type generator;
+// 
+//         // wrap user supplied iterator into our own output iterator
+//         typedef typename mpl::if_<
+//             traits::requires_buffering<generator>
+//           , detail::output_iterator<OutputIterator>
+//           , detail::plain_output_iterator<OutputIterator>
+//         >::type output_iterator;
+
         detail::output_iterator<OutputIterator> sink(target_sink);
         return compile<karma::domain>(expr).generate(sink, unused, unused, unused);
     }
Modified: trunk/boost/spirit/home/karma/generator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/generator.hpp	(original)
+++ trunk/boost/spirit/home/karma/generator.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -20,6 +20,7 @@
     struct generator
     {
         struct generator_id;
+        typedef mpl::false_ requires_buffering;
         typedef Derived derived_type;
         typedef karma::domain domain;
 
@@ -110,6 +111,7 @@
 {
     namespace detail
     {
+        // generator tags
         BOOST_MPL_HAS_XXX_TRAIT_DEF(generator_id)
         BOOST_MPL_HAS_XXX_TRAIT_DEF(primitive_generator_id)
         BOOST_MPL_HAS_XXX_TRAIT_DEF(nary_generator_id)
@@ -117,6 +119,7 @@
         BOOST_MPL_HAS_XXX_TRAIT_DEF(binary_generator_id)
     }
 
+    // check for generator tags
     template <typename T>
     struct is_generator : detail::has_generator_id<T> {};
 
@@ -132,6 +135,10 @@
     template <typename T>
     struct is_binary_generator : detail::has_binary_generator_id<T> {};
 
+    // check for generator properties
+    template <typename T>
+    struct requires_buffering : T::requires_buffering {};
+
 }}}
 
 #endif
Modified: trunk/boost/spirit/home/karma/operator/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/alternative.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/alternative.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -43,6 +43,8 @@
     template <typename Elements>
     struct alternative : nary_generator<alternative<Elements> >
     {
+        typedef mpl::true_ requires_buffering;
+
         template <typename Context, typename Unused = unused_type>
         struct attribute
         {
Modified: trunk/boost/spirit/home/karma/operator/and_predicate.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/and_predicate.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/and_predicate.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -34,6 +34,7 @@
     template <typename Subject>
     struct and_predicate : unary_generator<and_predicate<Subject> >
     {
+        typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
         template <typename Context, typename Iterator>
Modified: trunk/boost/spirit/home/karma/operator/not_predicate.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/not_predicate.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/not_predicate.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -34,6 +34,7 @@
     template <typename Subject>
     struct not_predicate : unary_generator<not_predicate<Subject> >
     {
+        typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
         template <typename Context, typename Iterator>
Modified: trunk/boost/spirit/home/karma/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/sequence.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/sequence.hpp	2009-07-19 22:38:27 EDT (Sun, 19 Jul 2009)
@@ -27,7 +27,9 @@
 #include <boost/fusion/include/for_each.hpp>
 #include <boost/type_traits/is_same.hpp>
 #include <boost/mpl/not.hpp>
+#include <boost/mpl/find_if.hpp>
 
+///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit
 {
     ///////////////////////////////////////////////////////////////////////////
@@ -44,11 +46,32 @@
 }}
 
 ///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace traits
+{
+    // specialization for sequences
+    template <typename Sequence>
+    struct sequence_requires_buffering
+    {
+        typedef typename mpl::find_if<
+            Sequence, requires_buffering<mpl::_1>
+        >::type iterator;
+
+        typedef typename mpl::not_<
+            is_same<iterator, typename mpl::end<Sequence>::type>
+        >::type type;
+    };
+
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
     template <typename Elements>
     struct sequence : nary_generator<sequence<Elements> >
     {
+        typedef typename traits::sequence_requires_buffering<Elements>::type 
+            requires_buffering;
+
         sequence(Elements const& elements)
           : elements(elements) {}