/* Copyright (c) 1997-2006
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
   http://www.math.tu-berlin.de/polymake,  mailto:polymake@math.tu-berlin.de

   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, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   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 General Public License for more details.
*/

#ifndef _POLYMAKE_STD_HASH_MAP
#define _POLYMAKE_STD_HASH_MAP "$Project: polymake $$Id: hash_map,v 1.9 2006/03/09 16:21:36 gawrilow Exp $"

#include <ext/defines.h>
#include_next STD_EXT_HEADER(hash_map)

#ifndef _POLYMAKE_TYPE_MANIP_H
#  include <type_manip.h>
#endif
#ifndef _POLYMAKE_STD_HASH_ADAPTER_H
#  include <ports/hash_adapter.h>
#endif

#if _POLYMAKE_ICC_ONLY

namespace std_ext {
   template <typename Key, typename Value, typename HashFcn=hash<Key>,
	     typename EqualKey=pm::operations::eq<const Key&, const Key&>, typename Alloc=std::allocator<std::pair<Key,Value> > >
   class hash_map
      : public std::hash_map<Key, Value, hash_compare<Key, HashFcn, EqualKey>, Alloc> {
      typedef hash_compare<Key, HashFcn, EqualKey> comparator;
      typedef std::hash_map<Key, Value, comparator, Alloc> super;
   public:
      explicit hash_map(size_t=0) { }

      hash_map(size_t, const HashFcn& hf)
	 : super(comparator(hf)) { }

      hash_map(size_t, const HashFcn& hf, const EqualKey& ek, const Alloc& al=Alloc())
	 : super(comparator(hf,ek), al) { }

      template <typename Iterator>
      hash_map(Iterator first, Iterator last, size_t=0)
	 : super(first,last) { }

      template <typename Iterator>
      hash_map(Iterator first, Iterator last, size_t, const HashFcn& hf)
	 : super(first,last,comparator(hf)) { }

      template <typename Iterator>
      hash_map(Iterator first, Iterator last, size_t, const HashFcn& hf, const EqualKey& ek, const Alloc& al=Alloc())
	 : super(first,last,comparator(hf,ek),al) { }

      void resize(size_t) { }
   };
} // end namespace std_ext

#endif // ! _POLYMAKE_ICC_ONLY

namespace pm {

template <typename Key, typename Value, typename HashFcn, typename EqualKey, typename Alloc>
struct spec_object_traits< std_ext::hash_map<Key,Value,HashFcn,EqualKey,Alloc> >
   : spec_object_traits<is_container> {
   static const IO_separator_kind IO_separator=IO_sep_inherit;
   static const bool is_ordered=false;
};

template <typename Key, typename Value, typename HashFcn=std_ext::hash<Key>, typename EqualKey=std::equal_to<Key> >
class hash_map_as_property_map
   : public std_ext::hash_map<Key, Value, HashFcn, EqualKey> {
   typedef std_ext::hash_map<Key, Value, HashFcn, EqualKey> _super;
public:
   hash_map_as_property_map() { }

   explicit hash_map_as_property_map(size_t cap)
      : _super(cap) { }

   Value& operator() (const Key& k)
   {
      return (_super::insert(typename _super::value_type(k, def_val))).first->second;
   }

   const Value& operator() (const Key& k) const
   {
      typename _super::const_iterator ii=this->find(k);
      return ii==this->end() ? def_val : ii->second;
   }

   std::pair<typename _super::iterator, bool>
   insert(const Key& k, typename function_argument<Value>::type v)
   {
      return _super::insert(typename _super::value_type(k, v));
   }

   void set_default_value(typename function_argument<Value>::type default_value)
   {
      def_val=default_value;
   }
protected:
   Value def_val;
};

} // end namespace pm

#endif // _POLYMAKE_STD_HASH_MAP

// Local Variables:
// mode:C++
// End:
