1 /*============================================================================= 2 Copyright (c) 2011 Eric Niebler 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 ==============================================================================*/ 7 #if !defined(BOOST_FUSION_SEGMENTED_ITERATOR_NEXT_IMPL_HPP_INCLUDED) 8 #define BOOST_FUSION_SEGMENTED_ITERATOR_NEXT_IMPL_HPP_INCLUDED 9 10 #include <boost/fusion/support/config.hpp> 11 #include <boost/type_traits/add_const.hpp> 12 #include <boost/type_traits/remove_reference.hpp> 13 #include <boost/fusion/iterator/equal_to.hpp> 14 #include <boost/fusion/container/list/cons_fwd.hpp> 15 #include <boost/fusion/iterator/next.hpp> 16 #include <boost/fusion/iterator/deref.hpp> 17 18 namespace boost { namespace fusion 19 { 20 template <typename First, typename Second> 21 struct iterator_range; 22 23 template <typename Context> 24 struct segmented_iterator; 25 26 namespace detail 27 { 28 template <typename Sequence, typename Stack> 29 struct segmented_begin_impl; 30 31 //bool is_invalid(stack) 32 //{ 33 // return empty(car(stack)); 34 //} 35 36 template <typename Stack> 37 struct is_invalid 38 : result_of::equal_to< 39 typename Stack::car_type::begin_type, 40 typename Stack::car_type::end_type 41 > 42 {}; 43 44 ////Advance the first iterator in the seq at the 45 ////top of a stack of iterator ranges. Return the 46 ////new stack. 47 //auto pop_front_car(stack) 48 //{ 49 // return cons(iterator_range(next(begin(car(stack))), end(car(stack))), cdr(stack)); 50 //} 51 52 template <typename Stack> 53 struct pop_front_car 54 { 55 typedef 56 iterator_range< 57 typename result_of::next< 58 typename Stack::car_type::begin_type 59 >::type 60 , typename Stack::car_type::end_type 61 > 62 car_type; 63 64 typedef 65 cons<car_type, typename Stack::cdr_type> 66 type; 67 68 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::pop_front_car69 static type call(Stack const & stack) 70 { 71 return type( 72 car_type(fusion::next(stack.car.first), stack.car.last), 73 stack.cdr); 74 } 75 }; 76 77 template < 78 typename Stack, 79 typename Next = typename pop_front_car<Stack>::type, 80 bool IsInvalid = is_invalid<Next>::value, 81 int StackSize = Stack::size::value> 82 struct segmented_next_impl_recurse; 83 84 // Handle the case where the top of the stack has no usable 85 //auto segmented_next_impl_recurse3(stack) 86 //{ 87 // if (size(stack) == 1) 88 // return cons(iterator_range(end(car(stack)), end(car(stack))), nil_); 89 // else 90 // return segmented_next_impl_recurse(stack.cdr); 91 //} 92 93 template < 94 typename Stack, 95 int StackSize = Stack::size::value> 96 struct segmented_next_impl_recurse3 97 { 98 typedef segmented_next_impl_recurse<typename Stack::cdr_type> impl; 99 typedef typename impl::type type; 100 101 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_recurse3102 static type call(Stack const & stack) 103 { 104 return impl::call(stack.cdr); 105 } 106 }; 107 108 template <typename Stack> 109 struct segmented_next_impl_recurse3<Stack, 1> 110 { 111 typedef typename Stack::car_type::end_type end_type; 112 typedef iterator_range<end_type, end_type> range_type; 113 typedef cons<range_type> type; 114 115 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_recurse3116 static type call(Stack const & stack) 117 { 118 return type(range_type(stack.car.last, stack.car.last)); 119 } 120 }; 121 122 //auto segmented_next_impl_recurse2(stack) 123 //{ 124 // auto res = segmented_begin_impl(front(car(stack)), stack); 125 // if (is_invalid(res)) 126 // return segmented_next_impl_recurse3(stack); 127 // else 128 // return res; 129 //} 130 131 template < 132 typename Stack, 133 typename Sequence = 134 typename remove_reference< 135 typename add_const< 136 typename result_of::deref< 137 typename Stack::car_type::begin_type 138 >::type 139 >::type 140 >::type, 141 typename Result = 142 typename segmented_begin_impl<Sequence, Stack>::type, 143 bool IsInvalid = 144 is_invalid<Result>::value> 145 struct segmented_next_impl_recurse2 146 { 147 typedef segmented_next_impl_recurse3<Stack> impl; 148 typedef typename impl::type type; 149 150 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_recurse2151 static type call(Stack const & stack) 152 { 153 return impl::call(stack); 154 } 155 }; 156 157 template <typename Stack, typename Sequence, typename Result> 158 struct segmented_next_impl_recurse2<Stack, Sequence, Result, false> 159 { 160 typedef Result type; 161 162 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_recurse2163 static type call(Stack const & stack) 164 { 165 return segmented_begin_impl<Sequence, Stack>::call(*stack.car.first, stack); 166 } 167 }; 168 169 //auto segmented_next_impl_recurse(stack) 170 //{ 171 // auto next = pop_front_car(stack); 172 // if (is_invalid(next)) 173 // if (1 == size(stack)) 174 // return next; 175 // else 176 // return segmented_next_impl_recurse(cdr(stack)); 177 // else 178 // return segmented_next_impl_recurse2(next) 179 //} 180 181 template <typename Stack, typename Next, bool IsInvalid, int StackSize> 182 struct segmented_next_impl_recurse 183 { 184 typedef 185 typename segmented_next_impl_recurse<typename Stack::cdr_type>::type 186 type; 187 188 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_recurse189 static type call(Stack const& stack) 190 { 191 return segmented_next_impl_recurse<typename Stack::cdr_type>::call(stack.cdr); 192 } 193 }; 194 195 template <typename Stack, typename Next> 196 struct segmented_next_impl_recurse<Stack, Next, true, 1> 197 { 198 typedef Next type; 199 200 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_recurse201 static type call(Stack const & stack) 202 { 203 return pop_front_car<Stack>::call(stack); 204 } 205 }; 206 207 template <typename Stack, typename Next, int StackSize> 208 struct segmented_next_impl_recurse<Stack, Next, false, StackSize> 209 { 210 typedef segmented_next_impl_recurse2<Next> impl; 211 typedef typename impl::type type; 212 213 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_recurse214 static type call(Stack const & stack) 215 { 216 return impl::call(pop_front_car<Stack>::call(stack)); 217 } 218 }; 219 220 //auto segmented_next_impl(stack) 221 //{ 222 // // car(stack) is a seq of values, not a seq of segments 223 // auto next = pop_front_car(stack); 224 // if (is_invalid(next)) 225 // return segmented_next_impl_recurse(cdr(next)); 226 // else 227 // return next; 228 //} 229 230 template < 231 typename Stack, 232 typename Next = typename pop_front_car<Stack>::type, 233 bool IsInvalid = is_invalid<Next>::value> 234 struct segmented_next_impl_aux 235 { 236 typedef segmented_next_impl_recurse<typename Stack::cdr_type> impl; 237 typedef typename impl::type type; 238 239 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_aux240 static type call(Stack const & stack) 241 { 242 return impl::call(stack.cdr); 243 } 244 }; 245 246 template <typename Stack, typename Next> 247 struct segmented_next_impl_aux<Stack, Next, false> 248 { 249 typedef Next type; 250 251 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::segmented_next_impl_aux252 static type call(Stack const & stack) 253 { 254 return pop_front_car<Stack>::call(stack); 255 } 256 }; 257 258 template <typename Stack> 259 struct segmented_next_impl 260 : segmented_next_impl_aux<Stack> 261 {}; 262 } 263 }} 264 265 #endif 266