/* * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include namespace JS { template class GCPtr; template class NonnullGCPtr { public: NonnullGCPtr() = delete; NonnullGCPtr(T& ptr) : m_ptr(&ptr) { } template NonnullGCPtr(U& ptr) requires(IsConvertible) : m_ptr(&static_cast(ptr)) { } NonnullGCPtr(NonnullGCPtr const& other) : m_ptr(other.ptr()) { } template NonnullGCPtr(NonnullGCPtr const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } NonnullGCPtr& operator=(NonnullGCPtr const& other) { m_ptr = other.ptr(); return *this; } template NonnullGCPtr& operator=(NonnullGCPtr const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } NonnullGCPtr& operator=(T& other) { m_ptr = &other; return *this; } template NonnullGCPtr& operator=(U& other) requires(IsConvertible) { m_ptr = &static_cast(other); 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 class GCPtr { public: GCPtr() = default; GCPtr(T& ptr) : m_ptr(&ptr) { } GCPtr(T* ptr) : m_ptr(ptr) { } GCPtr(GCPtr const& other) : m_ptr(other.ptr()) { } template GCPtr(GCPtr const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } GCPtr(NonnullGCPtr const& other) : m_ptr(other.ptr()) { } template GCPtr(NonnullGCPtr const& other) requires(IsConvertible) : m_ptr(other.ptr()) { } GCPtr(nullptr_t) : m_ptr(nullptr) { } GCPtr& operator=(GCPtr const&) = default; template GCPtr& operator=(GCPtr const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } GCPtr& operator=(NonnullGCPtr const& other) { m_ptr = other.ptr(); return *this; } template GCPtr& operator=(NonnullGCPtr const& other) requires(IsConvertible) { m_ptr = static_cast(other.ptr()); return *this; } GCPtr& operator=(T& other) { m_ptr = &other; return *this; } template GCPtr& operator=(U& other) requires(IsConvertible) { m_ptr = &static_cast(other); return *this; } GCPtr& operator=(T* other) { m_ptr = other; return *this; } template GCPtr& operator=(U* other) requires(IsConvertible) { m_ptr = static_cast(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 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(); } } namespace AK { template struct Traits> : public GenericTraits> { static unsigned hash(JS::GCPtr const& value) { return Traits::hash(value.ptr()); } }; template struct Traits> : public GenericTraits> { static unsigned hash(JS::NonnullGCPtr const& value) { return Traits::hash(value.ptr()); } }; }