mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 18:52:45 +00:00 
			
		
		
		
	 66a428ae03
			
		
	
	
		66a428ae03
		
	
	
	
	
		
			
			Even if the pointer value is const, the value they point to is not necessarily const, so these functions should not add the qualifier. This also removes the redundant non-const implementations of these operators.
		
			
				
	
	
		
			162 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/Badge.h>
 | |
| #include <AK/IntrusiveList.h>
 | |
| #include <AK/Noncopyable.h>
 | |
| #include <AK/RefCounted.h>
 | |
| #include <AK/RefPtr.h>
 | |
| #include <LibJS/Forward.h>
 | |
| #include <LibJS/Runtime/Value.h>
 | |
| 
 | |
| namespace JS {
 | |
| 
 | |
| class HandleImpl : public RefCounted<HandleImpl> {
 | |
|     AK_MAKE_NONCOPYABLE(HandleImpl);
 | |
|     AK_MAKE_NONMOVABLE(HandleImpl);
 | |
| 
 | |
| public:
 | |
|     ~HandleImpl();
 | |
| 
 | |
|     Cell* cell() { return m_cell; }
 | |
|     Cell const* cell() const { return m_cell; }
 | |
| 
 | |
| private:
 | |
|     template<class T>
 | |
|     friend class Handle;
 | |
| 
 | |
|     explicit HandleImpl(Cell*);
 | |
|     Cell* m_cell { nullptr };
 | |
| 
 | |
|     IntrusiveListNode<HandleImpl> m_list_node;
 | |
| 
 | |
| public:
 | |
|     using List = IntrusiveList<&HandleImpl::m_list_node>;
 | |
| };
 | |
| 
 | |
| template<class T>
 | |
| class Handle {
 | |
| public:
 | |
|     Handle() = default;
 | |
| 
 | |
|     static Handle create(T* cell)
 | |
|     {
 | |
|         return Handle(adopt_ref(*new HandleImpl(cell)));
 | |
|     }
 | |
| 
 | |
|     Handle(T* cell)
 | |
|     {
 | |
|         if (cell)
 | |
|             m_impl = adopt_ref(*new HandleImpl(cell));
 | |
|     }
 | |
| 
 | |
|     Handle(T& cell)
 | |
|         : m_impl(adopt_ref(*new HandleImpl(&cell)))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     T* cell() const
 | |
|     {
 | |
|         if (!m_impl)
 | |
|             return nullptr;
 | |
|         return static_cast<T*>(m_impl->cell());
 | |
|     }
 | |
| 
 | |
|     T* ptr() const
 | |
|     {
 | |
|         return cell();
 | |
|     }
 | |
| 
 | |
|     bool is_null() const
 | |
|     {
 | |
|         return m_impl.is_null();
 | |
|     }
 | |
| 
 | |
|     T* operator->() const
 | |
|     {
 | |
|         return cell();
 | |
|     }
 | |
| 
 | |
|     T& operator*() const
 | |
|     {
 | |
|         return *cell();
 | |
|     }
 | |
| 
 | |
|     bool operator!() const
 | |
|     {
 | |
|         return !cell();
 | |
|     }
 | |
|     operator bool() const
 | |
|     {
 | |
|         return cell();
 | |
|     }
 | |
| 
 | |
|     operator T*() const { return cell(); }
 | |
| 
 | |
| private:
 | |
|     explicit Handle(NonnullRefPtr<HandleImpl> impl)
 | |
|         : m_impl(move(impl))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     RefPtr<HandleImpl> m_impl;
 | |
| };
 | |
| 
 | |
| template<class T>
 | |
| inline Handle<T> make_handle(T* cell)
 | |
| {
 | |
|     if (!cell)
 | |
|         return Handle<T> {};
 | |
|     return Handle<T>::create(cell);
 | |
| }
 | |
| 
 | |
| template<class T>
 | |
| inline Handle<T> make_handle(T& cell)
 | |
| {
 | |
|     return Handle<T>::create(&cell);
 | |
| }
 | |
| 
 | |
| template<>
 | |
| class Handle<Value> {
 | |
| public:
 | |
|     Handle() = default;
 | |
| 
 | |
|     static Handle create(Value value)
 | |
|     {
 | |
|         if (value.is_cell())
 | |
|             return Handle(value, &value.as_cell());
 | |
|         return Handle(value);
 | |
|     }
 | |
| 
 | |
|     auto cell() { return m_handle.cell(); }
 | |
|     auto cell() const { return m_handle.cell(); }
 | |
|     auto value() const { return *m_value; }
 | |
|     bool is_null() const { return m_handle.is_null() && !m_value.has_value(); }
 | |
| 
 | |
| private:
 | |
|     explicit Handle(Value value)
 | |
|         : m_value(value)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     explicit Handle(Value value, Cell* cell)
 | |
|         : m_value(value)
 | |
|         , m_handle(Handle<Cell>::create(cell))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Optional<Value> m_value;
 | |
|     Handle<Cell> m_handle;
 | |
| };
 | |
| 
 | |
| inline Handle<Value> make_handle(Value value)
 | |
| {
 | |
|     return Handle<Value>::create(value);
 | |
| }
 | |
| 
 | |
| }
 |