$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r53585 - in trunk: boost/spirit/home/karma/detail boost/spirit/home/karma/operator boost/spirit/home/qi/detail boost/spirit/home/support libs/spirit/test/karma
From: hartmut.kaiser_at_[hidden]
Date: 2009-06-02 20:06:00
Author: hkaiser
Date: 2009-06-02 20:05:58 EDT (Tue, 02 Jun 2009)
New Revision: 53585
URL: http://svn.boost.org/trac/boost/changeset/53585
Log:
Spirit: fixed a problem with Karma alternatives
Text files modified: 
   trunk/boost/spirit/home/karma/detail/alternative_function.hpp |    42 +++++++++++++++++++++++++++++++++++---- 
   trunk/boost/spirit/home/karma/operator/sequence.hpp           |    15 ++++++++++++-                           
   trunk/boost/spirit/home/qi/detail/alternative_function.hpp    |    10 --------                                
   trunk/boost/spirit/home/support/attributes.hpp                |     8 +++++++                                 
   trunk/libs/spirit/test/karma/alternative.cpp                  |    10 +++++++++                               
   5 files changed, 69 insertions(+), 16 deletions(-)
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-06-02 20:05:58 EDT (Tue, 02 Jun 2009)
@@ -28,21 +28,38 @@
     //  A component is compatible to a given Attribute type if the Attribute
     //  is the same as the expected type of the component
     ///////////////////////////////////////////////////////////////////////////
+    template <typename Expected, typename Attribute, typename IsNotVariant>
+    struct compute_compatible_component_variant
+    {
+        typedef mpl::int_<-1> distance;
+        typedef typename is_same<Expected, Attribute>::type type;
+        enum { value = type::value };
+    };
+
     template <typename Expected, typename Attribute>
-    struct compute_compatible_component
+    struct compute_compatible_component_variant<Expected, Attribute, mpl::false_>
     {
         typedef typename Attribute::types types;
         typedef typename mpl::end<types>::type end;
-        typedef typename mpl::begin<types>::type begin;
 
         typedef typename 
             mpl::find_if<types, is_same<Expected, mpl::_1> >::type 
         iter;
 
+        typedef typename mpl::distance<
+            typename mpl::begin<types>::type, iter
+        >::type distance;
+
         typedef typename mpl::not_<is_same<iter, end> >::type type;
         enum { value = type::value };
     };
 
+    template <typename Expected, typename Attribute>
+    struct compute_compatible_component
+      : compute_compatible_component_variant<Expected, Attribute
+          , typename spirit::traits::not_is_variant<Attribute>::type>
+    {};
+
     template <typename Expected>
     struct compute_compatible_component<Expected, unused_type>
       : mpl::false_ {};
@@ -111,13 +128,28 @@
         call(Component const& component, OutputIterator& sink,
             Context& ctx, Delimiter const& d, Attribute const& attr)
         {
+            return call(component, sink, ctx, d, attr
+              , spirit::traits::not_is_variant<Attribute>());
+        }
+
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const& component, OutputIterator& sink,
+            Context& ctx, Delimiter const& d, Attribute const& attr, mpl::true_)
+        {
+            return component.generate(sink, ctx, d, attr);
+        }
+
+        template <typename OutputIterator, typename Context, typename Delimiter>
+        static bool
+        call(Component const& component, OutputIterator& sink,
+            Context& ctx, Delimiter const& d, Attribute const& attr, mpl::false_)
+        {
             typedef
                 compute_compatible_component<Expected, Attribute>
             component_type;
 
-            typedef typename mpl::distance<
-                typename component_type::begin, typename component_type::iter
-            >::type distance_type;
+            typedef typename component_type::distance distance_type;
 
             // make sure, the content of the passed variant matches our
             // expectations
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-06-02 20:05:58 EDT (Tue, 02 Jun 2009)
@@ -16,6 +16,7 @@
 #include <boost/spirit/home/karma/meta_compiler.hpp>
 #include <boost/spirit/home/karma/detail/fail_function.hpp>
 #include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/output_iterator.hpp>
 #include <boost/spirit/home/support/info.hpp>
 #include <boost/spirit/home/support/detail/what_function.hpp>
 #include <boost/spirit/home/support/attributes.hpp>
@@ -120,8 +121,18 @@
         bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
           , Attribute const& attr) const
         {
-            return generate_impl(sink, ctx, d, attr
-                , traits::is_container<Attribute>());
+            // wrap the given output iterator avoid output as long as one
+            // component of the sequence fails
+            detail::enable_buffering<OutputIterator> buffering(sink);
+            bool r = false;
+            {
+                detail::disable_counting<OutputIterator> nocounting(sink);
+                r = generate_impl(sink, ctx, d, attr
+                  , traits::is_container<Attribute>());
+            }
+            if (r) 
+                buffering.buffer_copy();
+            return r;
         }
 
         template <typename Context>
Modified: trunk/boost/spirit/home/qi/detail/alternative_function.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/alternative_function.hpp	(original)
+++ trunk/boost/spirit/home/qi/detail/alternative_function.hpp	2009-06-02 20:05:58 EDT (Tue, 02 Jun 2009)
@@ -19,14 +19,6 @@
 
 namespace boost { namespace spirit { namespace qi { namespace detail
 {
-    template <typename T>
-    struct not_is_variant
-      : mpl::true_ {};
-
-    template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-    struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-      : mpl::false_ {};
-
     template <typename Iterator, typename Context, typename Skipper,
         typename Attribute>
     struct alternative_function
@@ -64,7 +56,7 @@
         bool operator()(Component const& component) const
         {
             // return true if the parser succeeds
-            return call(component, not_is_variant<Attribute>());
+            return call(component, spirit::traits::not_is_variant<Attribute>());
         }
 
         Iterator& first;
Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp	(original)
+++ trunk/boost/spirit/home/support/attributes.hpp	2009-06-02 20:05:58 EDT (Tue, 02 Jun 2009)
@@ -37,6 +37,14 @@
     // components.
     ///////////////////////////////////////////////////////////////////////////
 
+    template <typename T>
+    struct not_is_variant
+      : mpl::true_ {};
+
+    template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+    struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+      : mpl::false_ {};
+
     ///////////////////////////////////////////////////////////////////////////
     // attribute_of
     //
Modified: trunk/libs/spirit/test/karma/alternative.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/alternative.cpp	(original)
+++ trunk/libs/spirit/test/karma/alternative.cpp	2009-06-02 20:05:58 EDT (Tue, 02 Jun 2009)
@@ -108,6 +108,16 @@
         BOOST_TEST(!test_delimited("", char_ | int_, v, char_(' ')));
     }
 
+    {
+        std::vector<int> v;
+        BOOST_TEST(test("[]", '[' << (int_ % ", ") << ']' | "[]", v));
+
+        v.push_back(5);
+        v.push_back(5);
+        v.push_back(5);
+        BOOST_TEST(test("[5, 5, 5]", '[' << (int_ % ", ") << ']' | "[]", v));
+    }
+
     return boost::report_errors();
 }