#ifndef APE_SMARTPTR_H
#define APE_SMARTPTR_H

// disable the operator -> on UDT warning
#ifdef _MSC_VER
    #pragma warning(push)
    #pragma warning(disable : 4284)
#endif

/*************************************************************************************************
CSmartPtr - a simple smart pointer class that can automatically initialize and free memory
    note: (doesn't do garbage collection / reference counting because of the many pitfalls)
*************************************************************************************************/
template <class TYPE> class CSmartPtr
{
public:
    TYPE * m_pObject;
    BOOL m_bArray;
    BOOL m_bDelete;

    CSmartPtr()
    {
        m_bDelete = TRUE;
        m_pObject = NULL;
    }
    CSmartPtr(TYPE * a_pObject, BOOL a_bArray = FALSE, BOOL a_bDelete = TRUE)
    {
        m_bDelete = TRUE;
        m_pObject = NULL;
        Assign(a_pObject, a_bArray, a_bDelete);
    }

    ~CSmartPtr()
    {
        Delete();
    }

    void Assign(TYPE * a_pObject, BOOL a_bArray = FALSE, BOOL a_bDelete = TRUE)
    {
        Delete();

        m_bDelete = a_bDelete;
        m_bArray = a_bArray;
        m_pObject = a_pObject;
    }

    void Delete()
    {
        if (m_bDelete && m_pObject)
        {
            if (m_bArray)
                delete [] m_pObject;
            else
                delete m_pObject;

            m_pObject = NULL;
        }
    }

    void SetDelete(const BOOL a_bDelete)
    {
        m_bDelete = a_bDelete;
    }

    __inline TYPE * GetPtr() const
    {
        return m_pObject;
    }

    __inline operator TYPE * () const
    {
        return m_pObject;
    }

    __inline TYPE * operator ->() const
    {
        return m_pObject;
    }

    // declare assignment, but don't implement (compiler error if we try to use)
    // that way we can't carelessly mix smart pointers and regular pointers
    __inline void * operator =(void *) const;
};

#ifdef _MSC_VER
    #pragma warning(pop)
#endif

#endif // #ifndef APE_SMARTPTR_H
