//------------------------------------------------------------------------------
// emOwnPtr.h
//
// Copyright (C) 2024 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#ifndef emOwnPtr_h
#define emOwnPtr_h
#ifndef emStd1_h
#include <emCore/emStd1.h>
#endif
//==============================================================================
//================================ emOwnPtrBase ================================
//==============================================================================
template <class OBJECT, class DELETER> class emOwnPtrBase {
public:
// Template class for a smart pointer which owns the referenced object.
// The object is deleted by calling the given DELETER when the pointer
// is destructed.
emOwnPtrBase(OBJECT * ptr=NULL);
// Construct from an object pointer. Ownership of that object
// goes to this emOwnPtrBase. NULL means to own no object.
~emOwnPtrBase();
// Destructor. This deletes the owned object.
void Set(OBJECT * ptr = NULL);
emOwnPtrBase & operator = (OBJECT * ptr);
// Assign an object pointer and take ownership of the pointed
// object. Assigning NULL is allowed. The previously owned
// object is deleted.
void Reset();
// Same as Set(NULL).
OBJECT * Release();
// Release ownership of the object, make this emOwnPtrBase a
// NULL pointer, and return the object pointer.
operator const OBJECT * () const;
operator OBJECT * ();
// Cast this to a normal pointer (can be NULL).
const OBJECT * Get() const;
OBJECT * Get();
// Get the normal pointer (can be NULL).
const OBJECT * operator -> () const;
OBJECT * operator -> ();
// This makes this class a so-called "smart pointer". For
// example, if p is an emOwnPtrBase to an object which has a
// method named Hello(), one could say p->Hello() instead of
// p.Get()->Hello().
private:
emOwnPtrBase(const emOwnPtrBase&);
emOwnPtrBase & operator = (const emOwnPtrBase&);
// Copying is not allowed.
OBJECT * Ptr;
};
template <class OBJECT> struct emOwnPtrDeleter {
void operator () (OBJECT * ptr) const;
};
template <class OBJECT> struct emOwnArrayPtrDeleter {
void operator () (OBJECT * ptr) const;
};
//==============================================================================
//================================== emOwnPtr ==================================
//==============================================================================
template <class OBJECT> class emOwnPtr :
public emOwnPtrBase<OBJECT, emOwnPtrDeleter<OBJECT> > {
public:
// Like emOwnPtrBase, but the object is deleted by calling the normal
// delete operator.
emOwnPtr(OBJECT * ptr=NULL);
emOwnPtr & operator = (OBJECT * ptr);
};
//==============================================================================
//=============================== emOwnArrayPtr ================================
//==============================================================================
template <class OBJECT> class emOwnArrayPtr :
public emOwnPtrBase<OBJECT, emOwnArrayPtrDeleter<OBJECT> > {
public:
// Like emOwnPtrBase, but the object is deleted by calling the array
// delete operator (delete []).
emOwnArrayPtr(OBJECT * ptr=NULL);
emOwnArrayPtr & operator = (OBJECT * ptr);
};
//==============================================================================
//============================== Implementations ===============================
//==============================================================================
template <class OBJECT, class DELETER>
inline emOwnPtrBase<OBJECT, DELETER>::emOwnPtrBase(OBJECT * ptr)
: Ptr(ptr)
{
}
template <class OBJECT, class DELETER>
inline emOwnPtrBase<OBJECT, DELETER>::~emOwnPtrBase()
{
if (Ptr) {
DELETER()(Ptr);
Ptr=NULL;
}
}
template <class OBJECT, class DELETER>
inline void emOwnPtrBase<OBJECT, DELETER>::Set(OBJECT * ptr)
{
if (Ptr!=ptr) {
if (Ptr) DELETER()(Ptr);
Ptr=ptr;
}
}
template <class OBJECT, class DELETER>
inline emOwnPtrBase<OBJECT, DELETER> & emOwnPtrBase<OBJECT, DELETER>::operator =
(OBJECT * ptr)
{
Set(ptr);
return *this;
}
template <class OBJECT, class DELETER>
inline void emOwnPtrBase<OBJECT, DELETER>::Reset()
{
Set(NULL);
}
template <class OBJECT, class DELETER>
inline OBJECT * emOwnPtrBase<OBJECT, DELETER>::Release()
{
OBJECT * ptr = Ptr;
Ptr=NULL;
return ptr;
}
template <class OBJECT, class DELETER>
inline emOwnPtrBase<OBJECT, DELETER>::operator const OBJECT * () const
{
return Ptr;
}
template <class OBJECT, class DELETER>
inline emOwnPtrBase<OBJECT, DELETER>::operator OBJECT * ()
{
return Ptr;
}
template <class OBJECT, class DELETER>
inline const OBJECT * emOwnPtrBase<OBJECT, DELETER>::Get() const
{
return Ptr;
}
template <class OBJECT, class DELETER>
inline OBJECT * emOwnPtrBase<OBJECT, DELETER>::Get()
{
return Ptr;
}
template <class OBJECT, class DELETER>
inline const OBJECT * emOwnPtrBase<OBJECT, DELETER>::operator -> () const
{
return Ptr;
}
template <class OBJECT, class DELETER>
inline OBJECT * emOwnPtrBase<OBJECT, DELETER>::operator -> ()
{
return Ptr;
}
template <class OBJECT, class DELETER>
inline emOwnPtrBase<OBJECT, DELETER>::emOwnPtrBase(const emOwnPtrBase&)
{
}
template <class OBJECT, class DELETER>
inline emOwnPtrBase<OBJECT, DELETER> & emOwnPtrBase<OBJECT, DELETER>::operator =
(const emOwnPtrBase&)
{
return *this;
}
template <class OBJECT>
inline void emOwnPtrDeleter<OBJECT>::operator () (OBJECT * ptr) const {
delete ptr;
}
template <class OBJECT>
inline void emOwnArrayPtrDeleter<OBJECT>::operator () (OBJECT * ptr) const {
delete [] ptr;
}
template <class OBJECT>
inline emOwnPtr<OBJECT>::emOwnPtr(OBJECT * ptr)
: emOwnPtrBase<OBJECT, emOwnPtrDeleter<OBJECT> >(ptr)
{
}
template <class OBJECT>
inline emOwnPtr<OBJECT> & emOwnPtr<OBJECT>::operator = (OBJECT * ptr)
{
this->Set(ptr);
return *this;
}
template <class OBJECT>
inline emOwnArrayPtr<OBJECT>::emOwnArrayPtr(OBJECT * ptr)
: emOwnPtrBase<OBJECT, emOwnArrayPtrDeleter<OBJECT> >(ptr)
{
}
template <class OBJECT>
inline emOwnArrayPtr<OBJECT> & emOwnArrayPtr<OBJECT>::operator = (OBJECT * ptr)
{
this->Set(ptr);
return *this;
}
#endif