#ifndef _IQUEUE2_
  #define _IQUEUE2_
/*******************************************************************************
*                                                                              *
* 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

  #include <istdops2.h>

  #define __USE_MALLOC
  #include <deque.h>
  template <class Element, class Imp>
  class ITImpQueue
  {
  public:
     ITImpQueue ( unsigned long numberOfElements = 100);
    ~ITImpQueue ();
     class Cursor
     {
     public:
       Cursor (const ITImpQueue<Element, Imp>& aList)
         : fList((ITImpQueue<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:
         ITImpQueue<Element, Imp>
          &fList;
         deque<Imp>::iterator
           fIterator;
        friend class ITImpQueue<Element, Imp>;
     }; // Cursor



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

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

     void
       dequeue ( ) { fImp.pop_front(); }

     void
       dequeue ( Element& elem ) { elem = (Element&)(*(fImp.begin())); fImp.pop_front(); }

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

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

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

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

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

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

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

     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)
       {
          deque<Imp>::iterator posIterator = fImp.begin();
          unsigned long count = 0;
          while(posIterator != fImp.end())
          {
             if(predicateFunction((Element&)*posIterator, data))
             {
               fImp.erase(posIterator);
               count++;
             }
             posIterator++;
          }
          return count;
       }

     void
       removeFirst ( )
       {
         fImp.erase(fImp.begin());
       }

     void
       removeLast ( )
       {
          deque<Imp>::iterator posIterator = fImp.end();
          posIterator--;
          if(posIterator!=fImp.begin())
             fImp.erase(posIterator);
       }


    private:
  deque<Imp>
    fImp;
  unsigned long
    fNumberOfElements;
  friend class Cursor;
  };

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


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

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



#else // Not STL
  #include <iqueue.h>
  #define IVPtrQueue IQueue
#endif

#endif  // _IQUEUE2_

