#ifndef POINTER_H #define POINTER_H #include #include namespace lunasvg { template class RefCounted { public: RefCounted() = default; void ref() { ++m_refCount; } void deref() { if(--m_refCount == 0) { delete static_cast(this); } } uint32_t refCount() const { return m_refCount; } bool hasOneRefCount() const { return m_refCount == 1; } private: uint32_t m_refCount{1}; }; template inline void refIfNotNull(T* ptr) { if(ptr) ptr->ref(); } template inline void derefIfNotNull(T* ptr) { if(ptr) ptr->deref(); } template class RefPtr; template RefPtr adoptPtr(T*); template class RefPtr { public: RefPtr() = default; RefPtr(std::nullptr_t) : m_ptr(nullptr) {} RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(m_ptr); } RefPtr(T& ref) : m_ptr(&ref) { m_ptr->ref(); } RefPtr(const RefPtr& p) : m_ptr(p.get()) { refIfNotNull(m_ptr); } RefPtr(RefPtr&& p) : m_ptr(p.release()) {} template RefPtr(const RefPtr& p) : m_ptr(p.get()) { refIfNotNull(m_ptr); } template RefPtr(RefPtr&& p) : m_ptr(p.release()) {} ~RefPtr() { derefIfNotNull(m_ptr); } T* get() const { return m_ptr; } T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } bool empty() const { return !m_ptr; } bool operator!() const { return !m_ptr; } operator bool() const { return !!m_ptr; } RefPtr& operator=(std::nullptr_t) { clear(); return *this; } RefPtr& operator=(T* o) { RefPtr p = o; swap(p); return *this; } RefPtr& operator=(T& o) { RefPtr p = o; swap(p); return *this; } RefPtr& operator=(const RefPtr& o) { RefPtr p = o; swap(p); return *this; } RefPtr& operator=(RefPtr&& o) { RefPtr p = std::move(o); swap(p); return *this; } template RefPtr& operator=(const RefPtr& o) { RefPtr p = o; swap(p); return *this; } template RefPtr& operator=(RefPtr&& o) { RefPtr p = std::move(o); swap(p); return *this; } void swap(RefPtr& o) { std::swap(m_ptr, o.m_ptr); } T* release() { T* ptr = m_ptr; m_ptr = nullptr; return ptr; } void clear() { derefIfNotNull(m_ptr); m_ptr = nullptr; } friend RefPtr adoptPtr(T*); private: RefPtr(T* ptr, std::nullptr_t) : m_ptr(ptr) {} T* m_ptr{nullptr}; }; template inline RefPtr adoptPtr(T* ptr) { return RefPtr(ptr, nullptr); } template inline void swap(RefPtr& a, RefPtr& b) { a.swap(b); } template inline bool operator==(const RefPtr& a, const RefPtr& b) { return a.get() == b.get(); } template inline bool operator==(const RefPtr& a, const U* b) { return a.get() == b; } template inline bool operator==(const T* a, const RefPtr& b) { return a == b.get(); } template inline bool operator==(const RefPtr& a, std::nullptr_t) { return a.get() == nullptr; } template inline bool operator!=(const RefPtr& a, const RefPtr& b) { return a.get() != b.get(); } template inline bool operator!=(const RefPtr& a, const U* b) { return a.get() != b; } template inline bool operator!=(const T* a, const RefPtr& b) { return a != b.get(); } template inline bool operator!=(const RefPtr& a, std::nullptr_t) { return a.get() != nullptr; } template struct is { template static bool check(const U& value); }; template constexpr bool is_a(U& value) { return is::check(value); } template constexpr bool is_a(const U& value) { return is::check(value); } template constexpr bool is_a(U* value) { return value && is::check(*value); } template constexpr bool is_a(const U* value) { return value && is::check(*value); } template constexpr T* to(U& value) { return is_a(value) ? static_cast(&value) : nullptr; } template constexpr const T* to(const U& value) { return is_a(value) ? static_cast(&value) : nullptr; } template constexpr T* to(U* value) { return is_a(value) ? static_cast(value) : nullptr; } template constexpr const T* to(const U* value) { return is_a(value) ? static_cast(value) : nullptr; } } // namespace lunasvg #endif // POINTER_H