xbot/myirc/include/ref.hpp

57 lines
1.4 KiB
C++
Raw Normal View History

2025-01-28 19:04:36 -08:00
#pragma once
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <memory>
2025-01-30 11:47:26 -08:00
// Specializations must Free to release a reference
// Specializations can implement UpRef to increase a reference count on copy
2025-01-29 09:54:17 -08:00
template <typename> struct RefTraits {};
template <> struct RefTraits<EVP_PKEY> {
static constexpr void (*Free)(EVP_PKEY*) = EVP_PKEY_free;
static constexpr int (*UpRef)(EVP_PKEY*) = EVP_PKEY_up_ref;
};
template <> struct RefTraits<X509> {
static constexpr void (*Free)(X509*) = X509_free;
static constexpr int (*UpRef)(X509*) = X509_up_ref;
};
template <> struct RefTraits<EVP_PKEY_CTX> {
static constexpr void (*Free)(EVP_PKEY_CTX*) = EVP_PKEY_CTX_free;
2025-01-30 11:47:26 -08:00
// this type does not implement UpRef
2025-01-29 09:54:17 -08:00
};
template <typename T>
2025-01-30 11:56:03 -08:00
struct RefDeleter {
2025-01-29 09:54:17 -08:00
auto operator()(T *ptr) const -> void { RefTraits<T>::Free(ptr); }
2025-01-28 19:04:36 -08:00
};
2025-01-29 09:54:17 -08:00
template <typename T>
2025-01-30 11:56:03 -08:00
struct Ref : std::unique_ptr<T, RefDeleter<T>>
2025-01-30 11:47:26 -08:00
{
2025-01-30 11:56:03 -08:00
using base = std::unique_ptr<T, RefDeleter<T>>;
2025-01-30 11:47:26 -08:00
/// Owns nothing
Ref() noexcept = default;
/// Takes ownership of the pointer
explicit Ref(T *x) noexcept : base{x} {}
Ref(Ref &&ref) noexcept = default;
Ref(const Ref &ref) noexcept {
2025-01-29 09:54:17 -08:00
*this = ref;
}
2025-01-30 11:47:26 -08:00
Ref &operator=(Ref&&) noexcept = default;
Ref &operator=(const Ref &ref) noexcept {
2025-01-30 09:28:28 -08:00
if (ref) {
RefTraits<T>::UpRef(ref.get());
}
2025-01-30 11:47:26 -08:00
this->reset(ref.get());
2025-01-29 09:54:17 -08:00
return *this;
}
};