#pragma once #include #include #include /// A smart pointer that can manage the lifecycle of Core Foundation objects. template class CFPointer { public: CFPointer() : storage(nullptr) {} CFPointer(T pointer) : storage(toStorageType(pointer)) { if (storage) { CFRetain(storage); } } CFPointer(const CFPointer& other) : storage(other.storage) { if (CFTypeRef ptr = storage) { CFRetain(ptr); } } CFPointer(CFPointer&& other) : storage(std::exchange(other.storage, nullptr)) {} ~CFPointer() { if (CFTypeRef pointer = storage) { CFRelease(pointer); } } static inline CFPointer adopt(T CF_RELEASES_ARGUMENT ptr) { return CFPointer(ptr, CFPointer::Adopt); } T get() const { return fromStorageType(storage); } CFPointer& operator=(CFPointer other) { swap(other); return *this; } T* operator&() { if (CFTypeRef pointer = storage) { CFRelease(pointer); } return (T*)&storage; } operator bool() const { return storage != nullptr; } void reset() { if (storage) { CFRelease(storage); storage = nullptr; } } private: CFTypeRef storage; enum AdoptTag { Adopt }; CFPointer(T ptr, AdoptTag) : storage(toStorageType(ptr)) {} inline CFTypeRef toStorageType(CFTypeRef ptr) const { return (CFTypeRef)ptr; } inline T fromStorageType(CFTypeRef pointer) const { return (T)pointer; } void swap(CFPointer& other) { std::swap(storage, other.storage); } }; /// A smart pointer that can manage the lifecycle of CoreFoundation IUnknown objects. template class IUnknownPointer { public: IUnknownPointer() : _storage(nullptr) {} IUnknownPointer(T** pointer) : _storage(toStorageType(pointer)) { if (_storage) { (*pointer)->AddRef(pointer); } } IUnknownPointer(const IUnknownPointer& other) : _storage(other._storage) { if (IUnknownVTbl** ptr = _storage) { (*ptr)->AddRef(ptr); } } IUnknownPointer& operator=(const IUnknownPointer& other) { if (IUnknownVTbl** pointer = _storage) { (*pointer)->Release(pointer); } _storage = other._storage; if (IUnknownVTbl** ptr = _storage) { (*ptr)->AddRef(ptr); } return *this; } IUnknownPointer(IUnknownPointer&& other) : _storage(std::exchange(other._storage, nullptr)) {} ~IUnknownPointer() { if (IUnknownVTbl** pointer = _storage) { (*pointer)->Release(pointer); } } static inline IUnknownPointer adopt(T** ptr) { return IUnknownPointer(ptr, IUnknownPointer::Adopt); } T* get() const { return fromStorageType(_storage); } T* operator->() const { return get(); } T** storage() const { return (T**)_storage; } LPVOID* operator&() { if (IUnknownVTbl** pointer = _storage) { (*pointer)->Release(pointer); } return (LPVOID*)&_storage; } operator bool() const { return _storage != nullptr; } private: IUnknownVTbl** _storage; enum AdoptTag { Adopt }; IUnknownPointer(T** ptr, AdoptTag) : _storage(toStorageType(ptr)) {} inline IUnknownVTbl** toStorageType(T** ptr) const { return (IUnknownVTbl**)ptr; } inline T* fromStorageType(IUnknownVTbl** pointer) const { return *(T**)pointer; } void swap(IUnknownPointer& other) { std::swap(_storage, other._storage); } };