|
||||
File indexing completed on 2025-01-18 09:54:48
0001 //----------------------------------*-C++-*----------------------------------// 0002 // Copyright 2022-2024 UT-Battelle, LLC, and other Celeritas developers. 0003 // See the top-level COPYRIGHT file for details. 0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0005 //---------------------------------------------------------------------------// 0006 //! \file corecel/io/StringEnumMapper.hh 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include <string_view> 0011 #include <type_traits> 0012 #include <unordered_map> 0013 0014 #include "corecel/Assert.hh" 0015 #include "corecel/cont/Range.hh" 0016 0017 namespace celeritas 0018 { 0019 //---------------------------------------------------------------------------// 0020 /*! 0021 * Map strings to enums for user input. 0022 * 0023 * Note that since a map is built at construction time, instances of this class 0024 * should be \c static to amortize the cost. The strings being converted *must* 0025 * exceed the lifetime of this class. (Usually it references `const char*`.) 0026 * 0027 * \todo If the size of the strings is short and there aren't a lot of them, it 0028 * will be faster to use a fixed-size array and search over them. 0029 * 0030 * Example: 0031 * \code 0032 void from_json(const nlohmann::json& j, GeantSetupOptions& opts) 0033 { 0034 static auto gspl_from_string 0035 = StringEnumMapper<PhysicsList>::from_cstring_func( 0036 to_cstring, "physics list"); 0037 opts.physics = gspl_from_string(j.at("physics").get<std::string>()); 0038 } 0039 \endcode 0040 */ 0041 template<class T> 0042 class StringEnumMapper 0043 { 0044 static_assert(std::is_enum<T>::value, "not an enum type"); 0045 static_assert(static_cast<int>(T::size_) >= 0, "invalid enum type"); 0046 0047 public: 0048 //!@{ 0049 //! \name Type aliases 0050 using EnumCStringFuncPtr = char const*(T); 0051 //!@} 0052 0053 public: 0054 // Construct from a "to_cstring" function pointer 0055 static inline StringEnumMapper<T> 0056 from_cstring_func(EnumCStringFuncPtr, char const* desc = nullptr); 0057 0058 // Construct with a function that takes an enum and returns a stringlike 0059 template<class U> 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 StringEnumMapper<T>::StringEnumMapper(U&& enum_to_string, char const* desc) 0094 : description_(desc) 0095 { 0096 map_.reserve(static_cast<std::size_t>(T::size_)); 0097 for (auto v : celeritas::range(T::size_)) 0098 { 0099 auto iter_inserted = map_.insert({enum_to_string(v), v}); 0100 CELER_ASSERT(iter_inserted.second); 0101 } 0102 } 0103 0104 //---------------------------------------------------------------------------// 0105 /*! 0106 * Convert a string_view to the corresponding enum. 0107 */ 0108 template<class T> 0109 T StringEnumMapper<T>::operator()(std::string_view s) const 0110 { 0111 auto result = map_.find(s); 0112 CELER_VALIDATE(result != map_.end(), 0113 << "invalid " << (description_ ? description_ : "value") 0114 << " '" << s << '\''); 0115 return result->second; 0116 } 0117 0118 //---------------------------------------------------------------------------// 0119 } // namespace celeritas
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |