-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
307 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
|
||
include(enum19/enum19.cmake) | ||
include(enum19/enum19.tests.cmake) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
Project { | ||
name: "flags19.lib" | ||
|
||
references: [ | ||
"flags19/flags19.qbs", | ||
"flags19/flags19.tests.qbs", | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#pragma once | ||
#include "FlagsOf.h" | ||
#include "enum19/Enum.names.h" | ||
|
||
/// noto: for this header you need fmt library (not included as library dependency) | ||
#include <fmt/format.h> | ||
#include <string_view> | ||
|
||
/// adds enum support for fmt | ||
template<enum19::HasMetaEnum Enum, class Char> struct fmt::formatter<flags19::FlagsOf<Enum>, Char> { | ||
using T = flags19::FlagsOf<Enum>; | ||
using Value = typename T::Value; | ||
constexpr auto parse(fmt::basic_format_parse_context<Char>& ctx) { return ctx.begin(); } | ||
|
||
template<typename FormatCtx> auto format(const T& v, FormatCtx& ctx) const { | ||
// auto underlying = static_cast<std::underlying_type_t<T>>(v); | ||
using namespace std::string_view_literals; | ||
auto printed = false; | ||
for (auto& member : enum19::meta_enum_for<Enum>.members) { | ||
if (!v[member.value]) continue; | ||
fmt::format_to(ctx.out(), "{}{}", (printed ? "|"sv : ""sv), enum19::valueName(member.value)); | ||
printed = true; | ||
} | ||
return fmt::format_to( | ||
ctx.out(), | ||
"{} ({:0{}b})", | ||
(printed ? ""sv : "<>"sv), | ||
static_cast<Value>(v), | ||
enum19::max_underlying_value_of<Enum>); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#pragma once | ||
#include "enum19/Enum.h" | ||
#include "enum19/Enum.max.h" | ||
|
||
#include <stdint.h> // int64_t, uint64_t | ||
|
||
namespace flags19 { | ||
|
||
using enum19::HasMetaEnum; | ||
using enum19::max_underlying_value_of; | ||
using enum19::meta_enum_for; | ||
|
||
namespace details { | ||
|
||
template<size_t maxBit> constexpr auto storageTypeForMaxBit() { | ||
if constexpr (maxBit <= sizeof(uint8_t)) { | ||
return uint8_t{}; | ||
} | ||
else if constexpr (maxBit <= sizeof(uint16_t)) { | ||
return uint16_t{}; | ||
} | ||
else if constexpr (maxBit <= sizeof(uint32_t)) { | ||
return uint32_t{}; | ||
} | ||
else if constexpr (maxBit <= sizeof(uint64_t)) { | ||
return uint64_t{}; | ||
} | ||
else { | ||
static_assert(maxBit > sizeof(uint64_t), "not supported right now"); | ||
} | ||
} | ||
|
||
} // namespace details | ||
|
||
template<HasMetaEnum Enum> struct FlagsOf { | ||
using UnderlyingBit = std::underlying_type_t<Enum>; | ||
using Value = decltype(details::storageTypeForMaxBit<max_underlying_value_of<Enum>>()); | ||
|
||
constexpr FlagsOf() = default; | ||
explicit constexpr FlagsOf(Value const& value) : m_value{value} {} | ||
|
||
template<class... Args> requires((sizeof...(Args) > 0) && ... && std::is_same_v<Args, Enum>) | ||
explicit constexpr FlagsOf(Args... args) : FlagsOf{((1U << static_cast<UnderlyingBit>(args)) | ...)} {} | ||
|
||
auto operator==(FlagsOf const&) const -> bool = default; | ||
|
||
explicit operator Value() const { return m_value; } | ||
|
||
[[nodiscard]] constexpr auto operator[](Enum bit) const noexcept -> bool { | ||
return 0U != (m_value & (1U << static_cast<UnderlyingBit>(bit))); | ||
} | ||
|
||
template<class... Args> requires((sizeof...(Args) > 0) && ... && std::is_same_v<Args, Enum>) | ||
constexpr auto allOf(Args... args) const -> bool { | ||
auto const mask = ((1U << static_cast<UnderlyingBit>(args)) | ...); | ||
return mask == (m_value & mask); | ||
} | ||
|
||
template<class... Args> requires((sizeof...(Args) > 0) && ... && std::is_same_v<Args, Enum>) | ||
constexpr auto someOf(Args... args) const -> bool { | ||
auto const mask = ((1U << static_cast<UnderlyingBit>(args)) | ...); | ||
return 0U != (m_value & mask); | ||
} | ||
|
||
template<class... Args> requires((sizeof...(Args) > 0) && ... && std::is_same_v<Args, Enum>) | ||
constexpr auto noneOf(Args... args) const -> bool { | ||
auto const mask = ((1U << static_cast<UnderlyingBit>(args)) | ...); | ||
return 0U == (m_value & mask); | ||
} | ||
|
||
constexpr void resetAll() { m_value = {}; } | ||
|
||
template<class... Args> requires((sizeof...(Args) > 0) && ... && std::is_same_v<Args, Enum>) | ||
constexpr void set(Args... args) { | ||
m_value |= ((1U << static_cast<UnderlyingBit>(args)) | ...); | ||
} | ||
|
||
template<class... Args> requires((sizeof...(Args) > 0) && ... && std::is_same_v<Args, Enum>) | ||
constexpr void reset(Args... args) { | ||
m_value &= ~static_cast<Value>(((1U << static_cast<UnderlyingBit>(args)) | ...)); | ||
} | ||
|
||
template<class... Args> requires((sizeof...(Args) > 0) && ... && std::is_same_v<Args, Enum>) | ||
constexpr void toggle(Args... args) { | ||
m_value ^= ((1U << static_cast<UnderlyingBit>(args)) | ...); | ||
} | ||
|
||
constexpr auto operator|(FlagsOf const& other) const -> FlagsOf { return FlagsOf{m_value | other.m_value}; } | ||
constexpr auto operator&(FlagsOf const& other) const -> FlagsOf { return FlagsOf{m_value & other.m_value}; } | ||
constexpr auto operator|=(FlagsOf const& other) -> FlagsOf& { return m_value |= other.m_value, *this; } | ||
constexpr auto operator&=(FlagsOf const& other) -> FlagsOf& { return m_value &= other.m_value, *this; } | ||
|
||
private: | ||
Value m_value{}; | ||
}; | ||
|
||
} // namespace flags19 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#pragma once | ||
#include "FlagsOf.h" | ||
|
||
#include <bitset> | ||
#include <enum19/Enum.names.h> | ||
#include <iosfwd> | ||
#include <string19/StringView.ostream.h> | ||
|
||
namespace flags19 { | ||
|
||
template<class Enum> auto operator<<(std::ostream& out, FlagsOf<Enum> const& flags) -> std::ostream& { | ||
using namespace std::string_view_literals; | ||
auto printed = false; | ||
for (auto& member : enum19::meta_enum_for<Enum>.members) { | ||
if (!flags[member.value]) continue; | ||
out << (printed ? "|"sv : ""sv) << enum19::valueName(member.value); | ||
printed = true; | ||
} | ||
return out << (printed ? " ("sv : "<> ("sv) | ||
<< std::bitset<max_underlying_value_of<Enum>>{static_cast<typename FlagsOf<Enum>::Value>(flags)} << ')'; | ||
} | ||
|
||
} // namespace flags19 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#include "FlagsOf.h" | ||
|
||
#include "FlagsOf.ostream.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
using namespace flags19; | ||
|
||
namespace my_test { | ||
|
||
ENUM19(CheckBit, uint8_t, Ordered, Packaged, Delivered, Received, Complained, ReturnLabeled, ReturnReceived); | ||
using CheckBits = FlagsOf<CheckBit>; | ||
|
||
} // namespace my_test | ||
|
||
TEST(Flags, example) { | ||
using enum my_test::CheckBit; | ||
constexpr auto checks = my_test::CheckBits{Ordered, Delivered}; | ||
|
||
static_assert(checks[Ordered]); | ||
static_assert(checks[Delivered]); | ||
static_assert(!checks[Packaged]); | ||
static_assert(!checks[ReturnReceived]); | ||
|
||
static_assert(checks.allOf(Delivered)); | ||
static_assert(!checks.allOf(Delivered, Received)); | ||
|
||
static_assert(checks.someOf(Delivered, Received)); | ||
|
||
static_assert(checks.noneOf(Complained, Received)); | ||
|
||
auto mutChecks = checks; | ||
mutChecks.set(Packaged); | ||
EXPECT_TRUE(mutChecks[Packaged]); | ||
|
||
mutChecks.reset(Delivered, Received); | ||
EXPECT_FALSE(mutChecks[Delivered]); | ||
EXPECT_TRUE(mutChecks.noneOf(Delivered, Received)); | ||
|
||
mutChecks.toggle(Packaged, Delivered); | ||
EXPECT_EQ(mutChecks, checks); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#pragma once | ||
#include "FlagsOf.h" | ||
|
||
namespace flags19 { | ||
|
||
template<class T> constexpr auto is_flags_of = false; | ||
template<class Enum> constexpr auto is_flags_of<FlagsOf<Enum>> = true; | ||
|
||
} // namespace flags19 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
add_library(flags19 INTERFACE) | ||
target_link_libraries(flags19 | ||
INTERFACE CoCpp19::enum19 | ||
) | ||
target_include_directories(flags19 | ||
INTERFACE | ||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/> | ||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | ||
) | ||
file(GLOB flags19_headers "${CMAKE_CURRENT_LIST_DIR}/*.h") | ||
target_sources(flags19 | ||
INTERFACE FILE_SET public_headers | ||
TYPE HEADERS | ||
FILES ${flags19_headers} | ||
) | ||
|
||
add_library(CoCpp19::flags19 ALIAS flags19) | ||
install(TARGETS flags19 | ||
EXPORT flags19Targets | ||
FILE_SET public_headers | ||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} | ||
COMPONENT "flags19" | ||
) | ||
install(EXPORT flags19Targets | ||
FILE "CoCpp19-flags19-targets.cmake" | ||
NAMESPACE "CoCpp19::" | ||
DESTINATION ${COCPP19_CMAKE_CONFIG_DESTINATION} | ||
COMPONENT "flags19" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
|
||
Product { | ||
Depends { name: "cpp" } | ||
Depends { name: "enum19" } | ||
Depends { name: "fmt"; required: false } | ||
|
||
Export { | ||
Depends { name: "cpp" } | ||
cpp.includePaths: [".."] | ||
Depends { name: "enum19" } | ||
} | ||
|
||
files: [ | ||
"FlagsOf.fmt.h", | ||
"FlagsOf.h", | ||
"FlagsOf.ostream.h", | ||
"FlagsOf.trait.h", | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
add_executable(flags19-test) | ||
file(GLOB flags19_test_sources "${CMAKE_CURRENT_LIST_DIR}/*.test.cpp") | ||
target_sources(flags19-test | ||
PRIVATE ${flags19_test_sources} | ||
) | ||
target_link_libraries(flags19-test | ||
PRIVATE GTest::gtest_main | ||
PRIVATE CoCpp19::flags19 | ||
) | ||
add_test(NAME flags19 COMMAND flags19-test) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
|
||
Application { | ||
name: "flags19.tests" | ||
condition: googletest.present | ||
|
||
consoleApplication: true | ||
type: ["application", "autotest"] | ||
|
||
Depends { name: "flags19" } | ||
Depends { name: "googletest" } | ||
|
||
files: [ | ||
"FlagsOf.test.cpp", | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
#include "flags19/FlagsOf.h" // requires variant19 | ||
#include "serialize.h" | ||
|
||
namespace serialize19 { | ||
|
||
template<Archive A, class Enum> void serialize(A& a, flags19::FlagsOf<Enum>& flags) { | ||
using Value = typename flags19::FlagsOf<Enum>::Value; | ||
auto value = static_cast<Value>(flags); | ||
serialize(a, value); | ||
if constexpr (A::mode == ArchiveMode::Read) { | ||
flags = flags19::FlagsOf<Enum>{value}; | ||
} | ||
} | ||
|
||
} // namespace serialize19 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters