/*  Metrowerks Standard Library  Version 4.0  1998 August 10  */

/*  $Date: 1998/12/04 23:58:22 $ 
 *  $Revision: 1.2 $ 
 *  $NoKeywords: $ 
 *
 *		Portions Copyright  1995-1998 Metrowerks, Inc.
 *		All rights reserved.
 */

/**
 **  set       // hh 971223 Changed filename from set.h to set
 **
 **  Lib++  : The Modena C++ Standard Library,
 **           Version 2.4, October 1997
 **
 **  Copyright (c) 1995-1997 Modena Software Inc.
 **/

#ifndef _SET              // hh 971223 Made include guards standard
#define _SET

#include <mcompile.h>

#include <tree.h>    // hh 971220 fixed MOD_INCLUDE

#ifndef RC_INVOKED // hh 971230

#pragma options align=native
#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
	#pragma import on
#endif

#ifdef MSIPL_USING_NAMESPACE
	namespace std {
#endif

// Subclause 23.3.3 -- class set

template <class Key, class DEFTEMPARG (Compare, less<Key>), 
          class DEFTEMPARG (Allocator, allocator<Key>) >
class set {

public:
    // typedefs:
    typedef Key     key_type;
    typedef Key     value_type;
    typedef Compare key_compare;
    typedef Compare value_compare;
    typedef rb_tree<key_type, value_type, ident<value_type, key_type>, 
                    key_compare, Allocator> rep_type;

private:
    rep_type t;  // red-black tree representing set

public:
    typedef          Allocator                          allocator_type;
    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;

    // 23.3.3.2 construct/copy/destroy
    explicit set (const Compare& comp = Compare (), 
         const Allocator& alloc = Allocator ())
    : t (comp, alloc) {}

#ifdef MSIPL_MEMBER_TEMPLATE
    template <class InputIterator>
    set (InputIterator first, InputIterator last, 
         const Compare& comp = Compare (), 
         const Allocator& alloc = Allocator ())
    : t (comp, alloc)
    {
        for (InputIterator i = first; i != last; ++i)
            t.insert_unique (*i);
    }
#else
    set (const value_type* first, const value_type* last, 
         const Compare& comp = Compare (), 
         const Allocator& alloc = Allocator ())
    : t (comp, alloc)
    {
        for (const value_type* i = first; i != last; ++i)
            t.insert_unique (*i);
    }
    set (const_iterator first, const_iterator last, 
         const Compare& comp = Compare (), 
         const Allocator& alloc = Allocator ())
    : t (comp, alloc)
    {
        for (const_iterator i = first; i != last; ++i)
            t.insert_unique (*i);
    }
#endif /* MSIPL_MEMBER_TEMPLATE */

    set (const set<Key, Compare, Allocator>& x) : t (x.t) {}

    set<Key, Compare, Allocator>& 
    operator= (const set<Key, Compare, Allocator>& x)
    { t = x.t; return *this; }

    allocator_type get_allocator () const
    { return t.get_allocator (); }
    
    // 23.3.3.3  Iterators:
    iterator                begin ()            { return t.begin (); }
    const_iterator          begin () const      { return t.begin (); }
    iterator                end ()              { return t.end ();   }
    const_iterator          end () const        { return t.end ();   }

    reverse_iterator        rbegin ()           { return t.rbegin (); } 
    const_reverse_iterator  rbegin () const     { return t.rbegin (); } 
    reverse_iterator        rend ()             { return t.rend ();   }
    const_reverse_iterator  rend () const       { return t.rend ();   }

    // 23.3.3.4  capacity:
    bool              empty ()      const { return t.empty ();    }
    size_type         size ()       const { return t.size ();     }
    size_type         max_size ()   const { return t.max_size (); }

    // 23.3.3.5  modifiers:
    typedef  pair<iterator, bool> pair_iterator_bool; 

    pair_iterator_bool insert (const value_type& x)
    {
        pair<typename rep_type::iterator, bool> p = t.insert_unique (x); 
        return pair<iterator, bool> (p.first, p.second);
    }
    iterator insert (iterator position, const value_type& x)
    { 
        return t.insert_unique ((typename rep_type::iterator&)position, x); 
    }

#ifdef MSIPL_MEMBER_TEMPLATE
    template <class InputIterator>
    void insert (InputIterator first, InputIterator last)
    {
        for (InputIterator i = first; i != last; ++i)
            t.insert_unique (*i);
    }

#else
    void insert (const value_type* first, const value_type* last)
    {
        for (const value_type* i = first; i != last; ++i)
            t.insert_unique (*i);
    }
    void insert (const_iterator first, const_iterator last)
    { 
        t.insert_unique (first, last); 
    }
#endif /* MSIPL_MEMBER_TEMPLATE */

    void erase (iterator position)
    { t.erase ((typename rep_type::iterator&)position); }

    size_type erase (const key_type& x)
    { return t.erase (x); }

    void erase (iterator first, iterator last)
    { t.erase ((typename rep_type::iterator&)first, 
               (typename rep_type::iterator&)last); }

    void swap (set<Key, Compare, Allocator>& x) { t.swap (x.t); }

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

    // 23.3.3.6  observers:
    key_compare       key_comp ()   const { return t.key_comp (); }
    value_compare     value_comp () const { return t.key_comp (); }

    // 23.3.3.7  set operations:
    iterator         find (const key_type& x)        { return t.find (x);  }
    const_iterator   find (const key_type& x)  const { return t.find (x);  }
    size_type        count (const key_type& x) const { return t.count (x); }

    iterator   lower_bound (const key_type& x)
    { return t.lower_bound (x); }
    const_iterator   lower_bound (const key_type& x) const
    { return t.lower_bound (x); }

    iterator upper_bound (const key_type& x)
    { return t.upper_bound (x); }
    const_iterator upper_bound (const key_type& x) const
    { return t.upper_bound (x); }

    typedef  pair<iterator, iterator> pair_iterator_iterator; 
    typedef  pair<const_iterator, const_iterator> pair_citerator_citerator; 

    pair_iterator_iterator equal_range (const key_type& x)
    { return t.equal_range (x); }

    pair_citerator_citerator equal_range (const key_type& x) const
    { return t.equal_range (x); }
};

template <class Key, class Compare, class Allocator>
inline bool operator== (const set<Key, Compare, Allocator>& x, 
                        const set<Key, Compare, Allocator>& y)
{ return x.size () == y.size () && equal (x.begin (), x.end (), y.begin ()); }

template <class Key, class Compare, class Allocator>
inline bool operator< (const set<Key, Compare, Allocator>& x, 
                       const set<Key, Compare, Allocator>& y)
{ return lexicographical_compare (x.begin (), x.end (), y.begin (), y.end ()); }

template <class Key, class Compare, class Allocator>
inline bool operator!= (const set<Key, Compare, Allocator>& x, 
                        const set<Key, Compare, Allocator>& y)
{ return ! (x == y); }

template <class Key, class Compare, class Allocator>
inline bool operator<= (const set<Key, Compare, Allocator>& x, 
                       const set<Key, Compare, Allocator>& y)
{ return ! ( y < x); }

template <class Key, class Compare, class Allocator>
inline bool operator>= (const set<Key, Compare, Allocator>& x, 
                        const set<Key, Compare, Allocator>& y)
{ return ! (x < y); }

template <class Key, class Compare, class Allocator>
inline bool operator> (const set<Key, Compare, Allocator>& x, 
                       const set<Key, Compare, Allocator>& y)
{ return (y < x); }

template <class Key, class Compare, class Allocator>
inline void swap (const set<Key, Compare, Allocator>& x, 
                  const set<Key, Compare, Allocator>& y)
{ x.swap (y); }

// Subclause 23.3.4 -- class multiset
template <class Key, class DEFTEMPARG (Compare, less<Key>), 
          class DEFTEMPARG (Allocator, allocator<Key>) >
class multiset {

public:
    // typedefs:
    typedef Key           key_type;
    typedef Key           value_type;
    typedef Compare       key_compare;
    typedef Compare       value_compare;
    typedef rb_tree<key_type, value_type, ident<value_type, key_type>, 
                    key_compare, Allocator> rep_type;

private:
    rep_type t;  // red-black tree representing multiset

public:
    typedef Allocator                                   allocator_type;
    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;
    
    // construct/copy/destroy
    explicit multiset (const Compare& comp = Compare (), 
              const Allocator& alloc = Allocator ())
    : t (comp, alloc) {}

#ifdef MSIPL_MEMBER_TEMPLATE
    template <class InputIterator>
    multiset (InputIterator first, InputIterator last, 
              const Compare& comp = Compare (), 
              const Allocator& alloc = Allocator ())
    : t (comp, alloc)
    {
        for (InputIterator i = first; i != last; ++i)
            t.insert_equal (*i);
    }
#else
    multiset (const value_type* first, const value_type* last, 
              const Compare& comp = Compare (), 
              const Allocator& alloc = Allocator ())
    : t (comp, alloc)
    {
        for (const value_type* i = first; i != last; ++i)
            t.insert_equal (*i);
    }
    // DWA 980305 changed iterator to const_iterator, hh 980311 checked
    multiset (const_iterator first, const_iterator last, 
              const Compare& comp = Compare (), 
              const Allocator& alloc = Allocator ())
    : t (comp, alloc)
    {
        for (const_iterator i = first; i != last; ++i)
            t.insert_equal (*i);
    }
#endif

    multiset (const multiset<Key, Compare, Allocator>& x) 
    : t (x.t) {}

    multiset<Key, Compare, Allocator>& 
    operator= (const multiset<Key, Compare, Allocator>& x)
    { t = x.t; return *this; }

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

    // iterators:
    iterator                begin ()            { return t.begin (); }
    const_iterator          begin () const      { return t.begin (); }
    iterator                end ()              { return t.end ();   }
    const_iterator          end () const        { return t.end ();   }

    reverse_iterator        rbegin ()           { return t.rbegin (); } 
    const_reverse_iterator  rbegin () const     { return t.rbegin (); } 
    reverse_iterator        rend ()             { return t.rend (); }
    const_reverse_iterator  rend () const       { return t.rend (); }

    // capacity:
    bool             empty ()      const { return t.empty ();    }
    size_type        size ()       const { return t.size ();     }
    size_type        max_size ()   const { return t.max_size (); }

    // modifiers:
    iterator insert (const value_type& x)
    { return t.insert_equal (x); }

    iterator insert (iterator position, const value_type& x)
    { return t.insert_equal ((typename rep_type::iterator&)position, x); }

#ifdef MSIPL_MEMBER_TEMPLATE
    template <class InputIterator>
    void insert (InputIterator first, InputIterator last)
    {
        for (InputIterator i = first; i != last; ++i)
            t.insert_equal (*i);
    }
#else
    void insert (const value_type* first, const value_type* last)
    {
        for (const value_type* i = first; i != last; ++i)
            t.insert_equal (*i);
    }
    void insert (const_iterator first, const_iterator last)
    { 
        t.insert_equal (first, last); 
    }
#endif

    void erase (iterator position)
    { 
        t.erase ((typename rep_type::iterator&)position); 
    }
    size_type erase (const key_type& x)
    { 
        return t.erase (x); 
    }
    void erase (iterator first, iterator last)
    { 
        t.erase ((typename rep_type::iterator&)first, 
                 (typename rep_type::iterator&)last); 
    }

    void swap (multiset<Key, Compare, Allocator>& x) { t.swap (x.t); }

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

    // observers:
    key_compare      key_comp ()   const { return t.key_comp (); }
    value_compare    value_comp () const { return t.key_comp (); }

    // set operations:
    iterator           find (const key_type& x)        { return t.find (x);  }
    const_iterator     find (const key_type& x)  const { return t.find (x);  }
    size_type          count (const key_type& x) const { return t.count (x); }

    iterator lower_bound (const key_type& x)
    { return t.lower_bound (x); }
    const_iterator lower_bound (const key_type& x) const
    { return t.lower_bound (x); }
    iterator upper_bound (const key_type& x)
    { return t.upper_bound (x); }
    const_iterator upper_bound (const key_type& x) const
    { return t.upper_bound (x); }

    typedef  pair<iterator, iterator> pair_iterator_iterator; 
    typedef  pair<const_iterator, const_iterator> pair_citerator_citerator; 

    pair_iterator_iterator equal_range (const key_type& x)
    { return t.equal_range (x); }

    pair_citerator_citerator equal_range (const key_type& x) const
    { return t.equal_range (x); }
};

template <class Key, class Compare, class Allocator>
inline bool operator== (const multiset<Key, Compare, Allocator>& x, 
                        const multiset<Key, Compare, Allocator>& y)
{ return x.size () == y.size () &&
           equal (x.begin (), x.end (), y.begin ()); }

template <class Key, class Compare, class Allocator>
inline bool operator< (const multiset<Key, Compare, Allocator>& x, 
                       const multiset<Key, Compare, Allocator>& y)
{ return lexicographical_compare (x.begin (), x.end (), 
                                    y.begin (), y.end ()); }

template <class Key, class Compare, class Allocator>
inline bool operator!= (const multiset<Key, Compare, Allocator>& x, 
                        const multiset<Key, Compare, Allocator>& y)
{ return ! (x == y); }

template <class Key, class Compare, class Allocator>
inline bool operator<= (const multiset<Key, Compare, Allocator>& x, 
                       const multiset<Key, Compare, Allocator>& y)
{ return ! (y < x); }

template <class Key, class Compare, class Allocator>
inline bool operator>= (const multiset<Key, Compare, Allocator>& x, 
                        const multiset<Key, Compare, Allocator>& y)
{ return ! (x < y); }

template <class Key, class Compare, class Allocator>
inline bool operator> (const multiset<Key, Compare, Allocator>& x, 
                       const multiset<Key, Compare, Allocator>& y)
{ return (y < x); }

template <class Key, class Compare, class Allocator>
inline void swap (const multiset<Key, Compare, Allocator>& x, 
                  const multiset<Key, Compare, Allocator>& y)
{ x.swap (y); }

#ifdef MSIPL_USING_NAMESPACE
	} // namespace std
#endif

#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
	#pragma import reset
#endif
#pragma options align=reset

#endif // RC_INVOKED

#endif /* MSIPL_SET_H */

// hh 971220 fixed MOD_INCLUDE
// hh 971223 Changed filename from set.h to set
// hh 971223 Made include guards standard
// hh 971223 added alignment wrapper
// hh 971230 added RC_INVOKED wrapper
// DWA 980305 changed iterator to const_iterator in multiset constructor, hh 980311 checked
