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