/*-----------------------------------------------------------------------
   Implementation file for a circular buffer facility.

   Mark Koennecke, October 1999
-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include "fortify.h"
#include "circular.h"

/*========================================================================
        Definitions of Structures 
*/

  typedef struct __CircularItem {
                                   void *pData;
                                   struct __CircularItem *next;
                                   struct __CircularItem *previous;
                                 }CircularItem, *pCircularItem;


  typedef struct __CIRCULAR {
                             pCircularItem pPointer;
                             CirKillFunc      killer;
                            }Circular;

/*=========================================================================
   Functions for Birth and Death
*/
  pCircular createCircular(int iSize, CirKillFunc kf)
  {
     pCircular pNew = NULL;
     pCircularItem pItem = NULL, pFirst = NULL;
     int i;
 
    
     assert(iSize > 0);

     /* create data structure */
     pNew = (pCircular)malloc(sizeof(Circular));
     if(!pNew)
       return NULL;
     memset(pNew,0,sizeof(Circular));

     /* create all the members of the circular buffer */
     pItem = (pCircularItem)malloc(sizeof(CircularItem));
     if(!pItem)
        return NULL;
     memset(pItem,0,sizeof(CircularItem));
     pNew->pPointer = pItem;
     pFirst = pItem;
     for(i = 1; i < iSize; i++)
     {
        pItem = (pCircularItem)malloc(sizeof(CircularItem));
        if(!pItem)
           return NULL;
        memset(pItem,0,sizeof(CircularItem));
        pItem->previous = pNew->pPointer;
        pNew->pPointer->next = pItem;
        pNew->pPointer = pItem;
     }
     pItem->next = pFirst;
     pFirst->previous = pItem;
     pNew->killer = kf;
     return pNew;    
  }
/*---------------------------------------------------------------------*/
  void deleteCircular(pCircular self)
  {
     pCircularItem pNext = NULL, pCurrent = NULL;

     assert(self);

     self->pPointer->previous->next = NULL;
     pNext = self->pPointer;
     while(pNext != NULL)
     {
        pCurrent = pNext;
        pNext = pCurrent->next;
        if(pCurrent->pData && self->killer)
	{
            self->killer(pCurrent->pData);
        }
        free(pCurrent);
     }    
     free(self);
  } 
/*========================================================================
    Data Manipulation functions
*/
  void setCircular(pCircular self, void *pData)
  {
      assert(self);

      /* delete if present */
      if(self->pPointer->pData && self->killer)
      {
         self->killer(self->pPointer->pData);
      }
      self->pPointer->pData = pData;
  }
/*----------------------------------------------------------------------*/
  void *getCircular(pCircular self)
  {
     assert(self);
     return self->pPointer->pData;
  }
/*========================================================================
  Pointer movement 
*/
  void nextCircular(pCircular self)
  {
     assert(self);
     self->pPointer = self->pPointer->next;
  }
/*---------------------------------------------------------------------*/
  void previousCircular(pCircular self)
  {
     assert(self);
     self->pPointer = self->pPointer->previous;
  }

