Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src/catch2/internal/catch_enum_info.cpp
diff options
context:
space:
mode:
authorMartin Hořeňovský2026-04-08 10:26:57 +0200
committerMartin Hořeňovský2026-04-08 12:57:09 +0200
commit47200ddbee03eaf4a9d3d99d18cb692381d8f5bc (patch)
treeec947545e5f35b38ea5592c6fafcd7861081648c /src/catch2/internal/catch_enum_info.cpp
parente51dcdcc595371828de2b1d28985e8d8c1895345 (diff)
downloadcatch3-47200ddbee03eaf4a9d3d99d18cb692381d8f5bc.tar.gz
Rework internals of CATCH_REGISTER_ENUM
The old internals reached into the global hub to stash the allocation(s) for enum value -> string value there, then kept around a potentially invalid (in case the hub was cleaned up) reference into it, going through whole bunch of virtual dispatch in the process. The new internals just store the data in a static variable inside the `StringMaker` specialization. This avoids potential lifetime issues, avoids all virtual dispatch and (almost) reduces the include bloat in the main header path. The reason for (almost) there is that for full include correctness, `EnumInfo` needs `<utility>` include for `std::pair`. However, this brings in things like `std::relops`, because the std headers in C++ are dumb. As this was not included before, and instead we relied on `std::pair` existing in an internal stdlib header that we transitively included, the full include size ends up bigger than before.
Diffstat (limited to 'src/catch2/internal/catch_enum_info.cpp')
-rw-r--r--src/catch2/internal/catch_enum_info.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/catch2/internal/catch_enum_info.cpp b/src/catch2/internal/catch_enum_info.cpp
new file mode 100644
index 00000000..0793abd9
--- /dev/null
+++ b/src/catch2/internal/catch_enum_info.cpp
@@ -0,0 +1,65 @@
+
+// Copyright Catch2 Authors
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+// SPDX-License-Identifier: BSL-1.0
+
+#include <catch2/internal/catch_enum_info.hpp>
+#include <catch2/internal/catch_string_manip.hpp>
+
+#include <cassert>
+
+namespace Catch {
+
+ namespace Detail {
+
+ namespace {
+ // Extracts the actual name part of an enum instance
+ // In other words, it returns the Blue part of Bikeshed::Colour::Blue
+ StringRef extractInstanceName(StringRef enumInstance) {
+ // Find last occurrence of ":"
+ size_t name_start = enumInstance.size();
+ while (name_start > 0 && enumInstance[name_start - 1] != ':') {
+ --name_start;
+ }
+ return enumInstance.substr(name_start, enumInstance.size() - name_start);
+ }
+ }
+
+ std::vector<StringRef> parseEnums( StringRef enums ) {
+ auto enumValues = splitStringRef( enums, ',' );
+ std::vector<StringRef> parsed;
+ parsed.reserve( enumValues.size() );
+ for( auto const& enumValue : enumValues ) {
+ parsed.push_back(trim(extractInstanceName(enumValue)));
+ }
+ return parsed;
+ }
+
+ StringRef EnumInfo::lookup( int64_t value ) const {
+ for( auto const& valueToName : m_values ) {
+ if( valueToName.first == value )
+ return valueToName.second;
+ }
+ return "{** unexpected enum value **}"_sr;
+ }
+
+ EnumInfo makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int64_t> const& values ) {
+ EnumInfo enumInfo;
+ enumInfo.m_name = enumName;
+ enumInfo.m_values.reserve( values.size() );
+
+ const auto valueNames = Catch::Detail::parseEnums( allValueNames );
+ assert( valueNames.size() == values.size() );
+ for (size_t i = 0; i < values.size(); ++i) {
+ enumInfo.m_values.emplace_back( values[i], valueNames[i] );
+ }
+
+ return enumInfo;
+ }
+
+ } // Detail
+} // Catch
+