From b66b7464ab09420f150daaec7571da31dc361cc0 Mon Sep 17 00:00:00 2001
From: Regina Pfeifer <regina@mailbox.org>
Date: Sun, 7 Apr 2019 22:14:52 +0200
Subject: [PATCH] Introduce cmSubcommandTable

---
 Source/CMakeLists.txt        |  2 ++
 Source/cmSubcommandTable.cxx | 31 +++++++++++++++++++++++++++++++
 Source/cmSubcommandTable.h   | 36 ++++++++++++++++++++++++++++++++++++
 bootstrap                    |  1 +
 4 files changed, 70 insertions(+)
 create mode 100644 Source/cmSubcommandTable.cxx
 create mode 100644 Source/cmSubcommandTable.h

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index b1f4ca51cc..ee82ff5be1 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -639,6 +639,8 @@ set(SRCS
   cmStringReplaceHelper.cxx
   cmStringCommand.cxx
   cmStringCommand.h
+  cmSubcommandTable.cxx
+  cmSubcommandTable.h
   cmSubdirCommand.cxx
   cmSubdirCommand.h
   cmSubdirDependsCommand.cxx
diff --git a/Source/cmSubcommandTable.cxx b/Source/cmSubcommandTable.cxx
new file mode 100644
index 0000000000..f6194f816d
--- /dev/null
+++ b/Source/cmSubcommandTable.cxx
@@ -0,0 +1,31 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmSubcommandTable.h"
+
+#include <algorithm>
+
+#include "cmExecutionStatus.h"
+#include "cmStringAlgorithms.h"
+
+cmSubcommandTable::cmSubcommandTable(std::initializer_list<InitElem> init)
+  : Impl(init.begin(), init.end())
+{
+  std::sort(this->Impl.begin(), this->Impl.end(),
+            [](Elem const& left, Elem const& right) {
+              return left.first < right.first;
+            });
+}
+
+bool cmSubcommandTable::operator()(cm::string_view key,
+                                   std::vector<std::string> const& args,
+                                   cmExecutionStatus& status) const
+{
+  auto const it = std::lower_bound(
+    this->Impl.begin(), this->Impl.end(), key,
+    [](Elem const& elem, cm::string_view k) { return elem.first < k; });
+  if (it != this->Impl.end() && it->first == key) {
+    return it->second(args, status);
+  }
+  status.SetError(cmStrCat("does not recognize sub-command ", key));
+  return false;
+}
diff --git a/Source/cmSubcommandTable.h b/Source/cmSubcommandTable.h
new file mode 100644
index 0000000000..21342bbab6
--- /dev/null
+++ b/Source/cmSubcommandTable.h
@@ -0,0 +1,36 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmSubcommandTable_h
+#define cmSubcommandTable_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_static_string_view.hxx"
+#include "cm_string_view.hxx"
+
+#include <initializer_list>
+#include <string>
+#include <utility>
+#include <vector>
+
+class cmExecutionStatus;
+
+class cmSubcommandTable
+{
+public:
+  using Command = bool (*)(std::vector<std::string> const&,
+                           cmExecutionStatus&);
+
+  using Elem = std::pair<cm::string_view, Command>;
+  using InitElem = std::pair<cm::static_string_view, Command>;
+
+  cmSubcommandTable(std::initializer_list<InitElem> init);
+
+  bool operator()(cm::string_view key, std::vector<std::string> const& args,
+                  cmExecutionStatus& status) const;
+
+private:
+  std::vector<Elem> Impl;
+};
+
+#endif
diff --git a/bootstrap b/bootstrap
index 06e11b5e31..c97a5d4e56 100755
--- a/bootstrap
+++ b/bootstrap
@@ -426,6 +426,7 @@ CMAKE_CXX_SOURCES="\
   cmStringAlgorithms \
   cmStringReplaceHelper \
   cmStringCommand \
+  cmSubcommandTable \
   cmSubdirCommand \
   cmSystemTools \
   cmTarget \
-- 
GitLab