#ifndef _ISTACK2_
  #define _ISTACK2_
/*******************************************************************************
*                                                                              *
* COPYRIGHT:                                                                   *
*   IBM Open Class Library                                                     *
*   (C) Copyright International Business Machines Corporation 1992, 1997       *
*   Licensed Material - Program-Property of IBM - All Rights Reserved.         *
*                                                                              *
*******************************************************************************/
// Note:  I had problems (Function overloading conflict) when trying to use
//        a vector to implement this class.  I resorted to a deque.

#include <ibase.hpp>

#ifdef IC_USE_STL

  #include <istdops2.h>

  #define __USE_MALLOC
  #ifdef _STACK_AS_VECTOR_
    #define STACK_CONTAINER vector
    #include <vector.h>
  #else
    #define STACK_CONTAINER deque
    #include <deque.h>
  #endif
  template <class Element, class Imp>
  class ITImpStack
  {
  public:
     ITImpStack ( unsigned long numberOfElements = 100);
    ~ITImpStack ();
     class Cursor
     {
     public:
       Cursor (const ITImpStack<Element, Imp>& aList)
         : fList((ITImpStack<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:
         ITImpStack<Element, Imp>
          &fList;

           STACK_CONTAINER<Imp>::iterator
             fIterator;

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

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

     bool
       addAsLast ( const Element& element)
              { fImp.push_back((const Imp&)element); return true;}

     bool
       allElementsDo   ( bool (*function) (Element&, void*),
                         void* additionalArgument = 0)
     {
       STACK_CONTAINER<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
        {
          STACK_CONTAINER<Imp>::const_iterator allIterator = fImp.begin();
          bool quit = false;
          while(allIterator != fImp.end() && quit == false)
          {
             quit = function((Element const&)*allIterator, additionalArgument);
             allIterator++;
          }
          return !quit;
        }

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


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

     const Element
      &firstElement       ( ) const
        { return (Element const&)fImp.front();  }

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

     const Element
      &lastElement       ( ) const
        { return (Element const&)fImp.back();  }

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

     void
       pop ( ) { fImp.pop_back(); }

     void
       push ( const Element& element) { fImp.push_back((const Imp&)element);}

     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)
       {
          STACK_CONTAINER<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;
       }

     Element const&
       top   ( ) const  {  return (Element const&)*fImp.begin(); }

    private:

    STACK_CONTAINER<Imp>
      fImp;

  unsigned long
    fNumberOfElements;
  friend class Cursor;
  };

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


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

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



#else // Not STL
  #include <istack.h>
  #define IVPtrStack IStack
#endif

#endif  // _ISTACK2_

