CoreFoundation: redesign

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2025-06-09 22:05:51 +02:00
parent c0e1163877
commit a04c27a14e
2 changed files with 83 additions and 22 deletions

View File

@ -8,34 +8,97 @@
#include "common.hpp" #include "common.hpp"
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <memory> #include <memory>
#include <system_error>
namespace macstd { namespace macstd {
/// ///
/// Deleter for unique_ptr using CFRelease /// IOKit handle wrapper class
/// ///
struct CFRelease_delete template <typename T, const T INVAL>
class cf_object : public handle<T, INVAL>
{ {
/// MACSTD_HANDLE_IMPL(cf_object, T, INVAL)
/// Default constructor
///
CFRelease_delete() noexcept {}
public:
/// ///
/// Delete a pointer /// Releases a Core Foundation object
/// ///
/// \sa [CFRelease function](https://developer.apple.com/documentation/corefoundation/1521153-cfrelease) /// \sa [CFRelease function](https://developer.apple.com/documentation/corefoundation/1521153-cfrelease)
/// ///
template <class _T> virtual ~cf_object()
void operator()(_T *_Ptr) const
{ {
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<CFStringRef, static_cast<CFStringRef>(NULL)>;
using cferror = cf_object<CFErrorRef, static_cast<CFErrorRef>(NULL)>;
/// ///
/// CFType helper /// Core Foundation runtime error
/// ///
/// \sa [CFType](https://developer.apple.com/documentation/corefoundation/cftype) class cf_runtime_error : public num_runtime_error<CFIndex>
template <class T> {
using CFType = std::unique_ptr<T, CFRelease_delete>; protected:
cferror m_error;
public:
///
/// Constructs an exception
///
/// \param[in] error Core Foundation error
///
cf_runtime_error(CFErrorRef error) :
num_runtime_error<CFIndex>(CFErrorGetCode(error), message(error)),
m_error(error)
{
}
///
/// Constructs an exception
///
/// \param[in] error Core Foundation error
///
cf_runtime_error(cferror&& error) :
num_runtime_error<CFIndex>(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;
}
};
} }

View File

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "common.hpp" #include "common.hpp"
#include "CoreFoundation.hpp"
#import <Security/Security.h> #import <Security/Security.h>
namespace macstd namespace macstd
@ -19,7 +20,7 @@ namespace macstd
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
/// \param[in] num WinSock2 error code /// \param[in] num Security error code
/// ///
security_runtime_error(error_type num) : num_runtime_error<OSStatus>(num, message(num)) security_runtime_error(error_type num) : num_runtime_error<OSStatus>(num, message(num))
{ {
@ -28,7 +29,7 @@ namespace macstd
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
/// \param[in] num WinSock2 error code /// \param[in] num Security error code
/// \param[in] msg Error message /// \param[in] msg Error message
/// ///
security_runtime_error(error_type num, const std::string &msg) : num_runtime_error<OSStatus>(num, msg + ": " + message(num)) security_runtime_error(error_type num, const std::string &msg) : num_runtime_error<OSStatus>(num, msg + ": " + message(num))
@ -38,7 +39,7 @@ namespace macstd
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
/// \param[in] num WinSock2 error code /// \param[in] num Security error code
/// \param[in] msg Error message /// \param[in] msg Error message
/// ///
security_runtime_error(error_type num, const char *msg) : num_runtime_error<OSStatus>(num, std::string(msg) + ": " + message(num)) security_runtime_error(error_type num, const char *msg) : num_runtime_error<OSStatus>(num, std::string(msg) + ": " + message(num))
@ -59,16 +60,13 @@ namespace macstd
case errAuthorizationDenied: return "Authorization was denied"; case errAuthorizationDenied: return "Authorization was denied";
case errAuthorizationInteractionNotAllowed: return "User interaction not allowed for authorization"; case errAuthorizationInteractionNotAllowed: return "User interaction not allowed for authorization";
} }
auto cfstr = SecCopyErrorMessageString(num, NULL); cfstring cfstr(SecCopyErrorMessageString(num, NULL));
if (!cfstr) if (!cfstr)
return "Security Framework error " + std::to_string(num); return "Security Framework error " + std::to_string(num);
auto ptr = CFStringGetCStringPtr(cfstr, kCFStringEncodingUTF8); auto ptr = CFStringGetCStringPtr(cfstr, kCFStringEncodingUTF8);
if (!ptr) { if (!ptr)
CFRelease(cfstr);
return "Security Framework error " + std::to_string(num); return "Security Framework error " + std::to_string(num);
}
std::string str(ptr); std::string str(ptr);
CFRelease(cfstr);
return str; return str;
} }
}; };