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 <CoreFoundation/CoreFoundation.h>
#include <memory>
#include <system_error>
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>
{
///
/// 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 <class _T>
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<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)
template <class T>
using CFType = std::unique_ptr<T, CFRelease_delete>;
class cf_runtime_error : public num_runtime_error<CFIndex>
{
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
#include "common.hpp"
#include "CoreFoundation.hpp"
#import <Security/Security.h>
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<OSStatus>(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<OSStatus>(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<OSStatus>(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;
}
};