#pragma once
#include "pluginterfaces/base/fplatform.h"
#if SMTG_CPP11_STDLIBSUPPORT
#include <utility>
#endif
namespace Steinberg {
template <class I>
class IPtr
{
public:
inline IPtr (I* ptr, bool addRef = true);
inline IPtr (const IPtr&);
template <class T>
inline IPtr (const IPtr<T>& other) : ptr (other.get ())
{
if (ptr)
ptr->addRef ();
}
inline IPtr ();
inline ~IPtr ();
inline I* operator= (I* ptr);
inline IPtr& operator= (const IPtr& other);
template <class T>
inline IPtr& operator= (const IPtr<T>& other)
{
operator= (other.get ());
return *this;
}
inline operator I* () const { return ptr; } inline I* operator-> () const { return ptr; }
inline I* get () const { return ptr; }
#if SMTG_CPP11_STDLIBSUPPORT
inline IPtr (IPtr<I>&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { }
template <typename T>
inline IPtr (IPtr<T>&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { }
inline IPtr& operator= (IPtr<I>&& movePtr) SMTG_NOEXCEPT
{
if (ptr)
ptr->release ();
ptr = movePtr.take ();
return *this;
}
template <typename T>
inline IPtr& operator= (IPtr<T>&& movePtr)
{
if (ptr)
ptr->release ();
ptr = movePtr.take ();
return *this;
}
#endif
inline void reset (I* obj = nullptr)
{
if (ptr)
ptr->release();
ptr = obj;
}
I* take () SMTG_NOEXCEPT
{
I* out = ptr;
ptr = nullptr;
return out;
}
template <typename T>
static IPtr<T> adopt (T* obj) SMTG_NOEXCEPT { return IPtr<T> (obj, false); }
protected:
I* ptr;
};
template <class I>
inline IPtr<I>::IPtr (I* _ptr, bool addRef) : ptr (_ptr)
{
if (ptr && addRef)
ptr->addRef ();
}
template <class I>
inline IPtr<I>::IPtr (const IPtr<I>& other) : ptr (other.ptr)
{
if (ptr)
ptr->addRef ();
}
template <class I>
inline IPtr<I>::IPtr () : ptr (0)
{
}
template <class I>
inline IPtr<I>::~IPtr ()
{
if (ptr)
{
ptr->release ();
ptr = nullptr; }
}
template <class I>
inline I* IPtr<I>::operator= (I* _ptr)
{
if (_ptr != ptr)
{
if (ptr)
ptr->release ();
ptr = _ptr;
if (ptr)
ptr->addRef ();
}
return ptr;
}
template <class I>
inline IPtr<I>& IPtr<I>::operator= (const IPtr<I>& _ptr)
{
operator= (_ptr.ptr);
return *this;
}
template <class I>
class OPtr : public IPtr<I>
{
public:
inline OPtr (I* p) : IPtr<I> (p, false) {}
inline OPtr (const IPtr<I>& p) : IPtr<I> (p) {}
inline OPtr (const OPtr<I>& p) : IPtr<I> (p) {}
inline OPtr () {}
inline I* operator= (I* _ptr)
{
if (_ptr != this->ptr)
{
if (this->ptr)
this->ptr->release ();
this->ptr = _ptr;
}
return this->ptr;
}
};
template <class I>
IPtr<I> owned (I* p)
{
return IPtr<I> (p, false);
}
template <class I>
IPtr<I> shared (I* p)
{
return IPtr<I> (p, true);
}
#if SMTG_CPP11_STDLIBSUPPORT
namespace SKI {
namespace Detail {
struct Adopt;
}
template <typename T>
class Shared
{
friend struct Detail::Adopt;
T* obj = nullptr;
};
template <typename T>
class Owned
{
friend struct Detail::Adopt;
T* obj = nullptr;
};
template <typename T>
class Used
{
friend struct Detail::Adopt;
T* obj = nullptr;
};
namespace Detail {
struct Adopt
{
template <typename T>
static IPtr<T> adopt (Shared<T>& ref)
{
using Steinberg::shared;
return shared (ref.obj);
}
template <typename T>
static IPtr<T> adopt (Owned<T>& ref)
{
using Steinberg::owned;
IPtr<T> out = owned (ref.obj);
ref.obj = nullptr;
return out;
}
template <typename T>
static T* adopt (Used<T>& ref)
{
return ref.obj;
}
template <template <typename> class OwnerType, typename T>
static OwnerType<T> toOwnerType (T* obj)
{
OwnerType<T> out;
out.obj = obj;
return out;
}
};
}
template <typename T>
IPtr<T> adopt (Shared<T>& ref) { return Detail::Adopt::adopt (ref); }
template <typename T>
IPtr<T> adopt (Shared<T>&& ref) { return Detail::Adopt::adopt (ref); }
template <typename T>
IPtr<T> adopt (Owned<T>& ref) { return Detail::Adopt::adopt (ref); }
template <typename T>
IPtr<T> adopt (Owned<T>&& ref) { return Detail::Adopt::adopt (ref); }
template <typename T>
T* adopt (Used<T>& ref) { return Detail::Adopt::adopt (ref); }
template <typename T>
T* adopt (Used<T>&& ref) { return Detail::Adopt::adopt (ref); }
template <typename T>
Owned<T> toOwned (T* obj) { return Detail::Adopt::toOwnerType<Owned> (obj); }
template <typename T>
Shared<T> toShared (T* obj) { return Detail::Adopt::toOwnerType<Shared> (obj); }
template <typename T>
Used<T> toUsed (T* obj) { return Detail::Adopt::toOwnerType<Used> (obj); }
} #endif
}