Browse Source

Merge topic 'cmrange-improvements'

b8031308f3 cmRange: Add unit tests
a8d51ef8b7 cmRange: Add functions filter and transform
da4773e8b8 cmRange: Add functions all_of, any_of, none_of
17a367e77f cmRange: Stylistic cleanup
9eb0e73f46 cmRange: Move to dedicated header file

Acked-by: Kitware Robot <[email protected]>
Acked-by: Artur Ryt <[email protected]>
Merge-request: !2972
Brad King 6 years ago
parent
commit
a4d99e4dec
41 changed files with 324 additions and 78 deletions
  1. 1 1
      Source/CTest/cmCTestMultiProcessHandler.cxx
  2. 1 1
      Source/CTest/cmCTestP4.cxx
  3. 1 1
      Source/cmAddDependenciesCommand.cxx
  4. 1 1
      Source/cmAddSubDirectoryCommand.cxx
  5. 2 65
      Source/cmAlgorithms.h
  6. 1 0
      Source/cmComputeLinkDepends.cxx
  7. 1 1
      Source/cmComputeTargetDepends.cxx
  8. 1 0
      Source/cmExtraCodeBlocksGenerator.cxx
  9. 1 1
      Source/cmFLTKWrapUICommand.cxx
  10. 1 0
      Source/cmFileCommand.cxx
  11. 1 0
      Source/cmFindBase.cxx
  12. 1 0
      Source/cmFindPackageCommand.cxx
  13. 1 0
      Source/cmForEachCommand.cxx
  14. 1 0
      Source/cmFunctionCommand.cxx
  15. 1 0
      Source/cmGeneratorTarget.cxx
  16. 1 0
      Source/cmGlobalGenerator.cxx
  17. 1 0
      Source/cmGlobalNinjaGenerator.cxx
  18. 1 1
      Source/cmInstallCommandArguments.cxx
  19. 1 1
      Source/cmInstallFilesCommand.cxx
  20. 1 0
      Source/cmListCommand.cxx
  21. 1 0
      Source/cmLocalUnixMakefileGenerator3.cxx
  22. 1 0
      Source/cmMacroCommand.cxx
  23. 1 0
      Source/cmMakefile.cxx
  24. 1 0
      Source/cmMakefileTargetGenerator.cxx
  25. 1 0
      Source/cmMessageCommand.cxx
  26. 1 0
      Source/cmParseArgumentsCommand.cxx
  27. 1 1
      Source/cmQTWrapCPPCommand.cxx
  28. 1 1
      Source/cmQTWrapUICommand.cxx
  29. 1 0
      Source/cmRST.cxx
  30. 239 0
      Source/cmRange.h
  31. 1 0
      Source/cmSetCommand.cxx
  32. 1 1
      Source/cmSetPropertyCommand.cxx
  33. 1 0
      Source/cmStateDirectory.cxx
  34. 1 0
      Source/cmStringCommand.cxx
  35. 1 0
      Source/cmSystemTools.cxx
  36. 1 0
      Source/cmTarget.cxx
  37. 1 1
      Source/cmTestGenerator.cxx
  38. 1 1
      Source/cmTryRunCommand.cxx
  39. 1 0
      Source/cmcmd.cxx
  40. 1 0
      Tests/CMakeLib/CMakeLists.txt
  41. 45 0
      Tests/CMakeLib/testRange.cxx

+ 1 - 1
Source/CTest/cmCTestMultiProcessHandler.cxx

@@ -3,12 +3,12 @@
 #include "cmCTestMultiProcessHandler.h"
 
 #include "cmAffinity.h"
-#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestRunTest.h"
 #include "cmCTestTestHandler.h"
 #include "cmDuration.h"
 #include "cmListFileCache.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 

+ 1 - 1
Source/CTest/cmCTestP4.cxx

@@ -2,10 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestP4.h"
 
-#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/RegularExpression.hxx"

+ 1 - 1
Source/cmAddDependenciesCommand.cxx

@@ -4,9 +4,9 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmRange.h"
 #include "cmTarget.h"
 
 class cmExecutionStatus;

+ 1 - 1
Source/cmAddSubDirectoryCommand.cxx

@@ -5,8 +5,8 @@
 #include <sstream>
 #include <string.h>
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;

+ 2 - 65
Source/cmAlgorithms.h

@@ -5,6 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmRange.h"
+
 #include "cm_kwiml.h"
 #include <algorithm>
 #include <functional>
@@ -156,69 +158,12 @@ private:
 };
 }
 
-template <typename const_iterator_>
-struct cmRange
-{
-  typedef const_iterator_ const_iterator;
-  typedef typename std::iterator_traits<const_iterator>::value_type value_type;
-  typedef typename std::iterator_traits<const_iterator>::difference_type
-    difference_type;
-  cmRange(const_iterator begin_, const_iterator end_)
-    : Begin(begin_)
-    , End(end_)
-  {
-  }
-  const_iterator begin() const { return Begin; }
-  const_iterator end() const { return End; }
-  bool empty() const { return std::distance(Begin, End) == 0; }
-  difference_type size() const { return std::distance(Begin, End); }
-
-  cmRange& advance(KWIML_INT_intptr_t amount) &
-  {
-    std::advance(this->Begin, amount);
-    return *this;
-  }
-  cmRange advance(KWIML_INT_intptr_t amount) &&
-  {
-    std::advance(this->Begin, amount);
-    return std::move(*this);
-  }
-
-  cmRange& retreat(KWIML_INT_intptr_t amount) &
-  {
-    std::advance(End, -amount);
-    return *this;
-  }
-
-  cmRange retreat(KWIML_INT_intptr_t amount) &&
-  {
-    std::advance(End, -amount);
-    return std::move(*this);
-  }
-
-private:
-  const_iterator Begin;
-  const_iterator End;
-};
-
 typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange;
 
 class cmListFileBacktrace;
 typedef cmRange<std::vector<cmListFileBacktrace>::const_iterator>
   cmBacktraceRange;
 
-template <typename Iter1, typename Iter2>
-cmRange<Iter1> cmMakeRange(Iter1 begin, Iter2 end)
-{
-  return cmRange<Iter1>(begin, end);
-}
-
-template <typename Range>
-cmRange<typename Range::const_iterator> cmMakeRange(Range const& range)
-{
-  return cmRange<typename Range::const_iterator>(range.begin(), range.end());
-}
-
 template <typename Range>
 void cmDeleteAll(Range const& r)
 {
@@ -334,14 +279,6 @@ 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; });
 }
 
-template <typename Range>
-cmRange<typename Range::const_reverse_iterator> cmReverseRange(
-  Range const& range)
-{
-  return cmRange<typename Range::const_reverse_iterator>(range.rbegin(),
-                                                         range.rend());
-}
-
 template <class Iter>
 std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it)
 {

+ 1 - 0
Source/cmComputeLinkDepends.cxx

@@ -9,6 +9,7 @@
 #include "cmListFileCache.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"

+ 1 - 1
Source/cmComputeTargetDepends.cxx

@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmComputeTargetDepends.h"
 
-#include "cmAlgorithms.h"
 #include "cmComputeComponentGraph.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
@@ -12,6 +11,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmStateTypes.h"

+ 1 - 0
Source/cmExtraCodeBlocksGenerator.cxx

@@ -13,6 +13,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"

+ 1 - 1
Source/cmFLTKWrapUICommand.cxx

@@ -4,9 +4,9 @@
 
 #include <stddef.h>
 
-#include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 

+ 1 - 0
Source/cmFileCommand.cxx

@@ -34,6 +34,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"
 #include "cm_sys_stat.h"

+ 1 - 0
Source/cmFindBase.cxx

@@ -9,6 +9,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmSearchPath.h"
 #include "cmState.h"
 #include "cmStateTypes.h"

+ 1 - 0
Source/cmFindPackageCommand.cxx

@@ -23,6 +23,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmRange.h"
 #include "cmSearchPath.h"
 #include "cmState.h"
 #include "cmStateTypes.h"

+ 1 - 0
Source/cmForEachCommand.cxx

@@ -11,6 +11,7 @@
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 
 cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf)

+ 1 - 0
Source/cmFunctionCommand.cxx

@@ -8,6 +8,7 @@
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmPolicies.h"
+#include "cmRange.h"
 #include "cmState.h"
 
 // define the class for function commands

+ 1 - 0
Source/cmGeneratorTarget.cxx

@@ -28,6 +28,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPropertyMap.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmSourceFileLocation.h"
 #include "cmState.h"

+ 1 - 0
Source/cmGlobalGenerator.cxx

@@ -35,6 +35,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmStateDirectory.h"

+ 1 - 0
Source/cmGlobalNinjaGenerator.cxx

@@ -26,6 +26,7 @@
 #include "cmMessageType.h"
 #include "cmNinjaLinkLineComputer.h"
 #include "cmOutputConverter.h"
+#include "cmRange.h"
 #include "cmState.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"

+ 1 - 1
Source/cmInstallCommandArguments.cxx

@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallCommandArguments.h"
 
-#include "cmAlgorithms.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 
 #include <utility>

+ 1 - 1
Source/cmInstallFilesCommand.cxx

@@ -2,12 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallFilesCommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallFilesGenerator.h"
 #include "cmInstallGenerator.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;

+ 1 - 0
Source/cmListCommand.cxx

@@ -19,6 +19,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmRange.h"
 #include "cmStringReplaceHelper.h"
 #include "cmSystemTools.h"
 

+ 1 - 0
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -22,6 +22,7 @@
 #include "cmMakefile.h"
 #include "cmMakefileTargetGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRange.h"
 #include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmState.h"

+ 1 - 0
Source/cmMacroCommand.cxx

@@ -10,6 +10,7 @@
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmPolicies.h"
+#include "cmRange.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
 

+ 1 - 0
Source/cmMakefile.cxx

@@ -31,6 +31,7 @@
 #include "cmInstallSubdirectoryGenerator.h"
 #include "cmListFileCache.h"
 #include "cmMessageType.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmSourceFileLocation.h"
 #include "cmState.h"

+ 1 - 0
Source/cmMakefileTargetGenerator.cxx

@@ -21,6 +21,7 @@
 #include "cmMakefileLibraryTargetGenerator.h"
 #include "cmMakefileUtilityTargetGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRange.h"
 #include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmState.h"

+ 1 - 0
Source/cmMessageCommand.cxx

@@ -6,6 +6,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmMessenger.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;

+ 1 - 0
Source/cmParseArgumentsCommand.cxx

@@ -10,6 +10,7 @@
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;

+ 1 - 1
Source/cmQTWrapCPPCommand.cxx

@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQTWrapCPPCommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 

+ 1 - 1
Source/cmQTWrapUICommand.cxx

@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQTWrapUICommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 

+ 1 - 0
Source/cmRST.cxx

@@ -3,6 +3,7 @@
 #include "cmRST.h"
 
 #include "cmAlgorithms.h"
+#include "cmRange.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 

+ 239 - 0
Source/cmRange.h

@@ -0,0 +1,239 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmRange_h
+#define cmRange_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+namespace RangeIterators {
+
+template <typename Iter, typename UnaryPredicate>
+class FilterIterator
+{
+public:
+  using iterator_category = std::bidirectional_iterator_tag;
+  using value_type = typename std::iterator_traits<Iter>::value_type;
+  using difference_type = typename std::iterator_traits<Iter>::difference_type;
+  using pointer = typename std::iterator_traits<Iter>::pointer;
+  using reference = typename std::iterator_traits<Iter>::reference;
+
+  FilterIterator(Iter b, Iter e, UnaryPredicate p)
+    : Cur(std::move(b))
+    , End(std::move(e))
+    , Pred(std::move(p))
+  {
+    this->SatisfyPredicate();
+  }
+
+  FilterIterator& operator++()
+  {
+    ++this->Cur;
+    this->SatisfyPredicate();
+    return *this;
+  }
+
+  FilterIterator& operator--()
+  {
+    do {
+      --this->Cur;
+    } while (!this->Pred(*this->Cur));
+    return *this;
+  }
+
+  bool operator==(FilterIterator const& other) const
+  {
+    return this->Cur == other.Cur;
+  }
+
+  bool operator!=(FilterIterator const& other) const
+  {
+    return !this->operator==(other);
+  }
+
+  auto operator*() const -> decltype(*std::declval<Iter>())
+  {
+    return *this->Cur;
+  }
+
+private:
+  void SatisfyPredicate()
+  {
+    while (this->Cur != this->End && !this->Pred(*this->Cur)) {
+      ++this->Cur;
+    }
+  }
+
+  Iter Cur;
+  Iter End;
+  UnaryPredicate Pred;
+};
+
+template <typename Iter, typename UnaryFunction>
+class TransformIterator
+{
+public:
+  using iterator_category = std::bidirectional_iterator_tag;
+  using value_type =
+    typename std::remove_cv<typename std::remove_reference<decltype(
+      std::declval<UnaryFunction>()(*std::declval<Iter>()))>::type>::type;
+  using difference_type = typename std::iterator_traits<Iter>::difference_type;
+  using pointer = value_type const*;
+  using reference = value_type const&;
+
+  TransformIterator(Iter i, UnaryFunction f)
+    : Base(std::move(i))
+    , Func(std::move(f))
+  {
+  }
+
+  TransformIterator& operator++()
+  {
+    ++this->Base;
+    return *this;
+  }
+
+  TransformIterator& operator--()
+  {
+    --this->Base;
+    return *this;
+  }
+
+  bool operator==(TransformIterator const& other) const
+  {
+    return this->Base == other.Base;
+  }
+
+  bool operator!=(TransformIterator const& other) const
+  {
+    return !this->operator==(other);
+  }
+
+  auto operator*() const
+    -> decltype(std::declval<UnaryFunction>()(*std::declval<Iter>()))
+  {
+    return this->Func(*this->Base);
+  }
+
+private:
+  Iter Base;
+  UnaryFunction Func;
+};
+
+} // namespace RangeIterators
+
+template <typename Iter>
+class cmRange
+{
+public:
+  using const_iterator = Iter;
+  using value_type = typename std::iterator_traits<Iter>::value_type;
+  using difference_type = typename std::iterator_traits<Iter>::difference_type;
+
+  cmRange(Iter b, Iter e)
+    : Begin(std::move(b))
+    , End(std::move(e))
+  {
+  }
+
+  Iter begin() const { return this->Begin; }
+  Iter end() const { return this->End; }
+  bool empty() const { return this->Begin == this->End; }
+
+  difference_type size() const
+  {
+    return std::distance(this->Begin, this->End);
+  }
+
+  cmRange& advance(difference_type amount) &
+  {
+    std::advance(this->Begin, amount);
+    return *this;
+  }
+
+  cmRange advance(difference_type amount) &&
+  {
+    std::advance(this->Begin, amount);
+    return std::move(*this);
+  }
+
+  cmRange& retreat(difference_type amount) &
+  {
+    std::advance(this->End, -amount);
+    return *this;
+  }
+
+  cmRange retreat(difference_type amount) &&
+  {
+    std::advance(this->End, -amount);
+    return std::move(*this);
+  }
+
+  template <typename UnaryPredicate>
+  bool all_of(UnaryPredicate p) const
+  {
+    return std::all_of(this->Begin, this->End, std::ref(p));
+  }
+
+  template <typename UnaryPredicate>
+  bool any_of(UnaryPredicate p) const
+  {
+    return std::any_of(this->Begin, this->End, std::ref(p));
+  }
+
+  template <typename UnaryPredicate>
+  bool none_of(UnaryPredicate p) const
+  {
+    return std::none_of(this->Begin, this->End, std::ref(p));
+  }
+
+  template <typename UnaryPredicate>
+  auto filter(UnaryPredicate p) const
+    -> cmRange<RangeIterators::FilterIterator<Iter, UnaryPredicate>>
+  {
+    using It = RangeIterators::FilterIterator<Iter, UnaryPredicate>;
+    return { It(this->Begin, this->End, p), It(this->End, this->End, p) };
+  }
+
+  template <typename UnaryFunction>
+  auto transform(UnaryFunction f) const
+    -> cmRange<RangeIterators::TransformIterator<Iter, UnaryFunction>>
+  {
+    using It = RangeIterators::TransformIterator<Iter, UnaryFunction>;
+    return { It(this->Begin, f), It(this->End, f) };
+  }
+
+private:
+  Iter Begin;
+  Iter End;
+};
+
+template <typename Iter1, typename Iter2>
+bool operator==(cmRange<Iter1> const& left, cmRange<Iter2> const& right)
+{
+  return left.size() == right.size() &&
+    std::equal(left.begin(), left.end(), right.begin());
+}
+
+template <typename Iter1, typename Iter2>
+auto cmMakeRange(Iter1 begin, Iter2 end) -> cmRange<Iter1>
+{
+  return { begin, end };
+}
+
+template <typename Range>
+auto cmMakeRange(Range const& range) -> cmRange<decltype(range.begin())>
+{
+  return { range.begin(), range.end() };
+}
+
+template <typename Range>
+auto cmReverseRange(Range const& range) -> cmRange<decltype(range.rbegin())>
+{
+  return { range.rbegin(), range.rend() };
+}
+
+#endif

+ 1 - 0
Source/cmSetCommand.cxx

@@ -5,6 +5,7 @@
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmRange.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"

+ 1 - 1
Source/cmSetPropertyCommand.cxx

@@ -4,11 +4,11 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstalledFile.h"
 #include "cmMakefile.h"
 #include "cmProperty.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmSystemTools.h"

+ 1 - 0
Source/cmStateDirectory.cxx

@@ -11,6 +11,7 @@
 #include "cmAlgorithms.h"
 #include "cmProperty.h"
 #include "cmPropertyMap.h"
+#include "cmRange.h"
 #include "cmState.h"
 #include "cmStatePrivate.h"
 #include "cmStateTypes.h"

+ 1 - 0
Source/cmStringCommand.cxx

@@ -13,6 +13,7 @@
 #include "cmCryptoHash.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
+#include "cmRange.h"
 #include "cmStringReplaceHelper.h"
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"

+ 1 - 0
Source/cmSystemTools.cxx

@@ -5,6 +5,7 @@
 #include "cmAlgorithms.h"
 #include "cmDuration.h"
 #include "cmProcessOutput.h"
+#include "cmRange.h"
 #include "cm_sys_stat.h"
 #include "cm_uv.h"
 

+ 1 - 0
Source/cmTarget.cxx

@@ -21,6 +21,7 @@
 #include "cmMessageType.h"
 #include "cmMessenger.h"
 #include "cmProperty.h"
+#include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmSourceFileLocation.h"
 #include "cmSourceFileLocationKind.h"

+ 1 - 1
Source/cmTestGenerator.cxx

@@ -5,7 +5,6 @@
 #include <ostream>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmListFileCache.h"
@@ -13,6 +12,7 @@
 #include "cmOutputConverter.h"
 #include "cmProperty.h"
 #include "cmPropertyMap.h"
+#include "cmRange.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTest.h"

+ 1 - 1
Source/cmTryRunCommand.cxx

@@ -5,10 +5,10 @@
 #include "cmsys/FStream.hxx"
 #include <stdio.h>
 
-#include "cmAlgorithms.h"
 #include "cmDuration.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmRange.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"

+ 1 - 0
Source/cmcmd.cxx

@@ -9,6 +9,7 @@
 #include "cmMakefile.h"
 #include "cmQtAutoGeneratorMocUic.h"
 #include "cmQtAutoGeneratorRcc.h"
+#include "cmRange.h"
 #include "cmState.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"

+ 1 - 0
Tests/CMakeLib/CMakeLists.txt

@@ -7,6 +7,7 @@ include_directories(
 set(CMakeLib_TESTS
   testGeneratedFileStream.cxx
   testRST.cxx
+  testRange.cxx
   testString.cxx
   testSystemTools.cxx
   testUTF8.cxx

+ 45 - 0
Tests/CMakeLib/testRange.cxx

@@ -0,0 +1,45 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmRange.h"
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#define ASSERT_TRUE(x)                                                        \
+  do {                                                                        \
+    if (!(x)) {                                                               \
+      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
+      return false;                                                           \
+    }                                                                         \
+  } while (false)
+
+int testRange(int /*unused*/, char* /*unused*/ [])
+{
+  std::vector<int> const testData = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+  ASSERT_TRUE(!cmMakeRange(testData).empty());
+  ASSERT_TRUE(cmMakeRange(testData).size() == 10);
+
+  ASSERT_TRUE(!cmMakeRange(testData).advance(5).empty());
+  ASSERT_TRUE(cmMakeRange(testData).advance(5).size() == 5);
+
+  ASSERT_TRUE(cmMakeRange(testData).advance(5).retreat(5).empty());
+  ASSERT_TRUE(cmMakeRange(testData).advance(5).retreat(5).size() == 0);
+
+  ASSERT_TRUE(cmMakeRange(testData).any_of([](int n) { return n % 3 == 0; }));
+  ASSERT_TRUE(cmMakeRange(testData).all_of([](int n) { return n < 11; }));
+  ASSERT_TRUE(cmMakeRange(testData).none_of([](int n) { return n > 11; }));
+
+  std::vector<int> const evenData = { 2, 4, 6, 8, 10 };
+  ASSERT_TRUE(cmMakeRange(testData).filter([](int n) { return n % 2 == 0; }) ==
+              cmMakeRange(evenData));
+
+  std::vector<std::string> const stringRange = { "1", "2", "3", "4", "5" };
+  ASSERT_TRUE(cmMakeRange(testData)
+                .transform([](int n) { return std::to_string(n); })
+                .retreat(5) == cmMakeRange(stringRange));
+
+  return 0;
+}