Merge branch enum stringification work

This commit is contained in:
Phil nash
2019-04-26 11:26:45 +01:00
13 changed files with 316 additions and 2 deletions

View File

@@ -0,0 +1,65 @@
/*
* 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>
#include <cassert>
namespace Catch {
IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}
namespace Detail {
std::vector<std::string> parseEnums( StringRef enums ) {
auto enumValues = splitStringRef( enums, ',' );
std::vector<std::string> parsed;
parsed.reserve( enumValues.size() );
for( auto const& enumValue : enumValues ) {
auto identifiers = splitStringRef( enumValue, ':' );
parsed.push_back( Catch::trim( identifiers.back() ) );
}
return parsed;
}
EnumInfo::~EnumInfo() {}
StringRef EnumInfo::lookup( int value ) const {
for( auto const& valueToName : m_values ) {
if( valueToName.first == value )
return valueToName.second;
}
return "{** unexpected enum value **}";
}
std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
std::unique_ptr<EnumInfo> enumInfo( new EnumInfo );
enumInfo->m_name = enumName;
enumInfo->m_values.reserve( values.size() );
const auto valueNames = Catch::Detail::parseEnums( allValueNames );
assert( valueNames.size() == values.size() );
std::size_t i = 0;
for( auto value : values )
enumInfo->m_values.push_back({ value, valueNames[i++] });
return enumInfo;
}
EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
auto enumInfo = makeEnumInfo( enumName, allValueNames, values );
EnumInfo* raw = enumInfo.get();
m_enumInfos.push_back( std::move( enumInfo ) );
return *raw;
}
} // Detail
} // Catch

View File

@@ -0,0 +1,34 @@
/*
* 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 {
std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
class EnumValuesRegistry : public IMutableEnumValuesRegistry {
std::vector<std::unique_ptr<EnumInfo>> m_enumInfos;
EnumInfo 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

View File

@@ -0,0 +1,45 @@
/*
* 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 {
namespace Detail {
struct EnumInfo {
StringRef m_name;
std::vector<std::pair<int, std::string>> m_values;
~EnumInfo();
StringRef lookup( int value ) const;
};
} // namespace Detail
struct IMutableEnumValuesRegistry {
virtual ~IMutableEnumValuesRegistry();
virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
template<typename E>
Detail::EnumInfo 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

View File

@@ -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();

View File

@@ -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;
};
}

View File

@@ -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<StringRef> splitStringRef( StringRef str, char delimiter ) {
std::vector<StringRef> 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 )

View File

@@ -7,8 +7,11 @@
#ifndef TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
#define TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
#include "catch_stringref.h"
#include <string>
#include <iosfwd>
#include <vector>
namespace Catch {
@@ -20,6 +23,9 @@ namespace Catch {
void toLowerInPlace( std::string& s );
std::string toLower( std::string const& s );
std::string trim( std::string const& str );
// !!! Be aware, returns refs into original string - make sure original string outlives them
std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
struct pluralise {

View File

@@ -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,15 @@ struct ratio_string<std::milli> {
}
#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
#define INTERNAL_CATCH_REGISTER_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 ) ); \
} \
};
#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
#ifdef _MSC_VER
#pragma warning(pop)