/* $Id: pointerwrapper.cpp,v 1.4 2004/01/02 03:54:01 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of a library used by the Archimedes email client     * 
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   This program 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.                                       *
 *                                                                             *
 *   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 Library General Public License for more details.                      *
 *                                                                             *
 *   You should have received a copy of the GNU Library 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.  *
 *                                                                             *
 ******************************************************************************/

#include <algorithm>
#include <vector>

using std::find;
using std::vector;

template<class T>
PointerWrapper<T>::PointerWrapper(T *p, dealloc de)
	: _p(p), _de(de) {}

template<class T>
PointerWrapper<T>::PointerWrapper(const PointerWrapper<T> &pw)
	: _p(pw._p), _de(pw._de)
{

	/* add reference pointers */
	pw.ref(this);
	ref(&pw);
}

template<class T>
PointerWrapper<T>::~PointerWrapper()
{

	if (refs.size() != 0) {
		for (int i = 0; i < refs.size(); i++)
			refs[i]->unref(this);
	} else if (_p != NULL) {
		if (_de != NULL)
			_de(_p);
		else
			free(_p);
	}
}

template<class T> T &
PointerWrapper<T>::operator*()
{

	return *_p;
}

template<class T> T *
PointerWrapper<T>::operator->()
{

	return _p;
}

template<class T> void
PointerWrapper<T>::setdealloc(dealloc de)
{

	_de = de;
}

template<class T> T *
PointerWrapper<T>::operator=(T *p)
{

	return (_p = p);
}

template<class T>
PointerWrapper<T>::operator T*() const
{

	return _p;
}

template<class T> PointerWrapper<T> &
PointerWrapper<T>::operator=(const PointerWrapper<T> &pw)
{

	/* don't copy to ourselves */
	if (this == &pw)
		return *this;

	/* perform a deletion/unreferencing before copying */
	if (refs.size() != 0) {
		for (int i = 0; i < refs.size(); i++)
			refs[i]->unref(this);
	} else if (_p != 0) {
		if (_de != NULL)
			_de(_p);
		else
			free(_p);
	}
	refs.clear();
	_p = pw._p;
	_de = pw._de;

	pw.ref(this);
	ref(&pw);

	return *this;
}			

template<class T> void
PointerWrapper<T>::ref(const PointerWrapper<T> *ref) const
{

	/* add ref only once */
	if (find(refs.begin(), refs.end(), ref) == refs.end())
		refs.push_back(const_cast<PointerWrapper<T> *>(ref));
}

template<class T> void
PointerWrapper<T>::unref(const PointerWrapper<T> *ref) const
{
	typename vector<PointerWrapper<T> *>::iterator p;

	p = find(refs.begin(), refs.end(), ref);
	while (p != refs.end())
		p = refs.erase(p);
}
