// -*- c++ -*-
//------------------------------------------------------------------------------
//                          AutoPtr.h
//------------------------------------------------------------------------------
//  Copyright (C) 1999  Vladislav Grinchenko <vladg@erols.com>
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version. 
//------------------------------------------------------------------------------
#ifndef AUTO_PTR_H
#define AUTO_PTR_H

/** @file AutoPtr.h 

   AutoPtr is a local implementation of STL's auto_ptr that makes dynamic
   memory handling a bit easier.
*/

#if defined(sun) && (__SUNPRO_CC == 0x420)
#if !defined(explicit)

/** @def explicit
	explicit keyword is missing from old Sun CC 4.2
*/
#define explicit
#endif
#endif

namespace ASSA {

/** 
	AutoPtr is based on SGI implementation of a auto_ptr < > template that 
	makes memory handling a little bit easier.

	AutoPtr interface does not completely confirm to that of auto_ptr as 
	specified in C++ Standard. 

	The feature missing is handling of derived classes caused
	by lack of nontrivial member function templates support
	in Sun CC 4.2 compiler (what do you want, it was released in year of 1996!).
*/

template <class X> class AutoPtr {
private:
    /// Pointer to object to own
    X* m_ptr;

    /** Ownership flag indicating whether *this owns the memory area
		pointed by the pointer.
	*/
    bool m_owns;

public:
    /** explicit constructor. Word 'explicit' disallows
		implicit construction of objects, for example in functions  calls. 
	  @param p_ pointer to the object to assume ownerwhip of.
     */
    explicit AutoPtr(X* p_ = 0) 
		: m_ptr(p_), m_owns( (p_ ? true : false) ) 	{}

    /** This constructor takes over the ownership of the object argument owns.
	 *  @param a_ AutoPtr object that is released of ownership.
     */
    AutoPtr (AutoPtr& a_)  
		: m_ptr(a_.m_ptr), m_owns(a_.m_owns) { a_.m_owns = 0; }

#if 0
    // Left for later, when compiler will support it.
    // Same as previous constructor to handle derived classes.
//      template <class T> AutoPtr(const AutoPtr<T>& a) 
//  	: m_ptr(a.m_ptr), m_owns(a.m_owns) {
//  	a.m_owns = 0;
//      }
#endif

    /** Assignment operator deletes memory are *this owns (if any),
     *  and transfers ownership from a to itself.
     *
     *  @param a_ object that is released of memory area ownership
     */
    AutoPtr& operator= (AutoPtr& a_)  {
		if (&a_ != this) {
			if (m_owns)
				delete m_ptr;
			m_owns = a_.m_owns;
			m_ptr = a_.m_ptr;
			a_.m_owns = 0;
		}
		return *this;
    }

#if 0
    // Left for later, when compiler will support it.
    // Same as previous to handle derived classes.

//      template <class T> AutoPtr& operator=(const AutoPtr<T>& a)  {
//  	if (&a != this) {
//  	    if (m_owns)
//  		delete m_ptr;
//  	    m_owns = a.m_owns;
//  	    m_ptr = a.m_ptr;
//  	    a.m_owns = 0;
//  	}
//      }
#endif

    /** Destructor always deletes the object *this owns if there is 
     *  an ownership assumed.
     */
    ~AutoPtr() { if (m_owns) delete m_ptr;  }
    
    X& operator*() const  { return *m_ptr; }
    X* operator->() const  { return m_ptr; }
	
    /** Get pointer to the memory area without changing ownership status. 
     *  Usefull when you need to pass a pointer to the function.
     */
    X* get() const  { return m_ptr; }
	
    /** Terminate ownership and return pointer back. 
     *  Caller of this method now owns the object and responsible
     *  for its deallocation.
     */
    X* release() { m_owns = false; return m_ptr; }
};

} // end namespace ASSA

#endif /* AUTO_PTR_H */
