Skip to content

Commit

Permalink
Fixed the issue on meta::fingerprint typename without null-terminatin…
Browse files Browse the repository at this point in the history
…g char.

Improved parse_raw_identifier_name to automatically remove leading 'struct', 'class', 'enum' on MSVC.
  • Loading branch information
refvalue committed Nov 14, 2024
1 parent 4c6ccf9 commit 6623789
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 1,559 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# 😀CPP Essence -- Modern C++ Utility Library

[![Windows Build](https://github.com/refvalue/cpp-essence/actions/workflows/windows.yaml/badge.svg)](https://github.com/refvalue/cpp-essence/actions/workflows/windows.yaml)[![Ubuntu Build](https://github.com/refvalue/cpp-essence/actions/workflows/ubuntu.yaml/badge.svg)](https://github.com/refvalue/cpp-essence/actions/workflows/ubuntu.yaml)[![MacOS Build](https://github.com/refvalue/cpp-essence/actions/workflows/macos.yaml/badge.svg)](https://github.com/refvalue/cpp-essence/actions/workflows/macos.yaml)
[![Windows Build](https://github.com/refvalue/cpp-essence/actions/workflows/windows.yaml/badge.svg)](https://github.com/refvalue/cpp-essence/actions/workflows/windows.yaml)

[![Ubuntu Build](https://github.com/refvalue/cpp-essence/actions/workflows/ubuntu.yaml/badge.svg)](https://github.com/refvalue/cpp-essence/actions/workflows/ubuntu.yaml)

## 📚Requirements

- MSVC >= 14.30 (Visual Studio 2022 17.0)
- GCC >= 11.2
- Clang >= 17.0 (Supporting Class Template argument Deduction for Aggregates)
- Clang >= 17.0 (Supporting [P1816R0 Class Template Argument Deduction for Aggregates](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1816r0.pdf))
- Emscripten >= 3.1.52
- Host GLIBC >= 2.31 (when compiling on Linux)
- Host GLIBC >= 2.31 (When compiling on Linux)
- C++ 20 Support
- JDK >= 8 (Optional if `ES_WITH_JNI` = `OFF`)

Expand Down
2 changes: 1 addition & 1 deletion include/essence/meta/detail/get_signature_suffix_size.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace essence::meta::detail {
*/
constexpr std::size_t get_signature_suffix_size(std::string_view signature) noexcept {
auto&& terminator =
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__clang__)
language_tokens::comma;
#else
language_tokens::semicolon;
Expand Down
9 changes: 9 additions & 0 deletions include/essence/meta/detail/language_tokens.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,24 @@
#include "../../char8_t_remediation.hpp"
#include "../literal_string.hpp"

#include <tuple>

namespace essence::meta::detail {
/**
* @brief Some tokens of the C++ programming language.
*/
struct language_tokens {
static constexpr literal_string reference{U8("&")};
static constexpr literal_string dot{U8(".")};
static constexpr literal_string scope{U8("::")};
static constexpr literal_string arrow{U8("->")};
static constexpr literal_string comma{U8(",")};
static constexpr literal_string semicolon{U8(";")};

static constexpr literal_string enum_prefix{U8("enum ")};
static constexpr literal_string class_prefix{U8("class ")};
static constexpr literal_string struct_prefix{U8("struct ")};

static constexpr literal_string left_parentheses{U8("(")};
static constexpr literal_string left_angle_bracket{U8("<")};
static constexpr literal_string left_square_bracket{U8("[")};
Expand All @@ -49,5 +56,7 @@ namespace essence::meta::detail {

static constexpr literal_string right_enclosing_tokens{
right_parentheses, right_angle_bracket, right_square_bracket};

static constexpr auto type_prefixes = std::forward_as_tuple(enum_prefix, class_prefix, struct_prefix);
};
} // namespace essence::meta::detail
14 changes: 12 additions & 2 deletions include/essence/meta/detail/parse_raw_identifier_name.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

#include <cstddef>
#include <string_view>
#include <tuple>

namespace essence::meta::detail {
/**
Expand Down Expand Up @@ -66,14 +67,23 @@ namespace essence::meta::detail {
#error "Unsupported compiler."
#endif

// Skips the possible '&' token for GCC and Clang.
const auto result = extract_keyword<find_mode_type::full_match>(signature, keyword,
extraction_param{
.preview_first_character = param.preview_first_character,
.ensure_correctness = param.ensure_correctness,
.suffix_size = get_signature_suffix_size(signature),
.extra_size_func = [](std::string_view str, std::size_t prefix_size) -> std::size_t {
return str[prefix_size] == '&' ? 1U : 0U;
#ifdef _MSC_VER
// Skips 'enum', 'class', 'struct' for MSVC.
return std::apply(
[&, size = std::size_t{}](const auto&... args) mutable {
return ((str.starts_with(args) == 0 ? (size = args.size()) : 0U), ..., size);
},
language_tokens::type_prefixes);
#else
// Skips the possible '&' token for GCC and Clang.
return static_cast<std::size_t>(str[prefix_size] == language_tokens::reference.front());
#endif
},
});

Expand Down
10 changes: 9 additions & 1 deletion include/essence/meta/fingerprint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,31 @@

#include "friendly_name.hpp"
#include "identifier.hpp"
#include "literal_string.hpp"

#include <compare>
#include <span>
#include <string_view>

namespace essence::meta {
/**
* @brief A unique identifier of a type, i.e. a fingerprint.
*/
class fingerprint {
template <typename T>
struct typename_cache {
static constexpr auto origin = get_literal_string_t<T>();
static constexpr literal_string value{std::span<const char, origin.size()>{origin.data(), origin.size()}};
};

public:
/**
* @brief Create a fingerprint for a type.
* @tparam T The type.
*/
template <typename T>
explicit consteval fingerprint(std::type_identity<T>) noexcept
: typename_{get_literal_string_t<T>()}, friendly_name_{friendly_name_v<T>} {}
: typename_{typename_cache<T>::value}, friendly_name_{friendly_name_v<T>} {}

constexpr auto operator<=>(const fingerprint&) const noexcept = default;

Expand Down
7 changes: 4 additions & 3 deletions include/essence/meta/struct.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>

namespace essence::meta {
/**
Expand All @@ -45,9 +46,9 @@ namespace essence::meta {
const auto names = []<std::size_t... Is>(
std::index_sequence<Is...>) -> generator<std::string_view> {
#if defined(__llvm__) && defined(__clang__)
co_yield (detail::parse_data_member_name(get_literal_string_v<T,
detail::make_fake_object_wrapper(std::get<Is>(
detail::make_data_member_pointers(detail::make_fake_object_wrapper<T>())))>()),
(co_yield detail::parse_data_member_name(get_literal_string_v<T,
detail::make_fake_object_wrapper(
std::get<Is>(detail::make_data_member_pointers(detail::make_fake_object_wrapper<T>())))>()),
...);
#else
(co_yield detail::parse_data_member_name(get_literal_string_v<T,
Expand Down
5 changes: 3 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ else()
endif()
endif()

add_test(NAME ${target_name} COMMAND ${target_name})

include(ESPackaging)

es_make_install_package(
TARGET_NAME ${target_name}
)

include(GoogleTest)
gtest_discover_tests(${target_name})
16 changes: 13 additions & 3 deletions test/meta_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,25 @@

#include <type_traits>

#include <essence/char8_t_remediation.hpp>
#include <essence/meta/fingerprint.hpp>
#include <essence/meta/literal_string.hpp>
#include <essence/meta/runtime/enum.hpp>

#include <gtest/gtest.h>

namespace test {
namespace essence::testing {
struct foo {};
} // namespace test

using namespace essence::meta;
enum class bazflags{a};
} // namespace essence::testing

using namespace essence;
using namespace essence::testing;

TEST(meta_test, identifiers) {
static constexpr meta::fingerprint fp_foo{std::type_identity<foo>{}};

EXPECT_STREQ(fp_foo.friendly_name(), U8("essence::testing::foo"));
EXPECT_EQ(meta::runtime::to_string(bazflags::a), U8("a"));
}
Loading

0 comments on commit 6623789

Please sign in to comment.