cmAlgorithms.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2015 Stephen Kelly <[email protected]>
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #ifndef cmAlgorithms_h
  11. #define cmAlgorithms_h
  12. #include <cmConfigure.h>
  13. #include "cmStandardIncludes.h"
  14. inline bool cmHasLiteralPrefixImpl(const std::string& str1, const char* str2,
  15. size_t N)
  16. {
  17. return strncmp(str1.c_str(), str2, N) == 0;
  18. }
  19. inline bool cmHasLiteralPrefixImpl(const char* str1, const char* str2,
  20. size_t N)
  21. {
  22. return strncmp(str1, str2, N) == 0;
  23. }
  24. inline bool cmHasLiteralSuffixImpl(const std::string& str1, const char* str2,
  25. size_t N)
  26. {
  27. size_t len = str1.size();
  28. return len >= N && strcmp(str1.c_str() + len - N, str2) == 0;
  29. }
  30. inline bool cmHasLiteralSuffixImpl(const char* str1, const char* str2,
  31. size_t N)
  32. {
  33. size_t len = strlen(str1);
  34. return len >= N && strcmp(str1 + len - N, str2) == 0;
  35. }
  36. template <typename T, size_t N>
  37. const T* cmArrayBegin(const T (&a)[N])
  38. {
  39. return a;
  40. }
  41. template <typename T, size_t N>
  42. const T* cmArrayEnd(const T (&a)[N])
  43. {
  44. return a + N;
  45. }
  46. template <typename T, size_t N>
  47. size_t cmArraySize(const T (&)[N])
  48. {
  49. return N;
  50. }
  51. template <typename T, size_t N>
  52. bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N])
  53. {
  54. return cmHasLiteralPrefixImpl(str1, str2, N - 1);
  55. }
  56. template <typename T, size_t N>
  57. bool cmHasLiteralSuffix(const T& str1, const char (&str2)[N])
  58. {
  59. return cmHasLiteralSuffixImpl(str1, str2, N - 1);
  60. }
  61. struct cmStrCmp
  62. {
  63. cmStrCmp(const char* test)
  64. : m_test(test)
  65. {
  66. }
  67. cmStrCmp(const std::string& test)
  68. : m_test(test)
  69. {
  70. }
  71. bool operator()(const std::string& input) const { return m_test == input; }
  72. bool operator()(const char* input) const
  73. {
  74. return strcmp(input, m_test.c_str()) == 0;
  75. }
  76. private:
  77. const std::string m_test;
  78. };
  79. template <typename FwdIt>
  80. FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last)
  81. {
  82. const typename std::iterator_traits<FwdIt>::difference_type dist =
  83. std::distance(middle, last);
  84. std::rotate(first, middle, last);
  85. std::advance(first, dist);
  86. return first;
  87. }
  88. namespace ContainerAlgorithms {
  89. template <typename T>
  90. struct cmIsPair
  91. {
  92. enum
  93. {
  94. value = false
  95. };
  96. };
  97. template <typename K, typename V>
  98. struct cmIsPair<std::pair<K, V> >
  99. {
  100. enum
  101. {
  102. value = true
  103. };
  104. };
  105. template <typename Range,
  106. bool valueTypeIsPair = cmIsPair<typename Range::value_type>::value>
  107. struct DefaultDeleter
  108. {
  109. void operator()(typename Range::value_type value) const { delete value; }
  110. };
  111. template <typename Range>
  112. struct DefaultDeleter<Range, /* valueTypeIsPair = */ true>
  113. {
  114. void operator()(typename Range::value_type value) const
  115. {
  116. delete value.second;
  117. }
  118. };
  119. template <typename FwdIt>
  120. FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n)
  121. {
  122. FwdIt m = i1;
  123. std::advance(m, n);
  124. return cmRotate(i1, m, i2);
  125. }
  126. template <typename Range>
  127. struct BinarySearcher
  128. {
  129. typedef typename Range::value_type argument_type;
  130. BinarySearcher(Range const& r)
  131. : m_range(r)
  132. {
  133. }
  134. bool operator()(argument_type const& item) const
  135. {
  136. return std::binary_search(m_range.begin(), m_range.end(), item);
  137. }
  138. private:
  139. Range const& m_range;
  140. };
  141. }
  142. template <typename const_iterator_>
  143. struct cmRange
  144. {
  145. typedef const_iterator_ const_iterator;
  146. typedef typename std::iterator_traits<const_iterator>::value_type value_type;
  147. typedef typename std::iterator_traits<const_iterator>::difference_type
  148. difference_type;
  149. cmRange(const_iterator begin_, const_iterator end_)
  150. : Begin(begin_)
  151. , End(end_)
  152. {
  153. }
  154. const_iterator begin() const { return Begin; }
  155. const_iterator end() const { return End; }
  156. bool empty() const { return std::distance(Begin, End) == 0; }
  157. difference_type size() const { return std::distance(Begin, End); }
  158. cmRange& advance(KWIML_INT_intptr_t amount)
  159. {
  160. std::advance(Begin, amount);
  161. return *this;
  162. }
  163. cmRange& retreat(KWIML_INT_intptr_t amount)
  164. {
  165. std::advance(End, -amount);
  166. return *this;
  167. }
  168. private:
  169. const_iterator Begin;
  170. const_iterator End;
  171. };
  172. typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange;
  173. class cmListFileBacktrace;
  174. typedef cmRange<std::vector<cmListFileBacktrace>::const_iterator>
  175. cmBacktraceRange;
  176. template <typename Iter1, typename Iter2>
  177. cmRange<Iter1> cmMakeRange(Iter1 begin, Iter2 end)
  178. {
  179. return cmRange<Iter1>(begin, end);
  180. }
  181. template <typename Range>
  182. cmRange<typename Range::const_iterator> cmMakeRange(Range const& range)
  183. {
  184. return cmRange<typename Range::const_iterator>(range.begin(), range.end());
  185. }
  186. template <typename Range>
  187. void cmDeleteAll(Range const& r)
  188. {
  189. std::for_each(r.begin(), r.end(),
  190. ContainerAlgorithms::DefaultDeleter<Range>());
  191. }
  192. template <typename Range>
  193. std::string cmJoin(Range const& r, const char* delimiter)
  194. {
  195. if (r.empty()) {
  196. return std::string();
  197. }
  198. std::ostringstream os;
  199. typedef typename Range::value_type ValueType;
  200. typedef typename Range::const_iterator InputIt;
  201. const InputIt first = r.begin();
  202. InputIt last = r.end();
  203. --last;
  204. std::copy(first, last, std::ostream_iterator<ValueType>(os, delimiter));
  205. os << *last;
  206. return os.str();
  207. }
  208. template <typename Range>
  209. std::string cmJoin(Range const& r, std::string delimiter)
  210. {
  211. return cmJoin(r, delimiter.c_str());
  212. }
  213. template <typename Range>
  214. typename Range::const_iterator cmRemoveN(Range& r, size_t n)
  215. {
  216. return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n);
  217. }
  218. template <typename Range, typename InputRange>
  219. typename Range::const_iterator cmRemoveIndices(Range& r, InputRange const& rem)
  220. {
  221. typename InputRange::const_iterator remIt = rem.begin();
  222. typename InputRange::const_iterator remEnd = rem.end();
  223. const typename Range::iterator rangeEnd = r.end();
  224. if (remIt == remEnd) {
  225. return rangeEnd;
  226. }
  227. typename Range::iterator writer = r.begin();
  228. std::advance(writer, *remIt);
  229. typename Range::iterator pivot = writer;
  230. typename InputRange::value_type prevRem = *remIt;
  231. ++remIt;
  232. size_t count = 1;
  233. for (; writer != rangeEnd && remIt != remEnd; ++count, ++remIt) {
  234. std::advance(pivot, *remIt - prevRem);
  235. prevRem = *remIt;
  236. writer = ContainerAlgorithms::RemoveN(writer, pivot, count);
  237. }
  238. return ContainerAlgorithms::RemoveN(writer, rangeEnd, count);
  239. }
  240. template <typename Range, typename MatchRange>
  241. typename Range::const_iterator cmRemoveMatching(Range& r, MatchRange const& m)
  242. {
  243. return std::remove_if(r.begin(), r.end(),
  244. ContainerAlgorithms::BinarySearcher<MatchRange>(m));
  245. }
  246. namespace ContainerAlgorithms {
  247. template <typename Range, typename T = typename Range::value_type>
  248. struct RemoveDuplicatesAPI
  249. {
  250. typedef typename Range::const_iterator const_iterator;
  251. typedef typename Range::const_iterator value_type;
  252. static bool lessThan(value_type a, value_type b) { return *a < *b; }
  253. static value_type uniqueValue(const_iterator a) { return a; }
  254. template <typename It>
  255. static bool valueCompare(It it, const_iterator it2)
  256. {
  257. return **it != *it2;
  258. }
  259. };
  260. template <typename Range, typename T>
  261. struct RemoveDuplicatesAPI<Range, T*>
  262. {
  263. typedef typename Range::const_iterator const_iterator;
  264. typedef T* value_type;
  265. static bool lessThan(value_type a, value_type b) { return a < b; }
  266. static value_type uniqueValue(const_iterator a) { return *a; }
  267. template <typename It>
  268. static bool valueCompare(It it, const_iterator it2)
  269. {
  270. return *it != *it2;
  271. }
  272. };
  273. }
  274. template <typename Range>
  275. typename Range::const_iterator cmRemoveDuplicates(Range& r)
  276. {
  277. typedef typename ContainerAlgorithms::RemoveDuplicatesAPI<Range> API;
  278. typedef typename API::value_type T;
  279. std::vector<T> unique;
  280. unique.reserve(r.size());
  281. std::vector<size_t> indices;
  282. size_t count = 0;
  283. const typename Range::const_iterator end = r.end();
  284. for (typename Range::const_iterator it = r.begin(); it != end;
  285. ++it, ++count) {
  286. const typename std::vector<T>::iterator low = std::lower_bound(
  287. unique.begin(), unique.end(), API::uniqueValue(it), API::lessThan);
  288. if (low == unique.end() || API::valueCompare(low, it)) {
  289. unique.insert(low, API::uniqueValue(it));
  290. } else {
  291. indices.push_back(count);
  292. }
  293. }
  294. if (indices.empty()) {
  295. return end;
  296. }
  297. return cmRemoveIndices(r, indices);
  298. }
  299. template <typename Range>
  300. std::string cmWrap(std::string prefix, Range const& r, std::string suffix,
  301. std::string sep)
  302. {
  303. if (r.empty()) {
  304. return std::string();
  305. }
  306. return prefix + cmJoin(r, (suffix + sep + prefix).c_str()) + suffix;
  307. }
  308. template <typename Range>
  309. std::string cmWrap(char prefix, Range const& r, char suffix, std::string sep)
  310. {
  311. return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep);
  312. }
  313. template <typename Range, typename T>
  314. typename Range::const_iterator cmFindNot(Range const& r, T const& t)
  315. {
  316. return std::find_if(r.begin(), r.end(),
  317. std::bind1st(std::not_equal_to<T>(), t));
  318. }
  319. template <typename Range>
  320. cmRange<typename Range::const_reverse_iterator> cmReverseRange(
  321. Range const& range)
  322. {
  323. return cmRange<typename Range::const_reverse_iterator>(range.rbegin(),
  324. range.rend());
  325. }
  326. template <class Iter>
  327. std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it)
  328. {
  329. return std::reverse_iterator<Iter>(it);
  330. }
  331. inline bool cmHasSuffix(const std::string& str, const std::string& suffix)
  332. {
  333. if (str.size() < suffix.size()) {
  334. return false;
  335. }
  336. return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
  337. }
  338. inline void cmStripSuffixIfExists(std::string& str, const std::string& suffix)
  339. {
  340. if (cmHasSuffix(str, suffix)) {
  341. str.resize(str.size() - suffix.size());
  342. }
  343. }
  344. #endif