www.pudn.com > using IOCP.zip > buffer.h
// Written by Oz Ben Eliezer // o_be@hotmail.com // September, 2000 #ifndef __BUFFER_H__ // Sentinels #define __BUFFER_H__ #include#include #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