|
// Written by Oz Ben Eliezer
// o_be@hotmail.com
// September, 2000
#ifndef __BUFFER_H__ // Sentinels
#define __BUFFER_H__
#include <windows.h>
#include <stdio.h>
#include "general.h"
extern int BASE_BUFFER_SIZE;
extern int BASE_BUFFER_INC;
class CAutoBuffer
{
protected:
char *buffer; // Yeah, this is our buffer
int nLength; // Current length of data
int nSize; // Current size of buffer
int nIncrement; // By how much we should increment
// when buffer is too small
CRITICAL_SECTION csInUse; // Make it thread safe
/*
__forceinline is a Microsoft-specific keyword, which forces the
compiler into inlining the code. In practice, the compiler can still
deny in inlining, but it will produce a warning. In order to create
a non-thread-safe version of this class, just inherit from it, and
override the XXXInUse functions, to do nothing.
*/
__forceinline void EnterInUse()
{
EnterCriticalSection(&csInUse);
}
__forceinline void LeaveInUse()
{
LeaveCriticalSection(&csInUse);
}
__forceinline void InitializeInUse()
{
InitializeCriticalSection(&csInUse);
}
__forceinline void DeleteInUse()
{
DeleteCriticalSection(&csInUse);
}
/*
The IncreaseSize(..) function re-allocates memory space for the
buffer and copies its current contents into the new memory space.
*/
__forceinline void IncreaseSize(int nIncrement_)
{
char *newbuf;
EnterInUse();
newbuf = new char [nSize + nIncrement_];
memcpy(newbuf, buffer, nSize);
delete [] buffer;
buffer = newbuf;
nSize += nIncrement_;
LeaveInUse();
}
__forceinline void IncreaseSize()
{
IncreaseSize(nIncrement);
}
public:
CAutoBuffer(int nIncrement_) : buffer(NULL),
nLength(0),
nIncrement(nIncrement_)
{
InitializeInUse();
buffer = new char [BASE_BUFFER_SIZE]; // Allocate memory
nSize = BASE_BUFFER_SIZE;
}
~CAutoBuffer()
{
DeleteInUse();
if (buffer)
delete [] buffer; // De-allocate memory
}
/*
I assume that memory can be allocated, and that the new keyword
never returns NULL. I didn't embed error-detection in order to
enhance performance. If there is not enough memory to be allocated,
something is terribly wrong.
Furthermore, no internal memory checks are performed inside the
functions.
*/
/*
AddToBuffer(..) adds data from a source buffer to the class' buffer.
src: the source buffer
len: the source buffer's size
*/
__forceinline void AddToBuffer(const char *src, int len)
{
if (len > 0)
{
if (len + nLength > nSize)
IncreaseSize(BASE_BUFFER_INC > len ? BASE_BUFFER_INC : len);
EnterInUse();
memcpy(buffer + nLength, src, len);
nLength += len;
LeaveInUse();
}
}
/*
AddToBufferBeg(..) adds data from a source buffer to the beginning
of the class' buffer.
*/
__forceinline void AddToBufferBeg(const char *src, int len)
{
if (len + nLength > nSize)
IncreaseSize(len);
EnterInUse();
memmove(buffer + len, buffer, nLength);
memcpy(buffer, src, len);
nLength += len;
LeaveInUse();
}
/*
GetBuffer(..) copies data from the class' buffer to a destination
buffer. dst is a pointer to the destination buffer. len is a pointer
to an integer that specifies the size of dst. The value to which len
points is changes by the function, to reflect the number of bytes
transferred from the class' buffer to the destination buffer.
*/
__forceinline void GetBuffer(char *dst, int *len)
{
if (nLength > *len)
{ // Supplied buffer is not large enough.
GetFromBuffer(dst, len);
}
else
{
EnterInUse();
memcpy(dst, buffer, nLength);
*len = nLength;
nLength = 0; // Clear buffer;
LeaveInUse();
}
}
__forceinline void GetFromBuffer(char *dst, int *len)
{
if (*len > nLength)
{
GetBuffer(dst, len);
return;
}
else if (*len != 0)
{
EnterInUse();
memcpy(dst, buffer, *len);
memmove(buffer, buffer + *len, nLength - *len);
nLength -= *len;
LeaveInUse();
}
}
__forceinline char *GetBuffer()
{
return buffer;
}
__forceinline bool IsEmpty()
{
return (nLength == 0);
}
__forceinline bool GetPacket(tagPacket *p)
{
bool bRet = false; // Assume that no packet is available.
EnterInUse();
if (nLength >= 4) // Received size description
{
memcpy(p, buffer, 4); // Size
// See if enough data has arrived
if ((unsigned)p->nLength <= (unsigned int)(nLength - 4))
{
// Packet is available. Copy data into packet.
// Allocate memory for packet's buffer.
p->buffer = new char [p->nLength];
memcpy(p->buffer, buffer + 4, p->nLength);
memmove(buffer, buffer + 4 + p->nLength, nLength - p->nLength - 4);
///////////////// FIXED - memmove moves nLength - p->nLength - 4 bytes, instead of
///////////////// nLength - p->nLength
nLength -= p->nLength;
nLength -= 4;
bRet = true;
}
}
LeaveInUse();
return bRet;
}
};
#endif
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.