PageRenderTime 42ms CodeModel.GetById 14ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/range/algorithm/search_n.hpp

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