mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-01 21:05:39 +02: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