2018-10-07 03:36:44 +00:00
|
|
|
#pragma once
|
2017-05-07 21:24:00 +00:00
|
|
|
|
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
|
|
#include <CoreFoundation/CFPlugInCOM.h>
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
/// A smart pointer that can manage the lifecycle of Core Foundation objects.
|
2018-12-08 05:17:51 +00:00
|
|
|
template <typename T>
|
2017-05-07 21:24:00 +00:00
|
|
|
class CFPointer {
|
|
|
|
public:
|
2018-12-08 05:17:51 +00:00
|
|
|
CFPointer() : storage(nullptr) {}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
CFPointer(T pointer) : storage(toStorageType(pointer)) {
|
|
|
|
if (storage) {
|
|
|
|
CFRetain(storage);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
CFPointer(const CFPointer& other) : storage(other.storage) {
|
|
|
|
if (CFTypeRef ptr = storage) {
|
|
|
|
CFRetain(ptr);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
CFPointer(CFPointer&& other) : storage(std::exchange(other.storage, nullptr)) {}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
~CFPointer() {
|
|
|
|
if (CFTypeRef pointer = storage) {
|
|
|
|
CFRelease(pointer);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
static inline CFPointer<T> adopt(T CF_RELEASES_ARGUMENT ptr) { return CFPointer<T>(ptr, CFPointer<T>::Adopt); }
|
2017-05-07 21:31:56 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
T get() const { return fromStorageType(storage); }
|
2017-05-07 21:31:56 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
CFPointer& operator=(CFPointer other) {
|
|
|
|
swap(other);
|
|
|
|
return *this;
|
|
|
|
}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
T* operator&() {
|
|
|
|
if (CFTypeRef pointer = storage) {
|
|
|
|
CFRelease(pointer);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
return (T*)&storage;
|
|
|
|
}
|
|
|
|
operator bool() const { return storage != nullptr; }
|
|
|
|
|
|
|
|
void reset() {
|
|
|
|
if (storage) {
|
|
|
|
CFRelease(storage);
|
|
|
|
storage = nullptr;
|
2017-05-11 19:12:44 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
}
|
2017-05-11 19:12:44 +00:00
|
|
|
|
2017-05-07 21:24:00 +00:00
|
|
|
private:
|
2018-12-08 05:17:51 +00:00
|
|
|
CFTypeRef storage;
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
enum AdoptTag { Adopt };
|
|
|
|
CFPointer(T ptr, AdoptTag) : storage(toStorageType(ptr)) {}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
inline CFTypeRef toStorageType(CFTypeRef ptr) const { return (CFTypeRef)ptr; }
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
inline T fromStorageType(CFTypeRef pointer) const { return (T)pointer; }
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
void swap(CFPointer& other) { std::swap(storage, other.storage); }
|
2017-05-07 21:24:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// A smart pointer that can manage the lifecycle of CoreFoundation IUnknown objects.
|
2018-12-08 05:17:51 +00:00
|
|
|
template <typename T>
|
2017-05-07 21:24:00 +00:00
|
|
|
class IUnknownPointer {
|
|
|
|
public:
|
2018-12-08 05:17:51 +00:00
|
|
|
IUnknownPointer() : _storage(nullptr) {}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
IUnknownPointer(T** pointer) : _storage(toStorageType(pointer)) {
|
|
|
|
if (_storage) {
|
|
|
|
(*pointer)->AddRef(pointer);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
IUnknownPointer(const IUnknownPointer& other) : _storage(other._storage) {
|
|
|
|
if (IUnknownVTbl** ptr = _storage) {
|
|
|
|
(*ptr)->AddRef(ptr);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
}
|
|
|
|
IUnknownPointer& operator=(const IUnknownPointer& other) {
|
|
|
|
if (IUnknownVTbl** pointer = _storage) {
|
|
|
|
(*pointer)->Release(pointer);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
_storage = other._storage;
|
|
|
|
if (IUnknownVTbl** ptr = _storage) {
|
|
|
|
(*ptr)->AddRef(ptr);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
IUnknownPointer(IUnknownPointer&& other) : _storage(std::exchange(other._storage, nullptr)) {}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
~IUnknownPointer() {
|
|
|
|
if (IUnknownVTbl** pointer = _storage) {
|
|
|
|
(*pointer)->Release(pointer);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
static inline IUnknownPointer<T> adopt(T** ptr) { return IUnknownPointer<T>(ptr, IUnknownPointer<T>::Adopt); }
|
2017-05-07 21:31:56 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
T* get() const { return fromStorageType(_storage); }
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
T* operator->() const { return get(); }
|
|
|
|
T** storage() const { return (T**)_storage; }
|
|
|
|
LPVOID* operator&() {
|
|
|
|
if (IUnknownVTbl** pointer = _storage) {
|
2019-08-31 20:12:12 +00:00
|
|
|
(*pointer)->Release(pointer);
|
2017-05-07 21:24:00 +00:00
|
|
|
}
|
2018-12-08 05:17:51 +00:00
|
|
|
return (LPVOID*)&_storage;
|
|
|
|
}
|
|
|
|
operator bool() const { return _storage != nullptr; }
|
2017-05-07 21:24:00 +00:00
|
|
|
|
|
|
|
private:
|
2018-12-08 05:17:51 +00:00
|
|
|
IUnknownVTbl** _storage;
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
enum AdoptTag { Adopt };
|
|
|
|
IUnknownPointer(T** ptr, AdoptTag) : _storage(toStorageType(ptr)) {}
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
inline IUnknownVTbl** toStorageType(T** ptr) const { return (IUnknownVTbl**)ptr; }
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
inline T* fromStorageType(IUnknownVTbl** pointer) const { return *(T**)pointer; }
|
2017-05-07 21:24:00 +00:00
|
|
|
|
2018-12-08 05:17:51 +00:00
|
|
|
void swap(IUnknownPointer& other) { std::swap(_storage, other._storage); }
|
2017-05-07 21:24:00 +00:00
|
|
|
};
|