#pragma once
#include <wtf/FastMalloc.h>
#include <wtf/Noncopyable.h>
namespace WTF {
template<typename T, typename Malloc = FastMalloc> class MallocPtr {
WTF_MAKE_NONCOPYABLE(MallocPtr);
public:
MallocPtr() = default;
constexpr MallocPtr(std::nullptr_t)
{
}
MallocPtr(MallocPtr&& other)
: m_ptr(other.leakPtr())
{
}
~MallocPtr()
{
Malloc::free(m_ptr);
}
T* get() const
{
return m_ptr;
}
T *leakPtr() WARN_UNUSED_RETURN
{
return std::exchange(m_ptr, nullptr);
}
explicit operator bool() const
{
return m_ptr;
}
bool operator!() const
{
return !m_ptr;
}
T& operator*() const
{
ASSERT(m_ptr);
return *m_ptr;
}
T* operator->() const
{
return m_ptr;
}
MallocPtr& operator=(MallocPtr&& other)
{
MallocPtr ptr = WTFMove(other);
swap(ptr);
return *this;
}
void swap(MallocPtr& other)
{
std::swap(m_ptr, other.m_ptr);
}
template<typename U, typename OtherMalloc> friend MallocPtr<U, OtherMalloc> adoptMallocPtr(U*);
static MallocPtr malloc(size_t size)
{
return MallocPtr {
static_cast<T*>(Malloc::malloc(size))
};
}
static MallocPtr zeroedMalloc(size_t size)
{
return MallocPtr {
static_cast<T*>(Malloc::zeroedMalloc(size))
};
}
static MallocPtr tryMalloc(size_t size)
{
return MallocPtr {
static_cast<T*>(Malloc::tryMalloc(size))
};
}
static MallocPtr tryZeroedMalloc(size_t size)
{
return MallocPtr {
static_cast<T*>(Malloc::tryZeroedMalloc(size))
};
}
void realloc(size_t newSize)
{
m_ptr = static_cast<T*>(Malloc::realloc(m_ptr, newSize));
}
private:
explicit MallocPtr(T* ptr)
: m_ptr(ptr)
{
}
T* m_ptr { nullptr };
};
static_assert(sizeof(MallocPtr<int>) == sizeof(int*), "");
template<typename U, typename OtherMalloc> MallocPtr<U, OtherMalloc> adoptMallocPtr(U* ptr)
{
return MallocPtr<U, OtherMalloc>(ptr);
}
}
using WTF::MallocPtr;
using WTF::adoptMallocPtr;