CMake/Source/cmAlgorithms.h

186 lines
4.4 KiB
C
Raw Normal View History

Simplify CMake per-source license notices Per-source copyright/license notice headers that spell out copyright holder names and years are hard to maintain and often out-of-date or plain wrong. Precise contributor information is already maintained automatically by the version control tool. Ultimately it is the receiver of a file who is responsible for determining its licensing status, and per-source notices are merely a convenience. Therefore it is simpler and more accurate for each source to have a generic notice of the license name and references to more detailed information on copyright holders and full license terms. Our `Copyright.txt` file now contains a list of Contributors whose names appeared source-level copyright notices. It also references version control history for more precise information. Therefore we no longer need to spell out the list of Contributors in each source file notice. Replace CMake per-source copyright/license notice headers with a short description of the license and links to `Copyright.txt` and online information available from "https://cmake.org/licensing". The online URL also handles cases of modules being copied out of our source into other projects, so we can drop our notices about replacing links with full license text. Run the `Utilities/Scripts/filter-notices.bash` script to perform the majority of the replacements mechanically. Manually fix up shebang lines and trailing newlines in a few files. Manually update the notices in a few files that the script does not handle.
2016-09-27 19:01:08 +00:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmAlgorithms_h
#define cmAlgorithms_h
#include "cmConfigure.h" // IWYU pragma: keep
#include <algorithm>
#include <functional>
#include <iterator>
#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>
#include "cm_kwiml.h"
#include "cmRange.h"
template <std::size_t N>
struct cmOverloadPriority : cmOverloadPriority<N - 1>
{
};
template <>
struct cmOverloadPriority<0>
{
};
template <typename FwdIt>
FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last)
{
const typename std::iterator_traits<FwdIt>::difference_type dist =
std::distance(middle, last);
std::rotate(first, middle, last);
std::advance(first, dist);
return first;
}
template <typename Range, typename Key>
auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<2>)
-> decltype(range.exists(key))
{
return range.exists(key);
}
template <typename Range, typename Key>
auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<1>)
-> decltype(range.find(key) != range.end())
{
return range.find(key) != range.end();
}
template <typename Range, typename Key>
bool cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<0>)
{
using std::begin;
using std::end;
return std::find(begin(range), end(range), key) != end(range);
}
template <typename Range, typename Key>
bool cmContains(Range const& range, Key const& key)
{
return cmContainsImpl(range, key, cmOverloadPriority<2>{});
}
namespace ContainerAlgorithms {
template <typename FwdIt>
FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n)
{
FwdIt m = i1;
std::advance(m, n);
return cmRotate(i1, m, i2);
}
template <typename Range>
struct BinarySearcher
{
2019-08-23 21:25:56 +00:00
using argument_type = typename Range::value_type;
BinarySearcher(Range const& r)
: m_range(r)
{
}
bool operator()(argument_type const& item) const
{
return std::binary_search(m_range.begin(), m_range.end(), item);
}
private:
Range const& m_range;
};
}
class cmListFileBacktrace;
2019-08-23 21:25:56 +00:00
using cmBacktraceRange =
cmRange<std::vector<cmListFileBacktrace>::const_iterator>;
template <typename Range>
typename Range::const_iterator cmRemoveN(Range& r, size_t n)
{
return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n);
}
template <typename Range, typename InputRange>
typename Range::const_iterator cmRemoveIndices(Range& r, InputRange const& rem)
{
typename InputRange::const_iterator remIt = rem.begin();
typename InputRange::const_iterator remEnd = rem.end();
const auto rangeEnd = r.end();
if (remIt == remEnd) {
return rangeEnd;
}
auto writer = r.begin();
std::advance(writer, *remIt);
auto pivot = writer;
typename InputRange::value_type prevRem = *remIt;
++remIt;
size_t count = 1;
for (; writer != rangeEnd && remIt != remEnd; ++count, ++remIt) {
std::advance(pivot, *remIt - prevRem);
prevRem = *remIt;
writer = ContainerAlgorithms::RemoveN(writer, pivot, count);
}
return ContainerAlgorithms::RemoveN(writer, rangeEnd, count);
}
template <typename Range, typename MatchRange>
typename Range::const_iterator cmRemoveMatching(Range& r, MatchRange const& m)
{
return std::remove_if(r.begin(), r.end(),
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
}
template <typename ForwardIterator>
ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last)
{
using Value = typename std::iterator_traits<ForwardIterator>::value_type;
using Hash = struct
{
std::size_t operator()(ForwardIterator it) const
{
return std::hash<Value>{}(*it);
}
};
using Equal = struct
{
bool operator()(ForwardIterator it1, ForwardIterator it2) const
{
return *it1 == *it2;
}
};
std::unordered_set<ForwardIterator, Hash, Equal> uniq;
ForwardIterator result = first;
while (first != last) {
if (!cmContains(uniq, first)) {
if (result != first) {
*result = std::move(*first);
}
uniq.insert(result);
++result;
}
++first;
}
return result;
}
template <typename Range>
typename Range::const_iterator cmRemoveDuplicates(Range& r)
{
return cmRemoveDuplicates(r.begin(), r.end());
}
template <typename Range, typename T>
2015-02-11 22:53:41 +00:00
typename Range::const_iterator cmFindNot(Range const& r, T const& t)
{
return std::find_if(r.begin(), r.end(), [&t](T const& i) { return i != t; });
2015-02-11 22:53:41 +00:00
}
#endif