boo/lib/inputdev/IOKitPointer.hpp

104 lines
2.7 KiB
C++
Raw Normal View History

2018-10-07 03:36:44 +00:00
#pragma once
2017-05-07 21:24:00 +00:00
#include "lib/CFPointer.hpp"
2017-05-07 21:24:00 +00:00
#include <IOKit/IOTypes.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <utility>
/// A smart pointer that can manage the lifecycle of IOKit objects.
2018-12-08 05:17:51 +00:00
template <typename T>
2017-05-07 21:24:00 +00:00
class IOObjectPointer {
public:
2018-12-08 05:17:51 +00:00
IOObjectPointer() : storage(0) {}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
IOObjectPointer(T pointer) : storage(toStorageType(pointer)) {
if (storage) {
IOObjectRetain(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
IOObjectPointer(const IOObjectPointer& other) : storage(other.storage) {
if (io_object_t ptr = storage) {
IOObjectRetain(ptr);
2017-05-07 21:24:00 +00:00
}
2018-12-08 05:17:51 +00:00
}
IOObjectPointer& operator=(const IOObjectPointer& other) {
if (io_object_t pointer = storage) {
IOObjectRelease(pointer);
2017-05-07 21:24:00 +00:00
}
2018-12-08 05:17:51 +00:00
storage = other.storage;
if (io_object_t ptr = storage) {
IOObjectRetain(ptr);
}
return *this;
}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
IOObjectPointer(IOObjectPointer&& other) : storage(std::exchange(other.storage, 0)) {}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
~IOObjectPointer() {
if (io_object_t pointer = storage) {
IOObjectRelease(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 IOObjectPointer<T> adopt(T ptr) { return IOObjectPointer<T>(ptr, IOObjectPointer<T>::Adopt); }
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
T get() const { return fromStorageType(storage); }
io_object_t* operator&() {
if (io_object_t pointer = storage) {
IOObjectRelease(pointer);
2017-05-07 21:24:00 +00:00
}
2018-12-08 05:17:51 +00:00
return &storage;
}
operator bool() const { return storage != 0; }
2017-05-07 21:24:00 +00:00
private:
2018-12-08 05:17:51 +00:00
io_object_t storage;
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
enum AdoptTag { Adopt };
IOObjectPointer(T ptr, AdoptTag) : storage(toStorageType(ptr)) {}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
inline io_object_t toStorageType(io_object_t ptr) const { return (io_object_t)ptr; }
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
inline T fromStorageType(io_object_t pointer) const { return (T)pointer; }
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
void swap(IOObjectPointer& other) { std::swap(storage, other.storage); }
2017-05-07 21:24:00 +00:00
};
/// A smart pointer that can manage the lifecycle of IOKit plugin objects.
class IOCFPluginPointer {
public:
2018-12-08 05:17:51 +00:00
IOCFPluginPointer() : _storage(nullptr) {}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
IOCFPluginPointer(const IOCFPluginPointer& other) = delete;
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
IOCFPluginPointer(IOCFPluginPointer&& other) : _storage(std::exchange(other._storage, nullptr)) {}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
~IOCFPluginPointer() {
if (IOCFPlugInInterface** pointer = _storage) {
IODestroyPlugInInterface(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
IOCFPlugInInterface*** operator&() {
if (IOCFPlugInInterface** pointer = _storage) {
IODestroyPlugInInterface(pointer);
2017-05-07 21:24:00 +00:00
}
2018-12-08 05:17:51 +00:00
return &_storage;
}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
HRESULT As(LPVOID* p, CFUUIDRef uuid) const {
(*_storage)->AddRef(_storage); // Needed for some reason
return (*_storage)->QueryInterface(_storage, CFUUIDGetUUIDBytes(uuid), p);
}
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
operator bool() const { return _storage != nullptr; }
2017-05-07 21:24:00 +00:00
2018-12-08 05:17:51 +00:00
IOCFPlugInInterface** storage() const { return _storage; }
2017-05-07 21:24:00 +00:00
private:
2018-12-08 05:17:51 +00:00
IOCFPlugInInterface** _storage;
void swap(IOCFPluginPointer& other) { std::swap(_storage, other._storage); }
2017-05-07 21:24:00 +00:00
};