MacStd/include/MacStd/CoreFoundation.hpp
Simon Rozman 3fe0006b22 CoreFoundation: Use explicit handle validation
Signed-off-by: Simon Rozman <simon@rozman.si>
2025-06-17 16:32:00 +02:00

106 lines
2.5 KiB
C++

/*
SPDX-License-Identifier: MIT
Copyright © 2023-2025 Amebis
*/
#pragma once
#include "common.hpp"
#include <CoreFoundation/CoreFoundation.h>
#include <memory>
#include <system_error>
namespace macstd {
///
/// IOKit handle wrapper class
///
template <typename T, const T INVAL>
class cf_object : public handle<T, INVAL>
{
MACSTD_HANDLE_IMPL(cf_object, T, INVAL)
public:
///
/// Releases a Core Foundation object
///
/// \sa [CFRelease function](https://developer.apple.com/documentation/corefoundation/1521153-cfrelease)
///
virtual ~cf_object()
{
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 cfarray = cf_object<CFArrayRef, static_cast<CFArrayRef>(NULL)>;
using cferror = cf_object<CFErrorRef, static_cast<CFErrorRef>(NULL)>;
///
/// Core Foundation runtime error
///
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.valid() && 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.valid() && CFStringGetLength(domain) > 0) {
auto str = CFStringGetCStringPtr(domain, kCFStringEncodingUTF8);
if (str)
msg += std::string(", domain ") + str;
}
return msg;
}
};
}