From bf4dd4a1d0447c2a67591c52cb1e2c6b19975d78 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Fri, 20 Jun 2025 10:22:00 +0200 Subject: [PATCH] common: merge dup_handle and handle and use traits Signed-off-by: Simon Rozman --- include/MacStd/CoreFoundation.hpp | 40 +++-- include/MacStd/IOKit.hpp | 32 ++-- include/MacStd/Security.hpp | 51 +++--- include/MacStd/common.hpp | 256 +++++++++--------------------- 4 files changed, 131 insertions(+), 248 deletions(-) diff --git a/include/MacStd/CoreFoundation.hpp b/include/MacStd/CoreFoundation.hpp index 8c4f4fe..ae12c65 100644 --- a/include/MacStd/CoreFoundation.hpp +++ b/include/MacStd/CoreFoundation.hpp @@ -12,41 +12,37 @@ namespace macstd { /// - /// IOKit handle wrapper class + /// Core Foundation object traits /// - template - class cf_object : public handle + template + struct cfobject_traits { - MACSTD_HANDLE_IMPL(cf_object, T, INVAL) + static inline constexpr T invalid = static_cast(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(NULL)>; - using cfdictionary = cf_object(NULL)>; - using cferror = cf_object(NULL)>; - using cfstring = cf_object(NULL)>; + /// + /// Core Foundation object traits + /// + template + using cfobject = handle>; + + using cfarray = cfobject; + using cfdictionary = cfobject; + using cferror = cfobject; + using cfstring = cfobject; /// /// Core Foundation runtime error diff --git a/include/MacStd/IOKit.hpp b/include/MacStd/IOKit.hpp index 2563c0d..6d0875c 100644 --- a/include/MacStd/IOKit.hpp +++ b/include/MacStd/IOKit.hpp @@ -6,41 +6,37 @@ #pragma once #include "common.hpp" -#import +#include namespace macstd { /// - /// IOKit handle wrapper class + /// IOKit handle traits /// template - class io_object : public handle + 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 + using io_object = handle>; + using io_connect = io_object; using io_enumerator = io_object; using io_ident = io_object; diff --git a/include/MacStd/Security.hpp b/include/MacStd/Security.hpp index b0e5403..0c11d9c 100644 --- a/include/MacStd/Security.hpp +++ b/include/MacStd/Security.hpp @@ -73,13 +73,32 @@ namespace macstd } }; + /// + /// Authorization traits + /// + struct authorization_traits + { + static inline constexpr AuthorizationRef invalid = static_cast(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(NULL)> + class authorization : public handle { - MACSTD_HANDLE_IMPL(authorization, AuthorizationRef, static_cast(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(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(NULL)>; - using sec_certificate = cf_object(NULL)>; + using sec_keychain = cfobject; + using sec_certificate = cfobject; } diff --git a/include/MacStd/common.hpp b/include/MacStd/common.hpp index 21711c3..d4f05a5 100644 --- a/include/MacStd/common.hpp +++ b/include/MacStd/common.hpp @@ -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( h ) {} \ - C (_Inout_ C &&h) noexcept : handle(std::move(h)) {} \ - C& operator=(_In_opt_ T h) noexcept { handle::operator=( h ); return *this; } \ - C& operator=(_Inout_ C &&h) noexcept { handle::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( h ) {} \ - C (_In_ const C &h) noexcept : dplhandle(duplicate_internal(h.m_h)) {} \ - C (_Inout_ C &&h) noexcept : dplhandle(std::move (h )) {} \ - C& operator=(_In_opt_ T h) noexcept { dplhandle::operator=( h ); return *this; } \ - C& operator=(_In_ const C &h) noexcept { dplhandle::operator=( h ); return *this; } \ - C& operator=(_Inout_ C &&h) noexcept { dplhandle::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 + template 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 &h) : m_h(TR::duplicate(h.m_h)) + {} + /// /// Move constructor /// /// \param[in,out] h A rvalue reference of another object /// - handle(_Inout_ handle &&h) noexcept + handle(handle &&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 &h) noexcept {}; - handle& operator=(_In_ const handle &h) noexcept {}; - public: /// /// Attaches already available object handle. /// /// \param[in] h Object handle value /// - handle& operator=(_In_opt_ T h) noexcept + handle& operator=(_In_opt_ T h) noexcept { attach(h); return *this; } + /// + /// Duplicates the object. + /// + /// \param[in] h Object + /// + handle& operator=(const handle &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& operator=(_Inout_ handle &&h) noexcept + handle& operator=(handle &&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 dplhandle : public handle - { - 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(h) - {} - - /// - /// Copy constructor - /// - /// \param[in,out] h A reference of another object - /// - dplhandle(_In_ const dplhandle &h) : handle(duplicate_internal(h.m_h)) - {} - - /// - /// Move constructor - /// - /// \param[in,out] h A rvalue reference of another object - /// - dplhandle(_Inout_ dplhandle &&h) noexcept : handle(std::move(h)) - {} - - /// - /// Attaches already available object handle. - /// - /// \param[in] h Object handle value - /// - dplhandle& operator=(_In_opt_ T h) noexcept - { - handle::operator=(h); - return *this; - } - - /// - /// Duplicates the object. - /// - /// \param[in] h Object - /// - dplhandle& operator=(_In_ const dplhandle &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& operator=(_Inout_ dplhandle &&h) noexcept - { - handle::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 ///