/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


#ifndef DDPTRMAP_H
#define DDPTRMAP_H

#include <ddmaprow.h>

using namespace std;


/// ddmapptr: eine Maprow mit welche Pointer statt Objekte speichert.
/**
	
	ddmapptr speichert Pointer statt Objekte, der operator[] liefert daher Pointer.
	Referenzen können über get_entry geholt werden.
	
	@see ddmaprow
	@see ddmapmulti
	@see ddmapindex
	
*/

template<class T>
class ddmapptr : public ddmaprow<T*>
{

public:

	/**
		Destructor.
	*/
	
	virtual ~ddmapptr()
	{
		for( size_t i=0; i<this->_data.size(); ++i )
			delete this->_data[i];
	}

	
  /**
		@Returns Eine Referenz auf den Eintrag an Position 'key'.
	*/
  
  T& get_entry( const ddstring& key )
  {
		int i = this->index_of( key );
		if( i<0 )
			throw runtime_error( "dddmapptr::get_entry: not found: " + key );
		return *( this->_data[i] );
	}
  
	
  /**
		@Returns Eine Referenz auf den Eintrag an Position 'key', const Version.
	*/
	  
  const T& get_entry( const ddstring& key ) const
  {
		int i = this->index_of( key );
		if( i<0 )
			throw runtime_error( "dddmapptr::get_entry: not found: " + key );
		return *( this->_data[i] );
	}
	
	
	/**
		@Returns Eine Referenz auf den Eintrag an Position 'index'.
	*/
  
  T& get_entry( int index )
  {
		if( (size_t) index < this->_data.size() )
			return *( this->_data[index] );
		throw out_of_range( "ddmapptr get_entry( size_t index ): out of range" );
	}
	
	
	/**
		@Returns Eine Referenz auf den Eintrag an Position 'index', const Version.
	*/
  
  const T& get_entry( int index ) const
  {
		if( (size_t) index < this->_data.size() )
			return *( this->_data[index] );
		throw out_of_range( "ddmapptr const get_entry( size_t index ): out of range" );
	}
  
	
	/**
		Löscht den Eintrag an Position 'key'.
	*/

 	bool kill_entry( const ddstring& key )
	{
		int idx = this->index_of( key );
		// warum keine exception?
		if( idx<0 )
			return false;
		return kill_entry( (size_t) idx );
	}
	
	
	/**
		Löscht den Eintrag an Position 'index'.
		Dazu wird 'ddmaprow<T*>::kill' aufgerufen.
		@see ddmaprow
	*/
	
	bool kill_entry( size_t index )
	{
		T* item = this->_data[index];
		if( ddmaprow<T*>::kill_entry( index ) )
		{
			delete item;
			return true;
		}
		return false;
	}
	
	
	bool remove_entry( const ddstring& key )
	{
		int idx = this->index_of( key );
		// warum keine exception?
		if( idx<0 )
			return false;
		
		return remove_entry( (size_t) idx );

	}
	
	
	bool remove_entry( size_t index )
	{
		
		if( index >= this->_data.size() )
			return false;
			
		// eintrag löschen
		this->_data.erase( this->_data.begin()+index );
		// index updaten
		this->_index.update( index );
		
		return true;	

	}
	/**
		Einen Eintrag ersetzen.
	*/
	
	void replace( int index, T* entry )
	{	
		if( (size_t) index >= this->_data.size() )
			throw out_of_range( "ddmapptr replace( size_t index ): out of range" );
		delete( this->_data[index] );
		this->_data[index] = entry;
	}
	
	
	/**
		Einen Eintrag ersetzen.
	*/
	
	void replace( const ddstring& key, T* entry )
	{
		replace( this->index_of( key ), entry );
	}
		
};


#endif
