// -*- C++ -*-
/***************************************************************************
 *
 * map - declarations for the Standard Library map class
 *
 * $Id: map 91768 2005-08-10 18:58:48Z drodgman $
 *
 ***************************************************************************
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 ***************************************************************************
 *
 * Copyright (c) 1994-2001 Rogue Wave Software, Inc.  All Rights Reserved.
 *
 * This computer software is owned by Rogue Wave Software, Inc. and is
 * protected by U.S. copyright laws and other laws and by international
 * treaties.  This computer software is furnished by Rogue Wave Software,
 * Inc. 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
 * computer software or any other copies thereof may not be provided or
 * otherwise made available to any other person.
 *
 * U.S. Government Restricted Rights.  This computer software is provided
 * with Restricted Rights.  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 or subparagraphs (c) (1) and (2) of the
 * Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19,
 * as applicable.  Manufacturer is Rogue Wave Software, Inc., 5500
 * Flatiron Parkway, Boulder, Colorado 80301 USA.
 *
 **************************************************************************/

#ifndef _RWSTD_MAP_INCLUDED
#define _RWSTD_MAP_INCLUDED


#include <memory>
#include <functional>

#include <rw/_tree.h>
#include <rw/_defs.h>


_RWSTD_NAMESPACE_BEGIN (__rw)


// This is used in the implementation of map and multimap.
template <class _TypeT, class _TypeU>
struct __select1st : public _STD::unary_function<_TypeT, _TypeU>
{
    const _TypeU& operator () (const _TypeT& __x) const {
        return __x.first;
    }
};


_RWSTD_NAMESPACE_END   // __rw


_RWSTD_NAMESPACE_BEGIN (std)

#define _RWSTD_MAP_VALUE_TYPE(key, value)   pair<const key, value>

template <class _Key, class _TypeT,
          class _Compare _RWSTD_COMPLEX_DEFAULT (less<_Key>), 
          class _Allocator
  _RWSTD_COMPLEX_DEFAULT (allocator<_RWSTD_MAP_VALUE_TYPE (_Key, _TypeT) >) >
class map
{
public:

    typedef _Key                                          key_type;
    typedef _TypeT                                        mapped_type;
    typedef _RWSTD_MAP_VALUE_TYPE (key_type, mapped_type) value_type;
    typedef _Compare                                      key_compare;
    typedef _Allocator                                    allocator_type;
    
  private:
    
    typedef _RW::__rb_tree<key_type, value_type,
      _RW::__select1st<value_type, key_type>, 
      key_compare, allocator_type> __rep_type;
    __rep_type _C_rep;

public:

    typedef _TYPENAME __rep_type::reference              reference;
    typedef _TYPENAME __rep_type::const_reference        const_reference;
    typedef _TYPENAME __rep_type::iterator               iterator;
    typedef _TYPENAME __rep_type::const_iterator         const_iterator;
    typedef _TYPENAME __rep_type::size_type              size_type;
    typedef _TYPENAME __rep_type::difference_type        difference_type;
    typedef _TYPENAME __rep_type::pointer                pointer;
    typedef _TYPENAME __rep_type::const_pointer          const_pointer;
    typedef _TYPENAME __rep_type::reverse_iterator       reverse_iterator;
    typedef _TYPENAME __rep_type::const_reverse_iterator const_reverse_iterator;

    class value_compare : public binary_function<value_type, value_type, bool>
    {
        friend class map<_Key, _TypeT, _Compare, _Allocator>;
    protected:
        _Compare comp;
        value_compare (_Compare __cmp) : comp (__cmp) {}
    public:
        bool operator () (const value_type& __x, const value_type& __y) const {
            return comp (__x.first, __y.first);
        }
    };

    _EXPLICIT
    map (const key_compare    &__cmp   = key_compare (),
         const allocator_type &__alloc = allocator_type ()) 
        : _C_rep (__cmp, false, __alloc) { }


#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    template<class _InputIter>
    map (_InputIter __first, _InputIter __last, 
         const _Compare& __cmp = _Compare (),
         const _Allocator& __alloc = _Allocator ())
      : _C_rep (__first, __last, __cmp, false, __alloc) {}

#else   // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    map (const value_type* __first, const value_type* __last, 
         const key_compare &__cmp = key_compare (),
         const allocator_type &__alloc = allocator_type ())
      : _C_rep (__first, __last, __cmp, false, __alloc) {}

    map (const_iterator __first, const_iterator __last, 
         const key_compare &__cmp = key_compare (),
         const allocator_type &__alloc = allocator_type ())
      : _C_rep (__first, __last, __cmp, false, __alloc) {}

#endif   // _RWSTD_NO_MEMBER_TEMPLATES


    map (const map &__x)
        : _C_rep (__x._C_rep, false) {}

    map& operator= (const map &__x) {
        _C_rep = __x._C_rep; return *this; 
    }

    allocator_type get_allocator () const {
        return _C_rep.get_allocator ();
    }

    iterator begin () {
        return _C_rep.begin ();
    }

    const_iterator begin () const {
        return _C_rep.begin ();
    }

    iterator end () {
        return _C_rep.end ();
    }

    const_iterator end () const {
        return _C_rep.end ();
    }

    reverse_iterator rbegin () {
        return _C_rep.rbegin ();
    }

    const_reverse_iterator rbegin () const {
        return _C_rep.rbegin ();
    }

    reverse_iterator rend () {
        return _C_rep.rend ();
    }

    const_reverse_iterator rend () const {
        return _C_rep.rend ();
    }

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

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

    size_type max_size () const {
        return _C_rep.max_size ();
    }

    mapped_type& operator[] (const key_type &__k) {
        // note: temporary is necessary to avoid bug with xlC 5.0
        iterator __i = insert (value_type (__k, mapped_type ())).first;
        return (*__i).second;
    }

    pair<iterator, bool> insert (const_reference __x) {
        return _C_rep.insert (__x);
    }

    iterator insert (iterator __it, const value_type& __x) {
        return _C_rep.insert (__it, __x);
    }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    template<class _InputIter>
    void insert (_InputIter __first, _InputIter __last) {
        _C_rep.insert (__first, __last);
    }

#else   // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    // overload provided to simulate a conversion from std::pair<key_type,
    // mapped_type> to value_type (not available w/o member templates)
    pair<iterator, bool> insert (const pair<key_type, mapped_type> &__x) {
        return insert (pair<const key_type, mapped_type> (__x.first,
                                                          __x.second));
    }

    void insert (const value_type* __first, const value_type* __last) {
        _C_rep.insert (__first, __last);
    }

    void insert (const_iterator __first, const_iterator __last) {
        _C_rep.insert (__first, __last);
    }

#endif   // _RWSTD_NO_MEMBER_TEMPLATES


    void erase (iterator __it) {
        _C_rep.erase (__it);
    }

    size_type erase (const key_type& __x) {
        return _C_rep.erase (__x);
    }

    void  erase (iterator __first, iterator __last) {
        _C_rep.erase (__first,__last);
    }
    void swap (map &__x) {
        _C_rep.swap (__x._C_rep);
    }

    void clear () {
        erase (begin (),end ());
    }

    key_compare key_comp () const {
        return _C_rep.key_comp ();
    }

    value_compare value_comp () const {
        return value_compare (_C_rep.key_comp ());
    }

    iterator find (const key_type& __x) {
        return _C_rep.find (__x);
    }

    const_iterator find (const key_type& __x) const {
        return _C_rep.find (__x);
    }

    size_type count (const key_type& __x) const {
        return _C_rep.count (__x);
    }

    iterator lower_bound (const key_type& __x) {
        return _C_rep.lower_bound (__x);
    }

    iterator upper_bound (const key_type& __x) {
        return _C_rep.upper_bound (__x);
    }

    const_iterator lower_bound (const key_type& __x) const {
        return _C_rep.lower_bound (__x); 
    }

    const_iterator upper_bound (const key_type& __x) const {
        return _C_rep.upper_bound (__x); 
    }

    pair<iterator,iterator> equal_range (const key_type& __x) {
        return _C_rep.equal_range (__x);
    }

    pair<const_iterator, const_iterator>
    equal_range (const key_type& __x) const {
        return _C_rep.equal_range (__x);
    }
};


template <class _Key, class _TypeT,
          class _Compare _RWSTD_COMPLEX_DEFAULT (less<_Key>), 
          class _Allocator
    _RWSTD_COMPLEX_DEFAULT (allocator<_RWSTD_MAP_VALUE_TYPE (_Key, _TypeT) >) >
class multimap
{
public:

    typedef _Key                                          key_type;
    typedef _TypeT                                        mapped_type;
    typedef _RWSTD_MAP_VALUE_TYPE (key_type, mapped_type) value_type;
    typedef _Compare                                      key_compare;
    typedef _Allocator                                    allocator_type;

private:
    
    typedef _RW::__rb_tree<key_type, value_type, 
    _RW::__select1st<value_type, key_type>, 
    key_compare, allocator_type> __rep_type;
    __rep_type _C_rep;

public:

    typedef _TYPENAME __rep_type::reference              reference;
    typedef _TYPENAME __rep_type::const_reference        const_reference;
    typedef _TYPENAME __rep_type::iterator               iterator;
    typedef _TYPENAME __rep_type::const_iterator         const_iterator; 
    typedef _TYPENAME __rep_type::size_type              size_type;
    typedef _TYPENAME __rep_type::difference_type        difference_type;
    typedef _TYPENAME __rep_type::pointer                pointer;
    typedef _TYPENAME __rep_type::const_pointer          const_pointer; 
    typedef _TYPENAME __rep_type::reverse_iterator       reverse_iterator;
    typedef _TYPENAME __rep_type::const_reverse_iterator const_reverse_iterator;

    class value_compare : public binary_function<value_type, value_type, bool>
    {
        friend class multimap<_Key, _TypeT, _Compare, _Allocator>;
    protected:
        _Compare comp;
        value_compare (_Compare __cmp) : comp (__cmp) { }
    public:
        bool operator () (const value_type& __x, const value_type& __y) const {
            return comp (__x.first, __y.first);
        }
    };

    _EXPLICIT
    multimap (const key_compare &__cmp = key_compare (),
              const allocator_type &__alloc = allocator_type ())
      : _C_rep (__cmp, true, __alloc) { }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    template<class _InputIter>
    multimap (_InputIter __first, _InputIter __last, 
              const _Compare& __cmp = _Compare (),
              const _Allocator& __alloc = _Allocator ()) 
      : _C_rep (__first, __last, __cmp, true, __alloc) { }

#else   // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    multimap (const value_type* __first, const value_type* __last, 
              const key_compare &__cmp = key_compare (),
              const allocator_type &__alloc = allocator_type ())
      : _C_rep (__first, __last, __cmp, true, __alloc) { }

    multimap (const_iterator __first, const_iterator __last,
              const key_compare &__cmp = key_compare (),
              const allocator_type &__alloc = allocator_type ())
      : _C_rep (__first, __last, __cmp, true, __alloc) { }

#endif   // _RWSTD_NO_MEMBER_TEMPLATES


    multimap (const multimap &__x)
        : _C_rep (__x._C_rep, true) { }

    multimap& operator= (const multimap &__x) {
        _C_rep = __x._C_rep; return *this; 
    }

    allocator_type get_allocator () const {
        return _C_rep.get_allocator ();
    }

    iterator begin () {
        return _C_rep.begin ();
    }

    const_iterator begin () const {
        return _C_rep.begin ();
    }

    iterator end () {
        return _C_rep.end ();
    }

    const_iterator end () const {
        return _C_rep.end ();
    }

    reverse_iterator rbegin () {
        return _C_rep.rbegin ();
    }

    const_reverse_iterator rbegin () const {
        return _C_rep.rbegin ();
    }

    reverse_iterator rend () {
        return _C_rep.rend ();
    }

    const_reverse_iterator rend () const {
        return _C_rep.rend ();
    }

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

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

    size_type  max_size () const {
        return _C_rep.max_size ();
    }

    iterator insert (const value_type& __x) {
        return _C_rep.insert (__x).first;
    }

    iterator insert (iterator __it, const value_type& __x) {
        return _C_rep.insert (__it, __x);
    }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    template<class _InputIter>
    void insert (_InputIter __first, _InputIter __last) {
        _C_rep.insert (__first, __last);
    }

#else  // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    void insert (const value_type* __first, const value_type* __last) {
        _C_rep.insert (__first, __last);
    }

    void insert (const_iterator __first, const_iterator __last) {
        _C_rep.insert (__first, __last);
    }

#endif   // _RWSTD_NO_MEMBER_TEMPLATES


    void  erase (iterator __it) {
        _C_rep.erase (__it);
    }

    size_type erase (const key_type& __x) {
        return _C_rep.erase (__x);
    }

    void erase (iterator __first, iterator __last) {
        _C_rep.erase (__first, __last);
    }

    void  clear () {
        erase (begin (),end ());
    }

    void swap (multimap &__x) {
        _C_rep.swap (__x._C_rep);
    }

    key_compare  key_comp () const {
        return _C_rep.key_comp ();
    }

    value_compare value_comp () const {
        return value_compare (_C_rep.key_comp ());
    }

    iterator find (const key_type& __x) {
        return _C_rep.find (__x);
    }

    const_iterator find (const key_type& __x) const {
        return _C_rep.find (__x);
    }

    size_type  count (const key_type& __x) const {
        return _C_rep.count (__x);
    }

    iterator lower_bound (const key_type& __x) {
        return _C_rep.lower_bound (__x);
    }

    iterator upper_bound (const key_type& __x) {
        return _C_rep.upper_bound (__x);
    }

    const_iterator  lower_bound (const key_type& __x) const {
        return _C_rep.lower_bound (__x); 
    }

    const_iterator  upper_bound (const key_type& __x) const {
        return _C_rep.upper_bound (__x); 
    }

    pair<iterator,iterator> equal_range (const key_type& __x) {
        return _C_rep.equal_range (__x);
    }

    pair<const_iterator,const_iterator>
    equal_range (const key_type& __x) const {
        return _C_rep.equal_range (__x);
    }
};


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool operator== (const map<_Key, _TypeT, _Compare, _Allocator> &__x,
                        const map<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return    __x.size () == __y.size ()
           && equal (__x.begin (), __x.end (), __y.begin ());
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool operator< (const map<_Key, _TypeT, _Compare, _Allocator> &__x, 
                       const map<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return lexicographical_compare (__x.begin (), __x.end (),
                                    __y.begin (), __y.end ());
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool operator!= (const map<_Key, _TypeT, _Compare, _Allocator> &__x, 
                        const map<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return !(__x == __y);
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool operator> (const map<_Key, _TypeT, _Compare, _Allocator> &__x, 
                       const map<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return __y < __x;
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool operator>= (const map<_Key, _TypeT, _Compare, _Allocator> &__x, 
                        const map<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return !(__x < __y);
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool operator<= (const map<_Key, _TypeT, _Compare, _Allocator> &__x, 
                        const map<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return !(__y <  __x);
}


#ifndef _RWSTD_NO_PART_SPEC_OVERLOAD

// 23.3.1.4
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline void swap (map<_Key, _TypeT, _Compare, _Allocator> &__y, 
                  map<_Key, _TypeT, _Compare, _Allocator> &__x)
{
    __x.swap (__y);
}

#endif   // _RWSTD_NO_PART_SPEC_OVERLOAD


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool
operator== (const multimap<_Key, _TypeT, _Compare, _Allocator> &__x, 
            const multimap<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return    __x.size () == __y.size ()
           && equal (__x.begin (), __x.end (), __y.begin ());
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool
operator< (const multimap<_Key, _TypeT, _Compare, _Allocator> &__x, 
           const multimap<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return lexicographical_compare (__x.begin (), __x.end (),
                                    __y.begin (), __y.end ());
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool
operator!= (const multimap<_Key, _TypeT, _Compare, _Allocator> &__x, 
            const multimap<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return !(__x == __y);
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool
operator> (const multimap<_Key, _TypeT, _Compare, _Allocator> &__x, 
           const multimap<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return __y < __x;
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool
operator>= (const multimap<_Key, _TypeT, _Compare, _Allocator> &__x, 
            const multimap<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return !(__x < __y);
}


// 23.1, p5 - table 65
template <class _Key, class _TypeT, class _Compare, class _Allocator>
inline bool
operator<= (const multimap<_Key, _TypeT, _Compare, _Allocator> &__x, 
            const multimap<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    return !(__y <  __x);
}


#ifndef _RWSTD_NO_PART_SPEC_OVERLOAD

// 23.3.2.3
template <class _Key, class _TypeT, class _Compare, class _Allocator>
void swap (multimap<_Key, _TypeT, _Compare, _Allocator> &__x, 
           multimap<_Key, _TypeT, _Compare, _Allocator> &__y)
{
    __x.swap (__y);
}

#endif   // _RWSTD_NO_PART_SPEC_OVERLOAD


_RWSTD_NAMESPACE_END   // std


#endif   // _RWSTD_MAP_INCLUDED
