From a04c27a14e649fda129bec0541a3bd46ff2d6a3f Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 9 Jun 2025 22:05:51 +0200 Subject: [PATCH] CoreFoundation: redesign Signed-off-by: Simon Rozman --- include/MacStd/CoreFoundation.hpp | 91 ++++++++++++++++++++++++++----- include/MacStd/Security.hpp | 14 ++--- 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/include/MacStd/CoreFoundation.hpp b/include/MacStd/CoreFoundation.hpp index b9f78dc..bbc873e 100644 --- a/include/MacStd/CoreFoundation.hpp +++ b/include/MacStd/CoreFoundation.hpp @@ -8,34 +8,97 @@ #include "common.hpp" #include #include +#include namespace macstd { /// - /// Deleter for unique_ptr using CFRelease + /// IOKit handle wrapper class /// - struct CFRelease_delete + template + class cf_object : public handle { - /// - /// Default constructor - /// - CFRelease_delete() noexcept {} + MACSTD_HANDLE_IMPL(cf_object, T, INVAL) + public: /// - /// Delete a pointer + /// Releases a Core Foundation object /// /// \sa [CFRelease function](https://developer.apple.com/documentation/corefoundation/1521153-cfrelease) /// - template - void operator()(_T *_Ptr) const + virtual ~cf_object() { - CFRelease(_Ptr); + if (this->m_h != INVAL) + free_internal(); + } + + protected: + /// + /// Releases a Core Foundation object + /// + /// \sa [CFRelease function](https://developer.apple.com/documentation/corefoundation/1521153-cfrelease) + /// + void free_internal() noexcept override + { + CFRelease(this->m_h); } }; + using cfstring = cf_object(NULL)>; + using cferror = cf_object(NULL)>; + /// - /// CFType helper + /// Core Foundation runtime error /// - /// \sa [CFType](https://developer.apple.com/documentation/corefoundation/cftype) - template - using CFType = std::unique_ptr; + class cf_runtime_error : public num_runtime_error + { + protected: + cferror m_error; + + public: + /// + /// Constructs an exception + /// + /// \param[in] error Core Foundation error + /// + cf_runtime_error(CFErrorRef error) : + num_runtime_error(CFErrorGetCode(error), message(error)), + m_error(error) + { + } + + /// + /// Constructs an exception + /// + /// \param[in] error Core Foundation error + /// + cf_runtime_error(cferror&& error) : + num_runtime_error(CFErrorGetCode(error), message(error)), + m_error(std::move(error)) + { + } + + CFErrorRef cferror() const noexcept { return m_error; } + + protected: + /// + /// Returns a string explaining the meaning of a Core Foundation error + /// + static std::string message(CFErrorRef error) + { + macstd::cfstring description(CFErrorCopyDescription(error)); + if (description && CFStringGetLength(description) > 0) { + auto str = CFStringGetCStringPtr(description, kCFStringEncodingUTF8); + if (str) + return str; + } + std::string msg("Core Foundation error " + std::to_string(CFErrorGetCode(error))); + macstd::cfstring domain(CFErrorGetDomain(error)); + if (domain && CFStringGetLength(domain) > 0) { + auto str = CFStringGetCStringPtr(domain, kCFStringEncodingUTF8); + if (str) + msg += std::string(", domain ") + str; + } + return msg; + } + }; } diff --git a/include/MacStd/Security.hpp b/include/MacStd/Security.hpp index aa57d1d..b8af425 100644 --- a/include/MacStd/Security.hpp +++ b/include/MacStd/Security.hpp @@ -6,6 +6,7 @@ #pragma once #include "common.hpp" +#include "CoreFoundation.hpp" #import namespace macstd @@ -19,7 +20,7 @@ namespace macstd /// /// Constructs an exception /// - /// \param[in] num WinSock2 error code + /// \param[in] num Security error code /// security_runtime_error(error_type num) : num_runtime_error(num, message(num)) { @@ -28,7 +29,7 @@ namespace macstd /// /// Constructs an exception /// - /// \param[in] num WinSock2 error code + /// \param[in] num Security error code /// \param[in] msg Error message /// security_runtime_error(error_type num, const std::string &msg) : num_runtime_error(num, msg + ": " + message(num)) @@ -38,7 +39,7 @@ namespace macstd /// /// Constructs an exception /// - /// \param[in] num WinSock2 error code + /// \param[in] num Security error code /// \param[in] msg Error message /// security_runtime_error(error_type num, const char *msg) : num_runtime_error(num, std::string(msg) + ": " + message(num)) @@ -59,16 +60,13 @@ namespace macstd case errAuthorizationDenied: return "Authorization was denied"; case errAuthorizationInteractionNotAllowed: return "User interaction not allowed for authorization"; } - auto cfstr = SecCopyErrorMessageString(num, NULL); + cfstring cfstr(SecCopyErrorMessageString(num, NULL)); if (!cfstr) return "Security Framework error " + std::to_string(num); auto ptr = CFStringGetCStringPtr(cfstr, kCFStringEncodingUTF8); - if (!ptr) { - CFRelease(cfstr); + if (!ptr) return "Security Framework error " + std::to_string(num); - } std::string str(ptr); - CFRelease(cfstr); return str; } };