
/*
  File: include/mia/MIAUtil.h
  Description: MIA helper classes
  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 _MIA_UTIL_H__
#define _MIA_UTIL_H__

#include "MIAInternals.h"
//#include "mia.h"
#include "mgeneric.h"
#include "HeapPtr.h"

#pragma warning( disable : 4042 )	//turn off annoying "bad storage class" bogus warning

template < class T, const MID *pFactoryMid, const MID *pInstanceMid, bool bSingleton = false > 
class HeapMidPtr : public RefPtr<T>
{
public:
	HeapMidPtr() 
	{
		if( MCreateInstance )
		{
			VERIFY( MCreateInstance( *pFactoryMid, *pInstanceMid, (void**)&m_pI, NULL )  == M_OK );

			// assert that this is created with the correct refcount
#ifdef _DEBUG
			if( m_pI )
			{
#ifndef _DEBUG_REFCOUNT
			ASSERT( m_pI->AddRef() == 2  || bSingleton );
			ASSERT( m_pI->Release() == 1 || bSingleton );
#endif
			}
#endif
		} else {
			ASSERT(0);
		}
	}

	// create in construction
	HeapMidPtr(MGeneric* pGeneric)
	{
		m_pI = NULL;
		if( pGeneric != NULL )
		{
			ASSERT(pGeneric);
			pGeneric->QueryModule(*pInstanceMid,(void**)&m_pI);
		}
	}

	// create by copy
	T* operator=( MGeneric* pGeneric )
	{
		MGeneric* pOld = m_pI;
		m_pI = NULL;

		if( pGeneric )
		{
			int32 ret = pGeneric->QueryModule(*pInstanceMid,(void**)&m_pI);
			ASSERT( (ret == M_OK) && m_pI );
		}

		if( pOld )
		{
			pOld->Release();
		}
		return m_pI;
	}
	

	operator const MID&() { return *pInstanceMid; }

	bool operator ==(const T* other) { return m_pI == other; }
	bool operator !=(const T* other) { return m_pI != other; }
};

template < class T, const MID* pMid > class HeapMorphPtr : public RefPtr<T>
{
public:
	// create in construction
	HeapMorphPtr(MGeneric*const pGeneric)
	{
		m_pI = NULL;
		if( pGeneric != NULL )
			pGeneric->QueryModule(*pMid,(void**)&m_pI);
	}
	template <class OTHERTYPE>
	HeapMorphPtr( const RefPtr<OTHERTYPE>& Other )
	{
		m_pI = NULL;
		if( Other != (OTHERTYPE*)NULL )
			Other->QueryModule(*pMid,(void**)&m_pI);
	}

	// create by copy
	T* operator=( MGeneric* pGeneric )
	{
		MGeneric* pOld = m_pI;
		m_pI = NULL;

		if( pGeneric )
		{
			int32 ret = pGeneric->QueryModule(*pMid,(void**)&m_pI);
			ASSERT( (ret == M_OK) && m_pI );
		}

		if( pOld )
		{
			pOld->Release();
		}
		return m_pI;
	}

	template <class OTHERTYPE>
	T* operator=( const RefPtr<OTHERTYPE>& Other )
	{
		return *this = (OTHERTYPE*)Other;
	}

	operator const MID&() { return *pInstanceMid; }
};


#endif
