$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r55064 - in trunk/boost/spirit/home/karma: . action auxiliary binary detail directive nonterminal operator stream
From: hartmut.kaiser_at_[hidden]
Date: 2009-07-21 10:42:59
Author: hkaiser
Date: 2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
New Revision: 55064
URL: http://svn.boost.org/trac/boost/changeset/55064
Log:
Spirit: Added output iterator composition
Text files modified: 
   trunk/boost/spirit/home/karma/action/action.hpp               |     5                                         
   trunk/boost/spirit/home/karma/auxiliary/eps.hpp               |     2                                         
   trunk/boost/spirit/home/karma/auxiliary/lazy.hpp              |     4                                         
   trunk/boost/spirit/home/karma/binary/binary.hpp               |     2                                         
   trunk/boost/spirit/home/karma/binary/padding.hpp              |     5                                         
   trunk/boost/spirit/home/karma/detail/alternative_function.hpp |     5                                         
   trunk/boost/spirit/home/karma/detail/output_iterator.hpp      |   321 +++++++++++++++++++++++---------------- 
   trunk/boost/spirit/home/karma/detail/string_generate.hpp      |    51 +++--                                   
   trunk/boost/spirit/home/karma/directive/center_alignment.hpp  |    10 +                                       
   trunk/boost/spirit/home/karma/directive/delimit.hpp           |     4                                         
   trunk/boost/spirit/home/karma/directive/left_alignment.hpp    |    10 +                                       
   trunk/boost/spirit/home/karma/directive/maxwidth.hpp          |     6                                         
   trunk/boost/spirit/home/karma/directive/repeat.hpp            |     5                                         
   trunk/boost/spirit/home/karma/directive/right_alignment.hpp   |    10 +                                       
   trunk/boost/spirit/home/karma/directive/verbatim.hpp          |     1                                         
   trunk/boost/spirit/home/karma/generate.hpp                    |    66 +++++--                                 
   trunk/boost/spirit/home/karma/generate_attr.hpp               |    39 +++                                     
   trunk/boost/spirit/home/karma/generator.hpp                   |    20 ++                                      
   trunk/boost/spirit/home/karma/nonterminal/grammar.hpp         |     4                                         
   trunk/boost/spirit/home/karma/nonterminal/rule.hpp            |     6                                         
   trunk/boost/spirit/home/karma/operator/alternative.hpp        |     2                                         
   trunk/boost/spirit/home/karma/operator/and_predicate.hpp      |     4                                         
   trunk/boost/spirit/home/karma/operator/kleene.hpp             |     1                                         
   trunk/boost/spirit/home/karma/operator/list.hpp               |     4                                         
   trunk/boost/spirit/home/karma/operator/not_predicate.hpp      |     5                                         
   trunk/boost/spirit/home/karma/operator/optional.hpp           |     1                                         
   trunk/boost/spirit/home/karma/operator/plus.hpp               |     1                                         
   trunk/boost/spirit/home/karma/operator/sequence.hpp           |    52 +++--                                   
   trunk/boost/spirit/home/karma/reference.hpp                   |     2                                         
   trunk/boost/spirit/home/karma/stream/format_manip.hpp         |     5                                         
   trunk/boost/spirit/home/karma/stream/stream.hpp               |    14                                         
   31 files changed, 433 insertions(+), 234 deletions(-)
Modified: trunk/boost/spirit/home/karma/action/action.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/action/action.hpp	(original)
+++ trunk/boost/spirit/home/karma/action/action.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -33,6 +33,9 @@
     template <typename Subject, typename Action>
     struct action : unary_generator<action<Subject, Action> >
     {
+        typedef Subject subject_type;
+        typedef typename subject_type::properties properties;
+
         template <typename Context, typename Unused>
         struct attribute
           : traits::attribute_of<Subject, Context, Unused>
@@ -69,7 +72,7 @@
             return subject.what(context);
         }
 
-        Subject subject;
+        subject_type subject;
         Action f;
     };
 
Modified: trunk/boost/spirit/home/karma/auxiliary/eps.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auxiliary/eps.hpp	(original)
+++ trunk/boost/spirit/home/karma/auxiliary/eps.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -68,7 +68,7 @@
         }
     };
 
-    struct semantic_predicate
+    struct semantic_predicate : primitive_generator<semantic_predicate>
     {
         template <typename Context, typename Unused>
         struct attribute
Modified: trunk/boost/spirit/home/karma/auxiliary/lazy.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auxiliary/lazy.hpp	(original)
+++ trunk/boost/spirit/home/karma/auxiliary/lazy.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -47,6 +47,8 @@
     template <typename Function, typename Modifiers>
     struct lazy_generator : generator<lazy_generator<Function, Modifiers> >
     {
+        typedef mpl::int_<generator_properties::all_properties> properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
@@ -108,6 +110,8 @@
     struct lazy_directive 
       : unary_generator<lazy_directive<Function, Subject, Modifiers> >
     {
+        typedef mpl::int_<generator_properties::all_properties> properties;
+
         typedef Subject subject_type;
 
         template <typename Context, typename Unused>
Modified: trunk/boost/spirit/home/karma/binary/binary.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/binary/binary.hpp	(original)
+++ trunk/boost/spirit/home/karma/binary/binary.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -223,7 +223,7 @@
     template <BOOST_SCOPED_ENUM(boost::integer::endianness) endian, int bits
       , bool no_attribute>
     struct literal_binary_generator
-      : primitive_generator<literal_binary_generator<endian, bits> >
+      : primitive_generator<literal_binary_generator<endian, bits, no_attribute> >
     {
         typedef boost::integer::endian<
             endian, typename karma::detail::integer<bits>::type, bits
Modified: trunk/boost/spirit/home/karma/binary/padding.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/binary/padding.hpp	(original)
+++ trunk/boost/spirit/home/karma/binary/padding.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -44,8 +44,11 @@
     using boost::spirit::pad;
     using boost::spirit::pad_type;
 
-    struct binary_padding_generator
+    struct binary_padding_generator 
+      : primitive_generator<binary_padding_generator>
     {
+        typedef mpl::int_<generator_properties::tracking> properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
Modified: trunk/boost/spirit/home/karma/detail/alternative_function.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/alternative_function.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/alternative_function.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -21,6 +21,7 @@
 #include <boost/mpl/distance.hpp>
 #include <boost/mpl/or.hpp>
 #include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
 #include <boost/variant.hpp>
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -32,7 +33,9 @@
     ///////////////////////////////////////////////////////////////////////////
     template <typename Expected, typename Attribute, typename IsNotVariant>
     struct compute_compatible_component_variant
-      : mpl::or_<is_same<Expected, Attribute>, is_same<Expected, hold_any> > {};
+      : mpl::or_<
+          is_convertible<Attribute, Expected>
+        , is_same<hold_any, Expected> > {};
 
     template <typename Expected, typename Attribute>
     struct compute_compatible_component_variant<Expected, Attribute, mpl::false_>
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -55,6 +55,39 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    struct position_policy
+    {
+        position_policy() {}
+        position_policy(position_policy const& rhs) 
+          : track_position_data(rhs.track_position_data) {}
+
+        template <typename T>
+        void output(T const& value) 
+        { 
+            // track position in the output 
+            track_position_data.output(value);
+        }
+
+        // return the current count in the output
+        std::size_t get_out_count() const
+        {
+            return track_position_data.get_count();
+        }
+
+    private:
+        position_sink track_position_data;            // for position tracking
+    };
+
+    struct no_position_policy
+    {
+        no_position_policy() {}
+        no_position_policy(no_position_policy const& rhs) {}
+
+        template <typename T>
+        void output(T const& value) {}
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
     //  This class is used to count the number of characters streamed into the 
     //  output.
     ///////////////////////////////////////////////////////////////////////////
@@ -95,6 +128,44 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    template <typename OutputIterator>
+    struct counting_policy
+    {
+    public:
+        counting_policy() : count(NULL) {}
+        counting_policy(counting_policy const& rhs) : count(rhs.count) {}
+
+        // functions related to counting
+        counting_sink<OutputIterator>* chain_counting(
+            counting_sink<OutputIterator>* count_data)
+        {
+            counting_sink<OutputIterator>* prev_count = count;
+            count = count_data;
+            return prev_count;
+        }
+
+        template <typename T>
+        void output(T const&) 
+        { 
+            // count characters, if appropriate
+            if (NULL != count)
+                count->output();
+        }
+
+    private:
+        counting_sink<OutputIterator>* count;      // for counting
+    };
+
+    struct no_counting_policy
+    {
+        no_counting_policy() {}
+        no_counting_policy(no_counting_policy const& rhs) {}
+
+        template <typename T>
+        void output(T const& value) {}
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
     //  The following classes are used to intercept the output into a buffer
     //  allowing to do things like alignment, character escaping etc.
     //
@@ -216,9 +287,107 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    template <typename OutputIterator>
+    struct buffering_policy
+    {
+    public:
+        buffering_policy() : buffer(NULL) {}
+        buffering_policy(buffering_policy const& rhs) : buffer(rhs.buffer) {}
+
+        // functions related to counting
+        buffer_sink<OutputIterator>* chain_buffering(
+            buffer_sink<OutputIterator>* buffer_data)
+        {
+            buffer_sink<OutputIterator>* prev_buffer = buffer;
+            buffer = buffer_data;
+            return prev_buffer;
+        }
+
+        template <typename T>
+        void output(T const& value) 
+        { 
+            // count characters, if appropriate
+            if (NULL != buffer) 
+                buffer->output(value);
+        }
+
+        bool has_buffer() const { return NULL != buffer; }
+
+    private:
+        buffer_sink<OutputIterator>* buffer;
+    };
+
+    struct no_buffering_policy
+    {
+        no_buffering_policy() {}
+        no_buffering_policy(no_counting_policy const& rhs) {}
+
+        template <typename T>
+        void output(T const& value) {}
+
+        bool has_buffer() const { return false; }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
     //  forward declaration only
+    template <typename OutputIterator> 
+    struct enable_buffering;
+
+    template <typename OutputIterator, typename Properties
+      , typename Derived = unused_type>
+    class output_iterator;
+
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator> struct enable_buffering;
+    template <typename Buffering, typename Counting, typename Tracking>
+    struct output_iterator_base : Buffering, Counting, Tracking
+    {
+        typedef Buffering buffering_policy;
+        typedef Counting counting_policy;
+        typedef Tracking tracking_policy;
+
+        output_iterator_base() {}
+        output_iterator_base(output_iterator_base const& rhs) 
+          : buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
+        {}
+
+        template <typename T>
+        void output(T const& value) 
+        { 
+            this->counting_policy::output(value);
+            this->tracking_policy::output(value);
+            this->buffering_policy::output(value);
+        }
+    };
+
+    template <typename OutputIterator, typename Properties, typename Derived>
+    struct make_output_iterator
+    {
+        // get the most derived type of this class
+        typedef typename mpl::if_<
+            traits::is_not_unused<Derived>, Derived
+          , output_iterator<OutputIterator, Properties, Derived>
+        >::type most_derived_type;
+
+        enum { properties = Properties::value };
+
+        typedef typename mpl::if_c<
+            properties & generator_properties::tracking ? true : false
+          , position_policy, no_position_policy
+        >::type tracking_type;
+
+        typedef typename mpl::if_c<
+            properties & generator_properties::buffering ? true : false
+          , buffering_policy<most_derived_type>, no_buffering_policy
+        >::type buffering_type;
+
+        typedef typename mpl::if_c<
+            properties & generator_properties::counting ? true : false
+          , counting_policy<most_derived_type>, no_counting_policy
+        >::type counting_type;
+
+        typedef output_iterator_base<
+            buffering_type, counting_type, tracking_type> type;
+    };
 
     ///////////////////////////////////////////////////////////////////////////
     //  Karma uses an output iterator wrapper for all output operations. This
@@ -232,33 +401,15 @@
     //  supplied iterator. But it is possible to enable additional functionality
     //  on demand, such as counting, buffering, and position tracking.
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator, typename Derived = unused_type>
-    class output_iterator : boost::noncopyable
+    template <typename OutputIterator, typename Properties, typename Derived>
+    class output_iterator 
+      : public make_output_iterator<OutputIterator, Properties, Derived>::type
+      , boost::noncopyable
     {
     private:
-        // get the most derived type of this class
-        typedef typename mpl::if_<
-            traits::is_not_unused<Derived>, Derived, output_iterator
-        >::type most_derived_type;
-
-    public:
-        // functions related to counting
-        counting_sink<most_derived_type>* chain_counting(
-            counting_sink<most_derived_type>* count_data)
-        {
-            counting_sink<most_derived_type>* prev_count = count;
-            count = count_data;
-            return prev_count;
-        }
-
-        // functions related to buffering
-        buffer_sink<most_derived_type>* chain_buffering(
-            buffer_sink<most_derived_type>* buffer_data)
-        {
-            buffer_sink<most_derived_type>* prev_buffer = buffer;
-            buffer = buffer_data;
-            return prev_buffer;
-        }
+        // base iterator type
+        typedef typename make_output_iterator<
+            OutputIterator, Properties, Derived>::type base_iterator;
 
     public:
         typedef std::output_iterator_tag iterator_category;
@@ -269,24 +420,21 @@
 
         explicit output_iterator(OutputIterator& sink_)
           : sink(sink_)
-          , count(NULL), buffer(NULL)
         {}
         output_iterator(output_iterator const& rhs)
-          : sink(rhs.sink)
-          , count(rhs.count), buffer(rhs.buffer)
-          , track_position_data(rhs.track_position_data)
+          : sink(rhs.sink), base_iterator(rhs)
         {}
 
         output_iterator& operator*() { return *this; }
         output_iterator& operator++() 
         { 
-            if (NULL == buffer)
+            if (!this->base_iterator::has_buffer())
                 ++sink;           // increment only if not buffering
             return *this; 
         } 
         output_iterator operator++(int) 
         {
-            if (NULL == buffer) {
+            if (!this->base_iterator::has_buffer()) {
                 output_iterator t(*this);
                 ++sink; 
                 return t; 
@@ -295,27 +443,11 @@
         }
 
         template <typename T>
-        output_iterator& operator=(T const& value) 
+        void operator=(T const& value) 
         { 
-            if (NULL != count)          // count characters, if appropriate
-                count->output();
-
-            // always track position in the output (this is needed by different 
-            // generators, such as indent, pad, etc.)
-            track_position_data.output(value);
-
-            if (NULL != buffer)         // buffer output, if appropriate
-                buffer->output(value);
-            else
+            this->base_iterator::output(value);
+            if (!this->base_iterator::has_buffer())
                 *sink = value; 
-
-            return *this;
-        }
-
-        // 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
@@ -326,24 +458,19 @@
         OutputIterator& sink;
 
     private:
-        // these are the hooks providing optional functionality
-        counting_sink<most_derived_type>* count;      // for counting
-        buffer_sink<most_derived_type>* buffer;       // for buffering
-        position_sink track_position_data;            // for position tracking
-
         // 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>
-          , output_iterator<ostream_iterator<T, Elem, Traits> > >
+    template <typename T, typename Elem, typename Traits, typename Properties>
+    class output_iterator<ostream_iterator<T, Elem, Traits>, Properties>
+      : public output_iterator<ostream_iterator<T, Elem, Traits>, Properties
+          , output_iterator<ostream_iterator<T, Elem, Traits>, Properties> >
     {
     private:
-        typedef output_iterator<ostream_iterator<T, Elem, Traits>
-              , output_iterator<ostream_iterator<T, Elem, Traits> > 
+        typedef output_iterator<ostream_iterator<T, Elem, Traits>, Properties
+          , output_iterator<ostream_iterator<T, Elem, Traits>, Properties> 
         > base_type;
         typedef ostream_iterator<T, Elem, Traits> base_iterator_type;
         typedef std::basic_ostream<Elem, Traits> ostream_type;
@@ -359,76 +486,6 @@
         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/detail/string_generate.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/string_generate.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/string_generate.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -24,61 +24,64 @@
     {
         for (Char ch = *str; ch != 0; ch = *++str)
         {
-            if (!detail::generate_to(sink, ch))
-                return false;
+            *sink = ch;
+            ++sink;
         }
-        return true;
+        return detail::sink_is_good(sink);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     //  generate a string given by a std::string
-    template <
-        typename OutputIterator, typename Char, typename Traits
+    template <typename OutputIterator, typename Char, typename Traits
       , typename Allocator>
     inline bool string_generate(OutputIterator& sink
       , std::basic_string<Char, Traits, Allocator> const& str)
     {
-        BOOST_FOREACH(Char ch, str)
-        {
-            if (!detail::generate_to(sink, ch))
-                return false;
-        }
-        return true;
+        return string_generate(sink, str.c_str());
     }
 
     ///////////////////////////////////////////////////////////////////////////
     //  generate a string given by a pointer, converting according using a 
     //  given character class and case tag
-    template <
-        typename OutputIterator, typename Char, typename CharEncoding
+    template <typename OutputIterator, typename Char, typename CharEncoding
       , typename Tag>
     inline bool string_generate(OutputIterator& sink, Char const* str
       , CharEncoding ce, Tag tag)
     {
         for (Char ch = *str; ch != 0; ch = *++str)
         {
-            if (!detail::generate_to(sink, ch, ce, tag))
-                return false;
+            *sink = spirit::char_class::convert<CharEncoding>::to(Tag(), ch);
+            ++sink;
         }
-        return true;
+        return detail::sink_is_good(sink);
+    }
+
+    template <typename OutputIterator, typename Char>
+    inline bool string_generate(OutputIterator& sink, Char const* str
+      , unused_type, unused_type)
+    {
+        return string_generate(sink, str);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     //  generate a string given by a std::string, converting according using a 
     //  given character class and case tag
-    template <
-        typename OutputIterator, typename Char, typename CharEncoding
+    template <typename OutputIterator, typename Char, typename CharEncoding
       , typename Tag, typename Traits, typename Allocator>
     inline bool string_generate(OutputIterator& sink
       , std::basic_string<Char, Traits, Allocator> const& str
       , CharEncoding ce, Tag tag)
     {
-        BOOST_FOREACH(Char ch, str)
-        {
-            if (!detail::generate_to(sink, ch, ce, tag))
-                return false;
-        }
-        return true;
+        return string_generate(sink, str.c_str(), ce, tag);
+    }
+
+    template <typename OutputIterator, typename Char, typename Traits
+      , typename Allocator>
+    inline bool string_generate(OutputIterator& sink
+      , std::basic_string<Char, Traits, Allocator> const& str
+      , unused_type, unused_type)
+    {
+        return string_generate(sink, str.c_str());
     }
 
 }}}}
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -128,9 +128,12 @@
     struct simple_center_alignment
       : unary_generator<simple_center_alignment<Subject, Width> >
     {
-//         typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
+        typedef mpl::int_<
+            generator_properties::countingbuffer | subject_type::properties::value
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
@@ -175,6 +178,11 @@
         typedef Subject subject_type;
         typedef Padding padding_type;
 
+        typedef mpl::int_<
+            generator_properties::countingbuffer |
+            subject_type::properties::value | padding_type::properties::value 
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
Modified: trunk/boost/spirit/home/karma/directive/delimit.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/delimit.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/delimit.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -58,6 +58,8 @@
     {
         typedef Subject subject_type;
 
+        typedef typename subject_type::properties properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
@@ -102,6 +104,8 @@
         typedef Subject subject_type;
         typedef Delimiter delimiter_type;
 
+        typedef typename subject_type::properties properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -111,9 +111,12 @@
     struct simple_left_alignment 
       : unary_generator<simple_left_alignment<Subject, Width> >
     {
-//         typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
+        typedef mpl::int_<
+            generator_properties::counting | subject_type::properties::value
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
@@ -158,6 +161,11 @@
         typedef Subject subject_type;
         typedef Padding padding_type;
 
+        typedef mpl::int_<
+            generator_properties::counting | 
+            subject_type::properties::value | padding_type::properties::value 
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -109,7 +109,6 @@
             // output to the target output iterator applying the given 
             // maxwidth
             bool r = false;
-
             {
                 detail::disable_counting<OutputIterator> nocounting(sink);
                 r = e.generate(sink, ctx, d, attr);
@@ -133,9 +132,12 @@
     struct maxwidth_width
       : unary_generator<maxwidth_width<Subject, Width, Rest> >
     {
-//         typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
+        typedef mpl::int_<
+            generator_properties::countingbuffer | subject_type::properties::value
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -124,9 +124,12 @@
     struct repeat_generator 
       : unary_generator<repeat_generator<Subject, LoopIter> >
     {
-//         typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
+        typedef mpl::int_<
+            generator_properties::countingbuffer | subject_type::properties::value
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -121,9 +121,12 @@
     struct simple_right_alignment 
       : unary_generator<simple_right_alignment<Subject, Width> >
     {
-//         typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
+        typedef mpl::int_<
+            generator_properties::countingbuffer | subject_type::properties::value
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
@@ -168,6 +171,11 @@
         typedef Subject subject_type;
         typedef Padding padding_type;
 
+        typedef mpl::int_<
+            generator_properties::countingbuffer |
+            subject_type::properties::value | padding_type::properties::value 
+        > properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
Modified: trunk/boost/spirit/home/karma/directive/verbatim.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/verbatim.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/verbatim.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -44,6 +44,7 @@
     struct verbatim_generator : unary_generator<verbatim_generator<Subject> >
     {
         typedef Subject subject_type;
+        typedef typename subject_type::properties properties;
 
         template <typename Context, typename Unused>
         struct attribute
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -40,25 +40,20 @@
         // then the expression (expr) is not a valid spirit karma expression.
         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
 
-//         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;
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Expr>::type
+        > properties;
 
-        detail::output_iterator<OutputIterator> sink(target_sink);
+        // wrap user supplied iterator into our own output iterator
+        detail::output_iterator<OutputIterator
+          , mpl::int_<properties::value> > sink(target_sink);
         return compile<karma::domain>(expr).generate(sink, unused, unused, unused);
     }
 
-    template <typename OutputIterator, typename Expr>
+    template <typename OutputIterator, typename Properties, typename Expr>
     inline bool
     generate(
-        detail::output_iterator<OutputIterator>& sink
+        detail::output_iterator<OutputIterator, Properties>& sink
       , Expr const& expr)
     {
         // Report invalid expression error as early as possible.
@@ -81,15 +76,21 @@
         // then the expression (expr) is not a valid spirit karma expression.
         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
 
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Expr>::type
+        > properties;
+
         // wrap user supplied iterator into our own output iterator
-        detail::output_iterator<OutputIterator> sink(target_sink);
+        detail::output_iterator<OutputIterator
+          , mpl::int_<properties::value> > sink(target_sink);
         return compile<karma::domain>(expr).generate(sink, unused, unused, attr);
     }
 
-    template <typename OutputIterator, typename Expr, typename Attr>
+    template <typename OutputIterator, typename Properties, typename Expr
+      , typename Attr>
     inline bool
     generate(
-        detail::output_iterator<OutputIterator>& sink
+        detail::output_iterator<OutputIterator, Properties>& sink
       , Expr const& expr
       , Attr const& attr)
     {
@@ -101,10 +102,11 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator, typename Expr, typename Delimiter>
+    template <typename OutputIterator, typename Properties, typename Expr
+      , typename Delimiter>
     inline bool
     generate_delimited(
-        detail::output_iterator<OutputIterator>& sink
+        detail::output_iterator<OutputIterator, Properties>& sink
       , Expr const& expr
       , Delimiter const& delimiter
       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit = 
@@ -139,17 +141,26 @@
       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit = 
             delimit_flag::dont_predelimit)
     {
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Expr>::type
+        > properties;
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Delimiter>::type
+        > delimiter_properties;
+
         // wrap user supplied iterator into our own output iterator
-        detail::output_iterator<OutputIterator> sink(target_sink);
+        detail::output_iterator<OutputIterator
+          , mpl::int_<properties::value | delimiter_properties::value>
+        > sink(target_sink);
         return generate_delimited(sink, expr, delimiter, pre_delimit);
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator, typename Expr, typename Delimiter
-      , typename Attribute>
+    template <typename OutputIterator, typename Properties, typename Expr
+      , typename Delimiter, typename Attribute>
     inline bool
     generate_delimited(
-        detail::output_iterator<OutputIterator>& sink
+        detail::output_iterator<OutputIterator, Properties>& sink
       , Expr const& expr
       , Delimiter const& delimiter
       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
@@ -186,8 +197,17 @@
       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
       , Attribute const& attr)
     {
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Expr>::type
+        > properties;
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Delimiter>::type
+        > delimiter_properties;
+
         // wrap user supplied iterator into our own output iterator
-        detail::output_iterator<OutputIterator> sink(target_sink);
+        detail::output_iterator<OutputIterator
+          , mpl::int_<properties::value | delimiter_properties::value>
+        > sink(target_sink);
         return generate_delimited(sink, expr, delimiter, pre_delimit, attr);
     }
 
Modified: trunk/boost/spirit/home/karma/generate_attr.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/generate_attr.hpp	(original)
+++ trunk/boost/spirit/home/karma/generate_attr.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -37,11 +37,11 @@
 namespace boost { namespace spirit { namespace karma
 {
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator, typename Expr
+    template <typename OutputIterator, typename Properties, typename Expr
       , BOOST_PP_ENUM_PARAMS(N, typename A)>
     inline bool
     generate(
-        detail::output_iterator<OutputIterator>& sink
+        detail::output_iterator<OutputIterator, Properties>& sink
       , Expr const& expr
       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
     {
@@ -66,17 +66,22 @@
       , Expr const& expr
       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
     {
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Expr>::type
+        > properties;
+
         // wrap user supplied iterator into our own output iterator
-        detail::output_iterator<OutputIterator> sink(target_sink);
+        detail::output_iterator<OutputIterator
+          , mpl::int_<properties::value> > sink(target_sink);
         return generate(sink, expr, BOOST_PP_ENUM_PARAMS(N, attr));
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename OutputIterator, typename Expr, typename Delimiter
-      , BOOST_PP_ENUM_PARAMS(N, typename A)>
+    template <typename OutputIterator, typename Properties, typename Expr
+      , typename Delimiter, BOOST_PP_ENUM_PARAMS(N, typename A)>
     inline bool
     generate_delimited(
-        detail::output_iterator<OutputIterator>& sink
+        detail::output_iterator<OutputIterator, Properties>& sink
       , Expr const& expr
       , Delimiter const& delimiter
       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
@@ -117,8 +122,17 @@
       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
     {
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Expr>::type
+        > properties;
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Delimiter>::type
+        > delimiter_properties;
+
         // wrap user supplied iterator into our own output iterator
-        detail::output_iterator<OutputIterator> sink(target_sink);
+        detail::output_iterator<OutputIterator
+          , mpl::int_<properties::value | delimiter_properties::value>
+        > sink(target_sink);
         return generate_delimited(sink, expr, delimiter, pre_delimit
           , BOOST_PP_ENUM_PARAMS(N, attr));
     }
@@ -132,8 +146,17 @@
       , Delimiter const& delimiter
       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
     {
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Expr>::type
+        > properties;
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Delimiter>::type
+        > delimiter_properties;
+
         // wrap user supplied iterator into our own output iterator
-        detail::output_iterator<OutputIterator> sink(target_sink);
+        detail::output_iterator<OutputIterator
+          , mpl::int_<properties::value | delimiter_properties::value>
+        > sink(target_sink);
         return generate_delimited(sink, expr, delimiter
           , delimit_flag::dont_predelimit, BOOST_PP_ENUM_PARAMS(N, attr));
     }
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -12,15 +12,29 @@
 #endif
 
 #include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
 #include <boost/spirit/home/karma/domain.hpp>
 
 namespace boost { namespace spirit { namespace karma
 {
+    BOOST_SCOPED_ENUM_START(generator_properties) 
+    {
+        no_properties = 0,
+        buffering = 0x01,        // generator requires buffering
+        counting = 0x02,         // generator requires counting
+        tracking = 0x04,         // generator requires position tracking
+
+        countingbuffer = 0x03,   // buffering | counting
+        all_properties = 0x07    // buffering | counting | tracking
+    };
+    BOOST_SCOPED_ENUM_END
+
     template <typename Derived>
     struct generator
     {
         struct generator_id;
-//         typedef mpl::true_ requires_buffering;
+        typedef mpl::int_<generator_properties::no_properties> properties;
         typedef Derived derived_type;
         typedef karma::domain domain;
 
@@ -136,8 +150,8 @@
     struct is_binary_generator : detail::has_binary_generator_id<T> {};
 
     // check for generator properties
-//     template <typename T>
-//     struct requires_buffering : T::requires_buffering {};
+    template <typename T>
+    struct properties : T::properties {};
 
 }}}
 
Modified: trunk/boost/spirit/home/karma/nonterminal/grammar.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/grammar.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal/grammar.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -38,6 +38,7 @@
     {
         typedef OutputIterator iterator_type;
         typedef rule<OutputIterator, T1, T2, T3> start_type;
+        typedef typename start_type::properties properties;
         typedef typename start_type::sig_type sig_type;
         typedef typename start_type::locals_type locals_type;
         typedef typename start_type::delimiter_type delimiter_type;
@@ -47,7 +48,8 @@
         static size_t const params_size = start_type::params_size;
 
         // the output iterator is always wrapped by karma
-        typedef detail::output_iterator<OutputIterator> output_iterator;
+        typedef detail::output_iterator<OutputIterator, properties> 
+            output_iterator;
 
         grammar(start_type const& start
               , std::string const& name_ = "unnamed-grammar")
Modified: trunk/boost/spirit/home/karma/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/rule.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal/rule.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -59,6 +59,8 @@
     template <typename Rule, typename Params>
     struct parameterized_rule : generator<parameterized_rule<Rule, Params> >
     {
+        typedef mpl::int_<generator_properties::all_properties> properties;
+
         parameterized_rule(Rule const& rule, Params const& params)
           : ref(rule), params(params) {}
 
@@ -99,6 +101,7 @@
         >
       , generator<rule<OutputIterator, T1, T2, T3> >
     {
+        typedef mpl::int_<generator_properties::all_properties> properties;
         typedef rule<OutputIterator, T1, T2, T3> this_type;
         typedef reference<this_type const> reference_;
         typedef typename proto::terminal<reference_>::type terminal;
@@ -106,7 +109,8 @@
         typedef mpl::vector<T1, T2, T3> template_params;
 
         // the output iterator is always wrapped by karma
-        typedef detail::output_iterator<OutputIterator> output_iterator;
+        typedef detail::output_iterator<OutputIterator, properties> 
+            output_iterator;
 
         // locals_type is a sequence of types to be used as local variables
         typedef typename fusion::result_of::as_vector<
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -43,7 +43,7 @@
     template <typename Elements>
     struct alternative : nary_generator<alternative<Elements> >
     {
-//         typedef mpl::true_ requires_buffering;
+        typedef mpl::int_<generator_properties::all_properties> properties;
 
         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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -34,8 +34,10 @@
     template <typename Subject>
     struct and_predicate : unary_generator<and_predicate<Subject> >
     {
-//         typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
+        typedef mpl::int_<
+            generator_properties::countingbuffer | subject_type::properties::value
+        > properties;
 
         template <typename Context, typename Iterator>
         struct attribute
Modified: trunk/boost/spirit/home/karma/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/kleene.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/kleene.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -39,6 +39,7 @@
     struct kleene : unary_generator<kleene<Subject> >
     {
         typedef Subject subject_type;
+        typedef typename subject_type::properties properties;
 
         template <typename Context, typename Unused>
         struct attribute
Modified: trunk/boost/spirit/home/karma/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/list.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/list.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -34,6 +34,10 @@
         typedef Left left_type;
         typedef Right right_type;
 
+        typedef mpl::int_<
+            left_type::properties::value | right_type::properties::value
+        > properties;
+
         template <typename Context, typename Iterator>
         struct attribute
         {
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -34,9 +34,12 @@
     template <typename Subject>
     struct not_predicate : unary_generator<not_predicate<Subject> >
     {
-//         typedef mpl::true_ requires_buffering;
         typedef Subject subject_type;
 
+        typedef mpl::int_<
+            generator_properties::countingbuffer | subject_type::properties::value
+        > properties;
+
         template <typename Context, typename Iterator>
         struct attribute
         {
Modified: trunk/boost/spirit/home/karma/operator/optional.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/optional.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/optional.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -80,6 +80,7 @@
     struct optional : unary_generator<optional<Subject> >
     {
         typedef Subject subject_type;
+        typedef typename subject_type::properties properties;
 
         template <typename Context, typename Unused>
         struct attribute
Modified: trunk/boost/spirit/home/karma/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/plus.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/plus.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -39,6 +39,7 @@
     struct plus : unary_generator<plus<Subject> >
     {
         typedef Subject subject_type;
+        typedef typename subject_type::properties properties;
 
         template <typename Context, typename Unused>
         struct attribute
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-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -26,8 +26,10 @@
 #include <boost/fusion/include/as_vector.hpp>
 #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>
+#include <boost/mpl/bitor.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/fusion/include/transform.hpp>
+#include <boost/mpl/accumulate.hpp>
 
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit
@@ -46,22 +48,33 @@
 }}
 
 ///////////////////////////////////////////////////////////////////////////////
-// 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 traits
+{
+    // specialization for sequences
+    template <typename Sequence>
+    struct sequence_properties
+    {
+        struct element_properties
+        {
+            template <typename T>
+            struct result;
+
+            template <typename F, typename Element>
+            struct result<F(Element)>
+            {
+                typedef properties<Element> type;
+            };
+        };
+
+        typedef typename mpl::accumulate<
+            typename fusion::result_of::transform<
+                Sequence, element_properties>::type
+          , mpl::int_<karma::generator_properties::no_properties>
+          , mpl::bitor_<mpl::_2, mpl::_1>
+        >::type type;
+    };
+
+}}}
 
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
@@ -69,8 +82,7 @@
     template <typename Elements>
     struct sequence : nary_generator<sequence<Elements> >
     {
-//         typedef typename traits::sequence_requires_buffering<Elements>::type 
-//             requires_buffering;
+        typedef typename traits::sequence_properties<Elements>::type properties;
 
         sequence(Elements const& elements)
           : elements(elements) {}
Modified: trunk/boost/spirit/home/karma/reference.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/reference.hpp	(original)
+++ trunk/boost/spirit/home/karma/reference.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -24,6 +24,8 @@
     template <typename Subject>
     struct reference : generator<reference<Subject> >
     {
+        typedef mpl::int_<generator_properties::all_properties> properties;
+
         reference(Subject& subject)
           : ref(subject) {}
 
Modified: trunk/boost/spirit/home/karma/stream/format_manip.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/stream/format_manip.hpp	(original)
+++ trunk/boost/spirit/home/karma/stream/format_manip.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -93,10 +93,13 @@
     inline std::basic_ostream<Char, Traits> & 
     operator<< (std::basic_ostream<Char, Traits> &os, generator<Derived> const& g)
     {
+        typedef traits::properties<
+            typename result_of::compile<karma::domain, Derived>::type
+        > properties;
         typedef karma::detail::ostream_iterator<Char, Char, Traits> outiter_type;
 
         outiter_type target_sink(os);
-        karma::detail::output_iterator<outiter_type> sink(target_sink);
+        karma::detail::output_iterator<outiter_type, properties> sink(target_sink);
 
         if (!g.derived().generate(sink, unused, unused, unused))
         {
Modified: trunk/boost/spirit/home/karma/stream/stream.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/stream/stream.hpp	(original)
+++ trunk/boost/spirit/home/karma/stream/stream.hpp	2009-07-21 10:42:55 EDT (Tue, 21 Jul 2009)
@@ -111,16 +111,16 @@
         // this is a special overload to detect if the output iterator has been
         // generated by a format_manip object.
         template <
-            typename T, typename Traits, typename Context, typename Delimiter
-          , typename Attribute
+            typename T, typename Traits, typename Properties, typename Context
+          , typename Delimiter, typename Attribute
         >
         static bool generate(
             karma::detail::output_iterator<
-                karma::detail::ostream_iterator<T, Char, Traits>
+                karma::detail::ostream_iterator<T, Char, Traits>, Properties
             >& sink, Context&, Delimiter const& d, Attribute const& attr)
         {
             typedef karma::detail::output_iterator<
-                karma::detail::ostream_iterator<T, Char, Traits>
+                karma::detail::ostream_iterator<T, Char, Traits>, Properties
             > output_iterator;
             typedef karma::detail::iterator_sink<
                 output_iterator, Char, CharEncoding, Tag
@@ -195,15 +195,15 @@
         // this is a special overload to detect if the output iterator has been
         // generated by a format_manip object.
         template <
-            typename T1, typename Traits
+            typename T1, typename Traits, typename Properties
           , typename Context, typename Delimiter, typename Attribute>
         bool generate(
             karma::detail::output_iterator<
-                karma::detail::ostream_iterator<T1, Char, Traits>
+                karma::detail::ostream_iterator<T1, Char, Traits>, Properties
             >& sink, Context&, Delimiter const& d, Attribute const&)
         {
             typedef karma::detail::output_iterator<
-                karma::detail::ostream_iterator<T1, Char, Traits>
+                karma::detail::ostream_iterator<T1, Char, Traits>, Properties
             > output_iterator;
             typedef karma::detail::iterator_sink<
                 output_iterator, Char, CharEncoding, Tag