From bfe4fb540971774890f4c0e0e59a78d2c97f11af Mon Sep 17 00:00:00 2001
From: Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de>
Date: Wed, 20 Mar 2024 19:55:25 +0000
Subject: [PATCH] cbmreco: Improve error messages when passing an unknown
 value.

---
 algo/CMakeLists.txt         |  1 +
 algo/base/Options.cxx       |  2 +-
 algo/base/util/EnumDict.cxx | 20 ++++++++++++++++++++
 algo/base/util/EnumDict.h   | 16 +++++++++++++++-
 4 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 algo/base/util/EnumDict.cxx

diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt
index fa94bdca04..b04d23c36f 100644
--- a/algo/CMakeLists.txt
+++ b/algo/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRCS
   base/MainConfig.cxx
   base/RecoParams.cxx
   base/util/StlUtils.cxx
+  base/util/EnumDict.cxx
   base/util/TimingsFormat.cxx
   data/sts/HitfinderPars.cxx
   data/sts/LandauTable.cxx
diff --git a/algo/base/Options.cxx b/algo/base/Options.cxx
index 5c4f42813a..62cb3e2690 100644
--- a/algo/base/Options.cxx
+++ b/algo/base/Options.cxx
@@ -75,7 +75,7 @@ Options::Options(int argc, char** argv)
     ("log-file,L", po::value(&fLogFile)->value_name("<file>"),
       "write log messages to file")
     ("output-types,O", po::value(&fOutputTypes)->multitoken()->value_name("<types>"),
-      "space seperated list of reconstruction output types (hit, digi, ...)")
+      "space seperated list of reconstruction output types (Hit, Tracks, RawDigi, DigiEvent, ...)")
     ("compress-archive", po::bool_switch(&fCompressArchive)->default_value(false), "Enable compression for output archives")
     ("steps", po::value(&fRecoSteps)->multitoken()->default_value({Step::Unpack, Step::DigiTrigger, Step::LocalReco, Step::Tracking})->value_name("<steps>"),
       "space seperated list of reconstruction steps (unpack, digitrigger, localreco, ...)")
diff --git a/algo/base/util/EnumDict.cxx b/algo/base/util/EnumDict.cxx
new file mode 100644
index 0000000000..a0ffd40f36
--- /dev/null
+++ b/algo/base/util/EnumDict.cxx
@@ -0,0 +1,20 @@
+/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Felix Weiglhofer [committer] */
+#include "EnumDict.h"
+
+#include <sstream>
+
+void cbm::algo::detail::RaiseUnknownEntry(std::string_view str, const std::vector<std::string_view>& validEntries)
+{
+  std::ostringstream oss;
+  oss << "Could not parse '" << str << "'. Valid entries are: ";
+
+  for (size_t i = 0; i < validEntries.size(); ++i) {
+    oss << validEntries[i];
+    if (i != validEntries.size() - 1) {
+      oss << ", ";
+    }
+  }
+  throw std::invalid_argument(oss.str());
+}
diff --git a/algo/base/util/EnumDict.h b/algo/base/util/EnumDict.h
index 9bd598e296..fde2d6d785 100644
--- a/algo/base/util/EnumDict.h
+++ b/algo/base/util/EnumDict.h
@@ -32,6 +32,18 @@ namespace cbm::algo
 
     template<typename T>
     inline constexpr bool EnumHasDict_v = EnumHasDict<T>::value;
+
+    template<typename T, typename = std::enable_if_t<detail::EnumHasDict_v<T>>>
+    std::vector<std::string_view> ValidEntries()
+    {
+      std::vector<std::string_view> entries;
+      for (const auto& pair : EnumDict<T>) {
+        entries.push_back(pair.first);
+      }
+      return entries;
+    }
+
+    void RaiseUnknownEntry(std::string_view str, const std::vector<std::string_view>& validEntries);
   }  // namespace detail
 
   template<typename T, typename = std::enable_if_t<detail::EnumHasDict_v<T>>>
@@ -112,7 +124,9 @@ namespace std
     is >> str;
     auto maybet = cbm::algo::FromString<T>(str);
 
-    if (!maybet) throw std::invalid_argument("Could not parse " + str + " as Enum");
+    if (!maybet) {
+      cbm::algo::detail::RaiseUnknownEntry(str, cbm::algo::detail::ValidEntries<T>());
+    }
     t = *maybet;
 
     return is;
-- 
GitLab