mirror of
https://github.com/wiiu-env/libnotifications.git
synced 2026-09-07 08:26:55 -05:00
Improve type checks
Some checks failed
Publish Docker Image / build-and-push-image (push) Has been cancelled
Some checks failed
Publish Docker Image / build-and-push-image (push) Has been cancelled
This commit is contained in:
@@ -3,13 +3,14 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstddef> /* For std::nullptr_t */
|
||||
#include <type_traits>
|
||||
#else
|
||||
#include <stddef.h> /* For NULL */
|
||||
#endif
|
||||
|
||||
/* * Warning generators (Common to C and C++)
|
||||
* These define static functions that trigger a compiler warning when called.
|
||||
*/
|
||||
/* =========================================================================
|
||||
* Warning generators (Common to C and C++)
|
||||
* ========================================================================= */
|
||||
#define _NM_WARNING(id, message) \
|
||||
static void __attribute__((__warning__(message))) \
|
||||
__attribute__((__unused__)) __attribute__((__noinline__)) \
|
||||
@@ -29,127 +30,99 @@ _NM_WARNING(_nm_warn_bool, "NotificationModule_SetDefaultValue expects 'bool' (o
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* =========================================================================
|
||||
* IMPLEMENTATION SELECTION
|
||||
* ========================================================================= */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
/* ==========================================
|
||||
* C++17 Implementation
|
||||
* Only active if -std=c++17 or higher is used.
|
||||
* ========================================== */
|
||||
/* ---------------------------------------------------------
|
||||
* C++ IMPLEMENTATION
|
||||
* --------------------------------------------------------- */
|
||||
#if __cplusplus >= 201703L
|
||||
|
||||
namespace NM_Check {
|
||||
/* NMColor Checker */
|
||||
inline bool check_NMColor(NMColor) { return true; }
|
||||
inline bool check_NMColor(void *) { return false; } /* Sink for NULL */
|
||||
template<typename T>
|
||||
inline bool check_NMColor(T) { return false; }
|
||||
|
||||
/* Float Checker (accepts float/double) */
|
||||
inline bool check_float(float) { return true; }
|
||||
inline bool check_float(double) { return true; }
|
||||
inline bool check_float(void *) { return false; } /* Sink for NULL */
|
||||
template<typename T>
|
||||
inline bool check_float(T) { return false; }
|
||||
template<typename Actual>
|
||||
using Decayed = std::decay_t<Actual>;
|
||||
|
||||
/* Bool Checker (accepts bool/int) */
|
||||
inline bool check_bool(bool) { return true; }
|
||||
inline bool check_bool(int) { return true; }
|
||||
inline bool check_bool(void *) { return false; } /* Sink for NULL */
|
||||
template<typename T>
|
||||
inline bool check_bool(T) { return false; }
|
||||
/* Strict matching: Must be the NMColor type or a raw integer (for hex literals) */
|
||||
template<typename Actual>
|
||||
constexpr bool is_NMColor = std::is_same_v<NMColor, Decayed<Actual>> || std::is_integral_v<Decayed<Actual>>;
|
||||
|
||||
/* Callback Checker */
|
||||
inline bool check_callback(NotificationModuleNotificationFinishedCallback) { return true; }
|
||||
/* Explicit void* (e.g. casting) */
|
||||
inline bool check_callback(void *) { return true; }
|
||||
inline bool check_callback(int i) { return i == 0; }
|
||||
inline bool check_callback(long i) { return i == 0; }
|
||||
inline bool check_callback(std::nullptr_t) { return true; }
|
||||
template<typename T>
|
||||
inline bool check_callback(T) { return false; }
|
||||
/* Strict matching: Float or Double only (Rejects implicit ints/pointers) */
|
||||
template<typename Actual>
|
||||
constexpr bool is_float = std::is_same_v<float, Decayed<Actual>> || std::is_same_v<double, Decayed<Actual>>;
|
||||
|
||||
/* Context Checker */
|
||||
inline bool check_context(void *) { return true; }
|
||||
inline bool check_context(int i) { return i == 0; }
|
||||
inline bool check_context(long i) { return i == 0; }
|
||||
inline bool check_context(std::nullptr_t) { return true; }
|
||||
template<typename T>
|
||||
inline bool check_context(T) { return false; }
|
||||
/* Strict matching: Bool or Int only (Rejects implicit pointers) */
|
||||
template<typename Actual>
|
||||
constexpr bool is_bool = std::is_same_v<bool, Decayed<Actual>> || std::is_same_v<int, Decayed<Actual>>;
|
||||
|
||||
/* Strict matching: Callback type, void*, nullptr, or 0 */
|
||||
template<typename Actual>
|
||||
constexpr bool is_callback =
|
||||
std::is_same_v<NotificationModuleNotificationFinishedCallback, Decayed<Actual>> ||
|
||||
std::is_same_v<void *, Decayed<Actual>> ||
|
||||
std::is_same_v<std::nullptr_t, Decayed<Actual>> ||
|
||||
std::is_integral_v<Decayed<Actual>>;
|
||||
|
||||
/* Strict matching: void*, nullptr, or 0 */
|
||||
template<typename Actual>
|
||||
constexpr bool is_context =
|
||||
std::is_same_v<void *, Decayed<Actual>> ||
|
||||
std::is_same_v<std::nullptr_t, Decayed<Actual>> ||
|
||||
std::is_integral_v<Decayed<Actual>>;
|
||||
|
||||
/* Compile-time option router */
|
||||
template<int Option, typename Actual>
|
||||
inline void check_option() {
|
||||
if constexpr (Option == NOTIFICATION_MODULE_DEFAULT_OPTION_BACKGROUND_COLOR ||
|
||||
Option == NOTIFICATION_MODULE_DEFAULT_OPTION_TEXT_COLOR) {
|
||||
if constexpr (!is_NMColor<Actual>) _nm_warn_NMColor();
|
||||
} else if constexpr (Option == NOTIFICATION_MODULE_DEFAULT_OPTION_DURATION_BEFORE_FADE_OUT) {
|
||||
if constexpr (!is_float<Actual>) _nm_warn_float();
|
||||
} else if constexpr (Option == NOTIFICATION_MODULE_DEFAULT_OPTION_FINISH_FUNCTION) {
|
||||
if constexpr (!is_callback<Actual>) _nm_warn_callback();
|
||||
} else if constexpr (Option == NOTIFICATION_MODULE_DEFAULT_OPTION_FINISH_FUNCTION_CONTEXT) {
|
||||
if constexpr (!is_context<Actual>) _nm_warn_context();
|
||||
} else if constexpr (Option == NOTIFICATION_MODULE_DEFAULT_OPTION_KEEP_UNTIL_SHOWN) {
|
||||
if constexpr (!is_bool<Actual>) _nm_warn_bool();
|
||||
}
|
||||
}
|
||||
} // namespace NM_Check
|
||||
|
||||
/* Macros mapping to C++ namespace calls */
|
||||
#define _nm_is_NMColor(x) NM_Check::check_NMColor(x)
|
||||
#define _nm_is_float(x) NM_Check::check_float(x)
|
||||
#define _nm_is_bool(x) NM_Check::check_bool(x)
|
||||
#define _nm_is_callback(x) NM_Check::check_callback(x)
|
||||
#define _nm_is_context(x) NM_Check::check_context(x)
|
||||
|
||||
/* C++17 Macro (Uses if constexpr) */
|
||||
#define NotificationModule_SetDefaultValue(type, option, value) \
|
||||
__extension__({ \
|
||||
NM_Check::check_option<__builtin_constant_p(option) ? (option) : -1, decltype(value)>(); \
|
||||
(NotificationModule_SetDefaultValue)(type, option, value); \
|
||||
})
|
||||
#else
|
||||
/* ==========================================
|
||||
* Pre-C++17 Implementation
|
||||
* Checks are DISABLED to avoid errors in older versions.
|
||||
* ========================================== */
|
||||
#define _nm_is_NMColor(x) (1)
|
||||
#define _nm_is_float(x) (1)
|
||||
#define _nm_is_bool(x) (1)
|
||||
#define _nm_is_callback(x) (1)
|
||||
#define _nm_is_context(x) (1)
|
||||
/* Fallback for old C++ (Checks disabled) */
|
||||
#define NotificationModule_SetDefaultValue(type, option, value) \
|
||||
(NotificationModule_SetDefaultValue)(type, option, value)
|
||||
#endif
|
||||
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
|
||||
/* ==========================================
|
||||
* C11 Implementation (using _Generic)
|
||||
* ========================================== */
|
||||
|
||||
#define _nm_is_NMColor(x) _Generic((x), \
|
||||
NMColor : 1, \
|
||||
default : 0)
|
||||
|
||||
#define _nm_is_float(x) _Generic((x), \
|
||||
float : 1, \
|
||||
double : 1, \
|
||||
default : 0)
|
||||
|
||||
#define _nm_is_bool(x) _Generic((x), \
|
||||
_Bool : 1, \
|
||||
int : 1, \
|
||||
default : 0)
|
||||
|
||||
#define _nm_is_callback(x) _Generic((x), \
|
||||
NotificationModuleNotificationFinishedCallback : 1, \
|
||||
void * : 1, \
|
||||
default : 0)
|
||||
|
||||
#define _nm_is_context(x) _Generic((x), \
|
||||
void * : 1, \
|
||||
default : 0)
|
||||
|
||||
#else
|
||||
|
||||
/* ==========================================
|
||||
* Legacy C Implementation
|
||||
* Partial checking only.
|
||||
* ========================================== */
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* C IMPLEMENTATION
|
||||
* --------------------------------------------------------- */
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
/* C11 Implementation */
|
||||
#define _nm_is_NMColor(x) _Generic((x), NMColor : 1, default : 0)
|
||||
#define _nm_is_float(x) _Generic((x), float : 1, double : 1, default : 0)
|
||||
#define _nm_is_bool(x) _Generic((x), _Bool : 1, int : 1, default : 0)
|
||||
#define _nm_is_callback(x) _Generic((x), NotificationModuleNotificationFinishedCallback : 1, void * : 1, default : 0)
|
||||
#define _nm_is_context(x) _Generic((x), void * : 1, default : 0)
|
||||
#else
|
||||
/* Legacy C Implementation */
|
||||
#define _nm_is_type(x, type) __builtin_types_compatible_p(__typeof__(x), type)
|
||||
|
||||
/* Disable complex checks in old C */
|
||||
#define _nm_is_NMColor(x) (1)
|
||||
#define _nm_is_callback(x) (1)
|
||||
#define _nm_is_context(x) (1)
|
||||
|
||||
/* Scalars are safe to check */
|
||||
#define _nm_is_float(x) (_nm_is_type(x, float) || _nm_is_type(x, double))
|
||||
#define _nm_is_bool(x) (_nm_is_type(x, int) || _nm_is_type(x, _Bool))
|
||||
#endif /* C11 Check */
|
||||
|
||||
#endif
|
||||
|
||||
/* Unified C Macro (C-only) */
|
||||
#define NotificationModule_SetDefaultValue(type, option, value) \
|
||||
__extension__({ \
|
||||
if (__builtin_constant_p(option)) { \
|
||||
@@ -168,5 +141,6 @@ namespace NM_Check {
|
||||
} \
|
||||
(NotificationModule_SetDefaultValue)(type, option, value); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif /* NOTIFICATIONS_TYPECHECK_GCC_H */
|
||||
Reference in New Issue
Block a user