common: merge dup_handle and handle and use traits
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
96ae46eaa9
commit
bf4dd4a1d0
@ -12,41 +12,37 @@
|
||||
|
||||
namespace macstd {
|
||||
///
|
||||
/// IOKit handle wrapper class
|
||||
/// Core Foundation object traits
|
||||
///
|
||||
template <typename T, const T INVAL>
|
||||
class cf_object : public handle<T, INVAL>
|
||||
template <typename T>
|
||||
struct cfobject_traits
|
||||
{
|
||||
MACSTD_HANDLE_IMPL(cf_object, T, INVAL)
|
||||
static inline constexpr T invalid = static_cast<T>(NULL);
|
||||
|
||||
public:
|
||||
///
|
||||
/// Releases a Core Foundation object
|
||||
///
|
||||
/// \sa [CFRelease function](https://developer.apple.com/documentation/corefoundation/1521153-cfrelease)
|
||||
///
|
||||
virtual ~cf_object()
|
||||
static void free(T h)
|
||||
{
|
||||
if (this->m_h != INVAL)
|
||||
free_internal();
|
||||
CFRelease(h);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
private:
|
||||
static T duplicate(T h);
|
||||
};
|
||||
|
||||
using cfarray = cf_object<CFArrayRef, static_cast<CFArrayRef>(NULL)>;
|
||||
using cfdictionary = cf_object<CFDictionaryRef, static_cast<CFDictionaryRef>(NULL)>;
|
||||
using cferror = cf_object<CFErrorRef, static_cast<CFErrorRef>(NULL)>;
|
||||
using cfstring = cf_object<CFStringRef, static_cast<CFStringRef>(NULL)>;
|
||||
///
|
||||
/// Core Foundation object traits
|
||||
///
|
||||
template <typename T>
|
||||
using cfobject = handle<T, cfobject_traits<T>>;
|
||||
|
||||
using cfarray = cfobject<CFArrayRef>;
|
||||
using cfdictionary = cfobject<CFDictionaryRef>;
|
||||
using cferror = cfobject<CFErrorRef>;
|
||||
using cfstring = cfobject<CFStringRef>;
|
||||
|
||||
///
|
||||
/// Core Foundation runtime error
|
||||
|
@ -6,41 +6,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#import <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
namespace macstd {
|
||||
///
|
||||
/// IOKit handle wrapper class
|
||||
/// IOKit handle traits
|
||||
///
|
||||
template <typename T>
|
||||
class io_object : public handle<T, 0>
|
||||
struct io_object_traits
|
||||
{
|
||||
MACSTD_HANDLE_IMPL(io_object, T, 0)
|
||||
static inline constexpr T invalid = 0;
|
||||
|
||||
public:
|
||||
///
|
||||
/// Releases an object handle
|
||||
///
|
||||
/// \sa [IOObjectRelease function](https://developer.apple.com/documentation/iokit/1514627-ioobjectrelease)
|
||||
///
|
||||
virtual ~io_object()
|
||||
static void free(T h) noexcept
|
||||
{
|
||||
if (this->m_h != 0)
|
||||
free_internal();
|
||||
IOObjectRelease(h);
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Releases an object handle
|
||||
///
|
||||
/// \sa [IOObjectRelease function](https://developer.apple.com/documentation/iokit/1514627-ioobjectrelease)
|
||||
///
|
||||
void free_internal() noexcept override
|
||||
{
|
||||
IOObjectRelease(this->m_h);
|
||||
}
|
||||
private:
|
||||
static T duplicate(T h);
|
||||
};
|
||||
|
||||
///
|
||||
/// IOKit handle traits
|
||||
///
|
||||
template <typename T>
|
||||
using io_object = handle<T, io_object_traits<T>>;
|
||||
|
||||
using io_connect = io_object<io_connect_t>;
|
||||
using io_enumerator = io_object<io_enumerator_t>;
|
||||
using io_ident = io_object<io_ident_t>;
|
||||
|
@ -73,13 +73,32 @@ namespace macstd
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// Authorization traits
|
||||
///
|
||||
struct authorization_traits
|
||||
{
|
||||
static inline constexpr AuthorizationRef invalid = static_cast<AuthorizationRef>(NULL);
|
||||
|
||||
///
|
||||
/// Releases an object handle
|
||||
///
|
||||
/// \sa [AuthorizationFree function](https://developer.apple.com/documentation/security/authorizationfree)
|
||||
///
|
||||
static void free(AuthorizationRef h) noexcept
|
||||
{
|
||||
AuthorizationFree(h, kAuthorizationFlagDefaults);
|
||||
}
|
||||
|
||||
private:
|
||||
static AuthorizationRef duplicate(AuthorizationRef h);
|
||||
};
|
||||
|
||||
///
|
||||
/// Authorization reference wrapper class
|
||||
///
|
||||
class authorization : public handle<AuthorizationRef, static_cast<AuthorizationRef>(NULL)>
|
||||
class authorization : public handle<AuthorizationRef, authorization_traits>
|
||||
{
|
||||
MACSTD_HANDLE_IMPL(authorization, AuthorizationRef, static_cast<AuthorizationRef>(NULL))
|
||||
|
||||
public:
|
||||
///
|
||||
/// Creates a new authorization reference and provides an option to authorize or preauthorize rights
|
||||
@ -108,30 +127,8 @@ namespace macstd
|
||||
throw security_runtime_error(status, "AuthorizationCreateFromExternalForm failed");
|
||||
this->m_h = h;
|
||||
}
|
||||
|
||||
///
|
||||
/// Releases an object handle
|
||||
///
|
||||
/// \sa [AuthorizationFree function](https://developer.apple.com/documentation/security/authorizationfree)
|
||||
///
|
||||
virtual ~authorization()
|
||||
{
|
||||
if (this->m_h != static_cast<AuthorizationRef>(NULL))
|
||||
free_internal();
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Releases an object handle
|
||||
///
|
||||
/// \sa [AuthorizationFree function](https://developer.apple.com/documentation/security/authorizationfree)
|
||||
///
|
||||
void free_internal() noexcept override
|
||||
{
|
||||
AuthorizationFree(this->m_h, kAuthorizationFlagDefaults);
|
||||
}
|
||||
};
|
||||
|
||||
using sec_keychain = cf_object<SecKeychainRef, static_cast<SecKeychainRef>(NULL)>;
|
||||
using sec_certificate = cf_object<SecCertificateRef, static_cast<SecCertificateRef>(NULL)>;
|
||||
using sec_keychain = cfobject<SecKeychainRef>;
|
||||
using sec_certificate = cfobject<SecCertificateRef>;
|
||||
}
|
||||
|
@ -32,32 +32,6 @@ private: \
|
||||
///
|
||||
#define MACSTD_STACK_BUFFER_BYTES 1024
|
||||
|
||||
///
|
||||
/// Implements default constructors and operators to prevent their auto-generation by compiler.
|
||||
///
|
||||
#define MACSTD_HANDLE_IMPL(C, T, INVAL) \
|
||||
public: \
|
||||
C ( ) noexcept {} \
|
||||
C (_In_opt_ T h) noexcept : handle<T, INVAL>( h ) {} \
|
||||
C (_Inout_ C &&h) noexcept : handle<T, INVAL>(std::move(h)) {} \
|
||||
C& operator=(_In_opt_ T h) noexcept { handle<T, INVAL>::operator=( h ); return *this; } \
|
||||
C& operator=(_Inout_ C &&h) noexcept { handle<T, INVAL>::operator=(std::move(h)); return *this; } \
|
||||
MACSTD_NONCOPYABLE(C)
|
||||
|
||||
///
|
||||
/// Implements default constructors and operators to prevent their auto-generation by compiler.
|
||||
///
|
||||
#define MACSTD_DPLHANDLE_IMPL(C, T, INVAL) \
|
||||
public: \
|
||||
C ( ) noexcept {} \
|
||||
C (_In_opt_ T h) noexcept : dplhandle<T, INVAL>( h ) {} \
|
||||
C (_In_ const C &h) noexcept : dplhandle<T, INVAL>(duplicate_internal(h.m_h)) {} \
|
||||
C (_Inout_ C &&h) noexcept : dplhandle<T, INVAL>(std::move (h )) {} \
|
||||
C& operator=(_In_opt_ T h) noexcept { dplhandle<T, INVAL>::operator=( h ); return *this; } \
|
||||
C& operator=(_In_ const C &h) noexcept { dplhandle<T, INVAL>::operator=( h ); return *this; } \
|
||||
C& operator=(_Inout_ C &&h) noexcept { dplhandle<T, INVAL>::operator=(std::move(h)); return *this; } \
|
||||
private:
|
||||
|
||||
namespace macstd
|
||||
{
|
||||
///
|
||||
@ -65,14 +39,14 @@ namespace macstd
|
||||
///
|
||||
/// It provides basic operators and methods common to all descendands of this class establishing a base to ease the replacement of native object handle type with classes in object-oriented approach.
|
||||
///
|
||||
template <class T, const T INVAL>
|
||||
template <class T, class TR>
|
||||
class handle
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Initializes a new class instance with the object handle set to INVAL.
|
||||
/// Initializes a new class instance with the object handle set to TR::invalid.
|
||||
///
|
||||
handle() noexcept : m_h(INVAL)
|
||||
handle() noexcept : m_h(TR::invalid)
|
||||
{}
|
||||
|
||||
///
|
||||
@ -83,49 +57,74 @@ namespace macstd
|
||||
handle(_In_opt_ T h) noexcept : m_h(h)
|
||||
{}
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
/// \param[in,out] h A reference of another object
|
||||
///
|
||||
handle(const handle<T, TR> &h) : m_h(TR::duplicate(h.m_h))
|
||||
{}
|
||||
|
||||
///
|
||||
/// Move constructor
|
||||
///
|
||||
/// \param[in,out] h A rvalue reference of another object
|
||||
///
|
||||
handle(_Inout_ handle<T, INVAL> &&h) noexcept
|
||||
handle(handle<T, TR> &&h) noexcept
|
||||
{
|
||||
// Transfer handle.
|
||||
m_h = h.m_h;
|
||||
h.m_h = INVAL;
|
||||
h.m_h = TR::invalid;
|
||||
}
|
||||
|
||||
private:
|
||||
// This class is noncopyable.
|
||||
handle(_In_ const handle<T, INVAL> &h) noexcept {};
|
||||
handle<T, INVAL>& operator=(_In_ const handle<T, INVAL> &h) noexcept {};
|
||||
|
||||
public:
|
||||
///
|
||||
/// Attaches already available object handle.
|
||||
///
|
||||
/// \param[in] h Object handle value
|
||||
///
|
||||
handle<T, INVAL>& operator=(_In_opt_ T h) noexcept
|
||||
handle<T, TR>& operator=(_In_opt_ T h) noexcept
|
||||
{
|
||||
attach(h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates the object.
|
||||
///
|
||||
/// \param[in] h Object
|
||||
///
|
||||
handle<T, TR>& operator=(const handle<T, TR> &h) noexcept
|
||||
{
|
||||
if (this != std::addressof(h)) {
|
||||
if (h.m_h != TR::invalid) {
|
||||
T h_new = TR::duplicate(h.m_h);
|
||||
|
||||
if (this->m_h != TR::invalid)
|
||||
TR::free(this->m_h);
|
||||
this->m_h = h_new;
|
||||
} else {
|
||||
if (this->m_h != TR::invalid)
|
||||
TR::free(this->m_h);
|
||||
this->m_h = TR::invalid;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// Move assignment
|
||||
///
|
||||
/// \param[inout] h A rvalue reference of another object
|
||||
/// \param[in,out] h A rvalue reference of another object
|
||||
///
|
||||
#pragma warning(suppress: 26432) // Move constructor is also present, but not detected by code analysis somehow.
|
||||
handle<T, INVAL>& operator=(_Inout_ handle<T, INVAL> &&h) noexcept
|
||||
handle<T, TR>& operator=(handle<T, TR> &&h) noexcept
|
||||
{
|
||||
if (this != std::addressof(h)) {
|
||||
// Transfer handle.
|
||||
if (m_h != INVAL)
|
||||
free_internal();
|
||||
if (m_h != TR::invalid)
|
||||
TR::free(this->m_h);
|
||||
m_h = h.m_h;
|
||||
h.m_h = INVAL;
|
||||
h.m_h = TR::invalid;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -147,7 +146,7 @@ namespace macstd
|
||||
///
|
||||
T*& operator*() const
|
||||
{
|
||||
assert(m_h != INVAL);
|
||||
assert(m_h != TR::invalid);
|
||||
return *m_h;
|
||||
}
|
||||
|
||||
@ -157,7 +156,7 @@ namespace macstd
|
||||
///
|
||||
T* operator&()
|
||||
{
|
||||
assert(m_h == INVAL);
|
||||
assert(m_h == TR::invalid);
|
||||
return &m_h;
|
||||
}
|
||||
|
||||
@ -168,7 +167,7 @@ namespace macstd
|
||||
///
|
||||
T operator->() const
|
||||
{
|
||||
assert(m_h != INVAL);
|
||||
assert(m_h != TR::invalid);
|
||||
return m_h;
|
||||
}
|
||||
|
||||
@ -183,7 +182,7 @@ namespace macstd
|
||||
///
|
||||
bool valid() const
|
||||
{
|
||||
return m_h != INVAL;
|
||||
return m_h != TR::invalid;
|
||||
}
|
||||
|
||||
///
|
||||
@ -264,20 +263,42 @@ namespace macstd
|
||||
return m_h == h;
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates and returns a new object handle.
|
||||
///
|
||||
/// \return Duplicated object handle
|
||||
///
|
||||
T duplicate() const
|
||||
{
|
||||
return this->m_h != TR::invalid ? TR::duplicate(this->m_h) : TR::invalid;
|
||||
}
|
||||
|
||||
///
|
||||
/// Sets a new object handle for the class
|
||||
///
|
||||
/// When the current object handle of the class is non-INVAL, the object is destroyed first.
|
||||
/// When the current object handle of the class is non-TR::invalid, the object is destroyed first.
|
||||
///
|
||||
/// \param[in] h New object handle
|
||||
///
|
||||
void attach(_In_opt_ T h) noexcept
|
||||
{
|
||||
if (m_h != INVAL)
|
||||
free_internal();
|
||||
if (m_h != TR::invalid)
|
||||
TR::free(m_h);
|
||||
m_h = h;
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates an object handle and sets a new object handle.
|
||||
///
|
||||
/// \param[in] h Object handle of existing object
|
||||
///
|
||||
void attach_duplicated(_In_opt_ T h)
|
||||
{
|
||||
if (this->m_h != TR::invalid)
|
||||
TR::free(this->m_h);
|
||||
this->m_h = h != TR::invalid ? TR::duplicate(h) : TR::invalid;
|
||||
}
|
||||
|
||||
///
|
||||
/// Dismisses the object handle from this class
|
||||
///
|
||||
@ -286,7 +307,7 @@ namespace macstd
|
||||
T detach()
|
||||
{
|
||||
T h = m_h;
|
||||
m_h = INVAL;
|
||||
m_h = TR::invalid;
|
||||
return h;
|
||||
}
|
||||
|
||||
@ -295,143 +316,16 @@ namespace macstd
|
||||
///
|
||||
void free()
|
||||
{
|
||||
if (m_h != INVAL) {
|
||||
free_internal();
|
||||
m_h = INVAL;
|
||||
if (m_h != TR::invalid) {
|
||||
TR::free(m_h);
|
||||
m_h = TR::invalid;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Abstract member function that must be implemented by child classes to do the actual object destruction.
|
||||
///
|
||||
virtual void free_internal() noexcept = 0;
|
||||
|
||||
protected:
|
||||
T m_h; ///< Object handle
|
||||
};
|
||||
|
||||
///
|
||||
/// Base abstract template class to support object handle keeping for objects that support trivial handle duplication
|
||||
///
|
||||
template <class T, T INVAL>
|
||||
class dplhandle : public handle<T, INVAL>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Initializes a new class instance with the object handle set to INVAL.
|
||||
///
|
||||
dplhandle() noexcept
|
||||
{}
|
||||
|
||||
///
|
||||
/// Initializes a new class instance with an already available object handle.
|
||||
///
|
||||
/// \param[in] h Initial object handle value
|
||||
///
|
||||
dplhandle(_In_opt_ T h) noexcept : handle<T, INVAL>(h)
|
||||
{}
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
/// \param[in,out] h A reference of another object
|
||||
///
|
||||
dplhandle<T, INVAL>(_In_ const dplhandle<T, INVAL> &h) : handle<T, INVAL>(duplicate_internal(h.m_h))
|
||||
{}
|
||||
|
||||
///
|
||||
/// Move constructor
|
||||
///
|
||||
/// \param[in,out] h A rvalue reference of another object
|
||||
///
|
||||
dplhandle<T, INVAL>(_Inout_ dplhandle<T, INVAL> &&h) noexcept : handle<T, INVAL>(std::move(h))
|
||||
{}
|
||||
|
||||
///
|
||||
/// Attaches already available object handle.
|
||||
///
|
||||
/// \param[in] h Object handle value
|
||||
///
|
||||
dplhandle<T, INVAL>& operator=(_In_opt_ T h) noexcept
|
||||
{
|
||||
handle<T, INVAL>::operator=(h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates the object.
|
||||
///
|
||||
/// \param[in] h Object
|
||||
///
|
||||
dplhandle<T, INVAL>& operator=(_In_ const dplhandle<T, INVAL> &h) noexcept
|
||||
{
|
||||
if (this != std::addressof(h)) {
|
||||
if (h.m_h != INVAL) {
|
||||
T h_new = duplicate_internal(h.m_h);
|
||||
|
||||
if (this->m_h != INVAL)
|
||||
this->free_internal();
|
||||
|
||||
this->m_h = h_new;
|
||||
} else {
|
||||
if (this->m_h != INVAL)
|
||||
this->free_internal();
|
||||
|
||||
this->m_h = INVAL;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// Moves the object.
|
||||
///
|
||||
/// \param[inout] h A rvalue reference of another object
|
||||
///
|
||||
#pragma warning(disable: 26432) // Move constructor is also present, but not detected by code analysis somehow.
|
||||
dplhandle<T, INVAL>& operator=(_Inout_ dplhandle<T, INVAL> &&h) noexcept
|
||||
{
|
||||
handle<T, INVAL>::operator=(std::move(h));
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates and returns a new object handle.
|
||||
///
|
||||
/// \return Duplicated object handle
|
||||
///
|
||||
T duplicate() const
|
||||
{
|
||||
return this->m_h != INVAL ? duplicate_internal(this->m_h) : INVAL;
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates an object handle and sets a new object handle.
|
||||
///
|
||||
/// \param[in] h Object handle of existing object
|
||||
///
|
||||
void attach_duplicated(_In_opt_ T h)
|
||||
{
|
||||
if (this->m_h != INVAL)
|
||||
this->free_internal();
|
||||
|
||||
this->m_h = h != INVAL ? duplicate_internal(h) : INVAL;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Abstract member function that must be implemented by child classes to do the actual object handle duplication.
|
||||
/// On failure, it should throw appropriate exception describing the cause, rather than return an invalid handle.
|
||||
///
|
||||
/// \param[in] h Object handle of existing object
|
||||
///
|
||||
/// \return Duplicated object handle
|
||||
///
|
||||
virtual T duplicate_internal(_In_ T h) const = 0;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// Numerical runtime error
|
||||
///
|
||||
|
Loading…
x
Reference in New Issue
Block a user