
/*
  File: include/mia/HeapPtr.h
  Description: MIA automatic pointers
  Part of the Mantis project
  (c) 2002 Lycos Inc.

  This file is distributed for the sole purpose of allowing you to write
  software to interface with Sonique 2 and other Mantis programs. It is
  not to be modified or used for any other purpose without written
  authorization.

  If you redistribute this file, it must be in the original package
  complete with all other files provided, including the usage agreement.

  Do not remove this notice.
*/

#ifndef _HEAP_PTR_H__
#define _HEAP_PTR_H__

#ifdef DEBUG_INCLUDE_ORDER
#pragma message("Including " __FILE__ "\n" )
#endif

#if _MSC_VER > 1000
#pragma once
#endif


#include "mgeneric.h"

#undef NULL
#define NULL 0


#define AUTOPTR(T)\
public:\
	__forceinline T&   operator*		()							const	{ ASSERT( NULL != m_pI ); return *m_pI; }\
	__forceinline T*   operator->		()							const	{ ASSERT( NULL != m_pI ); return  m_pI; }\
	__forceinline bool operator==		(const T* pI)				const	{	return (pI == m_pI);				}\
	__forceinline bool operator==		(      T* pI)				const	{	return (pI == m_pI);				}\
	__forceinline bool operator!=		(const T* pI)				const	{	return (pI != m_pI);				}\
	__forceinline bool operator!=		(      T* pI)				const	{	return (pI != m_pI);				}\
	__forceinline bool operator!		()							const	{	return m_pI == NULL;				}\
	__forceinline   	 operator T*	()							const	{	return m_pI;						}\
protected:\
	T* m_pI;




template <class T> class RefPtr
{
#ifdef _DEBUG

public:
	T&   operator*		()							const	{ ASSERT( NULL != m_pI ); return *m_pI; }
	T*   operator->		()							const	{ ASSERT( NULL != m_pI ); return  m_pI; }
	bool operator==		(const T* pI)				const	{	return (pI == m_pI);				}
	bool operator==		(      T* pI)				const	{	return (pI == m_pI);				}
	bool operator!=		(const T* pI)				const	{	return (pI != m_pI);				}
	bool operator!=		(      T* pI)				const	{	return (pI != m_pI);				}
	bool operator!		()							const	{	return m_pI == NULL;				}
	  	 operator T*	()							const	{	return m_pI;						}
protected:
	T* m_pI;

#else

	AUTOPTR(T)

#endif

public:

	// custom routines
	__forceinline void RefCountPlus( T* pI )
	{
		pI->AddRef();
	}
	__forceinline void RefCountSub( T* pI )
	{
		pI->Release();
	}
	
	// constructor
	__forceinline  RefPtr()
	{
		m_pI = NULL;
	}


	__forceinline  RefPtr(int iNULL)
	{
		ASSERT( iNULL == (int)NULL );
		m_pI = NULL;
	}
	
	template< class OTHER >
	__forceinline  RefPtr(const RefPtr<OTHER> &from)
	{
		m_pI = (OTHER*)from;
		if( m_pI )
			RefCountPlus( m_pI );
	}

	__forceinline  RefPtr(const RefPtr<T> &from)
	{
		m_pI = (T*)from;
		if( m_pI )
			RefCountPlus( m_pI );
	}
	
	template< class OTHER >
	__forceinline  RefPtr( OTHER* pI)
	{
		m_pI = pI;
		if( m_pI )
			RefCountPlus( m_pI );
	}

	__forceinline RefPtr( T* pI)
	{
		m_pI = pI;
		if( m_pI )
			RefCountPlus( m_pI );
	}
	
	// Destructor
	__forceinline  ~RefPtr()
	{
		if( m_pI )
			RefCountSub( m_pI );

#ifdef _DEBUG
		m_pI = NULL;
#endif

	}

	// Reset
	__forceinline  void Release()
	{
		if( m_pI != NULL )
		{
			T* pOld		= m_pI;
			m_pI		= NULL;

			RefCountSub( pOld );
		}
	}


	
	// assign
	T* operator=( int iNULL )
	{
		ASSERT( iNULL == (int) NULL );
		
		if( m_pI != (T*)iNULL )
		{
			T* pOld = m_pI;
			m_pI = (T*)iNULL;
			if( m_pI != NULL )
			{
				RefCountPlus( m_pI );
			}
			
			if( pOld != NULL )
			{
				RefCountSub( pOld );
			}
		}
		return m_pI;
	}
	
	template< class OTHER >
	__forceinline RefPtr& operator=( const RefPtr<OTHER>& other )
	{
		*this = (OTHER*)other;
		return *this;
	}

	__forceinline RefPtr& operator=( const RefPtr<T>& other )
	{
		*this = (T*)other;
		return *this;
	}
	
	template< class OTHER >
	__forceinline T* operator=( OTHER* pI )
	{
		
		if( m_pI != pI )
		{
			T* pOld = m_pI;
			m_pI = pI;
			if( m_pI != NULL )
			{
				RefCountPlus( m_pI );
			}
			
			if( pOld != NULL )
			{
				RefCountSub( pOld );
			}
		}
		return m_pI;
	}

	__forceinline T* operator=( T* pI )
	{
		
		if( m_pI != pI )
		{
			T* pOld = m_pI;
			m_pI = pI;
			if( m_pI != NULL )
			{
				RefCountPlus( m_pI );
			}
			
			if( pOld != NULL )
			{
				RefCountSub( pOld );
			}
		}
		return m_pI;
	}
	
};

__forceinline void RefPtr<MInnerGeneric>::RefCountPlus( MInnerGeneric* pI )
{
	pI->InnerAddRef();
}


__forceinline void RefPtr<MInnerGeneric>::RefCountSub( MInnerGeneric* pI )
{
	pI->InnerRelease();
}


template <class T, int size = 1 > class AutoHeapPtr
{
	AUTOPTR(T)
public:
	
	__forceinline AutoHeapPtr()
	{
		
		if( size != 1 )
			m_pI = new T[size];
		else
			m_pI = new T;
	}

	
	template< class OTHER >
	__forceinline AutoHeapPtr(const AutoHeapPtr<OTHER> &from)
	{
		m_pI = (OTHER*) from;
	}

	template< class OTHER >
	__forceinline AutoHeapPtr( OTHER* pI)
	{
		m_pI = pI;
	}

	// Destructor
	__forceinline ~AutoHeapPtr()
	{
		if( size != 1 )
			delete [] m_pI;
		else
			delete m_pI;

#ifdef _DEBUG
		m_pI = NULL;
#endif
	}

	void Delete()
	{
		if( size != 1 )
			delete [] m_pI;
		else
			delete m_pI;

		m_pI = NULL;
	}

	__forceinline T&  operator [](int			index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	__forceinline T&  operator [](int32			index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	__forceinline T&  operator [](unsigned int  index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	__forceinline T&  operator [](uint32		index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	
	// Assignment 

	template< class OTHER >
	__forceinline  AutoHeapPtr& operator=( const AutoHeapPtr<OTHER>& other )
	{
		*this = (OTHER*)other;
		return *this;
	}

	template< class OTHER >
	__forceinline  T* operator=( OTHER* pI )
	{
		// this should only be valid for size 1's
		// because 'size' might be invalid for the new pointer.

		ASSERT(size==1);

		if( m_pI != pI )
		{
			T* pOld = m_pI;
			m_pI = pI;

			if( pOld != NULL )
			{
				delete pOld;
			}
		}
		return m_pI;
	}

	__forceinline  T* operator=( int iNull )
	{
		ASSERT(iNull == (int)NULL);

		// this should only be valid for size 1's
		// because 'size' might be invalid for the new pointer.

		ASSERT(size==1);

		if( m_pI != (T*)iNull )
		{
			T* pOld = m_pI;
			m_pI = (T*)iNull;

			if( pOld != NULL )
			{
				delete pOld;
			}
		}
		return m_pI;
	}

};

template <class T, int size = 1 > class HeapPtr
{
	AUTOPTR(T)
public:
	
	__forceinline HeapPtr()
	{
		m_pI = NULL;
	}

	
	template< class OTHER >
	__forceinline HeapPtr(const HeapPtr<OTHER> &from)
	{
		m_pI = (OTHER*) from;
	}

	template< class OTHER >
	__forceinline HeapPtr( OTHER* pI)
	{
		m_pI = pI;
	}

	// Destructor
	__forceinline ~HeapPtr()
	{
		if( size != 1 )
			delete [] m_pI;
		else
			delete m_pI;

#ifdef _DEBUG
		m_pI = NULL;
#endif
	}

	void Delete()
	{
		if( size != 1 )
			delete [] m_pI;
		else
			delete m_pI;

		m_pI = NULL;
	}

	__forceinline T&  operator [](int			index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	__forceinline T&  operator [](int32			index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	__forceinline T&  operator [](unsigned int  index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	__forceinline T&  operator [](uint32		index) const	{	ASSERT(index>=0&&index<size); return m_pI[index];	}
	
	// Assignment 

	template< class OTHER >
	__forceinline  HeapPtr& operator=( const HeapPtr<OTHER>& other )
	{
		*this = (OTHER*)other;
		return *this;
	}

	template< class OTHER >
	__forceinline  T* operator=( OTHER* pI )
	{
		// this should only be valid for size 1's
		// because 'size' might be invalid for the new pointer.

		ASSERT(size==1);

		if( m_pI != pI )
		{
			T* pOld = m_pI;
			m_pI = pI;

			if( pOld != NULL )
			{
				delete pOld;
			}
		}
		return m_pI;
	}

	__forceinline  T* operator=( int iNull )
	{
		ASSERT(iNull == (int)NULL);

		// this should only be valid for size 1's
		// because 'size' might be invalid for the new pointer.

		ASSERT(size==1);

		if( m_pI != (T*)iNull )
		{
			T* pOld = m_pI;
			m_pI = (T*)iNull;

			if( pOld != NULL )
			{
				delete pOld;
			}
		}
		return m_pI;
	}

};

#ifdef DEBUG_INCLUDE_ORDER
#pragma message("Done including " __FILE__ "\n" )
#endif

#endif

