#include "afxtempl.h"
#include "GDIInclude.h"
// 【注意事项】
// 1, bool会和CString类型混淆,所以不支持bool,建议使用byte类型或者int类型代替
class DataStream
{
public:
DataStream();
DataStream(size_t mallocMemSize);
DataStream(const DataStream& copySrc);
virtual ~DataStream();
DataStream(byte* pBuffer, size_t bufferLength, size_t mallocMemSize = -1);
void Attach(byte* pDestBuffer, size_t destBufferLen);
void Detach();
void Reset(size_t mallocMemSize);
void SeekReadToBegin();
void SeekWriteToBegin();
bool CanRead(int dataLen);
byte* GetData(size_t startIndex = 0);
size_t GetDataLength();
size_t MakeSureCanWriteByIncreaseMemorySpace(size_t byteCountToWrite);
BOOL Open(CString strFilePath); //从文件获取Data
void Save(CString strFilePath); //把Data保存为文件
// short数组
DataStream& Write(IN short* val, IN UINT count);
DataStream& Read(OUT short** val, OUT UINT* count);
DataStream& Write(IN byte* val, IN UINT count);
DataStream& Read(OUT byte** val, OUT UINT* count);
DataStream& Write(IN char* val, IN UINT count);
DataStream& Read(OUT char** val, OUT UINT* count);
DataStream& AddFile(CString strSrcPath); //把文件添加到Data
DataStream& GetFile(CString& strSavePath); //从Data中获取文件并保存
DataStream& operator << (DataStream& val);
DataStream& operator >> (DataStream& val);
DataStream& operator << (CArray<int, int>& val);
DataStream& operator >> (CArray<int, int>& val);
DataStream& operator << (CStringArray& val);
DataStream& operator >> (CStringArray& val);
DataStream& operator << (CString val);
DataStream& operator >> (CString& val);
DataStream& operator << (int val);
DataStream& operator >> (int& val);
DataStream& operator << (UINT val);
DataStream& operator >> (UINT& val);
DataStream& operator << (long val);
DataStream& operator >> (long& val);
DataStream& operator << (DWORD val);
DataStream& operator >> (DWORD& val);
DataStream& operator << (byte val);
DataStream& operator >> (byte& val);
DataStream& operator << (char val);
DataStream& operator >> (char& val);
DataStream& operator << (WCHAR val);
DataStream& operator >> (WCHAR& val);
DataStream& operator << (short val);
DataStream& operator >> (short& val);
DataStream& operator << (float val);
DataStream& operator >> (float& val);
DataStream& operator << (CRect val);
DataStream& operator >> (CRect& val);
DataStream& operator << (Rect val);
DataStream& operator >> (Rect& val);
DataStream& operator << (RectF val);
DataStream& operator >> (RectF& val);
DataStream& operator << (CPoint val);
DataStream& operator >> (CPoint& val);
DataStream& operator << (Point val);
DataStream& operator >> (Point& val);
DataStream& operator << (PointF val);
DataStream& operator >> (PointF& val);
DataStream& operator << (Image* val);
DataStream& operator >> (Image** val);
DataStream& operator << (Font* val);
DataStream& operator >> (Font** val);
DataStream& operator << (Matrix* val);
DataStream& operator >> (Matrix** val);
DataStream& operator << (Color val);
DataStream& operator >> (Color &val);
private:
byte* m_pData;
size_t m_mallocMemSize;
size_t m_currWritePos;
size_t m_currReadPos;
};
#include "stdafx.h"
#include "datastream.h"
#include "String.h"
#include "PublicFunctions.h"
DataStream::DataStream()
{
m_pData = NULL;
m_mallocMemSize = 0;
m_currWritePos = 0;
m_currReadPos = 0;
}
DataStream::DataStream(size_t mallocMemSize)
{
m_pData = NULL;
Reset(mallocMemSize);
}
DataStream::DataStream(const DataStream& copySrc)
{
m_pData = new byte[copySrc.m_mallocMemSize];
m_mallocMemSize = copySrc.m_mallocMemSize;
m_currWritePos = copySrc.m_currWritePos;
m_currReadPos = copySrc.m_currReadPos;
memcpy(m_pData, copySrc.m_pData, copySrc.m_mallocMemSize);
}
void DataStream::Reset(size_t mallocMemSize)
{
SAFE_RELEASE(m_pData);
m_pData = new byte[(size_t)mallocMemSize];
m_mallocMemSize = mallocMemSize;
m_currWritePos = 0;
m_currReadPos = 0;
}
DataStream::~DataStream()
{
SAFE_RELEASE(m_pData);
m_mallocMemSize = 0;
m_currWritePos = 0;
m_currReadPos = 0;
}
DataStream::DataStream(byte* pBuffer, size_t bufferLength, size_t mallocMemSize)
{
if (mallocMemSize == -1)
mallocMemSize = bufferLength;
m_pData = NULL;
Reset(mallocMemSize);
memcpy(m_pData, pBuffer, bufferLength);
m_currWritePos = bufferLength;
m_currReadPos = 0;
}
void DataStream::Attach(byte* pDestBuffer, size_t destBufferLen)
{
m_pData = pDestBuffer;
m_currReadPos = 0;
m_currWritePos = 0;
m_mallocMemSize = destBufferLen;
}
void DataStream::Detach()
{
m_pData = NULL;
m_mallocMemSize = 0;
m_currWritePos = 0;
m_currReadPos = 0;
}
bool DataStream::CanRead(int dataLen)
{
if (m_currReadPos + dataLen > GetDataLength())
return FALSE;
return TRUE;
}
void DataStream::SeekReadToBegin()
{
m_currReadPos = 0;
}
void DataStream::SeekWriteToBegin()
{
m_currWritePos = 0;
}
byte* DataStream::GetData(size_t startIndex)
{
return m_pData + startIndex;
}
size_t DataStream::GetDataLength()
{
return m_currWritePos;
}
BOOL DataStream::Open(CString strFilePath)
{
m_pData = NULL;
m_mallocMemSize = 0;
m_currWritePos = 0;
m_currReadPos = 0;
CFile file;
if (file.Open(strFilePath, CFile::modeRead | CFile::shareDenyWrite))
{
m_mallocMemSize = (size_t)file.GetLength();
m_pData = new byte[m_mallocMemSize];
file.Read(m_pData, (UINT)m_mallocMemSize);
file.Close();
m_currWritePos = m_mallocMemSize;
return TRUE;
}
return FALSE;
}
void DataStream::Save(CString strFilePath)
{
PublicFunctions::MakesureDirPathValid(strFilePath);
CFile file;
file.Open(strFilePath, CFile::modeCreate | CFile::modeWrite);
file.Write(GetData(), (UINT)GetDataLength());
file.Close();
}
size_t DataStream::MakeSureCanWriteByIncreaseMemorySpace(size_t byteCountToWrite)
{
if (byteCountToWrite > m_mallocMemSize - m_currWritePos)
{
size_t increaseSize = byteCountToWrite * 2;
if (increaseSize < 1024)
increaseSize = 1024;
size_t newSize = m_mallocMemSize + increaseSize;
byte* pNewData = new byte[newSize];
memset(pNewData, 0, newSize);
if (m_pData != NULL)
memcpy(pNewData, m_pData, m_mallocMemSize);
SAFE_RELEASE(m_pData);
m_pData = pNewData;
m_mallocMemSize = newSize;
}
return m_mallocMemSize;
}
DataStream& DataStream::operator << (CString val)
{
int len = val.GetLength();
MakeSureCanWriteByIncreaseMemorySpace(len * 2 + 4);
(*this) << (len);
for (int i = 0; i < len; i++)
{
(*this) << (WCHAR)val.GetAt(i);
}
return *this;
}
DataStream& DataStream::operator >> (CString& val)
{
val.Empty();
int len = 0;
(*this) >> (len);
for (int i = 0; i < len; i++)
{
WCHAR c = 0;
(*this) >> c;
val.Insert(val.GetLength(), c);
}
return *this;
}
DataStream& DataStream::operator << (int val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(int));
byte v0 = (byte) ((val << 24) >> 24);
byte v1 = (byte) ((val << 16) >> 24);
byte v2 = (byte) ((val << 8) >> 24);
byte v3 = (byte) ((val) >> 24);
*(m_pData + (m_currWritePos++)) = v0;
*(m_pData + (m_currWritePos++)) = v1;
*(m_pData + (m_currWritePos++)) = v2;
*(m_pData + (m_currWritePos++)) = v3;
return *this;
}
DataStream& DataStream::operator >> (int& val)
{
// ASSERT(CanRead(sizeof(int)));
int v0 = *(m_pData + (m_currReadPos++));
int v1 = *(m_pData + (m_currReadPos++));
int v2 = *(m_pData + (m_currReadPos++));
int v3 = *(m_pData + (m_currReadPos++));
val = v0 | (v1 << 8) | (v2 << 16) | (v3 << 24);
return *this;
}
DataStream& DataStream::operator << (UINT val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(UINT));
byte v0 = (byte) ((val << 24) >> 24);
byte v1 = (byte) ((val << 16) >> 24);
byte v2 = (byte) ((val << 8) >> 24);
byte v3 = (byte) ((val) >> 24);
*(m_pData + (m_currWritePos++)) = v0;
*(m_pData + (m_currWritePos++)) = v1;
*(m_pData + (m_currWritePos++)) = v2;
*(m_pData + (m_currWritePos++)) = v3;
return *this;
}
DataStream& DataStream::operator >> (UINT& val)
{
UINT v0 = *(m_pData + (m_currReadPos++));
UINT v1 = *(m_pData + (m_currReadPos++));
UINT v2 = *(m_pData + (m_currReadPos++));
UINT v3 = *(m_pData + (m_currReadPos++));
val = v0 | (v1 << 8) | (v2 << 16) | (v3 << 24);
return *this;
}
DataStream& DataStream::operator << (long val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(long));
int temp = val;
(*this) << temp;
return *this;
}
DataStream& DataStream::operator >> (long& val)
{
int temp;
(*this) >> temp;
val = temp;
return *this;
}
DataStream& DataStream::operator << (DWORD val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(WORD));
CString temp;
temp.Format(_T("%d"), val);
(*this) << temp;
return *this;
}
DataStream& DataStream::operator >> (DWORD& val)
{
CString temp;
(*this) >> temp;
val = _wtoi(temp.GetBuffer(temp.GetLength()));
temp.ReleaseBuffer();
return *this;
}
DataStream& DataStream::operator << (byte val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(byte));
*(m_pData + (m_currWritePos++)) = val;
return *this;
}
DataStream& DataStream::operator >> (byte& val)
{
val = *(m_pData + (m_currReadPos++));
return *this;
}
DataStream& DataStream::operator << (short val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(short));
byte v0 = (byte) ((val << 8) >> 8);
byte v1 = (byte) ((val) >> 8);
*(m_pData + (m_currWritePos++)) = v0;
*(m_pData + (m_currWritePos++)) = v1;
return *this;
}
DataStream& DataStream::operator >> (short& val)
{
short v0 = *(m_pData + (m_currReadPos++));
short v1 = *(m_pData + (m_currReadPos++));
val = v0 | (v1 << 8);
return *this;
}
DataStream& DataStream::operator << (CArray<int, int>& val)
{
int count = (int)val.GetSize();
*this << count;
MakeSureCanWriteByIncreaseMemorySpace(count * sizeof(int));
for (int i = 0; i < count; i++)
{
*this << val.GetAt(i);
}
return *this;
}
DataStream& DataStream::operator >> (CArray<int, int>& val)
{
int count = 0;
*this >> count;
for (int i = 0; i< count; i++)
{
int tempItem = 0;
*this >> tempItem;
val.Add(tempItem);
}
return *this;
}
DataStream& DataStream::operator << (CStringArray& val)
{
int count = (int)val.GetSize();
*this << count;
for (int i = 0; i < count; i++)
{
*this << val.GetAt(i);
}
return *this;
}
DataStream& DataStream::operator >> (CStringArray& val)
{
int count = 0;
*this >> count;
for (int i = 0; i < count; i++)
{
CString strTemp;
*this >> strTemp;
val.Add(strTemp);
}
return *this;
}
DataStream& DataStream::operator << (float val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(float));
CString temp;
temp.Format(_T("%f"), val);
(*this) << (temp);
return *this;
}
DataStream& DataStream::operator >> (float& val)
{
CString temp;
(*this) >> (temp);
val = (float)_wtof(temp.GetBuffer(temp.GetLength()));
temp.ReleaseBuffer();
return *this;
}
DataStream& DataStream::Write(short* val, UINT count)
{
MakeSureCanWriteByIncreaseMemorySpace(count);
(*this) << count;
for (UINT i = 0; i < count; i++)
(*this) << (short) (val[i]);
return *this;
}
DataStream& DataStream::Read(short** val, UINT* count)
{
UINT countTemp;
(*this) >> countTemp;
if (count!= NULL)
*count = countTemp;
if (*val != NULL)
delete *val;
*val = new short[countTemp];
for (UINT i = 0; i < countTemp; i++)
(*this) >> (*val)[i];
return *this;
}
DataStream& DataStream::Write(byte* val, UINT count)
{
MakeSureCanWriteByIncreaseMemorySpace(count);
(*this) << count;
memcpy(m_pData + m_currWritePos, val, count);
m_currWritePos += count;
return *this;
}
DataStream& DataStream::Read(byte** val, UINT* count)
{
UINT countTemp;
(*this) >> countTemp;
if (count != NULL)
*count = countTemp;
SAFE_RELEASE(*val);
if (countTemp == 0)
{
*val = NULL;
}
else
{
*val = new byte[countTemp];
memcpy(*val, m_pData + m_currReadPos, countTemp);
}
m_currReadPos += countTemp;
return *this;
}
DataStream& DataStream::Write(IN char* val, IN UINT count)
{
MakeSureCanWriteByIncreaseMemorySpace(count);
*this << count;
for (UINT i = 0; i < count; i++)
*this << *(val + count);
return *this;
}
DataStream& DataStream::Read(OUT char** val, OUT UINT* count)
{
*this >> *count;
*val = new char[*count];
for (UINT i = 0; i < *count; i++)
*this >> *(*val + i);
return *this;
}
DataStream& DataStream::operator << (char val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(short));
short temp = val;
(*this) << temp;
return *this;
}
DataStream& DataStream::operator >> (char& val)
{
short temp;
(*this) >> temp;
val = (char)temp;
return *this;
}
DataStream& DataStream::operator << (WCHAR val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(short));
short temp = val;
(*this) << temp;
return *this;
}
DataStream& DataStream::operator >> (WCHAR& val)
{
short temp;
(*this) >> temp;
val = (WCHAR)temp;
return *this;
}
DataStream& DataStream::operator << (DataStream& val)
{
MakeSureCanWriteByIncreaseMemorySpace(val.GetDataLength());
int cnt = (int)val.GetDataLength();
(*this) << cnt;
memcpy(m_pData + m_currWritePos, val.m_pData, cnt);
m_currWritePos += cnt;
return *this;
}
DataStream& DataStream::operator >> (DataStream& val)
{
int cnt;
(*this) >> cnt;
val.Reset(cnt);
memcpy(val.m_pData, m_pData + m_currReadPos, cnt);
val.m_currWritePos += cnt;
m_currReadPos += cnt;
return *this;
}
DataStream& DataStream::operator << (CRect val)
{
MakeSureCanWriteByIncreaseMemorySpace(4 * sizeof(long));
*this << val.left << val.top << val.right << val.bottom;
return *this;
}
DataStream& DataStream::operator >> (CRect& val)
{
int left, top, right, bottom;
*this >> left >> top >> right >> bottom;
val = CRect(left, top, right, bottom);
return *this;
}
DataStream& DataStream::operator << (Rect val)
{
MakeSureCanWriteByIncreaseMemorySpace(4 * sizeof(int));
*this << val.GetLeft() << val.GetTop() << val.Width << val.Height;
return *this;
}
DataStream& DataStream::operator >> (Rect& val)
{
int left, top, width, height;
*this >> left >> top >> width >> height;
val = Rect(left, top, width, height);
return *this;
}
DataStream& DataStream::operator << (RectF val)
{
MakeSureCanWriteByIncreaseMemorySpace(4 * sizeof(float));
*this << val.GetLeft() << val.GetTop() << val.Width << val.Height;
return *this;
}
DataStream& DataStream::operator >> (RectF& val)
{
float left, top, width, height;
*this >> left >> top >> width >> height;
val = RectF(left, top, width, height);
return *this;
}
DataStream& DataStream::operator << (CPoint val)
{
MakeSureCanWriteByIncreaseMemorySpace(2 * sizeof(long));
*this << val.x << val.y;
return *this;
}
DataStream& DataStream::operator >> (CPoint& val)
{
int x, y;
*this >> x >> y;
val = CPoint(x, y);
return *this;
}
DataStream& DataStream::operator << (Point val)
{
MakeSureCanWriteByIncreaseMemorySpace(2 * sizeof(long));
*this << val.X << val.Y;
return *this;
}
DataStream& DataStream::operator >> (Point& val)
{
int x, y;
*this >> x >> y;
val = Point(x, y);
return *this;
}
DataStream& DataStream::operator << (PointF val)
{
MakeSureCanWriteByIncreaseMemorySpace(2 * sizeof(float));
*this << val.X << val.Y;
return *this;
}
DataStream& DataStream::operator >> (PointF& val)
{
float x, y;
*this >> x >> y;
val = PointF(x, y);
return *this;
}
DataStream& DataStream::operator << (Image* val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(byte));
if (val == NULL)
{
*this << (byte)0;
}
else
{
*this << (byte)1;
UINT len = 0;
byte *pdatas = NULL;
PublicFunctions::ImageToByte(&pdatas, val, len);
MakeSureCanWriteByIncreaseMemorySpace(len);
Write(pdatas, len);
delete[] pdatas;
}
return *this;
}
DataStream& DataStream::operator >> (Image** val)
{
byte bNull = 0;
*this >> bNull;
if (bNull == 0)
{
SAFE_RELEASE((*val));
}
else
{
SAFE_RELEASE((*val));
UINT len = 0;
byte *pData = NULL;
Read(&pData, &len);
*val = PublicFunctions::ByteToImage(pData, len);
delete[] pData;
}
return *this;
}
DataStream& DataStream::AddFile(CString strSrcPath)
{
if (!PublicFunctions::IsValidFilePath(strSrcPath))
{
*this << (byte)0;
}
else
{
*this << (byte)1;
CFile file(strSrcPath, CFile::modeRead);
CString str = file.GetFileName();
*this << file.GetFileName();
UINT wLen = (UINT)file.GetLength();
MakeSureCanWriteByIncreaseMemorySpace(wLen);
byte* pDatas = new byte[wLen];
file.Read(pDatas, wLen);
Write(pDatas, wLen);
delete[] pDatas;
file.Close();
}
return *this;
}
DataStream& DataStream::GetFile(CString& strSavePath)
{
byte bNull = 0;
*this >> bNull;
if (bNull == 0)
{
strSavePath.Empty();
}
else
{
CString fileName;
UINT filelen = 0;
byte* pDatas = NULL;
*this >> fileName;
Read(&pDatas, &filelen);
strSavePath = strSavePath + _T("\\") + fileName;
CFile file(strSavePath, CFile::modeWrite | CFile::modeCreate);
file.Write(pDatas, filelen);
file.Close();
delete[] pDatas;
}
return *this;
}
DataStream& DataStream::operator << (Font* val)
{
MakeSureCanWriteByIncreaseMemorySpace(LF_FACESIZE + sizeof(float) + 1);
if (val == NULL)
{
*this << (byte)0;
}
else
{
*this << (byte)1;
FontFamily fontfamily;
val->GetFamily(&fontfamily);
WCHAR familyName[LF_FACESIZE];
fontfamily.GetFamilyName(familyName);
int style = val->GetStyle();
int unit = val->GetUnit();
*this << (CString)familyName << val->GetSize() << style << unit;
}
return *this;
}
DataStream& DataStream::operator >> (Font** val)
{
byte bNull = 0;
*this >> bNull;
if (bNull == 0)
{
SAFE_RELEASE((*val));
}
else
{
SAFE_RELEASE((*val));
CString familyName;
float fontSize;
int style, unit;
*this >> familyName >> fontSize >> style >> unit;
FontFamily family(familyName);
(*val) = new Font(&family, fontSize, style, Unit(unit));
}
return *this;
}
DataStream& DataStream::operator << (Matrix* val)
{
MakeSureCanWriteByIncreaseMemorySpace(6 * sizeof(float) + 1);
if (val == NULL)
{
*this << (byte)0;
}
else
{
*this << (byte)1;
float m[6] = {0.0f};
val->GetElements(m);
for (int i = 0; i < 6; i++)
{
*this << m[i];
}
}
return *this;
}
DataStream& DataStream::operator >> (Matrix** val)
{
byte bNull = 0;
*this >> bNull;
if (bNull == 0)
{
SAFE_RELEASE((*val));
}
else
{
if ((*val) == NULL)
(*val) = new Matrix;
float m[6];
*this >> m[0] >> m[1] >> m[2] >> m[3] >> m[4] >> m[5];
(*val)->Reset();
(*val)->SetElements(m[0], m[1], m[2], m[3], m[4], m[5]);
}
return *this;
}
DataStream& DataStream::operator << (Color val)
{
MakeSureCanWriteByIncreaseMemorySpace(sizeof(DWORD));
*this << val.GetAlpha() << val.GetRed() << val.GetGreen() << val.GetBlue();
return *this;
}
DataStream& DataStream::operator >> (Color &val)
{
byte a, r, g, b;
*this >> a >> r >> g >> b;
val = Color(a, r, g, b);
return *this;
}