forked from boostorg/range
[boost][range] - Update to relax preconditions for the strided adaptor, and numerous fixes to inspection report issues.
[SVN r67419]
This commit is contained in:
@ -15,6 +15,7 @@
|
||||
#include <boost/range/concepts.hpp>
|
||||
#include <boost/range/detail/range_return.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost
|
||||
@ -22,6 +23,218 @@ namespace boost
|
||||
namespace range
|
||||
{
|
||||
|
||||
namespace range_detail
|
||||
{
|
||||
// Rationale: search_n is implemented rather than delegate to
|
||||
// the standard library implementation because some standard
|
||||
// library implementations are broken eg. MSVC.
|
||||
|
||||
// search_n forward iterator version
|
||||
template<typename ForwardIterator, typename Integer, typename Value>
|
||||
inline ForwardIterator
|
||||
search_n_impl(ForwardIterator first, ForwardIterator last, Integer count,
|
||||
const Value& value, std::forward_iterator_tag)
|
||||
{
|
||||
first = std::find(first, last, value);
|
||||
while (first != last)
|
||||
{
|
||||
typename std::iterator_traits<ForwardIterator>::difference_type n = count;
|
||||
ForwardIterator i = first;
|
||||
++i;
|
||||
while (i != last && n != 1 && *i==value)
|
||||
{
|
||||
++i;
|
||||
--n;
|
||||
}
|
||||
if (n == 1)
|
||||
return first;
|
||||
if (i == last)
|
||||
return last;
|
||||
first = std::find(++i, last, value);
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
// search_n random-access iterator version
|
||||
template<typename RandomAccessIterator, typename Integer, typename Value>
|
||||
inline RandomAccessIterator
|
||||
search_n_impl(RandomAccessIterator first, RandomAccessIterator last,
|
||||
Integer count, const Value& value,
|
||||
std::random_access_iterator_tag)
|
||||
{
|
||||
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;
|
||||
|
||||
difference_t tail_size = last - first;
|
||||
const difference_t pattern_size = count;
|
||||
|
||||
if (tail_size < pattern_size)
|
||||
return last;
|
||||
|
||||
const difference_t skip_offset = pattern_size - 1;
|
||||
RandomAccessIterator look_ahead = first + skip_offset;
|
||||
tail_size -= pattern_size;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// look_ahead here is pointing to the last element of the
|
||||
// next possible match
|
||||
while (!(*look_ahead == value)) // skip loop...
|
||||
{
|
||||
if (tail_size < pattern_size)
|
||||
return last; // no match
|
||||
look_ahead += pattern_size;
|
||||
tail_size -= pattern_size;
|
||||
}
|
||||
difference_t remainder = skip_offset;
|
||||
for (RandomAccessIterator back_track = look_ahead - 1;
|
||||
*back_track == value; --back_track)
|
||||
{
|
||||
if (--remainder == 0)
|
||||
{
|
||||
return look_ahead - skip_offset; // matched
|
||||
}
|
||||
}
|
||||
if (remainder > tail_size)
|
||||
return last; // no match
|
||||
look_ahead += remainder;
|
||||
tail_size -= remainder;
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
// search_n for forward iterators using a binary predicate
|
||||
// to determine a match
|
||||
template<typename ForwardIterator, typename Integer, typename Value,
|
||||
typename BinaryPredicate>
|
||||
inline ForwardIterator
|
||||
search_n_impl(ForwardIterator first, ForwardIterator last,
|
||||
Integer count, const Value& value,
|
||||
BinaryPredicate pred, std::forward_iterator_tag)
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::difference_type difference_t;
|
||||
|
||||
while (first != last && !static_cast<bool>(pred(*first, value)))
|
||||
++first;
|
||||
|
||||
while (first != last)
|
||||
{
|
||||
difference_t n = count;
|
||||
ForwardIterator i = first;
|
||||
++i;
|
||||
while (i != last && n != 1 && static_cast<bool>(pred(*i, value)))
|
||||
{
|
||||
++i;
|
||||
--n;
|
||||
}
|
||||
if (n == 1)
|
||||
return first;
|
||||
if (i == last)
|
||||
return last;
|
||||
first = ++i;
|
||||
while (first != last && !static_cast<bool>(pred(*first, value)))
|
||||
++first;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
// search_n for random-access iterators using a binary predicate
|
||||
// to determine a match
|
||||
template<typename RandomAccessIterator, typename Integer,
|
||||
typename Value, typename BinaryPredicate>
|
||||
inline RandomAccessIterator
|
||||
search_n_impl(RandomAccessIterator first, RandomAccessIterator last,
|
||||
Integer count, const Value& value,
|
||||
BinaryPredicate pred, std::random_access_iterator_tag)
|
||||
{
|
||||
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;
|
||||
|
||||
difference_t tail_size = last - first;
|
||||
const difference_t pattern_size = count;
|
||||
|
||||
if (tail_size < pattern_size)
|
||||
return last;
|
||||
|
||||
const difference_t skip_offset = pattern_size - 1;
|
||||
RandomAccessIterator look_ahead = first + skip_offset;
|
||||
tail_size -= pattern_size;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// look_ahead points to the last element of the next
|
||||
// possible match
|
||||
while (!static_cast<bool>(pred(*look_ahead, value))) // skip loop
|
||||
{
|
||||
if (tail_size < pattern_size)
|
||||
return last; // no match
|
||||
look_ahead += pattern_size;
|
||||
tail_size -= pattern_size;
|
||||
}
|
||||
difference_t remainder = skip_offset;
|
||||
for (RandomAccessIterator back_track = look_ahead - 1;
|
||||
pred(*back_track, value); --back_track)
|
||||
{
|
||||
if (--remainder == 0)
|
||||
return look_ahead -= skip_offset; // success
|
||||
}
|
||||
if (remainder > tail_size)
|
||||
{
|
||||
return last; // no match
|
||||
}
|
||||
look_ahead += remainder;
|
||||
tail_size -= remainder;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename Integer, typename Value>
|
||||
inline ForwardIterator
|
||||
search_n_impl(ForwardIterator first, ForwardIterator last,
|
||||
Integer count, const Value& value)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
|
||||
BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<Value>));
|
||||
BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<typename std::iterator_traits<ForwardIterator>::value_type>));
|
||||
//BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept2<typename std::iterator_traits<ForwardIterator>::value_type, Value>));
|
||||
|
||||
typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
|
||||
|
||||
if (count <= 0)
|
||||
return first;
|
||||
if (count == 1)
|
||||
return std::find(first, last, value);
|
||||
return range_detail::search_n_impl(first, last, count, value, cat_t());
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename Integer, typename Value,
|
||||
typename BinaryPredicate>
|
||||
inline ForwardIterator
|
||||
search_n_impl(ForwardIterator first, ForwardIterator last,
|
||||
Integer count, const Value& value,
|
||||
BinaryPredicate pred)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
|
||||
BOOST_RANGE_CONCEPT_ASSERT((
|
||||
BinaryPredicateConcept<
|
||||
BinaryPredicate,
|
||||
typename std::iterator_traits<BinaryPredicate>::value_type,
|
||||
Value>
|
||||
));
|
||||
|
||||
typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
|
||||
|
||||
if (count <= 0)
|
||||
return first;
|
||||
if (count == 1)
|
||||
{
|
||||
while (first != last && !static_cast<bool>(pred(*first, value)))
|
||||
++first;
|
||||
return first;
|
||||
}
|
||||
return range_detail::search_n_impl(first, last, count,
|
||||
value, pred, cat_t());
|
||||
}
|
||||
} // namespace range_detail
|
||||
|
||||
/// \brief template function search
|
||||
///
|
||||
/// range-based version of the search std algorithm
|
||||
@ -36,7 +249,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
|
||||
search_n(ForwardRange& rng, Integer count, const Value& value)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
|
||||
return std::search_n(boost::begin(rng),boost::end(rng), count, value);
|
||||
return range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
@ -45,7 +258,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
|
||||
search_n(const ForwardRange& rng, Integer count, const Value& value)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
|
||||
return std::search_n(boost::begin(rng), boost::end(rng), count, value);
|
||||
return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
@ -58,7 +271,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value,
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
|
||||
BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
|
||||
BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type, const Value&>));
|
||||
return std::search_n(boost::begin(rng), boost::end(rng),
|
||||
return range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
|
||||
count, value, binary_pred);
|
||||
}
|
||||
|
||||
@ -72,7 +285,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value,
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
|
||||
BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
|
||||
BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type, const Value&>));
|
||||
return std::search_n(boost::begin(rng), boost::end(rng),
|
||||
return range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
|
||||
count, value, binary_pred);
|
||||
}
|
||||
|
||||
@ -86,7 +299,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
|
||||
return range_return<ForwardRange,re>::
|
||||
pack(std::search_n(boost::begin(rng),boost::end(rng),
|
||||
pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng),
|
||||
count, value),
|
||||
rng);
|
||||
}
|
||||
@ -99,7 +312,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
|
||||
return range_return<const ForwardRange,re>::
|
||||
pack(std::search_n(boost::begin(rng), boost::end(rng),
|
||||
pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
|
||||
count, value),
|
||||
rng);
|
||||
}
|
||||
@ -116,7 +329,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value,
|
||||
BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type,
|
||||
const Value&>));
|
||||
return range_return<ForwardRange,re>::
|
||||
pack(std::search_n(boost::begin(rng), boost::end(rng),
|
||||
pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
|
||||
count, value, pred),
|
||||
rng);
|
||||
}
|
||||
@ -133,7 +346,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value,
|
||||
BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type,
|
||||
const Value&>));
|
||||
return range_return<const ForwardRange,re>::
|
||||
pack(std::search_n(boost::begin(rng), boost::end(rng),
|
||||
pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
|
||||
count, value, pred),
|
||||
rng);
|
||||
}
|
||||
|
Reference in New Issue
Block a user