//----------------------- CSPTools.h --------------------------

//*************************************************************
//*****       Copyright ©2002 - 2004 Micronovae Ltd       *****
//*****                All rights reserved                *****
//*************************************************************


#ifndef _CSPTOOLS
#define _CSPTOOLS

#include "CSPConf.h"
#include "CSPObject.h"
#include <stdlib.h>

//------------------- CSPHandle Class---------------------
/*template <class T = HANDLE , BOOL( __stdcall *F )( T ) = CloseHandle>
class CSPHandle : public CSPObject
{
	public:
		CSPHandle() : m_hHandle( 0 ){};
		CSPHandle( T h ) : m_hHandle( h ){};
		virtual ~CSPHandle(){ F( m_hHandle ); }
		
		operator T(){ return m_hHandle; }
		T operator = ( T h ){ F( m_hHandle ); m_hHandle = h; return m_hHandle; }
		bool operator == ( T h ){ return m_hHandle == h; }
		bool operator != ( T h ){ return m_hHandle != h; }
		T* operator & (){ return &m_hHandle; }
		bool operator ! (){ return m_hHandle ? false : true; }
		void Close(){ F( m_hHandle ); m_hHandle = 0; }
		T Detach(){ T h = m_hHandle; m_hHandle = 0; return h; }

	protected:
		T m_hHandle;

	private:
		CSPHandle( const CSPHandle& );
		CSPHandle& operator = ( const CSPHandle& );
};*/

class CSPHandle : public CSPObject
{
	public:
		CSPHandle() : m_hHandle( 0 ){};
		CSPHandle( HANDLE h ) : m_hHandle( h ){};
		virtual ~CSPHandle(){ CloseHandle( m_hHandle ); }
		
		operator HANDLE(){ return m_hHandle; }
		HANDLE operator = ( HANDLE h ){ CloseHandle( m_hHandle ); m_hHandle = h; return m_hHandle; }
		bool operator == ( HANDLE h ){ return m_hHandle == h; }
		bool operator != ( HANDLE h ){ return m_hHandle != h; }
		HANDLE* operator & (){ return &m_hHandle; }
		bool operator ! (){ return m_hHandle ? false : true; }
		void Close(){ CloseHandle( m_hHandle ); m_hHandle = 0; }
		HANDLE Detach(){ HANDLE h = m_hHandle; m_hHandle = 0; return h; }

	protected:
		HANDLE m_hHandle;

	private:
		CSPHandle( const CSPHandle& );
		CSPHandle& operator = ( const CSPHandle& );
};

//------------------- CSPThreadToken Class---------------------

class CSPImpersonation : public CSPObject
{
	public:
		CSPImpersonation() : m_hToken( 0 )
		{ OpenThreadToken( GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &m_hToken ); }
		virtual ~CSPImpersonation(){ Client(); }
		bool System()
		{
			if( !m_hToken )return true;
			BOOL bRet = RevertToSelf();
			if( !bRet )return false;
			return true;
		}

		bool Client()
		{
			if( !m_hToken )return true;
			if( !SetThreadToken( NULL, m_hToken ) )return false;
			return true;
		}
		
	protected:
		CSPHandle m_hToken;

	private:
		CSPImpersonation( const CSPImpersonation& );
		CSPImpersonation& operator = ( const CSPImpersonation& );
};




//------------------- CSPPtr Template Class ---------------------
//#pragma warning( disable : 4284 )
template< class T >
class CSPPtr : public CSPObject
{
	public:
		CSPPtr() : m_p( 0 ){};
		CSPPtr( T* p ) : m_p( p ){};
		virtual ~CSPPtr(){ delete m_p; }
		
		operator T*() const { return m_p; }
		T* operator -> () const{ return m_p; }
		T* operator = ( T* p ){ delete m_p; return m_p = p; }
		bool operator == ( T* p ) const { return m_p == p; }
		bool operator != ( T* p ) const { return m_p != p; }
		T** operator & () { return &m_p; }
		T& operator * () const { return *m_p; }
		bool operator ! () const { return m_p ? false : true; }
		void Free(){ delete m_p; m_p = 0; }
		void New(){ Free(); m_p = new T; if( !m_p )ThrowOutOfMemory(); }
		void New( const T& obj ){ Free(); m_p = new T( obj ); if( !m_p )ThrowOutOfMemory(); }
		T* Detach(){ T* p = m_p; m_p = 0; return p; }
		void Attach( CSPPtr< T >& sp ){ delete m_p; m_p = sp.m_p; sp.m_p = 0; }
		void Attach( T* p ){ delete m_p; m_p = p; }

	protected:
		T* m_p;

	private:
		CSPPtr( const CSPPtr< T >& );
		CSPPtr& operator = ( const CSPPtr< T >& );
};

//------------------- CSPArray Template Class ---------------------

#define ARRAY_INIT	m_p( 0 ), m_ulSize( 0 )

template< class T >
class CSPArray : public CSPObject
{
	public:
		CSPArray() : ARRAY_INIT{}
		CSPArray( unsigned long ulSize ) : ARRAY_INIT{ SetSize( ulSize ); }
		CSPArray( const CSPArray< T >& aArray ) : ARRAY_INIT{ Copy( aArray ); }
		virtual ~CSPArray(){ delete[] m_p; }

		void SetSize( unsigned long ulSize );
		void Resize( unsigned long ulSize );
		void Grow( unsigned long ulSize );
		void Shrink( unsigned long ulSize );
		unsigned long GetSize() const {	return m_ulSize; }

		operator T* () const { return m_p; }
//		operator void* () const { return ( void* )m_p; }
		bool operator ! () const { return m_p ? false : true; }
		CSPArray< T >& operator = ( const CSPArray< T >& aArray ){ Copy( aArray ); return *this; };
		T& operator * () const { return *m_p; }
		T** operator & () { return &m_p; }
		bool operator == ( const CSPArray< T >& aArray ) const;
		bool operator != ( const CSPArray< T >& aArray ) const{ return !operator == ( aArray );	}

		void Free();
		void Empty(){ Free(); }
		T* Detach();
		void Attach( CSPArray< T >& aArray );
		void Attach( T* p, unsigned long ulSize );
		void Copy( const CSPArray< T >& aArray );
		void Copy( const T* p, unsigned long ulSize );
		void Add( const CSPArray< T >& aArray );
		void Add( const T* p, unsigned long ulSize );
		T& Get( unsigned long ulIndex ) const;
		void Set( unsigned long ulIndex, const T& Value );


	protected:
		T* m_p;
		unsigned long m_ulSize;
};

template< class T >
void CSPArray<T>::SetSize( unsigned long ulSize )
{
	if( ulSize == 0 )
	{
		delete[] m_p;
		m_p = 0;
	}
	else
	{
		delete[] m_p;
		m_ulSize = 0;

		m_p = new T[ ulSize ];
		if( !m_p )ThrowOutOfMemory();
	}

	m_ulSize = ulSize;
}

template< class T >
void CSPArray<T>::Resize( unsigned long ulSize )
{
	if( ulSize == 0 )
	{
		delete[] m_p;
		m_p = 0;
	}
	else
	{
		T* pTemp = new T[ ulSize ];
		if( !pTemp )ThrowOutOfMemory();

		unsigned long ulMinSize = min( ulSize, m_ulSize );
		for( unsigned long x = 0; x < ulMinSize; x++ )pTemp[ x ] = m_p[ x ];

		delete[] m_p;
		m_p = pTemp;
	}

	m_ulSize = ulSize;
}

template< class T >
bool CSPArray<T>::operator == ( const CSPArray< T >& aArray ) const
{
	if( m_ulSize != aArray.m_ulSize )return false;
	else for( unsigned long x = 0; x < m_ulSize; x++ )
			if( m_p[ x ] != aArray.m_p[ x ] )return false;
	return true;
}

template< class T >
void CSPArray<T>::Grow( unsigned long ulSize )
{
	unsigned long ulFinalSize = m_ulSize + ulSize;
	if( ulFinalSize < m_ulSize )ThrowOutOfMemory(); // Overflow
	Resize( ulFinalSize );
}

template< class T >
void CSPArray<T>::Shrink( unsigned long ulSize )
{
	unsigned long ulFinalSize = m_ulSize - ulSize;
	if( ulFinalSize > m_ulSize )ThrowOutOfMemory(); // Overflow
	Resize( ulFinalSize );
}

template< class T >
void CSPArray< T >::Copy( const CSPArray< T >& aArray )
{
	Free();
	SetSize( aArray.m_ulSize );
	for( unsigned long x = 0; x < m_ulSize; x++ )m_p[ x ] = aArray.m_p[ x ];
}

template< class T >
void CSPArray< T >::Copy( const T* p, unsigned long ulSize )
{
	Free();
	SetSize( ulSize );
	for( unsigned long x = 0; x < m_ulSize; x++ )m_p[ x ] = p[ x ];
}

template< class T >
void CSPArray< T >::Add( const CSPArray< T >& aArray )
{
	unsigned long ulPrevSize = m_ulSize;
	Grow( aArray.m_ulSize );
	for( unsigned long x = ulPrevSize; x < m_ulSize; x++ )m_p[ x ] = aArray.m_p[ x - ulPrevSize ];
}

template< class T >
void CSPArray< T >::Add( const T* p, unsigned long ulSize )
{
	unsigned long ulPrevSize = m_ulSize;
	Grow( ulSize );
	for( unsigned long x = ulPrevSize; x < m_ulSize; x++ )m_p[ x ] = p[ x - ulPrevSize ];
}

template< class T >
T& CSPArray< T >::Get( unsigned long ulIndex ) const
{
	if( ulIndex >= m_ulSize )ThrowOutOfRange();
	return m_p[ ulIndex ];
}

template< class T >
void CSPArray< T >::Set( unsigned long ulIndex, const T& Value )
{
	if( ulIndex >= m_ulSize )ThrowOutOfRange();
	m_p[ ulIndex ] = Value;
}

template< class T >
void CSPArray< T >::Free()
{
	delete[] m_p;
	m_p = 0;
	m_ulSize = 0;
}

template< class T >
T* CSPArray< T >::Detach()
{
	T* pRet = m_p;
	m_p = 0;
	m_ulSize = 0;
	return pRet;
}

template< class T >
void CSPArray< T >::Attach( CSPArray< T >& aArray )
{
	Free();
	m_p = aArray.m_p;
	m_ulSize = aArray.m_ulSize;
	aArray.m_p = 0;
	aArray.m_ulSize = 0;
}

template< class T >
void CSPArray< T >::Attach( T* p, unsigned long ulSize )
{
	Free();
	m_p = p;
	m_ulSize = ulSize;
}

#undef ARRAY_INIT

//------------------- CSPScalarArray Template Class ---------------------

#define ARRAY_INIT	m_p( 0 ), m_ulSize( 0 )

template< class T >
class CSPScalarArray : public CSPObject
{
	public:
		CSPScalarArray() : ARRAY_INIT{}
		CSPScalarArray( unsigned long ulSize ) : ARRAY_INIT{ SetSize( ulSize ); }
		CSPScalarArray( const CSPScalarArray< T >& aArray ) : ARRAY_INIT{ Copy( aArray ); }
		virtual ~CSPScalarArray(){ delete[] m_p; }

		void SetSize( unsigned long ulSize );
		void Resize( unsigned long ulSize );
		void Grow( unsigned long ulSize );
		void Shrink( unsigned long ulSize );
		unsigned long GetSize() const {	return m_ulSize; }

		operator T* () const { return m_p; }
//		operator void* () const { return ( void* )m_p; }
		bool operator ! () const { return m_p ? false : true; }
		CSPScalarArray< T >& operator = ( const CSPScalarArray< T >& aArray ){ Copy( aArray ); return *this; };
		T& operator * () const { return *m_p; }
		T** operator & () { return &m_p; }
		bool operator == ( const CSPScalarArray< T >& aArray ) const;
		bool operator != ( const CSPScalarArray< T >& aArray ) const { return !operator == ( aArray ); }

		void Free();
		void Empty(){ Free(); }
		T* Detach();
		void Attach( CSPScalarArray< T >& aArray );
		void Attach( T* p, unsigned long ulSize );
		void Copy( const CSPScalarArray< T >& aArray );
		void Copy( const T* p, unsigned long ulSize );
		void Add( const CSPScalarArray< T >& aArray );
		void Add( const T* p, unsigned long ulSize );
		T& Get( unsigned long ulIndex ) const;
		void Set( unsigned long ulIndex, const T& Value );

	protected:
		T* m_p;
		unsigned long m_ulSize;
};

template< class T >
bool CSPScalarArray<T>:: operator == ( const CSPScalarArray< T >& aArray ) const
{
	if( m_ulSize != aArray.m_ulSize )return false;
	else for( unsigned long x = 0; x < m_ulSize; x++ )
			if( m_p[ x ] != aArray.m_p[ x ] )return false;
	return true;
}

template< class T >
void CSPScalarArray<T>::SetSize( unsigned long ulSize )
{
	if( ulSize == 0 )
	{
		free( m_p );
		m_p = 0;
	}
	else
	{
		free( m_p );
		m_ulSize = 0;
		
		m_p = ( T* )malloc( ulSize * sizeof( T ) );
		if( !m_p )ThrowOutOfMemory();
	}

	m_ulSize = ulSize;
}

template< class T >
void CSPScalarArray<T>::Resize( unsigned long ulSize )
{
	if( ulSize == 0 )
	{
		free( m_p );
		m_p = 0;
	}
	else
	{
		T* pTemp = ( T* )realloc( m_p, ulSize * sizeof( T ) );
		if( !pTemp )ThrowOutOfMemory();

		m_p = pTemp;
	}

	m_ulSize = ulSize;
}

template< class T >
void CSPScalarArray<T>::Grow( unsigned long ulSize )
{
	unsigned long ulFinalSize = m_ulSize + ulSize;
	if( ulFinalSize < m_ulSize )ThrowOutOfMemory(); // Overflow
	Resize( ulFinalSize );
}

template< class T >
void CSPScalarArray<T>::Shrink( unsigned long ulSize )
{
	unsigned long ulFinalSize = m_ulSize - ulSize;
	if( ulFinalSize > m_ulSize )ThrowOutOfMemory(); // Overflow
	Resize( ulFinalSize );
}

template< class T >
void CSPScalarArray< T >::Copy( const CSPScalarArray< T >& aArray )
{
	Free();
	SetSize( aArray.m_ulSize );
	memcpy( m_p, aArray.m_p, m_ulSize );
}

template< class T >
void CSPScalarArray< T >::Copy( const T* p, unsigned long ulSize )
{
	Free();
	SetSize( ulSize );
	memcpy( m_p, p, m_ulSize );
}

template< class T >
void CSPScalarArray< T >::Add( const CSPScalarArray< T >& aArray )
{
	unsigned long ulPrevSize = m_ulSize;
	Grow( aArray.m_ulSize );
	for( unsigned long x = ulPrevSize; x < m_ulSize; x++ )m_p[ x ] = aArray.m_p[ x - ulPrevSize ];
}

template< class T >
void CSPScalarArray< T >::Add( const T* p, unsigned long ulSize )
{
	unsigned long ulPrevSize = m_ulSize;
	Grow( ulSize );
	for( unsigned long x = ulPrevSize; x < m_ulSize; x++ )m_p[ x ] = p[ x - ulPrevSize ];
}

template< class T >
T& CSPScalarArray< T >::Get( unsigned long ulIndex ) const
{
	if( ulIndex >= m_ulSize )ThrowOutOfRange();
	return m_p[ ulIndex ];
}

template< class T >
void CSPScalarArray< T >::Set( unsigned long ulIndex, const T& Value )
{
	if( ulIndex >= m_ulSize )ThrowOutOfRange();
	m_p[ ulIndex ] = Value;
}

template< class T >
void CSPScalarArray< T >::Free()
{
	free( m_p );
	m_p = 0;
	m_ulSize = 0;
}

template< class T >
T* CSPScalarArray< T >::Detach()
{
	T* pRet = m_p;
	m_p = 0;
	m_ulSize = 0;
	return pRet;
}

template< class T >
void CSPScalarArray< T >::Attach( CSPScalarArray< T >& aArray )
{
	Free();
	m_p = aArray.m_p;
	m_ulSize = aArray.m_ulSize;
	aArray.m_p = 0;
	aArray.m_ulSize = 0;
}

template< class T >
void CSPScalarArray< T >::Attach( T* p, unsigned long ulSize )
{
	Free();
	m_p = p;
	m_ulSize = ulSize;
}

#undef ARRAY_INIT

#endif
