summaryrefslogtreecommitdiff
path: root/boost/geometry/iterators/flatten_iterator.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/iterators/flatten_iterator.hpp')
-rw-r--r--boost/geometry/iterators/flatten_iterator.hpp259
1 files changed, 259 insertions, 0 deletions
diff --git a/boost/geometry/iterators/flatten_iterator.hpp b/boost/geometry/iterators/flatten_iterator.hpp
new file mode 100644
index 0000000000..078079dc2c
--- /dev/null
+++ b/boost/geometry/iterators/flatten_iterator.hpp
@@ -0,0 +1,259 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
+#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
+
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+
+template
+<
+ typename OuterIterator,
+ typename InnerIterator,
+ typename Value,
+ typename AccessInnerBegin,
+ typename AccessInnerEnd,
+ typename Reference = Value&
+>
+class flatten_iterator
+ : public boost::iterator_facade
+ <
+ flatten_iterator
+ <
+ OuterIterator,
+ InnerIterator,
+ Value,
+ AccessInnerBegin,
+ AccessInnerEnd,
+ Reference
+ >,
+ Value,
+ boost::bidirectional_traversal_tag,
+ Reference
+ >
+{
+private:
+ OuterIterator m_outer_it, m_outer_end;
+ InnerIterator m_inner_it;
+
+public:
+ typedef OuterIterator outer_iterator_type;
+ typedef InnerIterator inner_iterator_type;
+
+ // default constructor
+ flatten_iterator() {}
+
+ // for begin
+ flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
+ : m_outer_it(outer_it), m_outer_end(outer_end)
+ {
+ advance_through_empty();
+ }
+
+ // for end
+ flatten_iterator(OuterIterator outer_end)
+ : m_outer_it(outer_end), m_outer_end(outer_end)
+ {}
+
+ template
+ <
+ typename OtherOuterIterator, typename OtherInnerIterator,
+ typename OtherValue,
+ typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,
+ typename OtherReference
+ >
+ flatten_iterator(flatten_iterator
+ <
+ OtherOuterIterator,
+ OtherInnerIterator,
+ OtherValue,
+ OtherAccessInnerBegin,
+ OtherAccessInnerEnd,
+ OtherReference
+ > const& other)
+ : m_outer_it(other.m_outer_it),
+ m_outer_end(other.m_outer_end),
+ m_inner_it(other.m_inner_it)
+ {
+ static const bool are_conv
+ = boost::is_convertible
+ <
+ OtherOuterIterator, OuterIterator
+ >::value
+ && boost::is_convertible
+ <
+ OtherInnerIterator, InnerIterator
+ >::value;
+
+ BOOST_MPL_ASSERT_MSG((are_conv),
+ NOT_CONVERTIBLE,
+ (types<OtherOuterIterator, OtherInnerIterator>));
+ }
+
+ template
+ <
+ typename OtherOuterIterator,
+ typename OtherInnerIterator,
+ typename OtherValue,
+ typename OtherAccessInnerBegin,
+ typename OtherAccessInnerEnd,
+ typename OtherReference
+ >
+ flatten_iterator operator=(flatten_iterator
+ <
+ OtherOuterIterator,
+ OtherInnerIterator,
+ OtherValue,
+ OtherAccessInnerBegin,
+ OtherAccessInnerEnd,
+ OtherReference
+ > const& other)
+ {
+ static const bool are_conv
+ = boost::is_convertible
+ <
+ OtherOuterIterator, OuterIterator
+ >::value
+ && boost::is_convertible
+ <
+ OtherInnerIterator, InnerIterator
+ >::value;
+
+ BOOST_MPL_ASSERT_MSG((are_conv),
+ NOT_CONVERTIBLE,
+ (types<OtherOuterIterator, OtherInnerIterator>));
+
+ m_outer_it = other.m_outer_it;
+ m_outer_end = other.m_outer_end;
+ m_inner_it = other.m_inner_it;
+ return *this;
+ }
+
+private:
+ friend class boost::iterator_core_access;
+
+ template
+ <
+ typename Outer,
+ typename Inner,
+ typename V,
+ typename InnerBegin,
+ typename InnerEnd,
+ typename R
+ >
+ friend class flatten_iterator;
+
+ static inline bool empty(OuterIterator outer_it)
+ {
+ return
+ AccessInnerBegin::apply(*outer_it) == AccessInnerEnd::apply(*outer_it);
+ }
+
+ inline void advance_through_empty()
+ {
+ while ( m_outer_it != m_outer_end && empty(m_outer_it) )
+ {
+ ++m_outer_it;
+ }
+
+ if ( m_outer_it != m_outer_end )
+ {
+ m_inner_it = AccessInnerBegin::apply(*m_outer_it);
+ }
+ }
+
+ inline Reference dereference() const
+ {
+ BOOST_ASSERT( m_outer_it != m_outer_end );
+ BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
+ return *m_inner_it;
+ }
+
+
+ template
+ <
+ typename OtherOuterIterator,
+ typename OtherInnerIterator,
+ typename OtherValue,
+ typename OtherAccessInnerBegin,
+ typename OtherAccessInnerEnd,
+ typename OtherReference
+ >
+ inline bool equal(flatten_iterator
+ <
+ OtherOuterIterator,
+ OtherInnerIterator,
+ OtherValue,
+ OtherAccessInnerBegin,
+ OtherAccessInnerEnd,
+ OtherReference
+ > const& other) const
+ {
+ if ( m_outer_it != other.m_outer_it )
+ {
+ return false;
+ }
+
+ if ( m_outer_it == m_outer_end )
+ {
+ return true;
+ }
+
+ return m_inner_it == other.m_inner_it;
+ }
+
+ inline void increment()
+ {
+ BOOST_ASSERT( m_outer_it != m_outer_end );
+ BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
+
+ ++m_inner_it;
+ if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
+ {
+ ++m_outer_it;
+ advance_through_empty();
+ }
+ }
+
+ inline void decrement()
+ {
+ if ( m_outer_it == m_outer_end
+ || m_inner_it == AccessInnerBegin::apply(*m_outer_it) )
+ {
+ do
+ {
+ --m_outer_it;
+ }
+ while ( empty(m_outer_it) );
+ m_inner_it = --AccessInnerEnd::apply(*m_outer_it);
+ }
+ else
+ {
+ --m_inner_it;
+ }
+ }
+};
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP