annotate DEPENDENCIES/generic/include/boost/range/algorithm/search_n.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright Neil Groves 2009. Use, modification and
Chris@16 2 // distribution is subject to the Boost Software License, Version
Chris@16 3 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 4 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5 //
Chris@16 6 //
Chris@16 7 // For more information, see http://www.boost.org/libs/range/
Chris@16 8 //
Chris@16 9 #ifndef BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED
Chris@16 10 #define BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED
Chris@16 11
Chris@16 12 #include <boost/concept_check.hpp>
Chris@16 13 #include <boost/range/begin.hpp>
Chris@16 14 #include <boost/range/end.hpp>
Chris@16 15 #include <boost/range/concepts.hpp>
Chris@16 16 #include <boost/range/detail/range_return.hpp>
Chris@16 17 #include <boost/range/value_type.hpp>
Chris@16 18 #include <iterator>
Chris@16 19 #include <algorithm>
Chris@16 20
Chris@16 21 namespace boost
Chris@16 22 {
Chris@16 23
Chris@16 24 namespace range_detail
Chris@16 25 {
Chris@16 26 // Rationale: search_n is implemented rather than delegate to
Chris@16 27 // the standard library implementation because some standard
Chris@16 28 // library implementations are broken eg. MSVC.
Chris@16 29
Chris@16 30 // search_n forward iterator version
Chris@16 31 template<typename ForwardIterator, typename Integer, typename Value>
Chris@16 32 inline ForwardIterator
Chris@16 33 search_n_impl(ForwardIterator first, ForwardIterator last, Integer count,
Chris@16 34 const Value& value, std::forward_iterator_tag)
Chris@16 35 {
Chris@16 36 first = std::find(first, last, value);
Chris@16 37 while (first != last)
Chris@16 38 {
Chris@16 39 typename std::iterator_traits<ForwardIterator>::difference_type n = count;
Chris@16 40 ForwardIterator i = first;
Chris@16 41 ++i;
Chris@16 42 while (i != last && n != 1 && *i==value)
Chris@16 43 {
Chris@16 44 ++i;
Chris@16 45 --n;
Chris@16 46 }
Chris@16 47 if (n == 1)
Chris@16 48 return first;
Chris@16 49 if (i == last)
Chris@16 50 return last;
Chris@16 51 first = std::find(++i, last, value);
Chris@16 52 }
Chris@16 53 return last;
Chris@16 54 }
Chris@16 55
Chris@16 56 // search_n random-access iterator version
Chris@16 57 template<typename RandomAccessIterator, typename Integer, typename Value>
Chris@16 58 inline RandomAccessIterator
Chris@16 59 search_n_impl(RandomAccessIterator first, RandomAccessIterator last,
Chris@16 60 Integer count, const Value& value,
Chris@16 61 std::random_access_iterator_tag)
Chris@16 62 {
Chris@16 63 typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;
Chris@16 64
Chris@16 65 difference_t tail_size = last - first;
Chris@16 66 const difference_t pattern_size = count;
Chris@16 67
Chris@16 68 if (tail_size < pattern_size)
Chris@16 69 return last;
Chris@16 70
Chris@16 71 const difference_t skip_offset = pattern_size - 1;
Chris@16 72 RandomAccessIterator look_ahead = first + skip_offset;
Chris@16 73 tail_size -= pattern_size;
Chris@16 74
Chris@16 75 while (1)
Chris@16 76 {
Chris@16 77 // look_ahead here is pointing to the last element of the
Chris@16 78 // next possible match
Chris@16 79 while (!(*look_ahead == value)) // skip loop...
Chris@16 80 {
Chris@16 81 if (tail_size < pattern_size)
Chris@16 82 return last; // no match
Chris@16 83 look_ahead += pattern_size;
Chris@16 84 tail_size -= pattern_size;
Chris@16 85 }
Chris@16 86 difference_t remainder = skip_offset;
Chris@16 87 for (RandomAccessIterator back_track = look_ahead - 1;
Chris@16 88 *back_track == value; --back_track)
Chris@16 89 {
Chris@16 90 if (--remainder == 0)
Chris@16 91 {
Chris@16 92 return look_ahead - skip_offset; // matched
Chris@16 93 }
Chris@16 94 }
Chris@16 95 if (remainder > tail_size)
Chris@16 96 return last; // no match
Chris@16 97 look_ahead += remainder;
Chris@16 98 tail_size -= remainder;
Chris@16 99 }
Chris@16 100
Chris@16 101 return last;
Chris@16 102 }
Chris@16 103
Chris@16 104 // search_n for forward iterators using a binary predicate
Chris@16 105 // to determine a match
Chris@16 106 template<typename ForwardIterator, typename Integer, typename Value,
Chris@16 107 typename BinaryPredicate>
Chris@16 108 inline ForwardIterator
Chris@16 109 search_n_pred_impl(ForwardIterator first, ForwardIterator last,
Chris@16 110 Integer count, const Value& value,
Chris@16 111 BinaryPredicate pred, std::forward_iterator_tag)
Chris@16 112 {
Chris@16 113 typedef typename std::iterator_traits<ForwardIterator>::difference_type difference_t;
Chris@16 114
Chris@16 115 while (first != last && !static_cast<bool>(pred(*first, value)))
Chris@16 116 ++first;
Chris@16 117
Chris@16 118 while (first != last)
Chris@16 119 {
Chris@16 120 difference_t n = count;
Chris@16 121 ForwardIterator i = first;
Chris@16 122 ++i;
Chris@16 123 while (i != last && n != 1 && static_cast<bool>(pred(*i, value)))
Chris@16 124 {
Chris@16 125 ++i;
Chris@16 126 --n;
Chris@16 127 }
Chris@16 128 if (n == 1)
Chris@16 129 return first;
Chris@16 130 if (i == last)
Chris@16 131 return last;
Chris@16 132 first = ++i;
Chris@16 133 while (first != last && !static_cast<bool>(pred(*first, value)))
Chris@16 134 ++first;
Chris@16 135 }
Chris@16 136 return last;
Chris@16 137 }
Chris@16 138
Chris@16 139 // search_n for random-access iterators using a binary predicate
Chris@16 140 // to determine a match
Chris@16 141 template<typename RandomAccessIterator, typename Integer,
Chris@16 142 typename Value, typename BinaryPredicate>
Chris@16 143 inline RandomAccessIterator
Chris@16 144 search_n_pred_impl(RandomAccessIterator first, RandomAccessIterator last,
Chris@16 145 Integer count, const Value& value,
Chris@16 146 BinaryPredicate pred, std::random_access_iterator_tag)
Chris@16 147 {
Chris@16 148 typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;
Chris@16 149
Chris@16 150 difference_t tail_size = last - first;
Chris@16 151 const difference_t pattern_size = count;
Chris@16 152
Chris@16 153 if (tail_size < pattern_size)
Chris@16 154 return last;
Chris@16 155
Chris@16 156 const difference_t skip_offset = pattern_size - 1;
Chris@16 157 RandomAccessIterator look_ahead = first + skip_offset;
Chris@16 158 tail_size -= pattern_size;
Chris@16 159
Chris@16 160 while (1)
Chris@16 161 {
Chris@16 162 // look_ahead points to the last element of the next
Chris@16 163 // possible match
Chris@16 164 while (!static_cast<bool>(pred(*look_ahead, value))) // skip loop
Chris@16 165 {
Chris@16 166 if (tail_size < pattern_size)
Chris@16 167 return last; // no match
Chris@16 168 look_ahead += pattern_size;
Chris@16 169 tail_size -= pattern_size;
Chris@16 170 }
Chris@16 171 difference_t remainder = skip_offset;
Chris@16 172 for (RandomAccessIterator back_track = look_ahead - 1;
Chris@16 173 pred(*back_track, value); --back_track)
Chris@16 174 {
Chris@16 175 if (--remainder == 0)
Chris@16 176 return look_ahead -= skip_offset; // success
Chris@16 177 }
Chris@16 178 if (remainder > tail_size)
Chris@16 179 {
Chris@16 180 return last; // no match
Chris@16 181 }
Chris@16 182 look_ahead += remainder;
Chris@16 183 tail_size -= remainder;
Chris@16 184 }
Chris@16 185 }
Chris@16 186
Chris@16 187 template<typename ForwardIterator, typename Integer, typename Value>
Chris@16 188 inline ForwardIterator
Chris@16 189 search_n_impl(ForwardIterator first, ForwardIterator last,
Chris@16 190 Integer count, const Value& value)
Chris@16 191 {
Chris@16 192 BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
Chris@16 193 BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<Value>));
Chris@16 194 BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<typename std::iterator_traits<ForwardIterator>::value_type>));
Chris@16 195 //BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept2<typename std::iterator_traits<ForwardIterator>::value_type, Value>));
Chris@16 196
Chris@16 197 typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
Chris@16 198
Chris@16 199 if (count <= 0)
Chris@16 200 return first;
Chris@16 201 if (count == 1)
Chris@16 202 return std::find(first, last, value);
Chris@16 203 return range_detail::search_n_impl(first, last, count, value, cat_t());
Chris@16 204 }
Chris@16 205
Chris@16 206 template<typename ForwardIterator, typename Integer, typename Value,
Chris@16 207 typename BinaryPredicate>
Chris@16 208 inline ForwardIterator
Chris@16 209 search_n_pred_impl(ForwardIterator first, ForwardIterator last,
Chris@16 210 Integer count, const Value& value,
Chris@16 211 BinaryPredicate pred)
Chris@16 212 {
Chris@16 213 BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
Chris@16 214 BOOST_RANGE_CONCEPT_ASSERT((
Chris@16 215 BinaryPredicateConcept<
Chris@16 216 BinaryPredicate,
Chris@16 217 typename std::iterator_traits<ForwardIterator>::value_type,
Chris@16 218 Value>
Chris@16 219 ));
Chris@16 220
Chris@16 221 typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
Chris@16 222
Chris@16 223 if (count <= 0)
Chris@16 224 return first;
Chris@16 225 if (count == 1)
Chris@16 226 {
Chris@16 227 while (first != last && !static_cast<bool>(pred(*first, value)))
Chris@16 228 ++first;
Chris@16 229 return first;
Chris@16 230 }
Chris@16 231 return range_detail::search_n_pred_impl(first, last, count,
Chris@16 232 value, pred, cat_t());
Chris@16 233 }
Chris@16 234 } // namespace range_detail
Chris@16 235
Chris@16 236 namespace range {
Chris@16 237
Chris@16 238 /// \brief template function search
Chris@16 239 ///
Chris@16 240 /// range-based version of the search std algorithm
Chris@16 241 ///
Chris@16 242 /// \pre ForwardRange is a model of the ForwardRangeConcept
Chris@16 243 /// \pre Integer is an integral type
Chris@16 244 /// \pre Value is a model of the EqualityComparableConcept
Chris@16 245 /// \pre ForwardRange's value type is a model of the EqualityComparableConcept
Chris@16 246 /// \pre Object's of ForwardRange's value type can be compared for equality with Objects of type Value
Chris@16 247 template< class ForwardRange, class Integer, class Value >
Chris@16 248 inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
Chris@16 249 search_n(ForwardRange& rng, Integer count, const Value& value)
Chris@16 250 {
Chris@16 251 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
Chris@16 252 return range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value);
Chris@16 253 }
Chris@16 254
Chris@16 255 /// \overload
Chris@16 256 template< class ForwardRange, class Integer, class Value >
Chris@16 257 inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
Chris@16 258 search_n(const ForwardRange& rng, Integer count, const Value& value)
Chris@16 259 {
Chris@16 260 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
Chris@16 261 return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value);
Chris@16 262 }
Chris@16 263
Chris@16 264 /// \overload
Chris@16 265 template< class ForwardRange, class Integer, class Value,
Chris@16 266 class BinaryPredicate >
Chris@16 267 inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
Chris@16 268 search_n(ForwardRange& rng, Integer count, const Value& value,
Chris@16 269 BinaryPredicate binary_pred)
Chris@16 270 {
Chris@16 271 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
Chris@16 272 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
Chris@16 273 BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type, const Value&>));
Chris@16 274 return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng),
Chris@16 275 count, value, binary_pred);
Chris@16 276 }
Chris@16 277
Chris@16 278 /// \overload
Chris@16 279 template< class ForwardRange, class Integer, class Value,
Chris@16 280 class BinaryPredicate >
Chris@16 281 inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
Chris@16 282 search_n(const ForwardRange& rng, Integer count, const Value& value,
Chris@16 283 BinaryPredicate binary_pred)
Chris@16 284 {
Chris@16 285 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
Chris@16 286 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
Chris@16 287 BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type, const Value&>));
Chris@16 288 return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng),
Chris@16 289 count, value, binary_pred);
Chris@16 290 }
Chris@16 291
Chris@16 292 // range_return overloads
Chris@16 293
Chris@16 294 /// \overload
Chris@16 295 template< range_return_value re, class ForwardRange, class Integer,
Chris@16 296 class Value >
Chris@16 297 inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange,re>::type
Chris@16 298 search_n(ForwardRange& rng, Integer count, const Value& value)
Chris@16 299 {
Chris@16 300 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
Chris@16 301 return range_return<ForwardRange,re>::
Chris@16 302 pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng),
Chris@16 303 count, value),
Chris@16 304 rng);
Chris@16 305 }
Chris@16 306
Chris@16 307 /// \overload
Chris@16 308 template< range_return_value re, class ForwardRange, class Integer,
Chris@16 309 class Value >
Chris@16 310 inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange,re>::type
Chris@16 311 search_n(const ForwardRange& rng, Integer count, const Value& value)
Chris@16 312 {
Chris@16 313 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
Chris@16 314 return range_return<const ForwardRange,re>::
Chris@16 315 pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
Chris@16 316 count, value),
Chris@16 317 rng);
Chris@16 318 }
Chris@16 319
Chris@16 320 /// \overload
Chris@16 321 template< range_return_value re, class ForwardRange, class Integer,
Chris@16 322 class Value, class BinaryPredicate >
Chris@16 323 inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange,re>::type
Chris@16 324 search_n(ForwardRange& rng, Integer count, const Value& value,
Chris@16 325 BinaryPredicate pred)
Chris@16 326 {
Chris@16 327 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
Chris@16 328 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
Chris@16 329 BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type,
Chris@16 330 const Value&>));
Chris@16 331 return range_return<ForwardRange,re>::
Chris@16 332 pack(range_detail::search_n_pred_impl(boost::begin(rng),
Chris@16 333 boost::end(rng),
Chris@16 334 count, value, pred),
Chris@16 335 rng);
Chris@16 336 }
Chris@16 337
Chris@16 338 /// \overload
Chris@16 339 template< range_return_value re, class ForwardRange, class Integer,
Chris@16 340 class Value, class BinaryPredicate >
Chris@16 341 inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange,re>::type
Chris@16 342 search_n(const ForwardRange& rng, Integer count, const Value& value,
Chris@16 343 BinaryPredicate pred)
Chris@16 344 {
Chris@16 345 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
Chris@16 346 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
Chris@16 347 BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type,
Chris@16 348 const Value&>));
Chris@16 349 return range_return<const ForwardRange,re>::
Chris@16 350 pack(range_detail::search_n_pred_impl(boost::begin(rng),
Chris@16 351 boost::end(rng),
Chris@16 352 count, value, pred),
Chris@16 353 rng);
Chris@16 354 }
Chris@16 355
Chris@16 356 } // namespace range
Chris@16 357 using range::search_n;
Chris@16 358 } // namespace boost
Chris@16 359
Chris@16 360 #endif // include guard