// File: genq.C
//
// Implementation of generic queue class

#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>
#include "genq.h"


//========================================================================
// Local function prototypes
//
static void CrashOnNULL(void *, char *) ;


// Local function definitions
//
static void CrashOnNULL(void * ptr, char *mesg) {
   if (ptr == NULL) {
      cerr << mesg << endl ;
      exit(1) ;
   }
}


//========================================================================
// Definition of GenQ member functions
//


// Constructor. There are no default constructors, because we must
// have the client supplied comparison and print functions.
//
GenQ::GenQ(GQcmp cmp_func, GQprt prt_func) {

   last = &dummy ;
   len  = 0 ;
   cmp  = cmp_func ;
   prnt = prt_func ;
}


// Destructor. Loop through list and delete each cell.
//
GenQ::~GenQ() {
   QCell *ptr, *temp ;

   ptr = dummy.next ;
   while (ptr != NULL) {
      temp = ptr->next ;
      delete ptr->data ;
      delete ptr ;
      ptr = temp ;
   }
}


// Add new item to the end of the list
//
void GenQ::enqueue(void * data) {
   QCell *newitem ;

   newitem = new QCell ;
   CrashOnNULL(newitem, "Out of memory in enqueue()") ;

   newitem->data = data ;
   last->next = newitem ;
   last = newitem ;
   len++ ;
}


// Remove item from the front of the list
//
void * GenQ::dequeue() {
   QCell *ptr ;
   void *result ;

   if (dummy.next == NULL)  return NULL ;

   ptr = dummy.next ;
   dummy.next = ptr->next ;

   // check if last item is removed
   //
   if (dummy.next == NULL) last = &dummy ;
   len-- ;

   result = ptr->data ;
   delete ptr ;

   return result ;
}


// Return data stored in item at the front.
// Does not alter the queue.
//
void * GenQ::peek() {

   if (dummy.next == NULL) return NULL ;

   return dummy.next->data ;
}


// Loop through the list and print each item using the
// client supplied print routine
//
void GenQ::print() {
   QCell *ptr ;

   ptr = dummy.next ;
   while (ptr != NULL) {
      prnt(ptr->data) ;
      ptr = ptr->next ;
   }
}


// Remove every occurrence of an item from the list.
// Items are compared using the client supplied comparsion function.
// The comparison function should return values similar to strcmp(a,b):
//   <0 if a < b.
//   =0 if a == b
//   >0 if a > b
//
void GenQ::remove(void *item) {
   QCell *ptr, *temp ;

   ptr = &dummy ;

   while (ptr->next != NULL) {
      if (cmp(ptr->next->data, item) == 0) {
         temp = ptr->next ;
         ptr->next = temp->next ;
         delete temp->data ;
         delete temp ;
         len-- ;
      } else {
         ptr = ptr->next ;
      }
   }

   if (len == 0) last = &dummy ;
}
