Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:55:05

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/io/StringEnumMapper.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <string_view>
0010 #include <type_traits>
0011 #include <unordered_map>
0012 
0013 #include "corecel/Assert.hh"
0014 #include "corecel/cont/Range.hh"
0015 
0016 namespace celeritas
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Map strings to enums for user input.
0021  *
0022  * Note that since a map is built at construction time, instances of this class
0023  * should be \c static to amortize the cost. The strings being converted *must*
0024  * exceed the lifetime of this class. (Usually it references `const char*`.)
0025  *
0026  * \todo If the size of the strings is short and there aren't a lot of them, it
0027  * will be faster to use a fixed-size array and search over them.
0028  *
0029  * Example:
0030  * \code
0031 void from_json(const nlohmann::json& j, GeantSetupOptions& opts)
0032 {
0033     static auto gspl_from_string
0034         = StringEnumMapper<PhysicsList>::from_cstring_func(
0035             to_cstring, "physics list");
0036     opts.physics = gspl_from_string(j.at("physics").get<std::string>());
0037 }
0038    \endcode
0039  */
0040 template<class T>
0041 class StringEnumMapper
0042 {
0043     static_assert(std::is_enum<T>::value, "not an enum type");
0044     static_assert(static_cast<int>(T::size_) >= 0, "invalid enum type");
0045 
0046   public:
0047     //!@{
0048     //! \name Type aliases
0049     using EnumCStringFuncPtr = char const*(T);
0050     //!@}
0051 
0052   public:
0053     // Construct from a "to_cstring" function pointer
0054     static inline StringEnumMapper<T>
0055     from_cstring_func(EnumCStringFuncPtr, char const* desc = nullptr);
0056 
0057     // Construct with a function that takes an enum and returns a stringlike
0058     template<class U>
0059     // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
0060     explicit inline StringEnumMapper(U&& enum_to_string,
0061                                      char const* desc = nullptr);
0062 
0063     // Convert from a string
0064     inline T operator()(std::string_view s) const;
0065 
0066   private:
0067     char const* description_;
0068     std::unordered_map<std::string_view, T> map_;
0069 };
0070 
0071 //---------------------------------------------------------------------------//
0072 // INLINE DEFINITIONS
0073 //---------------------------------------------------------------------------//
0074 /*!
0075  * Construct using a \c to_cstring function.
0076  */
0077 template<class T>
0078 StringEnumMapper<T>
0079 StringEnumMapper<T>::from_cstring_func(EnumCStringFuncPtr fp, char const* desc)
0080 {
0081     CELER_EXPECT(fp);
0082     return StringEnumMapper<T>{fp, desc};
0083 }
0084 
0085 //---------------------------------------------------------------------------//
0086 /*!
0087  * Construct with a "stringify" function.
0088  *
0089  * The result just has to be implicitly convertible to a \c std::string_view .
0090  */
0091 template<class T>
0092 template<class U>
0093 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
0094 StringEnumMapper<T>::StringEnumMapper(U&& enum_to_string, char const* desc)
0095     : description_(desc)
0096 {
0097     map_.reserve(static_cast<std::size_t>(T::size_));
0098     for (auto v : celeritas::range(T::size_))
0099     {
0100         auto iter_inserted = map_.insert({enum_to_string(v), v});
0101         CELER_ASSERT(iter_inserted.second);
0102     }
0103 }
0104 
0105 //---------------------------------------------------------------------------//
0106 /*!
0107  * Convert a string_view to the corresponding enum.
0108  */
0109 template<class T>
0110 T StringEnumMapper<T>::operator()(std::string_view s) const
0111 {
0112     auto result = map_.find(s);
0113     CELER_VALIDATE(result != map_.end(),
0114                    << "invalid " << (description_ ? description_ : "value")
0115                    << " '" << s << '\'');
0116     return result->second;
0117 }
0118 
0119 //---------------------------------------------------------------------------//
0120 }  // namespace celeritas