/*
 * The UDS Collection
 * Copyright (C) 1999, 2000, 2001  Julian v. Bock
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *	(See file COPYING for more information)
 */

#ifndef _uds_auto_ptr_hh
#define _uds_auto_ptr_hh


/** auto_ptr implementation. For performance reasons all function are inline
	\author Julian v. Bock */
template < class T >
class auto_ptr
{
public:
	/** \param p pointer */
	explicit
	auto_ptr( T* p = 0 ) : pointee( p ) {}
	
	/** \param rhs compatible auto pointer */
	template < class U >
	auto_ptr( auto_ptr< U >& rhs ) : pointee( rhs.release() ) {}
	
	/** destructor */
	~auto_ptr() { delete pointee; }
	
	/** \return pointee */
	T*
	get() const { return pointee; }
	
	/** sets the pointee to null and returns the old one
		\return old pointee */
	T*
	release()
	{
		T* oldPointee = pointee;
		pointee = 0;
		return oldPointee;
	}
	
	/** sets a new pointee (and deletes the old one)
		\param p new pointee */
	void
	reset( T* p = 0 ) { delete pointee; pointee = p; }
	
	/** dereferences the pointee
		\return dereferenced pointer */
	const T&
	operator * () const { return *pointee; }
	
	/** dereferences the pointee
		\return dereferenced pointer */
	T&
	operator * () { return *pointee; }
	
	/** \return pointee */
	T*
	operator -> () const { return pointee; }
	
	auto_ptr&
	operator = ( auto_ptr& rhs )
	{
		if ( this != &rhs )
			reset( rhs.release() );
		return *this;
	}

private:
	/// wrapped pointer
	T*	pointee;
	
	/// forbidden
	auto_ptr( const auto_ptr& );
	
	/// forbidden
	void
	operator = ( const auto_ptr& );
};


/** array auto pointer implementation. For performance reasons all function
	are inline
	\author Julian v. Bock */
template < class T >
class vec_auto_ptr
{
public:
	/** \param p pointer */
	explicit
	vec_auto_ptr( T* p = 0 ) : pointee( p ) {}
	
	/** \param rhs compatible auto pointer */
	template < class U >
	vec_auto_ptr( vec_auto_ptr< U >& rhs ) : pointee( rhs.release() ) {}
	
	/** destructor */
	~vec_auto_ptr() { delete [] pointee; }
	
	/** \return pointee */
	T*
	get() const { return pointee; }
	
	/** sets the pointee to null and returns the old one
		\return old pointee */
	T*
	release()
	{
		T* oldPointee = pointee;
		pointee = 0;
		return oldPointee;
	}
	
	/** sets a new pointee (and deletes the old one)
		\param p new pointee */
	void
	reset( T* p = 0 ) { delete [] pointee; pointee = p; }
	
	/** dereferences the pointee
		\return dereferenced pointer */
	const T&
	operator * () const { return *pointee; }
	
	/** dereferences the pointee
		\return dereferenced pointer */
	T&
	operator * () { return *pointee; }
	
	/** \return pointee */
	T*
	operator -> () const { return pointee; }
	
	/** \param array index
		\return array element */
	T&
	operator [] ( int i ) { return pointee[i]; }
	
	/** assignment operator
		\return *this */
	vec_auto_ptr&
	operator = ( vec_auto_ptr& rhs )
	{
		if ( this != &rhs )
			reset( rhs.release() );
		return *this;
	}
	
private:
	/// wrapped pointer
	T*	pointee;
	
	/// forbidden
	vec_auto_ptr( const vec_auto_ptr& rhs );
	
	/// forbidden
	void
	operator = ( const vec_auto_ptr& rhs );
};

#endif // _uds_auto_ptr_hh
