/* $Id$
 * vim:tabstop=8:shiftwidth=8:filetype=cpp:textwidth=72:
 *
 * Misc. utility functions, template implementations.
 *
 * Copyright (C) 2007-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include <sstream>
#include <algorithm>

namespace util {

template<typename T>
bool MiscUtil::compareObject(const T* obj1, const T* obj2)
{
	if ((obj1 == NULL) || (obj2 == NULL)) {
		return false;
	}

	return (*obj1) == (*obj2);
}


template<typename T>
bool MiscUtil::listMatch(const std::list<T*>& l1, const std::list<T*>& l2)
{
	if (l1.size() != l2.size()) {
		return false;
	}
	
	return std::equal(l1.begin(), l1.end(), l2.begin(), 
			MiscUtil::compareObject<T>);
}

template<typename T>
bool MiscUtil::listMatch(
		const std::list<T*>& l1, 
		const std::list<T*>& l2,
		bool (*compare)(const T*, const T*))
{
	if (l1.size() != l2.size()) {
		return false;
	}
	
	return std::equal(l1.begin(), l1.end(), l2.begin(), compare);
}

template <typename T>
std::string
MiscUtil::toString(const T &val)
{
	std::stringstream stream;
	stream << val;
	std::string result = stream.str();

	return result;
}

template <typename T, typename U>
bool
MiscUtil::listContainsObj(const T& haystack, const U needle)
{
	for (typename T::const_iterator i = haystack.begin();
		i != haystack.end(); i++) {
		
		if (MiscUtil::compareObject((*i), needle)) {
			return true;
		}
	}

	return false;
}

template <typename T>
bool
MiscUtil::listStartsWith(const std::list<T*> begin, 
			 const std::list<T*> reference)
{
	if (begin.size() > reference.size()) {
		return false;
	}

	return std::equal(begin.begin(), begin.end(), reference.begin(), 
			  MiscUtil::compareObject<T>);
}

template <typename T>
void
MiscUtil::ldelete(T& l)
{
	for (typename T::const_iterator i = l.begin(); i != l.end(); i++) {
		delete *i;
	}
	l.clear();
}

template <typename T>
void
MiscUtil::lterminate(T*& l)
{
	if (l == NULL) {
		return;
	}

	delete l;
	l = NULL;
}

template <typename T>
void
MiscUtil::terminate(T& item)
{
	item = NULL;
}



template <typename T, typename U>
void 
MiscUtil::ldelete_if(T& l, U functor)
{
	for (typename T::iterator i = l.begin(); i != l.end();) {
		if (functor(*i)) {
			typename T::value_type cur = *i;
			i = l.erase(i);
			delete cur;
			continue;
		}

		i++;
	}
}

template <typename T>
void
MiscUtil::listPut(T *l, std::ostream &stream, const char *delim)
{
	if (l == NULL) {
		stream << "(null)";
		return;
	}

	for (typename T::const_iterator i = l->begin(); i != l->end(); 
		/* nothing */) {
		stream << **i;
		i++;
		if (i != l->end()) {
			stream << delim;
		}
	}
}

}; /* namespace util */
