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
;
}
}