Subversion Repositories shark

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

/*
 * Copyright 1995, Brown University, Providence, RI
 *
 * Permission to use and modify this software and its documentation for
 * any purpose other than its incorporation into a commercial product is
 * hereby granted without fee.  Permission to copy and distribute this
 * software and its documentation only for non-commercial use is also
 * granted without fee, provided, however, that the above copyright notice
 * appear in all copies, that both that copyright notice and this permission
 * notice appear in supporting documentation, that the name of Brown
 * University not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission,
 * and that the person doing the distribution notify Brown University of
 * such distributions outside of his or her organization. Brown University
 * makes no representations about the suitability of this software for
 * any purpose.  It is provided "as is" without express or implied warranty.
 * Brown University requests notification of any modifications to this
 * software or its documentation.
 *
 * Send the following redistribution information:
 *
 *      Name:
 *      Organization:
 *      Address (postal and/or electronic):
 *
 * To:
 *      Software Librarian
 *      Computer Science Department, Box 1910
 *      Brown University
 *      Providence, RI 02912
 *
 *              or
 *
 *      brusd@cs.brown.edu
 *
 * We will acknowledge all electronic notifications.
 */


#include "buffer.H"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

long BUFFER::totalAllocated=0;

// Constructor
//     Default:  bytesGet=4, bytesSave=3, stepSize=25
//
BUFFER::BUFFER(int itemSize, int bytesGet, int bytesSave,int stepSize)
:
     _size(0),
     bufferSize(stepSize),
     location(0),
     firstRetrieve(1),
     _bytesGet(bytesGet),
     _bytesSave(bytesSave),
     _stepSize(stepSize),
     sizeGet(itemSize),
     sizeSave(itemSize),
     tmpBlock(NULL)
{
        buffer=new char*[stepSize];
        if (!buffer) {
                // Should not die, but return a result code...
                bufferSize=0;
                return;
        }

        // Should add checking for bytesSave, bytesGet
        // only supported value for bytesGet [4]
        // only supported value for bytesSave [3,4]

        //Initialize pointers to buffer blocks
        for (int i=0;i<stepSize;i++) {
                buffer[i]=NULL;
        }

        //If we are trying to compress
        if (bytesGet!=bytesSave) {
                sizeSave=sizeGet/bytesGet*bytesSave;
                tmpBlock=(char *) malloc(sizeGet);
        }
}

// Destructor
//
//
BUFFER::~BUFFER()
{
        if (tmpBlock) free(tmpBlock);
        for (int i=0;i<_size;i++) {
           free(buffer[i]);
        }
        delete [] buffer;
}

// addToBuffer
//    buffer an item, compressing if need be
//
int
BUFFER::addToBuffer(void *item)
{
        // Enlarge the buffer if need be
        if (_size>=bufferSize) {
           int oldSize=bufferSize;
           bufferSize+=_stepSize;
           char **tmpBuffer=buffer;
           buffer=(char **) realloc(buffer,sizeof(char *)*bufferSize);
           if (!buffer) {
               //can't get more memory
               //set buffer to point to old buffer;
               buffer=tmpBuffer;
               bufferSize=oldSize;
               return 0;
           }
           for (int i=oldSize;i<bufferSize;i++) {
               buffer[i]=NULL;
           }
        }
        if ( !(buffer[_size]=(char *)malloc(sizeGet)) ) {
               //can't get more memory
               return 0;
        }
        if (sizeGet==sizeSave) {
           // No compressing, straight copy
           memcpy(buffer[_size],item,sizeGet);
        } else {
           // Compressing, copy 3 out of 4 bytes
           char *ptrTo, *ptrFrom;
           int x;
           for (ptrTo=buffer[_size],ptrFrom=(char *) item,x=0;
                x<sizeGet;
                ptrFrom+=_bytesGet,ptrTo+=_bytesSave,x+=_bytesGet) {
                *(ptrTo+0)=*(ptrFrom+3);
                *(ptrTo+1)=*(ptrFrom+2);
                *(ptrTo+2)=*(ptrFrom+1);
           }
        }
        _size++;
        return 1;
}

const char * const BUFFER::nextBufferItem(int *looped)
{
        int tmpLoc=location;

        // If first time we are retrieving
        if (firstRetrieve) {
           // shrink buffer array down to size
           char **oldLoc=buffer;
           buffer=(char **) realloc(buffer,sizeof(char*)*_size);  
           if (!buffer) {
                //since we are shortening the size of a memory block
                //  we shouldn't get here...
                buffer=oldLoc;
           }
           firstRetrieve=0;
           long allocated=sizeSave * _size;

           printf("Data allocated for buffer: %d (%dk)\n",
              allocated, (int) allocated/1024);
           totalAllocated+=allocated;
           printf("Running total: %d (%dk)\n",
              totalAllocated, (int) totalAllocated/1024);
        }

        location++;

        //Tell the caller if we have looped around
        if (looped) {
                *looped  =(location==_size);
        }

        location %= _size;
        if (_bytesGet==_bytesSave) {
           // No compressing, straight return
           return buffer[tmpLoc];
        } else {
           // Compressing, copy 3 out of 4 bytes
           char *ptrTo, *ptrFrom;
           int x;
           for (ptrTo=tmpBlock,ptrFrom=buffer[tmpLoc],x=0;
                x<sizeGet;ptrFrom+=_bytesSave,ptrTo+=_bytesGet,x+=_bytesGet) {
                *(ptrTo+3)=*(ptrFrom+0);
                *(ptrTo+2)=*(ptrFrom+1);
                *(ptrTo+1)=*(ptrFrom+2);
           }
           return tmpBlock;
        }
}