Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor CMakeLists and update enum handling for improved clarity and… #3

Merged
merged 1 commit into from
Feb 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the

Check failure on line 1 in .devcontainer/devcontainer.json

View check run for this annotation

Trunk.io / Trunk Check

prettier

Incorrect formatting, autoformat by running 'trunk fmt'
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "C++",
Expand Down Expand Up @@ -49,7 +49,8 @@
"usernamehw.errorlens",
"twxs.cmake",
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
"ms-vscode.cmake-tools",
"GitHub.copilot"
]
}
}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
- { compiler: gcc, version: 9, build_type: Release, cppstd: 17 }
- { compiler: gcc, version: 10, build_type: Debug, cppstd: 20 }
- { compiler: gcc, version: 12, build_type: Release, cppstd: 20 }
- { compiler: gcc, version: 13, build_type: Release, cppstd: 20 }
- { compiler: clang, version: 11, build_type: Release, cppstd: 11 }
- { compiler: clang, version: 11, build_type: Release, cppstd: 14 }
- { compiler: clang, version: 11, build_type: Release, cppstd: 17 }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ FetchContent_MakeAvailable(enum_name)
target_link_libraries(${PROJECT_NAME} PRIVATE mgutility::enum_name)
```

## Example usage ([try it!](https://godbolt.org/z/5Ye185MWa))
## Example usage ([try it!](https://godbolt.org/z/1nqrj78vb))

```C++
#include <iostream>
Expand Down
1 change: 1 addition & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
cmake_minimum_required(VERSION 3.14)

Check failure on line 1 in example/CMakeLists.txt

View check run for this annotation

Trunk.io / Trunk Check

cmake-format

Incorrect formatting, autoformat by running 'trunk fmt'
project(
enum_name_example
VERSION 0.1
LANGUAGES CXX)


add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} mgutility::enum_name)
62 changes: 33 additions & 29 deletions example/main.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#include <iostream>

Check failure on line 1 in example/main.cpp

View check run for this annotation

Trunk.io / Trunk Check

clang-format

Incorrect formatting, autoformat by running 'trunk fmt'

#include "mgutility/reflection/enum_name.hpp"
#include "mgutility/std/string_view.hpp"

#if defined(__cpp_lib_print)
#include <print>
#include <ranges>
#endif

enum class Position : std::uint8_t {
enum class Position {
Top = 1 << 0,
Right = 1 << 1,
Bottom = 1 << 2,
Left = 1 << 3
};


// Define bitwise OR operator for Position
constexpr static auto operator|(Position lhs, Position rhs) -> Position {
return static_cast<Position>(mgutility::enum_to_underlying(lhs) |
Expand All @@ -27,7 +27,6 @@
mgutility::enum_to_underlying(rhs));
}


// Define the range for Position enum values (Option 1)
template <> struct mgutility::enum_range<Position> {
static constexpr auto min = 0; // Minimum value
Expand All @@ -37,36 +36,41 @@
// Specialize individual or all enum names
template <> struct mgutility::custom_enum<Position> {
static constexpr mgutility::flat_map<Position> map{
{.first = Position::Top, .second = "TOP"},
{.first = Position::Right, .second = "RIGHT"},
{.first = Position::Bottom, .second = "BOTTOM"},
{.first = Position::Left, .second = "LEFT"},
{.first =
Position::Top | Position::Right | Position::Bottom | Position::Left,
.second = "CENTER"}};
{Position::Top, "TOP"},
{Position::Right, "RIGHT"},
{Position::Bottom, "BOTTOM"},
{Position::Left, "LEFT"},
{Position::Top | Position::Right | Position::Bottom | Position::Left,
"CENTER"}};
};

int main() {
int aaa = 0;

// Specify enum range when call enum_name function (Option 2)
// Lambda function to get enum name
auto enum_name = [](Position c) { return mgutility::enum_name<0, 16>(c); };
auto enum_name = [](Position pos) {
return mgutility::enum_name<0, 16>(pos);
};

auto x = Position::Left;
auto y = mgutility::to_enum<Position>("CENTER"); // Convert string to enum
auto posLeft = Position::Left;
auto posCenter =
mgutility::to_enum<Position>("CENTER"); // Convert string to enum

#if defined(__cpp_lib_constexpr_string) && defined(__GNUC__) && \
!defined(__clang__) && __GNUC__ > 11
#if MGUTILITY_CPLUSPLUS > 201402L && \
((defined(__clang__) && __clang_major__ > 11) || (defined(__GNUC__) && __GNUC__ > 11))
static_assert(mgutility::enum_name(Position::Top | Position::Right) ==
"TOP|RIGHT"); // Compile-time check
static_assert(mgutility::to_enum<Position>("BOTTOM|LEFT") ==
(Position::Bottom | Position::Left)); // Compile-time check
"TOP|RIGHT",
"Compile-time check failed: TOP|RIGHT");
#if MGUTILITY_CPLUSPLUS > 201703L && \
(defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 11))
static_assert(mgutility::to_enum<Position>("BOTTOM|LEFT").value() ==
(Position::Bottom | Position::Left),
"Compile-time check failed");
#endif
#endif

#if defined(__cpp_lib_print) || __GNUC__ > 12
#if defined(__cpp_lib_print)

// Print each Position and its underlying value using ranges
// Print each Position and its underlying value using ranges
auto positions =
mgutility::enum_for_each<Position>() |
std::ranges::views::filter([](auto &&pair) {
Expand All @@ -82,18 +86,18 @@
#else

// Print each Position and its underlying value using a for loop
for (auto &&e : mgutility::enum_for_each<Position>()) {
if (!e.second.empty() &&
e.second.find('|') == mgutility::string_view::npos) {
std::cout << mgutility::enum_to_underlying(e.first) << " \t: " << e.second
<< '\n';
for (auto &&elem : mgutility::enum_for_each<Position>()) {
if (!elem.second.empty() &&
elem.second.find('|') == mgutility::string_view::npos) {
std::cout << mgutility::enum_to_underlying(elem.first)
<< " \t: " << elem.second << '\n';
}
}
#endif

// Print the value of x
std::cout << '\n' << x << '\n';
std::cout << '\n' << posLeft << '\n';

// Print the name of y or "TOP" if y is not valid
std::cout << y.value_or(Position::Top) << '\n';
std::cout << posCenter.value_or(Position::Top) << '\n';
}
2 changes: 1 addition & 1 deletion include/mgutility/_common/definitions.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check failure on line 1 in include/mgutility/_common/definitions.hpp

View check run for this annotation

Trunk.io / Trunk Check

clang-format

Incorrect formatting, autoformat by running 'trunk fmt'
MIT License

Copyright (c) 2024 mguludag
Expand Down Expand Up @@ -64,7 +64,7 @@
* MGUTILITY_CNSTXPR_CLANG_WA is defined as constexpr. Otherwise, it is defined
* as empty.
*/
#if MGUTILITY_CPLUSPLUS > 201703L && defined(__cpp_lib_constexpr_string)
#if (MGUTILITY_CPLUSPLUS >= 201703L && !defined(__clang__)) || (defined(__clang__) && __clang_major__ > 11 && MGUTILITY_CPLUSPLUS >= 201703L)
#define MGUTILITY_CNSTXPR_CLANG_WA constexpr
#else
#define MGUTILITY_CNSTXPR_CLANG_WA
Expand Down
8 changes: 6 additions & 2 deletions include/mgutility/reflection/detail/enum_for_each.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check failure on line 1 in include/mgutility/reflection/detail/enum_for_each.hpp

View check run for this annotation

Trunk.io / Trunk Check

clang-format

Incorrect formatting, autoformat by running 'trunk fmt'
MIT License

Copyright (c) 2024 mguludag
Expand Down Expand Up @@ -31,6 +31,10 @@
#include <cstdint>
#include <utility>

#ifndef MGUTILITY_ENUM_NAME_BUFFER_SIZE
#define MGUTILITY_ENUM_NAME_BUFFER_SIZE 512U

Check failure on line 35 in include/mgutility/reflection/detail/enum_for_each.hpp

View check run for this annotation

Trunk.io / Trunk Check

clang-tidy(cppcoreguidelines-macro-usage)

[new] macro 'MGUTILITY_ENUM_NAME_BUFFER_SIZE' used to declare a constant; consider using a 'constexpr' constant
#endif

namespace mgutility {
namespace detail {
/**
Expand All @@ -44,7 +48,7 @@
*/
template <typename T>
using string_or_view_t =
typename std::conditional<has_bit_or<T>::value, std::string,
typename std::conditional<has_bit_or<T>::value, mgutility::fixed_string<MGUTILITY_ENUM_NAME_BUFFER_SIZE>,
mgutility::string_view>::type;

/**
Expand Down Expand Up @@ -89,7 +93,7 @@
*
* @param value The initial position of the iterator.
*/
enum_iter(iter_type value) : m_pos{value} {}
explicit enum_iter(iter_type value) : m_pos{value} {}

/**
* @brief Pre-increment operator.
Expand Down
54 changes: 26 additions & 28 deletions include/mgutility/reflection/detail/enum_name_impl.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check failure on line 1 in include/mgutility/reflection/detail/enum_name_impl.hpp

View check run for this annotation

Trunk.io / Trunk Check

clang-format

Incorrect formatting, autoformat by running 'trunk fmt'
MIT License

Copyright (c) 2024 mguludag
Expand Down Expand Up @@ -27,6 +27,7 @@

#include "enum_for_each.hpp"
#include "meta.hpp"
#include "mgutility/_common/definitions.hpp"
#include "mgutility/std/optional.hpp"
#include "mgutility/std/string_view.hpp"

Expand Down Expand Up @@ -87,7 +88,7 @@
typename Enum, Enum e,
detail::enable_if_t<!detail::is_scoped_enum<Enum>::value, bool> = true>
MGUTILITY_CNSTXPR static auto name() noexcept -> mgutility::string_view {
for (auto &pair : mgutility::custom_enum<Enum>::map) {
for (const auto &pair : mgutility::custom_enum<Enum>::map) {
if (pair.first == e) {
return pair.second;
}
Expand All @@ -113,7 +114,7 @@
typename Enum, Enum e,
detail::enable_if_t<detail::is_scoped_enum<Enum>::value, bool> = true>
MGUTILITY_CNSTXPR static auto name() noexcept -> mgutility::string_view {
for (auto &pair : mgutility::custom_enum<Enum>::map) {
for (const auto &pair : mgutility::custom_enum<Enum>::map) {
if (pair.first == e) {
return pair.second;
}
Expand All @@ -124,20 +125,21 @@
MGUTILITY_CNSTXPR auto result =
str.substr(index, str.size() - lastidxenumname[0] - index);
MGUTILITY_CNSTXPR auto is_invalid =
result.rfind(lastidxenumname[5]) != result.npos || (result.size() > 4 && result[4] == lastidxenumname[4]);
result.rfind(lastidxenumname[5]) != mgutility::string_view::npos ||
(result.size() > 4 && result[4] == lastidxenumname[4]);
return is_invalid ? "" : result;
}

private:
static constexpr int lastidxenumname[] =
#if defined(__clang__)
{1, 1, ' ', ':', '(',
{1, 1, ' ', ':', '(',
#if __clang_major__ < 13
','
','
#else
')'
')'
#endif
};
};
#elif defined(_MSC_VER)
{21, 0, ',', ':', '<', ')'};
#elif defined(__GNUC__)
Expand All @@ -147,7 +149,7 @@
#else
157,
#endif
5, ' ', ':', '(', ')'};
5, ' ', ':', '(', ')'};
#endif
};

Expand Down Expand Up @@ -194,10 +196,11 @@
MGUTILITY_CNSTXPR inline auto to_enum_impl(mgutility::string_view str) noexcept
-> mgutility::optional<Enum> {
MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();
const auto index{std::find(arr.begin() + 1, arr.end(), str)};
return index == arr.end() ? mgutility::nullopt
: mgutility::optional<Enum>{static_cast<Enum>(
std::distance(arr.begin(), index) + Min - 1)};

const auto index{detail::find(arr, str)};
return index == 0
? mgutility::nullopt
: mgutility::optional<Enum>{static_cast<Enum>(index + Min - 1)};
}

/**
Expand Down Expand Up @@ -256,10 +259,10 @@
*/
template <typename Enum, int Min, int Max,
detail::enable_if_t<!detail::has_bit_or<Enum>::value, bool> = true>
MGUTILITY_CNSTXPR auto enum_name_impl(Enum e) noexcept
MGUTILITY_CNSTXPR auto enum_name_impl(Enum enumValue) noexcept
-> mgutility::string_view {
MGUTILITY_CNSTXPR auto arr = get_enum_array<Enum, Min, Max>();
const auto index{(Min < 0 ? -Min : Min) + static_cast<int>(e) + 1};
const auto index{(Min < 0 ? -Min : Min) + static_cast<int>(enumValue) + 1};
return arr[(index < Min || index > arr.size() - 1) ? 0 : index];
}

Expand All @@ -275,32 +278,30 @@
*/
template <typename Enum, int Min, int Max,
detail::enable_if_t<detail::has_bit_or<Enum>::value, bool> = true>
MGUTILITY_CNSTXPR_CLANG_WA inline auto enum_name_impl(Enum e) noexcept
-> detail::string_or_view_t<Enum> {
MGUTILITY_CNSTXPR_CLANG_WA auto enum_name_impl(Enum enumValue) noexcept
-> mgutility::fixed_string<MGUTILITY_ENUM_NAME_BUFFER_SIZE> {

// Get the array of enum names
MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();

// Calculate the index in the array
const auto index = (Min < 0 ? -Min : Min) + static_cast<int>(e) + 1;
const auto index = (Min < 0 ? -Min : Min) + static_cast<int>(enumValue) + 1;
const auto name =
arr[(index < Min || index >= static_cast<int>(arr.size())) ? 0 : index];

// Lambda to check if a character is a digit
const auto is_digit = [](char c) { return c >= '0' && c <= '9'; };

// Return the name if it's valid
if (!name.empty() && !is_digit(name[0])) {
return std::string{name};
return mgutility::fixed_string<MGUTILITY_ENUM_NAME_BUFFER_SIZE>{}.append(
name);
}

// Construct bitmasked name
std::string bitmasked_name;
mgutility::fixed_string<MGUTILITY_ENUM_NAME_BUFFER_SIZE> bitmasked_name;
for (auto i = Min; i < Max; ++i) {
const auto idx = (Min < 0 ? -Min : Min) + i + 1;
if (idx >= 0 && idx < static_cast<int>(arr.size()) && !arr[idx].empty() &&
!is_digit(arr[idx][0]) &&
(e & static_cast<Enum>(i)) == static_cast<Enum>(i)) {
!detail::is_digit(arr[idx][0]) &&
(enumValue & static_cast<Enum>(i)) == static_cast<Enum>(i)) {
bitmasked_name.append(arr[idx]).append("|");
}
}
Expand All @@ -310,10 +311,7 @@
bitmasked_name.pop_back();
}

if (bitmasked_name.find('|') != std::string::npos) {
return bitmasked_name;
}
return std::string{""};
return bitmasked_name;
}
} // namespace detail
} // namespace mgutility
Expand Down
2 changes: 1 addition & 1 deletion include/mgutility/reflection/detail/meta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ template <typename T, typename U> struct pair {
};

template <typename T>
#if MGUTILITY_CPLUSPLUS > 201103L || defined(__GNUC__) && !defined(__clang__)
#if MGUTILITY_CPLUSPLUS > 201402L || defined(__GNUC__) && !defined(__clang__)
using flat_map = std::initializer_list<pair<T, const char *>>;
#else
using flat_map = pair<T, const char *>[];
Expand Down
13 changes: 7 additions & 6 deletions include/mgutility/reflection/enum_name.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check failure on line 1 in include/mgutility/reflection/enum_name.hpp

View check run for this annotation

Trunk.io / Trunk Check

clang-format

Incorrect formatting, autoformat by running 'trunk fmt'
MIT License

Copyright (c) 2023 mguludag
Expand Down Expand Up @@ -27,6 +27,7 @@

#include "detail/enum_name_impl.hpp"


namespace mgutility {

/**
Expand All @@ -37,10 +38,10 @@
* @return The underlying integer value of the enum.
*/
template <typename Enum>
constexpr auto enum_to_underlying(Enum e) noexcept
constexpr auto enum_to_underlying(Enum enumValue) noexcept
-> detail::underlying_type_t<Enum> {
static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
return static_cast<detail::underlying_type_t<Enum>>(e);
return static_cast<detail::underlying_type_t<Enum>>(enumValue);
}

/**
Expand All @@ -53,11 +54,11 @@
* @return A string view or string representing the name of the enum value.
*/
template <int Min, int Max, typename Enum>
MGUTILITY_CNSTXPR auto enum_name(Enum e) noexcept
MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept
-> detail::string_or_view_t<Enum> {
static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
return detail::enum_name_impl<Enum, Min, Max>(e);
return detail::enum_name_impl<Enum, Min, Max>(enumValue);
}

/**
Expand All @@ -71,11 +72,11 @@
*/
template <typename Enum, int Min = enum_range<Enum>::min,
int Max = enum_range<Enum>::max>
MGUTILITY_CNSTXPR auto enum_name(Enum e) noexcept
MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept
-> detail::string_or_view_t<Enum> {
static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
return detail::enum_name_impl<Enum, Min, Max>(e);
return detail::enum_name_impl<Enum, Min, Max>(enumValue);
}

/**
Expand Down
Loading
Loading