diff --git a/Userland/Libraries/LibJS/Heap/GCPtr.h b/Userland/Libraries/LibJS/Heap/GCPtr.h new file mode 100644 index 0000000000..1d809166b4 --- /dev/null +++ b/Userland/Libraries/LibJS/Heap/GCPtr.h @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace JS { + +template +class GCPtr; + +template +class NonnullGCPtr { +public: + NonnullGCPtr() = delete; + + NonnullGCPtr(T& ptr) + : m_ptr(&ptr) + { + } + + NonnullGCPtr(T const& ptr) + : m_ptr(&const_cast(ptr)) + { + } + + template + NonnullGCPtr(U& ptr) requires(IsConvertible) + : m_ptr(&static_cast(ptr)) + { + } + + template + NonnullGCPtr(U const& ptr) requires(IsConvertible) + : m_ptr(&const_cast(static_cast(ptr))) + { + } + + template + NonnullGCPtr(NonnullGCPtr ptr) requires(IsConvertible) + : m_ptr(ptr) + { + } + + NonnullGCPtr& operator=(GCPtr const& other) + { + m_ptr = const_cast(other.ptr()); + return *this; + } + + NonnullGCPtr& operator=(T const& other) + { + m_ptr = &const_cast(other); + return *this; + } + + template + NonnullGCPtr& operator=(U const& other) requires(IsConvertible) + { + m_ptr = &const_cast(static_cast(other)); + return *this; + } + + template + NonnullGCPtr& operator=(NonnullGCPtr const& other) requires(IsConvertible) + { + m_ptr = const_cast(static_cast(other.ptr())); + return *this; + } + + T* operator->() { return m_ptr; } + T const* operator->() const { return m_ptr; } + + T& operator*() { return *m_ptr; } + T const& operator*() const { return *m_ptr; } + + T* ptr() { return m_ptr; } + T const* ptr() const { return m_ptr; } + + operator T*() { return m_ptr; } + operator T const*() const { return m_ptr; } + + operator T&() { return *m_ptr; } + operator T const&() const { return *m_ptr; } + +private: + T* m_ptr { nullptr }; +}; + +template +class GCPtr { +public: + GCPtr() = default; + + GCPtr(T& ptr) + : m_ptr(&ptr) + { + } + + GCPtr(T const& ptr) + : m_ptr(&const_cast(ptr)) + { + } + + GCPtr(T* ptr) + : m_ptr(ptr) + { + } + + GCPtr(T const* ptr) + : m_ptr(const_cast(ptr)) + { + } + + GCPtr(NonnullGCPtr ptr) + : m_ptr(ptr) + { + } + + template + GCPtr(NonnullGCPtr ptr) requires(IsConvertible) + : m_ptr(ptr) + { + } + + GCPtr(std::nullptr_t) + : m_ptr(nullptr) + { + } + + GCPtr(GCPtr const&) = default; + GCPtr& operator=(GCPtr const&) = default; + + template + GCPtr& operator=(GCPtr const& other) requires(IsConvertible) + { + m_ptr = const_cast(static_cast(other.ptr())); + return *this; + } + + GCPtr& operator=(NonnullGCPtr const& other) + { + m_ptr = const_cast(other.ptr()); + return *this; + } + + template + GCPtr& operator=(NonnullGCPtr const& other) requires(IsConvertible) + { + m_ptr = const_cast(static_cast(other.ptr())); + return *this; + } + + GCPtr& operator=(T const& other) + { + m_ptr = &const_cast(other); + return *this; + } + + template + GCPtr& operator=(U const& other) requires(IsConvertible) + { + m_ptr = &const_cast(static_cast(other)); + return *this; + } + + GCPtr& operator=(T const* other) + { + m_ptr = const_cast(other); + return *this; + } + + template + GCPtr& operator=(U const* other) requires(IsConvertible) + { + m_ptr = const_cast(static_cast(other)); + return *this; + } + + T* operator->() { return m_ptr; } + T const* operator->() const { return m_ptr; } + + T& operator*() { return *m_ptr; } + T const& operator*() const { return *m_ptr; } + + T* ptr() { return m_ptr; } + T const* ptr() const { return m_ptr; } + + operator bool() const { return !!m_ptr; } + bool operator!() const { return !m_ptr; } + + operator T*() { return m_ptr; } + operator T const*() const { return m_ptr; } + +private: + T* m_ptr { nullptr }; +}; + +template +inline bool operator==(GCPtr const& a, GCPtr const& b) +{ + return a.ptr() == b.ptr(); +} + +template +inline bool operator==(GCPtr const& a, NonnullGCPtr const& b) +{ + return a.ptr() == b.ptr(); +} + +template +inline bool operator==(NonnullGCPtr const& a, NonnullGCPtr const& b) +{ + return a.ptr() == b.ptr(); +} + +template +inline bool operator==(NonnullGCPtr const& a, GCPtr const& b) +{ + return a.ptr() == b.ptr(); +} + +template +inline bool operator==(NonnullGCPtr const& a, U const* b) +{ + return a.ptr() == b; +} + +template +inline bool operator==(GCPtr const& a, U const* b) +{ + return a.ptr() == b; +} + +}