/*----------------------------------------------------------------------*
 * GIO.C  Generic I/O Speed Up Package                        01/06/86
 * See GIOCall.C for an example of usage.
 * Read not speeded-up yet.  Only one Write file buffered at a time.
 * Note: The speed-up provided is ONLY significant for code such as IFF
 * which does numerous small Writes and Seeks.
 *----------------------------------------------------------------------*/
#include "gio.h"   /* See comments here for explanation.*/
 
#if GIO_ACTIVE
 
#define local static
 
 
local BPTR wFile = NULL;
local BYTE *wBuffer = NULL;
local LONG wNBytes=0;    /* buffer size in bytes.*/
local LONG wIndex=0;    /* index of next available byte.*/
local LONG wWaterline=0; /* Count of # bytes to be written.
           * Different than wIndex because of GSeek.*/
 
/*----------- GOpen ----------------------------------------------------*/
int GOpen(filename, openmode)
 char *filename;
 int openmode;
 {
    return( Open(filename, openmode) );
 }
 
/*----------- GClose ---------------------------------------------------*/
int GClose(file)
 BPTR file;
 {
    int signal = 0, signal2;
    if (file == wFile)
      signal = GWriteDeclare(NULL, NULL, 0);
    signal2 = Close(file);   /* Call Close even if trouble with write.*/
    if (signal2 < 0)
      signal = signal2;
    return( signal );
 }
 
/*----------- GRead ----------------------------------------------------*/
int GRead(file, buffer, nBytes)
 BPTR file;
 BYTE *buffer;
 int nBytes;
 {
    int signal = 0;
    /* We don't yet read directly from the buffer, so flush it to disk and
     * let the DOS fetch it back. */
    if (file == wFile)
       signal = GWriteFlush(file);
    if (signal >= 0)
       signal = Read(file, buffer, nBytes);
    return( signal );
 }
 
/* ---------- GWriteFlush ----------------------------------------------*/
int GWriteFlush(file)
 BPTR file;
 {
    int gWrite = 0;
    if (wFile != NULL  &&  wBuffer != NULL  &&  wIndex > 0L)
       gWrite = Write(wFile, wBuffer, wWaterline);
    wWaterline = wIndex = 0;   /* No matter what, make sure this happens.*/
    return( gWrite );
 }
 
/* ---------- GWriteDeclare --------------------------------------------*/
int GWriteDeclare(file, buffer, nBytes)
    BPTR file;
    BYTE *buffer;
    LONG nBytes;
    {
       int gWrite = GWriteFlush(wFile);  /* Finish any existing usage.*/
       if ( file==NULL  ||  buffer==NULL  ||  nBytes<=3) {
         wFile = NULL;   wBuffer = NULL;     wNBytes = 0;
       }
       else
       {
         wFile = file;   wBuffer = buffer;   wNBytes = nBytes;
       }
       return( gWrite );
    }
 
/* ---------- GWrite ---------------------------------------------------*/
int GWrite(file, buffer, nBytes)
 BPTR file;
 BYTE *buffer;
 int nBytes;
 {
    int gWrite = 0;
    if (file == wFile  &&  wBuffer != NULL) {
       if (wNBytes >= wIndex + nBytes) {
         /* Append to wBuffer.*/
         movmem(buffer, wBuffer+wIndex, nBytes);
         wIndex += nBytes;
         if (wIndex > wWaterline)
           wWaterline = wIndex;
         nBytes = 0;      /* Indicate data has been swallowed.*/
       }
       else {
         wWaterline = wIndex;     /* We are about to overwrite any
         * data above wIndex, up to at least the buffer end.*/
       gWrite = GWriteFlush(file);  /* Write data out in proper order.*/
       }
   }
    if (nBytes > 0  &&  gWrite >= 0)
       gWrite += Write(file, buffer, nBytes);
    return( gWrite );
 }
 
/* ---------- GSeek ----------------------------------------------------*/
int GSeek(file, position, mode)
 BPTR file;
 int position;
 int mode;
 {
    int gSeek = -2;
    int newWIndex = wIndex + position;
 
    if (file == wFile  &&  wBuffer != NULL) {
       if (mode == OFFSET_CURRENT  &&
         newWIndex >= 0  &&  newWIndex <= wWaterline) {
         wIndex = newWIndex;
         gSeek = 0;      /* Okay */
       }
       else {
       /* Can't optimize it.*/
       gSeek = GWriteFlush(file);
       if (gSeek >= 0)   gSeek = -2;  /* OK so far */
       }
   }
   if (gSeek == -2)
      gSeek = Seek(file, position, mode);
   return( gSeek );
 }
 
#endif GIO_ACTIVE
