GEOS
EnumStrings.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 Total, S.A
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
25 #ifndef GEOS_COMMON_FORMAT_ENUMSTRINGS_HPP
26 #define GEOS_COMMON_FORMAT_ENUMSTRINGS_HPP
27 
29 // #include "codingUtilities/RTTypes.hpp"
30 #include "common/DataTypes.hpp"
31 #include "common/logger/Logger.hpp"
32 #include "common/format/Format.hpp"
33 
34 #include <iostream>
35 #include <type_traits>
36 #include <algorithm>
37 
38 namespace geos
39 {
40 
41 namespace internal
42 {
48 template< typename ... ARGS >
49 constexpr int countArgs( ARGS ... )
50 {
51  return sizeof...( ARGS );
52 }
53 }
54 
79 #define ENUM_STRINGS( ENUM, ... ) \
80  inline auto const & getEnumStrings( ENUM const ) \
81  { \
82  static constexpr char const * ss[] { __VA_ARGS__ }; \
83  return ss; \
84  } \
85  \
86  inline auto const & getEnumTypeNameString( ENUM const ) \
87  { \
88  return #ENUM; \
89  } \
90  \
91  inline std::ostream & operator<<( std::ostream & os, ENUM const e ) \
92  { \
93  os << EnumStrings< ENUM >::toString( e ); \
94  return os; \
95  } \
96  \
97  inline std::istream & operator>>( std::istream & is, ENUM & e ) \
98  { \
99  string s; is >> s; \
100  e = EnumStrings< ENUM >::fromString( s ); \
101  return is; \
102  } \
103  \
104  inline string toString( ENUM const e ) \
105  { \
106  return EnumStrings< ENUM >::toString( e ); \
107  } \
108  \
109  static_assert( std::is_enum< ENUM >::value, "Not an enumeration" )
110 
115 template< typename ENUM >
117 {
119  using enum_type = ENUM;
120 
122  using base_type = std::underlying_type_t< ENUM >;
123 
127  static auto const & get()
128  {
129  return getEnumStrings( enum_type{} ); // invoke ADL
130  }
131 
137  static string concat( string const & delim = " " )
138  {
139  auto const & strings = get();
140  return stringutilities::join( std::begin( strings ), std::end( strings ), delim );
141  }
142 
150  static string toString( enum_type const & e )
151  {
152  auto const & strings = get();
153  std::size_t size = std::distance( std::begin( strings ), std::end( strings ) );
154  base_type const index = static_cast< base_type >( e );
155  GEOS_THROW_IF( index >= LvArray::integerConversion< base_type >( size ),
156  "Invalid value " << index << " of type " << getEnumTypeNameString( enum_type{} ) << ". Valid range is 0.." << size - 1,
157  InputError );
158  return strings[ index ];
159  }
160 
166  static enum_type fromString( string const & s )
167  {
168  auto const & strings = get();
169  auto const it = std::find( std::begin( strings ), std::end( strings ), s );
170  GEOS_THROW_IF( it == std::end( strings ),
171  "Invalid value '" << s << "' of type " << getEnumTypeNameString( enum_type{} ) << ". Valid options are: " << concat( ", " ),
172  InputError );
173  enum_type const e = static_cast< enum_type >( LvArray::integerConversion< base_type >( std::distance( std::begin( strings ), it ) ) );
174  return e;
175  }
176 };
177 
178 namespace internal
179 {
180 IS_VALID_EXPRESSION( HasEnumStrings, ENUM, getEnumStrings( std::declval< ENUM >() ) );
181 }
182 
183 } // namespace geos
184 
185 // Formatter specialization for enums
186 template< typename Enum >
187 struct GEOS_FMT_NS::formatter< Enum, std::enable_if_t< std::is_enum< Enum >::value && geos::internal::HasEnumStrings< Enum >, char > >
188  : GEOS_FMT_NS::formatter< std::string >
189 {
190  template< typename FormatContext >
191  auto format( Enum e, FormatContext & ctx ) const
192  {
193  return formatter< std::string >::format( toString( e ), ctx );
194  }
195 };
196 
197 // Formatter specialization for enums
198 template< typename Enum >
199 struct GEOS_FMT_NS::formatter< Enum, std::enable_if_t< std::is_enum< Enum >::value && !geos::internal::HasEnumStrings< Enum >, char > >
200  : GEOS_FMT_NS::formatter< std::underlying_type_t< Enum > >
201 {
202  template< typename FormatContext >
203  auto format( Enum e, FormatContext & ctx ) const
204  {
205  return GEOS_FMT_NS::formatter< std::underlying_type_t< Enum > >::format( toUnderlying( e ), ctx );
206  }
207 };
208 
209 #endif //GEOS_COMMON_FORMAT_ENUMSTRINGS_HPP
#define GEOS_THROW_IF(EXP, msg, TYPE)
Conditionally throw an exception.
Definition: Logger.hpp:151
std::size_t size_t
Unsigned size type.
Definition: DataTypes.hpp:79
Provides enum <-> string conversion facilities.
static enum_type fromString(string const &s)
Convert string to enum.
static auto const & get()
ENUM enum_type
Alias for the enumeration type.
std::underlying_type_t< ENUM > base_type
Alias for enum's underlying fundamental type.
static string concat(string const &delim=" ")
Get a list of valid options as a delimited string.
static string toString(enum_type const &e)
Convert enum to string.
Exception class used to report errors in user input.
Definition: Logger.hpp:502