|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r61468 - in trunk: boost/spirit/home/karma/detail libs/spirit/test/karma
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-21 13:22:39
Author: hkaiser
Date: 2010-04-21 13:22:37 EDT (Wed, 21 Apr 2010)
New Revision: 61468
URL: http://svn.boost.org/trac/boost/changeset/61468
Log:
Spirit: fixing problem with using a karma::repeat[] in a sequence.
Text files modified:
trunk/boost/spirit/home/karma/detail/pass_container.hpp | 92 +++++++++++++++++++++++++++++++++------
trunk/libs/spirit/test/karma/sequence.cpp | 11 ++++
2 files changed, 88 insertions(+), 15 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/pass_container.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/pass_container.hpp 2010-04-21 13:22:37 EDT (Wed, 21 Apr 2010)
@@ -22,6 +22,7 @@
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/range/iterator_range.hpp>
+#include <boost/iterator/iterator_facade.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
@@ -58,6 +59,63 @@
#undef BOOST_SPIRIT_IS_CONVERTIBLE
+ ///////////////////////////////////////////////////////////////////////////
+ // This is a wrapper for any iterator allowing to pass a reference of it
+ // to the components of the sequence
+ template <typename Iterator>
+ class indirect_iterator
+ : public boost::iterator_facade<
+ indirect_iterator<Iterator>
+ , typename boost::detail::iterator_traits<Iterator>::value_type
+ , boost::forward_traversal_tag
+ , typename boost::detail::iterator_traits<Iterator>::value_type const&>
+ {
+ public:
+ indirect_iterator()
+ : iter_(0)
+ {}
+
+ indirect_iterator(Iterator& iter)
+ : iter_(&iter)
+ {}
+
+ private:
+ friend class boost::iterator_core_access;
+
+ void increment()
+ {
+ ++*iter_;
+ }
+
+ bool equal(indirect_iterator const& other) const
+ {
+ if (0 == iter_)
+ return 0 == other.iter_;
+ return other.iter_ != 0 && *iter_ == *other.iter_;
+ }
+
+ reference dereference() const
+ {
+ return **iter_;
+ }
+
+ private:
+ Iterator* iter_;
+ };
+
+ template <typename Iterator>
+ struct make_indirect_iterator
+ {
+ typedef indirect_iterator<Iterator> type;
+ };
+
+ template <>
+ struct make_indirect_iterator<unused_type const*>
+ {
+ typedef unused_type const* type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
// This function handles the case where the attribute (Attr) given
// to the sequence is an STL container. This is a wrapper around F.
// The function F does the actual generating.
@@ -65,6 +123,7 @@
struct pass_container
{
typedef typename F::context_type context_type;
+ typedef typename traits::container_iterator<Attr>::type iterator_type;
pass_container(F const& f, Attr& attr)
: f(f), attr(attr), iter(traits::begin(attr)) {}
@@ -75,8 +134,7 @@
bool dispatch_attribute_element(Component const& component, mpl::false_) const
{
// get the next value to generate from container
- typename traits::container_iterator<Attr>::type end =
- traits::end(attr);
+ iterator_type end = traits::end(attr);
if (!traits::compare(iter, end) && !f(component, traits::deref(iter)))
{
// needs to return false as long as everything is ok
@@ -93,12 +151,14 @@
template <typename Component>
bool dispatch_attribute_element(Component const& component, mpl::true_) const
{
- typename traits::container_iterator<Attr>::type end =
- traits::end(attr);
- bool result = f(component, make_iterator_range(iter, end));
- if (result)
- iter = traits::end(attr); // adjust current iter to the end
- return result;
+ typedef typename make_indirect_iterator<iterator_type>::type
+ indirect_iterator_type;
+
+ iterator_type end = traits::end(attr);
+ indirect_iterator_type ind_iter(iter);
+ indirect_iterator_type ind_end(end);
+
+ return f(component, make_iterator_range(ind_iter, ind_end));
}
// This handles the distinction between elements in a sequence expecting
@@ -149,12 +209,14 @@
template <typename Component>
bool dispatch_main(Component const& component, mpl::true_) const
{
- typename traits::container_iterator<Attr>::type end =
- traits::end(attr);
- bool result = f(component, make_iterator_range(iter, end));
- if (result)
- iter = traits::end(attr); // adjust current iter to the end
- return result;
+ typedef typename make_indirect_iterator<iterator_type>::type
+ indirect_iterator_type;
+
+ iterator_type end = traits::end(attr);
+ indirect_iterator_type ind_iter(iter);
+ indirect_iterator_type ind_end(end);
+
+ return f(component, make_iterator_range(ind_iter, ind_end));
}
// Dispatches to dispatch_main depending on the attribute type
@@ -172,7 +234,7 @@
F f;
Attr const& attr;
- mutable typename traits::container_iterator<Attr>::type iter;
+ mutable iterator_type iter;
private:
// silence MSVC warning C4512: assignment operator could not be generated
Modified: trunk/libs/spirit/test/karma/sequence.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/sequence.cpp (original)
+++ trunk/libs/spirit/test/karma/sequence.cpp 2010-04-21 13:22:37 EDT (Wed, 21 Apr 2010)
@@ -235,6 +235,17 @@
BOOST_TEST(test("abc", r, p));
}
+ {
+ std::list<int> v;
+ v.push_back(1);
+ v.push_back(2);
+ v.push_back(3);
+ v.push_back(4);
+
+ BOOST_TEST(test("1234", repeat(2)[int_] << *int_, v));
+ BOOST_TEST(test_delimited("1 2 3 4 ", repeat(2)[int_] << *int_, v, char(' ')));
+ }
+
return boost::report_errors();
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk