1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 05:44:58 +00:00
serenity/Userland/Libraries/LibJS/Heap/GCPtr.h
Ali Mohammad Pur f96a3c002a Everywhere: Stop shoving things into ::std and mentioning them as such
Note that this still keeps the old behaviour of putting things in std by
default on serenity so the tools can be happy, but if USING_AK_GLOBALLY
is unset, AK behaves like a good citizen and doesn't try to put things
in the ::std namespace.

std::nothrow_t and its friends get to stay because I'm being told that
compilers assume things about them and I can't yeet them into a
different namespace...for now.
2022-12-14 11:44:32 +01:00

237 lines
4.5 KiB
C++

/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
namespace JS {
template<typename T>
class GCPtr;
template<typename T>
class NonnullGCPtr {
public:
NonnullGCPtr() = delete;
NonnullGCPtr(T& ptr)
: m_ptr(&ptr)
{
}
NonnullGCPtr(T const& ptr)
: m_ptr(&const_cast<T&>(ptr))
{
}
template<typename U>
NonnullGCPtr(U& ptr)
requires(IsConvertible<U*, T*>)
: m_ptr(&static_cast<T&>(ptr))
{
}
template<typename U>
NonnullGCPtr(U const& ptr)
requires(IsConvertible<U*, T*>)
: m_ptr(&const_cast<T&>(static_cast<T const&>(ptr)))
{
}
template<typename U>
NonnullGCPtr(NonnullGCPtr<U> ptr)
requires(IsConvertible<U*, T*>)
: m_ptr(ptr)
{
}
NonnullGCPtr& operator=(GCPtr<T> const& other)
{
m_ptr = const_cast<T*>(other.ptr());
VERIFY(m_ptr);
return *this;
}
NonnullGCPtr& operator=(T const& other)
{
m_ptr = &const_cast<T&>(other);
return *this;
}
template<typename U>
NonnullGCPtr& operator=(U const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = &const_cast<T&>(static_cast<T const&>(other));
return *this;
}
template<typename U>
NonnullGCPtr& operator=(NonnullGCPtr<U> const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other.ptr()));
return *this;
}
T* operator->() const { return m_ptr; }
T& operator*() const { return *m_ptr; }
T* ptr() const { return m_ptr; }
operator T*() const { return m_ptr; }
operator T&() const { return *m_ptr; }
private:
T* m_ptr { nullptr };
};
template<typename T>
class GCPtr {
public:
GCPtr() = default;
GCPtr(T& ptr)
: m_ptr(&ptr)
{
}
GCPtr(T const& ptr)
: m_ptr(&const_cast<T&>(ptr))
{
}
GCPtr(T* ptr)
: m_ptr(ptr)
{
}
GCPtr(T const* ptr)
: m_ptr(const_cast<T*>(ptr))
{
}
GCPtr(NonnullGCPtr<T> ptr)
: m_ptr(ptr)
{
}
template<typename U>
GCPtr(NonnullGCPtr<U> ptr)
requires(IsConvertible<U*, T*>)
: m_ptr(ptr)
{
}
GCPtr(nullptr_t)
: m_ptr(nullptr)
{
}
GCPtr(GCPtr const&) = default;
GCPtr& operator=(GCPtr const&) = default;
template<typename U>
GCPtr& operator=(GCPtr<U> const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other.ptr()));
return *this;
}
GCPtr& operator=(NonnullGCPtr<T> const& other)
{
m_ptr = const_cast<T*>(other.ptr());
return *this;
}
template<typename U>
GCPtr& operator=(NonnullGCPtr<U> const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other.ptr()));
return *this;
}
GCPtr& operator=(T const& other)
{
m_ptr = &const_cast<T&>(other);
return *this;
}
template<typename U>
GCPtr& operator=(U const& other)
requires(IsConvertible<U*, T*>)
{
m_ptr = &const_cast<T&>(static_cast<T const&>(other));
return *this;
}
GCPtr& operator=(T const* other)
{
m_ptr = const_cast<T*>(other);
return *this;
}
template<typename U>
GCPtr& operator=(U const* other)
requires(IsConvertible<U*, T*>)
{
m_ptr = const_cast<T*>(static_cast<T const*>(other));
return *this;
}
T* operator->() const
{
VERIFY(m_ptr);
return m_ptr;
}
T& operator*() const
{
VERIFY(m_ptr);
return *m_ptr;
}
T* ptr() const { return m_ptr; }
operator bool() const { return !!m_ptr; }
bool operator!() const { return !m_ptr; }
operator T*() const { return m_ptr; }
private:
T* m_ptr { nullptr };
};
template<typename T, typename U>
inline bool operator==(GCPtr<T> const& a, GCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
template<typename T, typename U>
inline bool operator==(GCPtr<T> const& a, NonnullGCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
template<typename T, typename U>
inline bool operator==(NonnullGCPtr<T> const& a, NonnullGCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
template<typename T, typename U>
inline bool operator==(NonnullGCPtr<T> const& a, GCPtr<U> const& b)
{
return a.ptr() == b.ptr();
}
}