#ifndef _STDEX_HASHMAP_H_
#define _STDEX_HASHMAP_H_
/***************************************************************************
 *
 * declaration for STL-like map based on hash table
 *
 * $Id: hashmap.h,v 7.8 1996/02/19 12:34:12 jims Exp $
 *
 * (c) Copyright 1989 - 1996 Rogue Wave Software, Inc.
 * ALL RIGHTS RESERVED
 *
 * The software and information contained herein are proprietary to, and
 * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
 * intends to preserve as trade secrets such software and information.
 * This software is furnished pursuant to a written license agreement and
 * may be used, copied, transmitted, and stored only in accordance with
 * the terms of such license and with the inclusion of the above copyright
 * notice.  This software and information or any other copies thereof may
 * not be provided or otherwise made available to any other person.
 *
 * Notwithstanding any other lease or license that may pertain to, or
 * accompany the delivery of, this computer software and information, the
 * rights of the Government regarding its use, reproduction and disclosure
 * are as set forth in Section 52.227-19 of the FARS Computer
 * Software-Restricted Rights clause.
 * 
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7013.
 * Contractor/Manufacturer is Rogue Wave Software, Inc.,
 * P.O. Box 2328, Corvallis, Oregon 97339.
 *
 * This computer software and information is distributed with "restricted
 * rights."  Use, duplication or disclosure is subject to restrictions as
 * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
 * Computer Software-Restricted Rights (April 1985)."  If the Clause at
 * 18-52.227-74 "Rights in Data General" is specified in the contract,
 * then the "Alternate III" clause applies.
 *
 ***************************************************************************
 *
 * $Log: hashmap.h,v $
 * Revision 7.8  1996/02/19 12:34:12  jims
 * Port to Stdlib 1.2
 *
 * Revision 7.7  1996/02/07 02:42:30  jims
 * Standard library extensions now in directory rw/stdex
 *
 * Revision 7.6  1995/09/21 00:20:55  griswolf
 * Provide more consistent typedefs.
 *
 * Revision 7.5  1995/09/12  17:13:32  griswolf
 * Move contents to this filename.
 *
 * Revision 7.4  1995/09/06  23:37:08  griswolf
 * Scopus # 2144: move operator== out of header. Add new method
 * bool equal_by_keys(const container&) con;st which ignores value parts.
 *
 * Revision 7.3  1995/09/05  19:36:28  jims
 * Use new copyright macro
 *
 * Revision 7.2  1995/08/31  12:03:51  jims
 * next rev
 *
 * Revision 7.1  1995/08/29  09:16:50  jims
 * Port to sgi and Borland
 *
 * Revision 1.1  1995/08/28  22:12:03  griswolf
 * Initial revision
 *
 */

#include <memory>
#include <assert.h>
#include "rw/stdex/lhash.h"

template <class K, class V, class Hash, class EQ> //, class Allocator>
class rw_hashmap
{
public:
#ifndef RWSTD_NO_CONST_INST
  typedef pair<const K, V>               value_type;
#else
  typedef pair<K,V>                      value_type;
#endif

private:
  struct h_k {
    Hash h_;
    h_k(const Hash& h = Hash()) : h_(h) {}
    inline unsigned long operator()(const value_type& p) const {
      return h_(p.first);
    }
  };

  struct eq_k {
    EQ eq_;
    eq_k(const EQ& eq = EQ()) : eq_(eq) {}
    inline bool operator()(const value_type& p1, const value_type& p2) const {
      return eq_(p1.first, p2.first);
    }
  };

public:
///// typdefs /////

  typedef LHashTable<value_type,h_k,eq_k> impl_type;
  typedef K				key_type;
  // typedef  pair<...K,V>              value_type is located above
  typedef impl_type::size_type		size_type;
  typedef impl_type::difference_type	difference_type;
  typedef impl_type::reference		reference;
  typedef impl_type::const_reference	const_reference;
  typedef impl_type::Iterator		iterator;
  typedef impl_type::ConstIterator	const_iterator;
    
  typedef Hash				key_hash_type;
  typedef EQ				key_equal_type;
  typedef h_k				value_hash_type;
  typedef eq_k				value_equal_type;

  key_hash_type   key_hash() const	{ return Hash(); }
  key_equal_type  key_equal() const	{ return EQ(); }
  value_hash_type value_hash() const	{ return impl.key_hash(); }
  value_equal_type value_equal() const	{ return impl.key_equal(); }

public:
///// constructors /////
  rw_hashmap(size_type sz=1024, const Hash& h = Hash(), const EQ& eq=EQ())
    : impl(sz,value_hash_type(h),value_equal_type(eq)) {}
  rw_hashmap(const rw_hashmap<K,V,Hash,EQ>& arg) : impl(arg.impl) {}
  rw_hashmap(const value_type* first, const value_type* bound,
	     size_type sz=1024, const Hash& h = Hash(), const EQ& eq=EQ()
	     );
  rw_hashmap(const_iterator first, const_iterator bound,
	     size_type sz=1024, const Hash& h = Hash(), const EQ& eq=EQ()
	    );
  ~rw_hashmap() {} // mainly to document no (non-base) action

///// operators ////
  rw_hashmap<K,V,Hash,EQ>&
    operator=(const rw_hashmap<K,V,Hash,EQ>& t)
  { impl = t.impl; return *this; }

  // tests both K and V in each pair. K is tested using EQ. V is tested
  // using operator ==() (which must therefore be defined for type V).
  // Takes slightly longer than the method equal_by_keys() below.
  bool
    operator==(const rw_hashmap<K,V,Hash,EQ>& t) const;

/*
 * Not to be used.  Present only to appease overacheiving compilers (the
 * ones that compile all member functions whether used or not).
 */
  bool
    operator<(const rw_hashmap<K,V,Hash,EQ>&) const
  { assert(false); return false; }

  V& operator[](const key_type& k);
  
  
  /*
   * const version of operator[] suspect.  Leave out for now.
   * (illegal to return reference to local or temporary if not found)
   *
   *  // returns V() if the key is not found.
   *  const V& operator[](const key_type& k) const
   *
   */
    
///// various public methods ////
  iterator
    begin() { return impl.begin(); }
  const_iterator
    begin() const { return impl.begin(); }

  iterator
    end() { return impl.end(); }
  const_iterator
    end() const { return impl.end(); }

  bool
    empty() const { return impl.empty(); }

  // Method equal_by_keys his is a fast and useful approximation to
  // operator==(). It tests that the two maps have the same set of K 
  // parts.  The V part of each stored pair is ignored.
  bool
    equal_by_keys(const rw_hashmap<K,V,Hash,EQ>& t) const 
    { return impl == t.impl; }

  size_type
    size() const { return impl.size(); }

  size_type
    count(const key_type& k) const
    { return find(k) == end() ? 0 : 1; }
      
  const_iterator
    find(const key_type& k) const
//    { pair<K,V> dum(k,V()); return impl.find(dum); }
    { value_type dum(k,V()); return impl.find(dum); }

  iterator
    find(const key_type& k)
//    { pair<K,V> dum(k,V()); return impl.find(dum); }
    { value_type dum(k,V()); return impl.find(dum); }

  iterator
    lower_bound(const key_type& k)
//    { pair<K,V> dum(k,V()); return impl.lower_bound(dum); }
    { value_type dum(k,V()); return impl.lower_bound(dum); }

  const_iterator
    lower_bound(const key_type& k) const
//    { pair<K,V> dum(k,V()); return impl.lower_bound(dum); }
    { value_type dum(k,V()); return impl.lower_bound(dum); }

  iterator
    upper_bound(const key_type& k)
//    { pair<K,V> dum(k,V()); return impl.upper_bound(dum); }
    { value_type dum(k,V()); return impl.upper_bound(dum); }

  const_iterator
    upper_bound(const key_type& k) const
//    { pair<K,V> dum(k,V()); return impl.upper_bound(dum); }
    { value_type dum(k,V()); return impl.upper_bound(dum); }

  pair<iterator,iterator>
    equal_range(const key_type& k)
//    { pair<K,V> dum(k,V()); return impl.equal_range(dum); }
    { value_type dum(k,V()); return impl.equal_range(dum); }

  pair<const_iterator,const_iterator>
    equal_range(const key_type& k) const
//    { pair<K,V> dum(k,V()); return impl.equal_range(dum); }
    { value_type dum(k,V()); return impl.equal_range(dum); }

  size_type
    capacity() const { return impl.capacity(); }

  float
    fill_ratio() const { return impl.fill_ratio(); }

  void
    resize(size_t n) { impl.resize(n); }
  void
    swap(rw_hashmap<K,V,Hash,EQ>& t) { impl.swap(t.impl); }

///// insertion and erasure ////

  pair<iterator,bool>
    insert(const value_type& pr)
    {
      rw_hashmap<K,V,Hash,EQ>::iterator itr;
      bool fits = impl.insertMaybe(pr,itr,true);
      return pair<rw_hashmap<K,V,Hash,EQ>::iterator,bool> (itr,fits);
    }
  
  iterator
    insert(iterator location_hint, const value_type& k)
    {
      rw_hashmap<K,V,Hash,EQ>::iterator ret;
      if(! impl.insertMaybe(k,ret,true))
	ret = end();
      return ret;
    }

  size_type
    insert(const value_type* first, const value_type* bound)
    { iterator dum; return impl.insertMaybe(first,bound,dum,true); }
  
  size_type
    insert(const_iterator first, const_iterator bound)
    { iterator dum; return impl.insertMaybe(first,bound,dum,true); }

  size_type
    erase(const key_type& k)
//    { pair<K,V> dum(k,V()); return impl.erase(dum); }
    { value_type dum(k,V()); return impl.erase(dum); }

  iterator
    erase(iterator it) { return impl.erase(it); }

  iterator
    erase(iterator it, iterator bound) { return impl.erase(it,bound); }

  void
    clear() { impl.clear(); }

private:
  LHashTable<value_type,h_k, eq_k> impl;
};

#ifdef RW_COMPILE_INSTANTIATE
#include "rw/stdex/hashmap.cc"
#endif

#endif /* _STDEX_HASHMAP_H_ */
