📄 databuffer.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// DataBuffer.cpp: implementation of the DataBuffer class.
//
// DataBuffer is a simple circular dynamical databuffer that wraps around and
// may dynamically expand its size
//
//////////////////////////////////////////////////////////////////////
#include <windows.h>
#include "DataBuffer.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//We initialize the size to two bytes more than asked for to
//allow the readposition to never reach the writeposition
DataBuffer::DataBuffer(DWORD initialsize)
{
mBuffer = new BYTE[initialsize+2];
mTotalSize=initialsize +2;
Flush();
}
DataBuffer::~DataBuffer()
{
delete[] mBuffer;
}
//Assignment operator
DataBuffer &
DataBuffer::operator=(DataBuffer &rhs)
{
BOOL fRet = TRUE;
if(&rhs==this) return *this;
DWORD size = rhs.DataAvailable();
if(mTotalSize < size) {
fRet = IncreaseBuffer(size - mTotalSize);
}
if (! fRet) {
DEBUGMSG(1, (L"WCESTREAMBT - Can't write data due to OOM.\n"));
return *this;
}
BYTE *buf = new BYTE[size];
rhs.ReadData(buf,size);
WriteData(buf,size);
delete[] buf;
return *this;
}
//DataAvailable: return the amount of data currently stored
DWORD
DataBuffer::DataAvailable()
{
return GetContentSize();
}
//WriteData: Store the requested data in our buffer. Increase buffer if needed.
// Wrap around if needed.
void
DataBuffer::WriteData(BYTE *buf, DWORD size)
{
BOOL fRet = TRUE;
if(size > GetEmptySpace()) {
fRet = IncreaseBuffer(size);
}
if (! fRet) {
DEBUGMSG(1, (L"WCESTREAMBT - Can't write data due to OOM.\n"));
return;
}
//Now we know there is space
if(mWritePos + size > mTotalSize)//we will wrap around
{
DWORD firstpart = mTotalSize - mWritePos;
DWORD secondpart = size - firstpart;
memcpy(mBuffer + mWritePos,buf,firstpart);
memcpy(mBuffer,buf + firstpart,secondpart);
mWritePos = secondpart;
}
else//we won't wrap around
{
memcpy(mBuffer + mWritePos,buf,size);
mWritePos = mWritePos + size;
}
}
//ReadData: Read the requested amount of data from our buffer. Correct the read-position
//afterwards
DWORD
DataBuffer::ReadData(BYTE *buf, DWORD size)
{
DWORD thisread=0;
if(GetContentSize() >= size) thisread = size;
else thisread = GetContentSize();
if(thisread + mReadPos > mTotalSize)// we will wrap around
{
DWORD firstpart = mTotalSize - mReadPos;
DWORD secondpart = thisread - firstpart;
memcpy(buf,mBuffer + mReadPos,firstpart);
memcpy(buf + firstpart,mBuffer,secondpart);
mReadPos = secondpart;
}
else//we won't wrap around
{
memcpy(buf,mBuffer + mReadPos,thisread);
mReadPos = mReadPos + thisread;
}
return thisread;
}
//Read in data into the passed in DataBuffer.
DWORD
DataBuffer::ReadData(DataBuffer *db,DWORD size)
{
DWORD thisread=0;
if(GetContentSize() >= size) thisread = size;
else thisread = GetContentSize();
BYTE *temp = new BYTE[thisread];
ReadData(temp,thisread);
db->WriteData(temp,thisread);
delete[] temp;
return thisread;
}
//Drop this amount of data
void
DataBuffer::DropData(DWORD size)
{
DWORD thisread=0;
if(GetContentSize() >= size) thisread = size;
else thisread = GetContentSize();
if(thisread + mReadPos > mTotalSize)// we will wrap around
{
DWORD firstpart = mTotalSize - mReadPos;
DWORD secondpart = thisread - firstpart;
mReadPos = secondpart;
}
else//we won't wrap around
{
mReadPos = mReadPos + thisread;
}
}
//Reset the write- and read-positions to zero.
void
DataBuffer::Flush()
{
mWritePos=0;
mReadPos=0;
}
//////////////////////////////////////////////////////
// Internal helper methods
///////////////////////////////////////////////////////
//IncreaseBuffer: Increase the buffersize with the requested amount
//and copy existing data into the new buffer
BOOL
DataBuffer::IncreaseBuffer(DWORD size)
{
BYTE *temp = mBuffer;
DWORD currentcontent = GetContentSize();
mBuffer = new BYTE[mTotalSize + size];
if (! mBuffer)
{
mBuffer = temp; // assign back to old value
DEBUGMSG(1, (L"WCESTREAMBT - OOM!\n"));
return FALSE;
}
//Copy the content to the new buffer
if(mWritePos >= mReadPos)//No wrap around
{
memcpy(mBuffer,temp + mReadPos,currentcontent);
}
else//wrap around
{
DWORD firstpart = mTotalSize - mReadPos;
DWORD secondpart = mWritePos;
memcpy(mBuffer,temp + mReadPos,firstpart);
memcpy(mBuffer + firstpart,temp,secondpart);
}
//Update sizes and pointers
mTotalSize = mTotalSize + size;
mReadPos = 0;
mWritePos = currentcontent;
delete[] temp;
return TRUE;
}
//GetContentSize: return the amount of data available
DWORD
DataBuffer::GetContentSize()
{
if(mWritePos>=mReadPos)//No wrap around
{
return mWritePos - mReadPos;
}
else
{
return mTotalSize + mWritePos - mReadPos;
}
}
//GetEmptySpace: Return the amount of free space in the buffer
DWORD
DataBuffer::GetEmptySpace()
{
return mTotalSize - GetContentSize() -2;//We always leave two empty bytes
}
//Peek into position pos in the data
BYTE
DataBuffer::Peek(DWORD pos)
{
if(mReadPos + pos < mTotalSize) return mBuffer[mReadPos + pos];
else return mBuffer[mReadPos + pos - mTotalSize];
}
//Return a pointer to the data at position pos. N.B: NOT THREAD SAFE!
//validbytes indicates how many bytes the caller wishes to look at. If our
//buffer wraps around before we need to reshuffle data
BYTE *
DataBuffer::c_ptr(DWORD pos, DWORD validbytes)
{
if(validbytes + mReadPos + pos > mTotalSize) ResetBuffer();
return mBuffer + mReadPos + pos;
}
//Move all data to start of buffer (no wrap)
void
DataBuffer::ResetBuffer()
{
DWORD size = DataAvailable();
BYTE *temp = new BYTE[size];
if (temp)
{
ReadData(temp,size);
memcpy(mBuffer,temp,size);
mReadPos = 0;
mWritePos = size;
delete[] temp;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -