mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	First commit of STRINGIFY_ENUM
This commit is contained in:
		
							
								
								
									
										68
									
								
								include/internal/catch_enum_values_registry.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								include/internal/catch_enum_values_registry.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /* | ||||
|  *  Created by Phil on 4/4/2019. | ||||
|  *  Copyright 2019 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  */ | ||||
| #include "catch_enum_values_registry.h" | ||||
| #include "catch_string_manip.h" | ||||
| #include "catch_stream.h" | ||||
|  | ||||
| #include <map> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {} | ||||
|     IEnumInfo::~IEnumInfo() {} | ||||
|  | ||||
|     namespace Detail { | ||||
|  | ||||
|         std::vector<std::string> parseEnums( StringRef enums ) { | ||||
|             auto enumValues = splitString( enums, ',' ); | ||||
|             std::vector<std::string> parsed; | ||||
|             parsed.reserve( enumValues.size() ); | ||||
|             for( auto const& enumValue : enumValues ) { | ||||
|                 auto identifiers = splitString( enumValue, ':' ); | ||||
|                 parsed.push_back( Catch::trim( identifiers.back() ) ); | ||||
|             } | ||||
|             return parsed; | ||||
|         } | ||||
|  | ||||
|         struct EnumInfo : IEnumInfo { | ||||
|             std::string m_name; | ||||
|             std::map<int, std::string> m_values; | ||||
|  | ||||
|             ~EnumInfo(); | ||||
|  | ||||
|             std::string lookup( int value ) const override { | ||||
|                 auto it = m_values.find( value ); | ||||
|                 if( it == m_values.end() ) { | ||||
|                     ReusableStringStream rss; | ||||
|                     rss << "{** unexpected value for " << m_name << ": " << value << "**}"; | ||||
|                     return rss.str(); | ||||
|                 } | ||||
|                 return it->second; | ||||
|             } | ||||
|         }; | ||||
|         EnumInfo::~EnumInfo() {} | ||||
|  | ||||
|         IEnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { | ||||
|             std::unique_ptr<EnumInfo> enumInfo( new EnumInfo ); | ||||
|             enumInfo->m_name = enumName; | ||||
|  | ||||
|             const auto valueNames = Catch::Detail::parseEnums( allValueNames ); | ||||
|             assert( valueNames.size() == values.size() ); | ||||
|             std::size_t i = 0; | ||||
|             for( auto value : values ) | ||||
|                 enumInfo->m_values.insert({ value, valueNames[i++] }); | ||||
|  | ||||
|             EnumInfo* raw = enumInfo.get(); | ||||
|             m_enumInfos.push_back( std::move( enumInfo ) ); | ||||
|             return *raw; | ||||
|         } | ||||
|  | ||||
|     } // Detail | ||||
|  | ||||
| } // Catch | ||||
|  | ||||
							
								
								
									
										32
									
								
								include/internal/catch_enum_values_registry.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								include/internal/catch_enum_values_registry.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
|  *  Created by Phil on 4/4/2019. | ||||
|  *  Copyright 2019 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_ENUMVALUESREGISTRY_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_ENUMVALUESREGISTRY_H_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_enum_values_registry.h" | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     namespace Detail { | ||||
|  | ||||
|         class EnumValuesRegistry : public IMutableEnumValuesRegistry { | ||||
|  | ||||
|             std::vector<std::unique_ptr<IEnumInfo>> m_enumInfos; | ||||
|  | ||||
|             IEnumInfo const& registerEnum(StringRef enumName, StringRef allEnums, std::vector<int> const& values) override; | ||||
|         }; | ||||
|  | ||||
|         std::vector<std::string> parseEnums( StringRef enums ); | ||||
|  | ||||
|     } // Detail | ||||
|  | ||||
| } // Catch | ||||
|  | ||||
| #endif //TWOBLUECUBES_CATCH_ENUMVALUESREGISTRY_H_INCLUDED | ||||
							
								
								
									
										40
									
								
								include/internal/catch_interfaces_enum_values_registry.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								include/internal/catch_interfaces_enum_values_registry.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|  *  Created by Phil on 4/4/2019. | ||||
|  *  Copyright 2019 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_INTERFACESENUMVALUESREGISTRY_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_INTERFACESENUMVALUESREGISTRY_H_INCLUDED | ||||
|  | ||||
| #include "catch_stringref.h" | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     struct IEnumInfo { | ||||
|         virtual ~IEnumInfo(); | ||||
|  | ||||
|         virtual std::string lookup( int value ) const = 0; | ||||
|     }; | ||||
|  | ||||
|     struct IMutableEnumValuesRegistry { | ||||
|         virtual ~IMutableEnumValuesRegistry(); | ||||
|  | ||||
|         virtual IEnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0; | ||||
|  | ||||
|         template<typename E> | ||||
|         IEnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) { | ||||
|             std::vector<int> intValues; | ||||
|             intValues.reserve( values.size() ); | ||||
|             for( auto enumValue : values ) | ||||
|                 intValues.push_back( static_cast<int>( enumValue ) ); | ||||
|             return registerEnum( enumName, allEnums, intValues ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| } // Catch | ||||
|  | ||||
| #endif //TWOBLUECUBES_CATCH_INTERFACESENUMVALUESREGISTRY_H_INCLUDED | ||||
| @@ -22,6 +22,8 @@ namespace Catch { | ||||
|     struct IReporterRegistry; | ||||
|     struct IReporterFactory; | ||||
|     struct ITagAliasRegistry; | ||||
|     struct IMutableEnumValuesRegistry; | ||||
|  | ||||
|     class StartupExceptionRegistry; | ||||
|  | ||||
|     using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; | ||||
| @@ -32,7 +34,6 @@ namespace Catch { | ||||
|         virtual IReporterRegistry const& getReporterRegistry() const = 0; | ||||
|         virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; | ||||
|         virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; | ||||
|  | ||||
|         virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; | ||||
|  | ||||
|  | ||||
| @@ -47,6 +48,7 @@ namespace Catch { | ||||
|         virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; | ||||
|         virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; | ||||
|         virtual void registerStartupException() noexcept = 0; | ||||
|         virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; | ||||
|     }; | ||||
|  | ||||
|     IRegistryHub const& getRegistryHub(); | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "catch_tag_alias_registry.h" | ||||
| #include "catch_startup_exception_registry.h" | ||||
| #include "catch_singletons.hpp" | ||||
| #include "catch_enum_values_registry.h" | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
| @@ -60,6 +61,9 @@ namespace Catch { | ||||
|             void registerStartupException() noexcept override { | ||||
|                 m_exceptionRegistry.add(std::current_exception()); | ||||
|             } | ||||
|             IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { | ||||
|                 return m_enumValuesRegistry; | ||||
|             } | ||||
|  | ||||
|         private: | ||||
|             TestRegistry m_testCaseRegistry; | ||||
| @@ -67,6 +71,7 @@ namespace Catch { | ||||
|             ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; | ||||
|             TagAliasRegistry m_tagAliasRegistry; | ||||
|             StartupExceptionRegistry m_exceptionRegistry; | ||||
|             Detail::EnumValuesRegistry m_enumValuesRegistry; | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -6,11 +6,13 @@ | ||||
|  */ | ||||
|  | ||||
| #include "catch_string_manip.h" | ||||
| #include "catch_stringref.h" | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <ostream> | ||||
| #include <cstring> | ||||
| #include <cctype> | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
| @@ -65,6 +67,21 @@ namespace Catch { | ||||
|         return replaced; | ||||
|     } | ||||
|  | ||||
|     std::vector<std::string> splitString( StringRef str, char delimiter ) { | ||||
|         std::vector<std::string> subStrings; | ||||
|         std::size_t start = 0; | ||||
|         for(std::size_t pos = 0; pos < str.size(); ++pos ) { | ||||
|             if( str[pos] == delimiter ) { | ||||
|                 if( pos - start > 1 ) | ||||
|                     subStrings.push_back( str.substr( start, pos-start ) ); | ||||
|                 start = pos+1; | ||||
|             } | ||||
|         } | ||||
|         if( start < str.size() ) | ||||
|             subStrings.push_back( str.substr( start, str.size()-start ) ); | ||||
|         return subStrings; | ||||
|     } | ||||
|  | ||||
|     pluralise::pluralise( std::size_t count, std::string const& label ) | ||||
|     :   m_count( count ), | ||||
|         m_label( label ) | ||||
|   | ||||
| @@ -12,6 +12,8 @@ | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     class StringRef; | ||||
|  | ||||
|     bool startsWith( std::string const& s, std::string const& prefix ); | ||||
|     bool startsWith( std::string const& s, char prefix ); | ||||
|     bool endsWith( std::string const& s, std::string const& suffix ); | ||||
| @@ -21,6 +23,7 @@ namespace Catch { | ||||
|     std::string toLower( std::string const& s ); | ||||
|     std::string trim( std::string const& str ); | ||||
|     bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); | ||||
|     std::vector<std::string> splitString( StringRef str, char delimiter ); | ||||
|  | ||||
|     struct pluralise { | ||||
|         pluralise( std::size_t count, std::string const& label ); | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include <string> | ||||
| #include "catch_compiler_capabilities.h" | ||||
| #include "catch_stream.h" | ||||
| #include "catch_interfaces_enum_values_registry.h" | ||||
|  | ||||
| #ifdef CATCH_CONFIG_CPP17_STRING_VIEW | ||||
| #include <string_view> | ||||
| @@ -639,6 +640,19 @@ struct ratio_string<std::milli> { | ||||
| } | ||||
| #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER | ||||
|  | ||||
| #define INTERNAL_CATCH_STRINGIFY_ENUM( enumName, ... ) \ | ||||
|     template<> struct ::Catch::StringMaker<enumName> { \ | ||||
|         static std::string convert( enumName value ) { \ | ||||
|             static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ | ||||
|             return enumInfo.lookup( static_cast<int>( value ) ); \ | ||||
|         } \ | ||||
|     }; | ||||
|  | ||||
| #ifdef CATCH_CONFIG_PREFIX_ALL | ||||
| #  define CATCH_STRINGIFY_ENUM( enumName, ... ) INTERNAL_CATCH_STRINGIFY_ENUM( enumName, __VA_ARGS__ ) | ||||
| #else | ||||
| #  define STRINGIFY_ENUM( enumName, ... ) INTERNAL_CATCH_STRINGIFY_ENUM( enumName, __VA_ARGS__ ) | ||||
| #endif | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #pragma warning(pop) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil nash
					Phil nash