File indexing completed on 2025-01-30 09:59:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED
0010 #define BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED
0011
0012 #include <boost/concept_check.hpp>
0013 #include <boost/range/begin.hpp>
0014 #include <boost/range/end.hpp>
0015 #include <boost/range/concepts.hpp>
0016 #include <boost/range/detail/range_return.hpp>
0017 #include <boost/range/value_type.hpp>
0018 #include <iterator>
0019 #include <algorithm>
0020
0021 namespace boost
0022 {
0023
0024 namespace range_detail
0025 {
0026
0027
0028
0029
0030
0031 template<typename ForwardIterator, typename Integer, typename Value>
0032 inline ForwardIterator
0033 search_n_impl(ForwardIterator first, ForwardIterator last, Integer count,
0034 const Value& value, std::forward_iterator_tag)
0035 {
0036 first = std::find(first, last, value);
0037 while (first != last)
0038 {
0039 typename std::iterator_traits<ForwardIterator>::difference_type n = count;
0040 ForwardIterator i = first;
0041 ++i;
0042 while (i != last && n != 1 && *i==value)
0043 {
0044 ++i;
0045 --n;
0046 }
0047 if (n == 1)
0048 return first;
0049 if (i == last)
0050 return last;
0051 first = std::find(++i, last, value);
0052 }
0053 return last;
0054 }
0055
0056
0057 template<typename RandomAccessIterator, typename Integer, typename Value>
0058 inline RandomAccessIterator
0059 search_n_impl(RandomAccessIterator first, RandomAccessIterator last,
0060 Integer count, const Value& value,
0061 std::random_access_iterator_tag)
0062 {
0063 typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;
0064
0065 difference_t tail_size = last - first;
0066 const difference_t pattern_size = count;
0067
0068 if (tail_size < pattern_size)
0069 return last;
0070
0071 const difference_t skip_offset = pattern_size - 1;
0072 RandomAccessIterator look_ahead = first + skip_offset;
0073 tail_size -= pattern_size;
0074
0075 while (1)
0076 {
0077
0078
0079 while (!(*look_ahead == value))
0080 {
0081 if (tail_size < pattern_size)
0082 return last;
0083 look_ahead += pattern_size;
0084 tail_size -= pattern_size;
0085 }
0086 difference_t remainder = skip_offset;
0087 for (RandomAccessIterator back_track = look_ahead - 1;
0088 *back_track == value; --back_track)
0089 {
0090 if (--remainder == 0)
0091 {
0092 return look_ahead - skip_offset;
0093 }
0094 }
0095 if (remainder > tail_size)
0096 return last;
0097 look_ahead += remainder;
0098 tail_size -= remainder;
0099 }
0100
0101 return last;
0102 }
0103
0104
0105
0106 template<typename ForwardIterator, typename Integer, typename Value,
0107 typename BinaryPredicate>
0108 inline ForwardIterator
0109 search_n_pred_impl(ForwardIterator first, ForwardIterator last,
0110 Integer count, const Value& value,
0111 BinaryPredicate pred, std::forward_iterator_tag)
0112 {
0113 typedef typename std::iterator_traits<ForwardIterator>::difference_type difference_t;
0114
0115 while (first != last && !static_cast<bool>(pred(*first, value)))
0116 ++first;
0117
0118 while (first != last)
0119 {
0120 difference_t n = count;
0121 ForwardIterator i = first;
0122 ++i;
0123 while (i != last && n != 1 && static_cast<bool>(pred(*i, value)))
0124 {
0125 ++i;
0126 --n;
0127 }
0128 if (n == 1)
0129 return first;
0130 if (i == last)
0131 return last;
0132 first = ++i;
0133 while (first != last && !static_cast<bool>(pred(*first, value)))
0134 ++first;
0135 }
0136 return last;
0137 }
0138
0139
0140
0141 template<typename RandomAccessIterator, typename Integer,
0142 typename Value, typename BinaryPredicate>
0143 inline RandomAccessIterator
0144 search_n_pred_impl(RandomAccessIterator first, RandomAccessIterator last,
0145 Integer count, const Value& value,
0146 BinaryPredicate pred, std::random_access_iterator_tag)
0147 {
0148 typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;
0149
0150 difference_t tail_size = last - first;
0151 const difference_t pattern_size = count;
0152
0153 if (tail_size < pattern_size)
0154 return last;
0155
0156 const difference_t skip_offset = pattern_size - 1;
0157 RandomAccessIterator look_ahead = first + skip_offset;
0158 tail_size -= pattern_size;
0159
0160 while (1)
0161 {
0162
0163
0164 while (!static_cast<bool>(pred(*look_ahead, value)))
0165 {
0166 if (tail_size < pattern_size)
0167 return last;
0168 look_ahead += pattern_size;
0169 tail_size -= pattern_size;
0170 }
0171 difference_t remainder = skip_offset;
0172 for (RandomAccessIterator back_track = look_ahead - 1;
0173 pred(*back_track, value); --back_track)
0174 {
0175 if (--remainder == 0)
0176 return look_ahead -= skip_offset;
0177 }
0178 if (remainder > tail_size)
0179 {
0180 return last;
0181 }
0182 look_ahead += remainder;
0183 tail_size -= remainder;
0184 }
0185 }
0186
0187 template<typename ForwardIterator, typename Integer, typename Value>
0188 inline ForwardIterator
0189 search_n_impl(ForwardIterator first, ForwardIterator last,
0190 Integer count, const Value& value)
0191 {
0192 BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
0193 BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<Value>));
0194 BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<typename std::iterator_traits<ForwardIterator>::value_type>));
0195
0196
0197 typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
0198
0199 if (count <= 0)
0200 return first;
0201 if (count == 1)
0202 return std::find(first, last, value);
0203 return range_detail::search_n_impl(first, last, count, value, cat_t());
0204 }
0205
0206 template<typename ForwardIterator, typename Integer, typename Value,
0207 typename BinaryPredicate>
0208 inline ForwardIterator
0209 search_n_pred_impl(ForwardIterator first, ForwardIterator last,
0210 Integer count, const Value& value,
0211 BinaryPredicate pred)
0212 {
0213 BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
0214 BOOST_RANGE_CONCEPT_ASSERT((
0215 BinaryPredicateConcept<
0216 BinaryPredicate,
0217 typename std::iterator_traits<ForwardIterator>::value_type,
0218 Value>
0219 ));
0220
0221 typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
0222
0223 if (count <= 0)
0224 return first;
0225 if (count == 1)
0226 {
0227 while (first != last && !static_cast<bool>(pred(*first, value)))
0228 ++first;
0229 return first;
0230 }
0231 return range_detail::search_n_pred_impl(first, last, count,
0232 value, pred, cat_t());
0233 }
0234 }
0235
0236 namespace range {
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 template< class ForwardRange, class Integer, class Value >
0248 inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
0249 search_n(ForwardRange& rng, Integer count, const Value& value)
0250 {
0251 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
0252 return range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value);
0253 }
0254
0255
0256 template< class ForwardRange, class Integer, class Value >
0257 inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
0258 search_n(const ForwardRange& rng, Integer count, const Value& value)
0259 {
0260 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
0261 return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value);
0262 }
0263
0264
0265 template< class ForwardRange, class Integer, class Value,
0266 class BinaryPredicate >
0267 inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
0268 search_n(ForwardRange& rng, Integer count, const Value& value,
0269 BinaryPredicate binary_pred)
0270 {
0271 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
0272 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
0273 BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type, const Value&>));
0274 return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng),
0275 count, value, binary_pred);
0276 }
0277
0278
0279 template< class ForwardRange, class Integer, class Value,
0280 class BinaryPredicate >
0281 inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
0282 search_n(const ForwardRange& rng, Integer count, const Value& value,
0283 BinaryPredicate binary_pred)
0284 {
0285 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
0286 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
0287 BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type, const Value&>));
0288 return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng),
0289 count, value, binary_pred);
0290 }
0291
0292
0293
0294
0295 template< range_return_value re, class ForwardRange, class Integer,
0296 class Value >
0297 inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange,re>::type
0298 search_n(ForwardRange& rng, Integer count, const Value& value)
0299 {
0300 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
0301 return range_return<ForwardRange,re>::
0302 pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng),
0303 count, value),
0304 rng);
0305 }
0306
0307
0308 template< range_return_value re, class ForwardRange, class Integer,
0309 class Value >
0310 inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange,re>::type
0311 search_n(const ForwardRange& rng, Integer count, const Value& value)
0312 {
0313 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
0314 return range_return<const ForwardRange,re>::
0315 pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
0316 count, value),
0317 rng);
0318 }
0319
0320
0321 template< range_return_value re, class ForwardRange, class Integer,
0322 class Value, class BinaryPredicate >
0323 inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange,re>::type
0324 search_n(ForwardRange& rng, Integer count, const Value& value,
0325 BinaryPredicate pred)
0326 {
0327 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
0328 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
0329 BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type,
0330 const Value&>));
0331 return range_return<ForwardRange,re>::
0332 pack(range_detail::search_n_pred_impl(boost::begin(rng),
0333 boost::end(rng),
0334 count, value, pred),
0335 rng);
0336 }
0337
0338
0339 template< range_return_value re, class ForwardRange, class Integer,
0340 class Value, class BinaryPredicate >
0341 inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange,re>::type
0342 search_n(const ForwardRange& rng, Integer count, const Value& value,
0343 BinaryPredicate pred)
0344 {
0345 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
0346 BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
0347 BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type,
0348 const Value&>));
0349 return range_return<const ForwardRange,re>::
0350 pack(range_detail::search_n_pred_impl(boost::begin(rng),
0351 boost::end(rng),
0352 count, value, pred),
0353 rng);
0354 }
0355
0356 }
0357 using range::search_n;
0358 }
0359
0360 #endif