#ifndef HASHTABLE2_H
#define HASHTABLE2_H

#include <vector>
using namespace std;

#include <bucketlink.h>
#include <typedefs.h>

/**
\brief Hash table with memory management.

\par Example
\verbatim
  hashfunction01 hfn(8);
  hashtable2<int,hashfunction01> h(60,hfn);
  h.insert(&v[0],&v[0]+vsz);

  ...
  if (h.contains(5)) ...
\endverbatim
*/
template< typename T, typename HFN >
class hashtable2 : public hashtable<T,HFN>
{  

  /** Memory managed links. */
  vector< bucketlink<T> * > bucketlinks;
  /** Memory managed data. */
  vector< T * > data;
public:

  /** Pre allocate the bucket size. */
  hashtable2
  (
    uintc bucketsize_,
    HFN fn_
  ) 
    : hashtable<T,HFN>(bucketsize_,fn_) {}

  /** Memory cleanup. */
  ~hashtable2();

  /** Insert a value into the hash table. */
  void insert( T const & val );

  /** Insert a container into the hash table. */
  template < typename K >
  void insert( K const * ibeg, K const * iend);

};

//---------------------------------------------------------
// Implementation

template< typename T, typename HFN >
hashtable2<T,HFN>::~hashtable2()
{
  uintc imax=bucketlinks.size();
  for (uint i=0; i<imax; ++i)
  {
    delete[] data[i];
    delete[] bucketlinks[i];
  }
  bucketlinks.clear();
}

template< typename T, typename HFN >
void hashtable2<T,HFN>::insert( T const & val )
{
  uintc sz=data.size();
  data.push_back( new T(val) );
  bucketlinks.push_back( new bucketlink<T>( data[sz] ) );
  hashtable<T,HFN>::insert( bucketlinks[sz] ); 
}

template< typename T, typename HFN >
template< typename K >
void hashtable2<T,HFN>::insert( K const * ibeg, K const * iend )
{
  T const * i=ibeg;
  for ( ; i!=iend; ++i )
    insert(*i);
}


#endif


