1
0

cmAlgorithms.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #ifndef cmAlgorithms_h
  4. #define cmAlgorithms_h
  5. #include "cmConfigure.h" // IWYU pragma: keep
  6. #include "cmRange.h"
  7. #include "cm_kwiml.h"
  8. #include <algorithm>
  9. #include <functional>
  10. #include <iterator>
  11. #include <unordered_set>
  12. #include <utility>
  13. #include <vector>
  14. template <typename FwdIt>
  15. FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last)
  16. {
  17. const typename std::iterator_traits<FwdIt>::difference_type dist =
  18. std::distance(middle, last);
  19. std::rotate(first, middle, last);
  20. std::advance(first, dist);
  21. return first;
  22. }
  23. template <typename Container, typename Predicate>
  24. void cmEraseIf(Container& cont, Predicate pred)
  25. {
  26. cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end());
  27. }
  28. namespace ContainerAlgorithms {
  29. template <typename T>
  30. struct cmIsPair
  31. {
  32. enum
  33. {
  34. value = false
  35. };
  36. };
  37. template <typename K, typename V>
  38. struct cmIsPair<std::pair<K, V>>
  39. {
  40. enum
  41. {
  42. value = true
  43. };
  44. };
  45. template <typename Range,
  46. bool valueTypeIsPair = cmIsPair<typename Range::value_type>::value>
  47. struct DefaultDeleter
  48. {
  49. void operator()(typename Range::value_type value) const { delete value; }
  50. };
  51. template <typename Range>
  52. struct DefaultDeleter<Range, /* valueTypeIsPair = */ true>
  53. {
  54. void operator()(typename Range::value_type value) const
  55. {
  56. delete value.second;
  57. }
  58. };
  59. template <typename FwdIt>
  60. FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n)
  61. {
  62. FwdIt m = i1;
  63. std::advance(m, n);
  64. return cmRotate(i1, m, i2);
  65. }
  66. template <typename Range>
  67. struct BinarySearcher
  68. {
  69. typedef typename Range::value_type argument_type;
  70. BinarySearcher(Range const& r)
  71. : m_range(r)
  72. {
  73. }
  74. bool operator()(argument_type const& item) const
  75. {
  76. return std::binary_search(m_range.begin(), m_range.end(), item);
  77. }
  78. private:
  79. Range const& m_range;
  80. };
  81. }
  82. class cmListFileBacktrace;
  83. typedef cmRange<std::vector<cmListFileBacktrace>::const_iterator>
  84. cmBacktraceRange;
  85. template <typename Range>
  86. void cmDeleteAll(Range const& r)
  87. {
  88. std::for_each(r.begin(), r.end(),
  89. ContainerAlgorithms::DefaultDeleter<Range>());
  90. }
  91. template <typename T, typename Range>
  92. void cmAppend(std::vector<T>& v, Range const& r)
  93. {
  94. v.insert(v.end(), r.begin(), r.end());
  95. }
  96. template <typename T, typename InputIt>
  97. void cmAppend(std::vector<T>& v, InputIt first, InputIt last)
  98. {
  99. v.insert(v.end(), first, last);
  100. }
  101. template <typename Range>
  102. typename Range::const_iterator cmRemoveN(Range& r, size_t n)
  103. {
  104. return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n);
  105. }
  106. template <typename Range, typename InputRange>
  107. typename Range::const_iterator cmRemoveIndices(Range& r, InputRange const& rem)
  108. {
  109. typename InputRange::const_iterator remIt = rem.begin();
  110. typename InputRange::const_iterator remEnd = rem.end();
  111. const typename Range::iterator rangeEnd = r.end();
  112. if (remIt == remEnd) {
  113. return rangeEnd;
  114. }
  115. typename Range::iterator writer = r.begin();
  116. std::advance(writer, *remIt);
  117. typename Range::iterator pivot = writer;
  118. typename InputRange::value_type prevRem = *remIt;
  119. ++remIt;
  120. size_t count = 1;
  121. for (; writer != rangeEnd && remIt != remEnd; ++count, ++remIt) {
  122. std::advance(pivot, *remIt - prevRem);
  123. prevRem = *remIt;
  124. writer = ContainerAlgorithms::RemoveN(writer, pivot, count);
  125. }
  126. return ContainerAlgorithms::RemoveN(writer, rangeEnd, count);
  127. }
  128. template <typename Range, typename MatchRange>
  129. typename Range::const_iterator cmRemoveMatching(Range& r, MatchRange const& m)
  130. {
  131. return std::remove_if(r.begin(), r.end(),
  132. ContainerAlgorithms::BinarySearcher<MatchRange>(m));
  133. }
  134. template <typename ForwardIterator>
  135. ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last)
  136. {
  137. using Value = typename std::iterator_traits<ForwardIterator>::value_type;
  138. using Hash = struct
  139. {
  140. std::size_t operator()(ForwardIterator it) const
  141. {
  142. return std::hash<Value>{}(*it);
  143. }
  144. };
  145. using Equal = struct
  146. {
  147. bool operator()(ForwardIterator it1, ForwardIterator it2) const
  148. {
  149. return *it1 == *it2;
  150. }
  151. };
  152. std::unordered_set<ForwardIterator, Hash, Equal> uniq;
  153. ForwardIterator result = first;
  154. while (first != last) {
  155. if (uniq.find(first) == uniq.end()) {
  156. if (result != first) {
  157. *result = std::move(*first);
  158. }
  159. uniq.insert(result);
  160. ++result;
  161. }
  162. ++first;
  163. }
  164. return result;
  165. }
  166. template <typename Range>
  167. typename Range::const_iterator cmRemoveDuplicates(Range& r)
  168. {
  169. return cmRemoveDuplicates(r.begin(), r.end());
  170. }
  171. template <typename Range, typename T>
  172. typename Range::const_iterator cmFindNot(Range const& r, T const& t)
  173. {
  174. return std::find_if(r.begin(), r.end(), [&t](T const& i) { return i != t; });
  175. }
  176. template <class Iter>
  177. std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it)
  178. {
  179. return std::reverse_iterator<Iter>(it);
  180. }
  181. namespace cm {
  182. #if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
  183. using std::size;
  184. #else
  185. // std::size backport from C++17.
  186. template <class C>
  187. # if !defined(_MSC_VER) || _MSC_VER >= 1900
  188. constexpr
  189. # endif
  190. auto
  191. size(C const& c) -> decltype(c.size())
  192. {
  193. return c.size();
  194. }
  195. template <typename T, size_t N>
  196. # if !defined(_MSC_VER) || _MSC_VER >= 1900
  197. constexpr
  198. # endif
  199. std::size_t
  200. size(const T (&)[N]) throw()
  201. {
  202. return N;
  203. }
  204. #endif
  205. template <typename T>
  206. int isize(const T& t)
  207. {
  208. return static_cast<int>(cm::size(t));
  209. }
  210. #if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
  211. using std::cbegin;
  212. using std::cend;
  213. #else
  214. // std::c{begin,end} backport from C++14
  215. template <class C>
  216. # if defined(_MSC_VER) && _MSC_VER < 1900
  217. auto cbegin(C const& c)
  218. # else
  219. constexpr auto cbegin(C const& c) noexcept(noexcept(std::begin(c)))
  220. # endif
  221. -> decltype(std::begin(c))
  222. {
  223. return std::begin(c);
  224. }
  225. template <class C>
  226. # if defined(_MSC_VER) && _MSC_VER < 1900
  227. auto cend(C const& c)
  228. # else
  229. constexpr auto cend(C const& c) noexcept(noexcept(std::end(c)))
  230. # endif
  231. -> decltype(std::end(c))
  232. {
  233. return std::end(c);
  234. }
  235. #endif
  236. } // namespace cm
  237. #endif