// hash_map extension header -*-c++-*-
// Copyright 2009-2017 IAR Systems AB.
#ifndef _HASH_MAP_
#define _HASH_MAP_

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <xhash>

namespace std {

// TEMPLATE CLASS _Hmap_traits
template<class _Kty,    // key type
         class _Ty,      // mapped type
         class _Tr,      // comparator predicate type
         class _Alloc,   // actual allocator type (should be value allocator)
         bool _Mfl>      // true if multiple equivalent keys are permitted
class _Hmap_traits
  : public _Tr
{       // traits required to make _Hash behave like a map
public:
  typedef _Kty key_type;
  typedef pair<const _Kty, _Ty> value_type;
  typedef _Tr key_compare;
  typedef _Alloc allocator_type;

  enum
  {       // make multi parameter visible as an enum constant
    _Multi = _Mfl};

  static const bool _Standard = false;

  _Hmap_traits(const _Tr& _Traits = _Tr())
    : _Tr(_Traits), _Max_buckets(0.0F)
  {       // construct with specified comparator
  }

  class value_compare
  {       // functor for comparing two element values
  public:
    typedef value_type first_argument_type;
    typedef value_type second_argument_type;
    typedef bool result_type;

    bool operator()(const value_type& _Left,
                    const value_type& _Right) const
    {       // test if _Left precedes _Right by comparing just keys
      return _Keycompobj(_Left.first, _Right.first);
    }

    value_compare(const key_compare& _Keycomparg)
      : _Keycompobj(_Keycomparg)
    {       // construct with specified predicate
    }

    key_compare _Keycompobj;
  };

  template<class _Ty1,
           class _Ty2>
  static const _Kty& _Kfn(const pair<_Ty1, _Ty2>& _Val)
  {       // extract key from element value
    return _Val.first;
  }

  template<class _Ty1,
           class _Ty2>
  static const _Ty2& _Nonkfn(const pair<_Ty1, _Ty2>& _Val)
  {       // extract non-key from element value
    return _Val.second;
  }

  float& _Get_max_bucket_size() _NOEXCEPT
  {	// return reference to current maximum bucket size
    return _Max_buckets;
  }

  const float& _Get_max_bucket_size() const _NOEXCEPT
  {	// return const reference to current maximum bucket size
    return _Max_buckets;
  }

  float _Max_buckets;	// current maximum bucket size
};

// TEMPLATE CLASS hash_map
template<class _Kty,
         class _Ty,
         class _Tr = hash_compare<_Kty, less<_Kty> >,
         class _Alloc = allocator<pair<const _Kty, _Ty> > >
class hash_map
  : public _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, false> >
{       // hash table of {key, mapped} values, unique keys
public:
  typedef hash_map<_Kty, _Ty, _Tr, _Alloc> _Myt;
  typedef _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, false> > _Mybase;
  typedef _Kty key_type;
  typedef _Ty mapped_type;
  typedef _Ty referent_type;
  typedef _Tr key_compare;
  typedef typename _Mybase::value_compare value_compare;
  typedef typename _Mybase::allocator_type allocator_type;
  typedef typename _Mybase::size_type size_type;
  typedef typename _Mybase::difference_type difference_type;
  typedef typename _Mybase::pointer pointer;
  typedef typename _Mybase::const_pointer const_pointer;
  typedef typename _Mybase::reference reference;
  typedef typename _Mybase::const_reference const_reference;
  typedef typename _Mybase::iterator iterator;
  typedef typename _Mybase::const_iterator const_iterator;
  typedef typename _Mybase::value_type value_type;

  hash_map()
    : _Mybase(key_compare(), allocator_type())
  {       // construct empty map from defaults
  }

  explicit hash_map(const allocator_type& _Al)
    : _Mybase(key_compare(), _Al)
  {       // construct empty map from defaults, allocator
  }

  hash_map(const _Myt& _Right)
    : _Mybase(_Right,
              _Right._List._Getal().select_on_container_copy_construction())
  {       // construct map by copying _Right
  }

  hash_map(const _Myt& _Right, const allocator_type& _Al)
    : _Mybase(_Right, _Al)
  {       // construct map by copying _Right, allocator
  }

  explicit hash_map(const key_compare& _Traits)
    : _Mybase(_Traits, allocator_type())
  {       // construct empty map from comparator
  }

  hash_map(const key_compare& _Traits, const allocator_type& _Al)
    : _Mybase(_Traits, _Al)
  {       // construct empty map from comparator and allocator
  }

  template<class _Iter>
  hash_map(_Iter _First, _Iter _Last)
    : _Mybase(key_compare(), allocator_type())
  {       // construct map from sequence, defaults
    _Mybase::insert(_First, _Last);
  }

  template<class _Iter>
  hash_map(_Iter _First, _Iter _Last,
           const key_compare& _Traits)
    : _Mybase(_Traits, allocator_type())
  {       // construct map from sequence, comparator
    _Mybase::insert(_First, _Last);
  }

  template<class _Iter>
  hash_map(_Iter _First, _Iter _Last,
           const key_compare& _Traits,
           const allocator_type& _Al)
    : _Mybase(_Traits, _Al)
  {       // construct map from sequence, comparator, and allocator
    _Mybase::insert(_First, _Last);
  }

  _Myt& operator=(const _Myt& _Right)
  {       // assign by copying _Right
    _Mybase::operator=(_Right);
    return *this;
  }

  hash_map(_Myt&& _Right)
    : _Mybase(std::move(_Right), std::move(_Right._List._Getal()))
  {       // construct map by moving _Right
  }

  hash_map(_Myt&& _Right, const allocator_type& _Al)
    : _Mybase(std::move(_Right), _Al)
  {       // construct map by moving _Right, allocator
  }

  _Myt& operator=(_Myt&& _Right)
  {       // assign by moving _Right
    _Mybase::operator=(std::move(_Right));
    return *this;
  }

  mapped_type& operator[](key_type&& _Keyval)
  {       // find element matching _Keyval or insert with default mapped
    iterator _Where = this->lower_bound(_Keyval);
    if (_Where == this->end())
      _Where = this->insert(pair<key_type, mapped_type>(std::move(_Keyval),
                                                        mapped_type())).first;
    return _Where->second;
  }

  void swap(_Myt& _Right)
  {       // exchange contents with non-movable _Right
    _Mybase::swap(_Right);
  }

  hash_map(::std::initializer_list<value_type> _Ilist)
    : _Mybase(key_compare(), allocator_type())
  {       // construct from initializer_list, defaults
    this->insert(_Ilist.begin(), _Ilist.end());
  }

  hash_map(::std::initializer_list<value_type> _Ilist,
           const key_compare& _Pred)
    : _Mybase(_Pred, allocator_type())
  {       // construct from initializer_list, comparator
    this->insert(_Ilist.begin(), _Ilist.end());
  }

  hash_map(::std::initializer_list<value_type> _Ilist,
           const key_compare& _Pred, const allocator_type& _Al)
    : _Mybase(_Pred, _Al)
  {       // construct from initializer_list, comparator, and allocator
    this->insert(_Ilist.begin(), _Ilist.end());
  }

  _Myt& operator=(::std::initializer_list<value_type> _Ilist)
  {       // assign initializer_list
    this->clear();
    this->insert(_Ilist.begin(), _Ilist.end());
    return *this;
  }

  // void insert(::std::initializer_list<value_type> _Ilist)
  // {       // insert initializer_list
  //   this->insert(_Ilist.begin(), _Ilist.end());
  // }

  mapped_type& operator[](const key_type& _Keyval)
  {       // find element matching _Keyval or insert with default mapped
    iterator _Where = this->lower_bound(_Keyval);
    if (_Where == this->end())
      _Where = this->insert(pair<key_type, mapped_type>(_Keyval,
                                                        mapped_type())).first;
    return _Where->second;
  }

  mapped_type& at(const key_type& _Keyval)
  {       // find element matching _Keyval
    iterator _Where = this->lower_bound(_Keyval);
    if (_Where == this->end())
      __iar_Raise_key();
    return _Where->second;
  }

  const mapped_type& at(const key_type& _Keyval) const
  {       // find element matching _Keyval
    const_iterator _Where = this->lower_bound(_Keyval);
    if (_Where == this->end())
      __iar_Raise_key();
    return _Where->second;
  }

  typedef std::reverse_iterator<iterator> reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

  reverse_iterator rbegin() _NOEXCEPT
  {	// return iterator for beginning of reversed mutable sequence
    return reverse_iterator(this->end());
  }

  const_reverse_iterator rbegin() const _NOEXCEPT
  {	// return iterator for beginning of reversed nonmutable sequence
    return const_reverse_iterator(this->end());
  }

  reverse_iterator rend() _NOEXCEPT
  {	// return iterator for end of reversed mutable sequence
    return reverse_iterator(this->begin());
  }

  const_reverse_iterator rend() const _NOEXCEPT
  {	// return iterator for end of reversed nonmutable sequence
    return const_reverse_iterator(this->begin());
  }

  const_reverse_iterator crbegin() const _NOEXCEPT
  {	// return iterator for beginning of reversed nonmutable sequence
    return rbegin();
  }

  const_reverse_iterator crend() const _NOEXCEPT
  {	// return iterator for end of reversed nonmutable sequence
    return rend();
  }
};

template<class _Kty,
         class _Ty,
         class _Tr,
         class _Alloc> inline
void swap(hash_map<_Kty, _Ty, _Tr, _Alloc>& _Left,
          hash_map<_Kty, _Ty, _Tr, _Alloc>& _Right)
{       // swap _Left and _Right hash_maps
  _Left.swap(_Right);
}

template<class _Kty,
         class _Ty,
         class _Tr,
         class _Alloc> inline
bool operator==(const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Left,
                const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Right)
{       // test for hash_map equality
  return std::_Hash_equal(_Left, _Right);
}

template<class _Kty,
         class _Ty,
         class _Tr,
         class _Alloc> inline
bool operator!=(const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Left,
                const hash_map<_Kty, _Ty, _Tr, _Alloc>& _Right)
{       // test for hash_map inequality
  return !(_Left == _Right);
}

// TEMPLATE CLASS hash_multimap
template<class _Kty,
         class _Ty,
         class _Tr = hash_compare<_Kty, less<_Kty> >,
         class _Alloc = allocator<pair<const _Kty, _Ty> > >
class hash_multimap
  : public _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, true> >
{       // hash table of {key, mapped} values, non-unique keys
public:
  typedef hash_multimap<_Kty, _Ty, _Tr, _Alloc> _Myt;
  typedef _Hash<_Hmap_traits<_Kty, _Ty, _Tr, _Alloc, true> > _Mybase;
  typedef _Kty key_type;
  typedef _Ty mapped_type;
  typedef _Ty referent_type;      // old name, magically gone
  typedef _Tr key_compare;
  typedef typename _Mybase::value_compare value_compare;
  typedef typename _Mybase::allocator_type allocator_type;
  typedef typename _Mybase::size_type size_type;
  typedef typename _Mybase::difference_type difference_type;
  typedef typename _Mybase::pointer pointer;
  typedef typename _Mybase::const_pointer const_pointer;
  typedef typename _Mybase::reference reference;
  typedef typename _Mybase::const_reference const_reference;
  typedef typename _Mybase::iterator iterator;
  typedef typename _Mybase::const_iterator const_iterator;
  typedef typename _Mybase::value_type value_type;

  hash_multimap()
    : _Mybase(key_compare(), allocator_type())
  {       // construct empty map from defaults
  }

  explicit hash_multimap(const allocator_type& _Al)
    : _Mybase(key_compare(), _Al)
  {       // construct empty map from defaults, allocator
  }

  hash_multimap(const _Myt& _Right)
    : _Mybase(_Right,
              _Right._List._Getal().select_on_container_copy_construction())
  {       // construct map by copying _Right
  }

  hash_multimap(const _Myt& _Right, const allocator_type& _Al)
    : _Mybase(_Right, _Al)
  {       // construct map by copying _Right, allocator
  }

  explicit hash_multimap(const key_compare& _Traits)
    : _Mybase(_Traits, allocator_type())
  {       // construct empty map from comparator
  }

  hash_multimap(const key_compare& _Traits, const allocator_type& _Al)
    : _Mybase(_Traits, _Al)
  {       // construct empty map from comparator and allocator
  }

  template<class _Iter>
  hash_multimap(_Iter _First, _Iter _Last)
    : _Mybase(key_compare(), allocator_type())
  {       // construct map from sequence, defaults
    _Mybase::insert(_First, _Last);
  }

  template<class _Iter>
  hash_multimap(_Iter _First, _Iter _Last,
                const key_compare& _Traits)
    : _Mybase(_Traits, allocator_type())
  {       // construct map from sequence, comparator
    _Mybase::insert(_First, _Last);
  }
  template<class _Iter>
  hash_multimap(_Iter _First, _Iter _Last,
                const key_compare& _Traits,
                const allocator_type& _Al)
    : _Mybase(_Traits, _Al)
  {       // construct map from sequence, comparator, and allocator
    _Mybase::insert(_First, _Last);
  }

  _Myt& operator=(const _Myt& _Right)
  {       // assign by copying _Right
    _Mybase::operator=(_Right);
    return *this;
  }

  hash_multimap(_Myt&& _Right)
    : _Mybase(std::move(_Right), std::move(_Right._List._Getal()))
  {       // construct map by moving _Right
  }

  hash_multimap(_Myt&& _Right, const allocator_type& _Al)
    : _Mybase(std::move(_Right), _Al)
  {       // construct map by moving _Right, allocator
  }

  _Myt& operator=(_Myt&& _Right)
  {       // assign by moving _Right
    _Mybase::operator=(std::move(_Right));
    return *this;
  }

  template<class _Valty>
  typename enable_if<is_convertible<_Valty, value_type>::value,
                     iterator>::type
  insert(_Valty&& _Val)
  {       // insert a {key, mapped} value
    return _Mybase::insert(std::forward<_Valty>(_Val)).first;
  }

  template<class _Valty>
  typename enable_if<is_convertible<_Valty, value_type>::value,
                     iterator>::type
  insert(const_iterator _Where, _Valty&& _Val)
  {       // insert a {key, mapped} value, with hint
    return _Mybase::insert(_Where, std::forward<_Valty>(_Val));
  }

  void swap(_Myt& _Right)
  {       // exchange contents with non-movable _Right
    _Mybase::swap(_Right);
  }

  hash_multimap(::std::initializer_list<value_type> _Ilist)
    : _Mybase(key_compare(), allocator_type())
  {       // construct from initializer_list, defaults
    this->insert(_Ilist.begin(), _Ilist.end());
  }

  hash_multimap(::std::initializer_list<value_type> _Ilist,
                const key_compare& _Pred)
    : _Mybase(_Pred, allocator_type())
  {       // construct from initializer_list, comparator
    this->insert(_Ilist.begin(), _Ilist.end());
  }

  hash_multimap(::std::initializer_list<value_type> _Ilist,
                const key_compare& _Pred, const allocator_type& _Al)
    : _Mybase(_Pred, _Al)
  {       // construct from initializer_list, comparator, and allocator
    this->insert(_Ilist.begin(), _Ilist.end());
  }

  _Myt& operator=(::std::initializer_list<value_type> _Ilist)
  {       // assign initializer_list
    this->clear();
    this->insert(_Ilist.begin(), _Ilist.end());
    return *this;
  }

  void insert(::std::initializer_list<value_type> _Ilist)
  {       // insert initializer_list
    this->insert(_Ilist.begin(), _Ilist.end());
  }

  iterator insert(const value_type& _Val)
  {       // insert a {key, mapped} value
    return _Mybase::insert(_Val).first;
  }

  iterator insert(const_iterator _Where, const value_type& _Val)
  {       // insert a {key, mapped} value, with hint
    return _Mybase::insert(_Where, _Val);
  }

  template<class _Iter>
  void insert(_Iter _First, _Iter _Last)
  {       // insert [_First, _Last), arbitrary iterators
    _Mybase::insert(_First, _Last);
  }

  typedef std::reverse_iterator<iterator> reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

  reverse_iterator rbegin() _NOEXCEPT
  {	// return iterator for beginning of reversed mutable sequence
    return reverse_iterator(this->end());
  }

  const_reverse_iterator rbegin() const _NOEXCEPT
  {	// return iterator for beginning of reversed nonmutable sequence
    return const_reverse_iterator(this->end());
  }

  reverse_iterator rend() _NOEXCEPT
  {	// return iterator for end of reversed mutable sequence
    return reverse_iterator(this->begin());
  }

  const_reverse_iterator rend() const _NOEXCEPT
  {	// return iterator for end of reversed nonmutable sequence
    return const_reverse_iterator(this->begin());
  }

  const_reverse_iterator crbegin() const _NOEXCEPT
  {	// return iterator for beginning of reversed nonmutable sequence
    return rbegin();
  }

  const_reverse_iterator crend() const _NOEXCEPT
  {	// return iterator for end of reversed nonmutable sequence
    return rend();
  }
};

template<class _Kty,
         class _Ty,
         class _Tr,
         class _Alloc> inline
void swap(hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Left,
          hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Right)
{       // swap _Left and _Right hash_multimaps
  _Left.swap(_Right);
}

template<class _Kty,
         class _Ty,
         class _Tr,
         class _Alloc> inline
bool operator==(const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Left,
                const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Right)
{       // test for hash_multimap equality
  return std::_Hash_equal(_Left, _Right);
}

template<class _Kty,
         class _Ty,
         class _Tr,
         class _Alloc> inline
bool operator!=(  const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Left,
                  const hash_multimap<_Kty, _Ty, _Tr, _Alloc>& _Right)
{       // test for hash_multimap inequality
  return !(_Left == _Right);
}

} /* namespace std */

namespace stdext {
  using ::std::hash_map;
  using ::std::hash_multimap;
}       // namespace stdext

#endif /* _HASH_MAP_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0576 */
