#ifndef _ISET2_
  #define _ISET2_
/*******************************************************************************
*                                                                              *
* COPYRIGHT:                                                                   *
*   IBM Open Class Library                                                     *
*   (C) Copyright International Business Machines Corporation 1992, 1997       *
*   Licensed Material - Program-Property of IBM - All Rights Reserved.         *
*                                                                              *
*******************************************************************************/
#include <ibase.hpp>

#ifdef IC_USE_STL
  // #define _MSC_VER 999

  #include <istdops2.h>

  #define __USE_MALLOC
  #include <set.h>
  template <class Element, class Imp>
  class ITImpSet
  {
  public:
     ITImpSet (unsigned long numberOfElements = 100);

    ~ITImpSet ();
     class Cursor
     {
     public:
       Cursor (const ITImpSet<Element, Imp>& aList)
         : fList((ITImpSet<Element, Imp>&)aList),
           fIterator(fList.fImp.begin()) {}

       Cursor ( const Cursor& cursor)
         : fList(cursor.fList),
           fIterator(cursor.fIterator) {}

       Cursor& operator=(const Cursor& cursor)
       {
          if(this != &cursor)
          {
             fList = cursor.fList;
             fIterator = cursor.fIterator;
          }
          return *this;
       }

       bool setToFirst ()    { fIterator = fList.fImp.begin(); return fList.fImp.empty();}
       bool setToLast ()     { fIterator = fList.fImp.end();   fIterator--;
                               return fList.fImp.empty();}
       bool setToNext ()     { fIterator++; return fList.fImp.empty();}
       bool setToPrevious () { fIterator--; return fList.fImp.empty();}
       bool isValid() const  { return (fList.fImp.begin()!=fList.fImp.end()
                                    && fIterator!=fList.fImp.end()); }
       void invalidate ( )
       {     fIterator = fList.fImp.end(); }

       Element const
        &element    ( ) const
            { return (Element const&)*fIterator;   }

       private:
         ITImpSet<Element, Imp>
          &fList;
         set<Imp, less<Imp> >::iterator
           fIterator;

        friend class ITImpSet<Element, Imp>;
     }; // Cursor



     bool
       add ( const Element& element)  { fImp.insert((const Imp&)element); return true;}

     bool
       allElementsDo   ( bool (*function) (Element&, void*),
                         void* additionalArgument = 0)
     {
       set<Imp, less<Imp> >::iterator allIterator = fImp.begin();
       bool quit = false;
       while(allIterator != fImp.end() && quit == false)
       {
          quit = function((Element&)*allIterator, additionalArgument);
          allIterator++;
       }
       return !quit;
     }

     bool
       allElementsDo   ( bool (*function) (Element const&, void*),
                         void* additionalArgument = 0) const
        {
          set<Imp, less<Imp> >::const_iterator allIterator = fImp.begin();
          bool quit = false;
          while(allIterator != fImp.end() && quit == false)
          {
             quit = function((Element const&)*allIterator, additionalArgument);
             allIterator++;
          }
          return !quit;
        }

     bool
       contains        ( const Element& element)
     {
        return (fImp.find((const Imp&)element) != fImp.end());
     }

     Element&
       elementAt   ( const Cursor& cursor)
        { return (Element &)*(cursor.fIterator); }

     Element const&
       elementAt   ( const Cursor& cursor) const
        { return (Element const&)*(cursor.fIterator); }

     bool
       isEmpty ( ) const { return (fImp.size() == 0); }

     const Element&
       lastElement       ( ) const
       {
         set<Imp, less<Imp> >::const_iterator lastIterator = fImp.end();
         lastIterator--;
         return (Element const&)*lastIterator;
       }

     unsigned long
       numberOfElements ( ) const { return fImp.size(); }

     bool
       remove ( const Element& element)
       {
          set<Imp, less<Imp> >::iterator elementIterator =
                                        fImp.find((const Imp&)element);
          bool found = (elementIterator != fImp.end());
          if(found)
             fImp.erase(elementIterator);
          return found;
       }

     unsigned long
       removeAll ( )
       {
         unsigned long count = fImp.size();
         fImp.erase(fImp.begin(), fImp.end());
         return count;
       }

     unsigned long
       removeAll ( bool (*predicateFunction)(Element const&, void*), void* data=0)
       {
          set<Imp, less<Imp> >::iterator posIterator = fImp.begin();
          unsigned long count = 0;
          while(posIterator != fImp.end())
          {
             if(predicateFunction((Element const&)*posIterator, data))
             {
               fImp.erase(posIterator);
               count++;
             }
             posIterator++;
          }
          return count;
       }

     void
       removeAt ( Cursor& cursor) { fImp.erase( cursor.fIterator++); }

     void
       replaceAt ( const Cursor& cursor, const Element& element)
       {
          // Note: The key determines the location of the new element in 
          // the set.  Here we remove the element at the cursor,
          // add the passed element, and leave the cursor where it was. 
          fImp.erase( cursor.fIterator);
          fImp.insert((const Imp&)element);
       } 



     void
       removeLast ( )
       {
         set<Imp, less<Imp> >::iterator lastIterator = fImp.end();
         lastIterator--;
         if(lastIterator != fImp.begin())
            fImp.erase(lastIterator);
         return;
       }

  private:
  set<Imp, less<Imp> >
    fImp;
  unsigned long
    fNumberOfElements;
  friend class Cursor;
};

template <class Element>
  class ISet : public ITImpSet<Element, Element>
{
  public:
  ISet( unsigned long numberOfElements = 100);
 ~ISet();
};


#ifdef IC_USE_STL_VPTR
  template <class Element>
  class IVPtrSet : public ITImpSet<Element, void*>
  {
    public:
    IVPtrSet( unsigned long numberOfElements = 100);
   ~IVPtrSet();
  };
#else
  #define IVPtrSet ISet
#endif


#ifndef __TEMPINC__
  #include <iset2.c>
#endif

#else // Not STL
  #include <iset.h>
  #define IVPtrSet ISet
#endif

#endif  // _ISET2_

