2023-02-06 15:58:16 +08:00
|
|
|
#pragma once
|
|
|
|
|
2024-08-16 22:07:23 +08:00
|
|
|
// Check LibCmo build type first.
|
2023-09-25 21:45:53 +08:00
|
|
|
#if !(defined(LIBCMO_BUILD_DEBUG) ^ defined(LIBCMO_BUILD_RELEASE))
|
|
|
|
#error "You must define ONE of LIBCMO_BUILD_DEBUG and LIBCMO_BUILD_RELEASE to indicate build type!"
|
2023-09-20 20:44:03 +08:00
|
|
|
#endif
|
|
|
|
|
2024-08-16 22:07:23 +08:00
|
|
|
// Include YYCC helper library
|
|
|
|
#include <YYCCommonplace.hpp>
|
2023-02-11 15:29:51 +08:00
|
|
|
|
2024-08-16 22:07:23 +08:00
|
|
|
// Header for this namespace implementation
|
|
|
|
#include <string>
|
2023-02-26 21:48:03 +08:00
|
|
|
#include <type_traits>
|
2023-03-01 10:48:50 +08:00
|
|
|
#include <initializer_list>
|
2023-09-17 10:38:46 +08:00
|
|
|
|
2024-08-17 20:43:27 +08:00
|
|
|
/**
|
|
|
|
* @brief The core namespace of LibCmo project.
|
|
|
|
* @details All functions and classes involving LibCmo are located in this namespace.
|
|
|
|
*/
|
2023-08-22 15:30:26 +08:00
|
|
|
namespace LibCmo {
|
2023-02-26 21:48:03 +08:00
|
|
|
|
2024-08-16 22:07:23 +08:00
|
|
|
#pragma region LibCmo Exceptions
|
2023-09-24 20:56:23 +08:00
|
|
|
|
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief The exception thrown when library entering unreachable scope.
|
2024-08-16 22:07:23 +08:00
|
|
|
* @details This exception usually used in \c switch syntax.
|
|
|
|
* It means that program enter the scope which it definitely can not enter.
|
2023-09-24 20:56:23 +08:00
|
|
|
*/
|
2024-08-16 22:07:23 +08:00
|
|
|
class UnreachableException : public std::exception {
|
|
|
|
public:
|
|
|
|
UnreachableException(const char* msg) : message(msg ? msg : "") {}
|
|
|
|
UnreachableException(const UnreachableException& rhs) : message(rhs.message) {}
|
|
|
|
virtual ~UnreachableException() {}
|
|
|
|
[[nodiscard]] virtual const char* what() const override { return message.c_str(); }
|
|
|
|
private:
|
|
|
|
std::string message;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief The exception thrown when library entering logic error.
|
2024-08-16 22:07:23 +08:00
|
|
|
* @details In theory, this exception can be found by reading code.
|
|
|
|
* It usually caused by programmer use functions in a wrong way.
|
|
|
|
* For example, pass invalid argument to function and etc.
|
|
|
|
*/
|
|
|
|
class LogicException : public std::exception {
|
|
|
|
public:
|
|
|
|
LogicException(const char* msg) : message(msg ? msg : "") {}
|
|
|
|
LogicException(const LogicException& rhs) : message(rhs.message) {}
|
|
|
|
virtual ~LogicException() {}
|
|
|
|
[[nodiscard]] virtual const char* what() const override { return message.c_str(); }
|
|
|
|
private:
|
|
|
|
std::string message;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief The exception thrown when library entering runtime error.
|
2024-08-16 22:07:23 +08:00
|
|
|
* @details In theory, this exception can not be found by reading code.
|
|
|
|
* It may caused by user input or anything else.
|
|
|
|
*/
|
|
|
|
class RuntimeException : public std::exception {
|
|
|
|
public:
|
|
|
|
RuntimeException(const char* msg) : message(msg ? msg : "") {}
|
|
|
|
RuntimeException(const RuntimeException& rhs) : message(rhs.message) {}
|
|
|
|
virtual ~RuntimeException() {}
|
|
|
|
[[nodiscard]] virtual const char* what() const override { return message.c_str(); }
|
|
|
|
private:
|
|
|
|
std::string message;
|
|
|
|
};
|
|
|
|
|
|
|
|
#pragma endregion
|
2023-08-25 21:57:22 +08:00
|
|
|
|
2024-08-17 20:43:27 +08:00
|
|
|
/**
|
|
|
|
* @brief The namespace for convenient C++ enum class logic operations.
|
|
|
|
* @details
|
|
|
|
* C++ enum class statement is a modern way to declare enum in C++.
|
|
|
|
* But it lack essential logic operations which is commonly used by programmer.
|
|
|
|
* So we create this helper to resolve this issue.
|
|
|
|
*/
|
2023-08-25 17:35:45 +08:00
|
|
|
namespace EnumsHelper {
|
2023-09-17 12:39:21 +08:00
|
|
|
|
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief Merge given enum flags like performing <TT>e1 | e2 | ... | en</TT>
|
|
|
|
* @tparam TEnum Enum type for processing.
|
|
|
|
* @param[in] il The list of enum flags to be merged.
|
|
|
|
* @return The merged enum flag.
|
2023-09-17 12:39:21 +08:00
|
|
|
*/
|
2023-08-25 17:35:45 +08:00
|
|
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
2024-08-17 20:43:27 +08:00
|
|
|
constexpr TEnum Merge(std::initializer_list<TEnum> il) {
|
2024-08-16 22:07:23 +08:00
|
|
|
using ut = std::underlying_type_t<TEnum>;
|
|
|
|
ut result = 0;
|
2023-08-25 17:35:45 +08:00
|
|
|
for (auto it = il.begin(); it != il.end(); ++it) {
|
2024-08-16 22:07:23 +08:00
|
|
|
result |= static_cast<ut>(*it);
|
2023-08-25 17:35:45 +08:00
|
|
|
}
|
|
|
|
return static_cast<TEnum>(result);
|
|
|
|
}
|
|
|
|
|
2023-09-17 12:39:21 +08:00
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief Reverse given enum flags like performing <TT>~(e)</TT>
|
|
|
|
* @tparam TEnum Enum type for processing.
|
|
|
|
* @param[in] il The list of enum flags to be inversed.
|
|
|
|
* @return The inversed enum flag.
|
2023-09-17 12:39:21 +08:00
|
|
|
*/
|
2023-08-25 17:35:45 +08:00
|
|
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
2024-08-17 20:43:27 +08:00
|
|
|
constexpr TEnum Inv(TEnum e) {
|
2024-08-16 22:07:23 +08:00
|
|
|
using ut = std::underlying_type_t<TEnum>;
|
|
|
|
return static_cast<TEnum>(~(static_cast<ut>(e)));
|
2023-08-25 17:35:45 +08:00
|
|
|
}
|
2023-09-17 12:39:21 +08:00
|
|
|
|
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief Remove specified enum flags from given enum flags like performing <TT>e1 &= (~e2)</TT>
|
|
|
|
* @tparam TEnum Enum type for processing.
|
|
|
|
* @param[in,out] e1 The enum flags to be processed.
|
|
|
|
* @param[in] e2 The enum flag to be removed.
|
2023-09-17 12:39:21 +08:00
|
|
|
*/
|
2023-08-25 17:35:45 +08:00
|
|
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
2024-08-17 20:43:27 +08:00
|
|
|
constexpr void Rm(TEnum& e1, TEnum e2) {
|
2024-08-16 22:07:23 +08:00
|
|
|
using ut = std::underlying_type_t<TEnum>;
|
|
|
|
e1 = static_cast<TEnum>(static_cast<ut>(e1) & static_cast<ut>(Inv(e2)));
|
2023-08-25 17:35:45 +08:00
|
|
|
}
|
2024-08-17 20:43:27 +08:00
|
|
|
|
2023-09-17 12:39:21 +08:00
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief Use specified enum flags to mask given enum flags like performing <TT>e1 &= e2</TT>
|
|
|
|
* @tparam TEnum Enum type for processing.
|
|
|
|
* @param[in,out] e1 The enum flags to be masked.
|
|
|
|
* @param[in] e2 The mask enum flag.
|
2023-09-17 12:39:21 +08:00
|
|
|
*/
|
2023-09-15 17:03:36 +08:00
|
|
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
2024-08-17 20:43:27 +08:00
|
|
|
constexpr void Mask(TEnum& e1, TEnum e2) {
|
2024-08-16 22:07:23 +08:00
|
|
|
using ut = std::underlying_type_t<TEnum>;
|
|
|
|
e1 = static_cast<TEnum>(static_cast<ut>(e1) & static_cast<ut>(e2));
|
2023-09-15 17:03:36 +08:00
|
|
|
}
|
2024-08-17 20:43:27 +08:00
|
|
|
|
2023-09-17 12:39:21 +08:00
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief Add specified enum flags to given enum flags like performing <TT>e1 |= e2</TT>
|
|
|
|
* @tparam TEnum Enum type for processing.
|
|
|
|
* @param[in,out] e1 The enum flags to be processed.
|
|
|
|
* @param[in] e2 The enum flag to be added.
|
2023-09-17 12:39:21 +08:00
|
|
|
*/
|
2023-08-25 17:35:45 +08:00
|
|
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
2024-08-17 20:43:27 +08:00
|
|
|
constexpr void Add(TEnum& e1, TEnum e2) {
|
2024-08-16 22:07:23 +08:00
|
|
|
using ut = std::underlying_type_t<TEnum>;
|
|
|
|
e1 = static_cast<TEnum>(static_cast<ut>(e1) | static_cast<ut>(e2));
|
2023-08-25 17:35:45 +08:00
|
|
|
}
|
2024-08-17 20:43:27 +08:00
|
|
|
|
2023-09-17 12:39:21 +08:00
|
|
|
/**
|
2024-08-17 20:43:27 +08:00
|
|
|
* @brief Check whether given enum flags has specified enum flag like performing <TT>bool(e & probe)</TT>
|
|
|
|
* @tparam TEnum Enum type for processing.
|
|
|
|
* @param[in] e1 The enum flags to be checked.
|
|
|
|
* @param[in] e2 The enum flag for checking.
|
|
|
|
* @return True if it has, otherwise false.
|
2023-09-17 12:39:21 +08:00
|
|
|
*/
|
2023-08-25 17:35:45 +08:00
|
|
|
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
|
2024-08-17 20:43:27 +08:00
|
|
|
constexpr bool Has(TEnum e1, TEnum e2) {
|
2024-08-16 22:07:23 +08:00
|
|
|
using ut = std::underlying_type_t<TEnum>;
|
2024-08-17 20:43:27 +08:00
|
|
|
return static_cast<bool>(static_cast<ut>(e1) & static_cast<ut>(e2));
|
2023-08-25 17:35:45 +08:00
|
|
|
}
|
|
|
|
}
|
2023-08-23 16:04:58 +08:00
|
|
|
|
2023-02-11 15:29:51 +08:00
|
|
|
}
|