1 /*
2  *  Created by Phil on 4/4/2019.
3  *  Copyright 2019 Two Blue Cubes Ltd. All rights reserved.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 #include "catch_enum_values_registry.h"
9 #include "catch_string_manip.h"
10 #include "catch_stream.h"
11 
12 #include <map>
13 #include <cassert>
14 
15 namespace Catch {
16 
~IMutableEnumValuesRegistry()17     IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}
18 
19     namespace Detail {
20 
21         namespace {
22             // Extracts the actual name part of an enum instance
23             // In other words, it returns the Blue part of Bikeshed::Colour::Blue
extractInstanceName(StringRef enumInstance)24             StringRef extractInstanceName(StringRef enumInstance) {
25                 // Find last occurrence of ":"
26                 size_t name_start = enumInstance.size();
27                 while (name_start > 0 && enumInstance[name_start - 1] != ':') {
28                     --name_start;
29                 }
30                 return enumInstance.substr(name_start, enumInstance.size() - name_start);
31             }
32         }
33 
parseEnums(StringRef enums)34         std::vector<StringRef> parseEnums( StringRef enums ) {
35             auto enumValues = splitStringRef( enums, ',' );
36             std::vector<StringRef> parsed;
37             parsed.reserve( enumValues.size() );
38             for( auto const& enumValue : enumValues ) {
39                 parsed.push_back(trim(extractInstanceName(enumValue)));
40             }
41             return parsed;
42         }
43 
~EnumInfo()44         EnumInfo::~EnumInfo() {}
45 
lookup(int value) const46         StringRef EnumInfo::lookup( int value ) const {
47             for( auto const& valueToName : m_values ) {
48                 if( valueToName.first == value )
49                     return valueToName.second;
50             }
51             return "{** unexpected enum value **}"_sr;
52         }
53 
makeEnumInfo(StringRef enumName,StringRef allValueNames,std::vector<int> const & values)54         std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
55             std::unique_ptr<EnumInfo> enumInfo( new EnumInfo );
56             enumInfo->m_name = enumName;
57             enumInfo->m_values.reserve( values.size() );
58 
59             const auto valueNames = Catch::Detail::parseEnums( allValueNames );
60             assert( valueNames.size() == values.size() );
61             std::size_t i = 0;
62             for( auto value : values )
63                 enumInfo->m_values.emplace_back(value, valueNames[i++]);
64 
65             return enumInfo;
66         }
67 
registerEnum(StringRef enumName,StringRef allValueNames,std::vector<int> const & values)68         EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
69             m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
70             return *m_enumInfos.back();
71         }
72 
73     } // Detail
74 } // Catch
75 
76