拆分数据流Stream为基类和内存数据流MemoryStream,编译通过,未测试

This commit is contained in:
nnhy 2015-10-15 06:50:09 +00:00
parent 98d1df4cfa
commit 0c6ee45297
5 changed files with 106 additions and 154 deletions

View File

@ -47,7 +47,7 @@ void Message::SetError(byte errorCode, const char* msg)
bool Message::Clone(const Message& msg)
{
Stream ms;
MemoryStream ms;
msg.Write(ms);
ms.SetPosition(0);

View File

@ -18,7 +18,7 @@ void MessageBase::WriteMessage(Message& msg)
{
// 如果是令牌消息,这里就要自己小心了
//Stream ms(msg.Data, 256);
Stream ms;
MemoryStream ms;
Write(ms);

View File

@ -1,87 +1,55 @@
#include "Stream.h"
Stream::Stream(uint len)
{
if(len <= ArrayLength(_Arr))
{
len = ArrayLength(_Arr);
_Buffer = _Arr;
_needFree = false;
}
else
{
_Buffer = new byte[len];
assert_ptr(_Buffer);
_needFree = true;
}
_Capacity = len;
_Position = 0;
Length = len;
_canWrite = true;
Little = true;
}
// 使用缓冲区初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream::Stream(byte* buf, uint len)
{
assert_ptr(buf);
//assert_param2(len > 0, "不能用0长度缓冲区来初始化数据流");
_Buffer = buf;
_Capacity = len;
_Position = 0;
_needFree = false;
_canWrite = true;
Length = len;
Little = true;
Init(buf, len);
}
Stream::Stream(const byte* buf, uint len)
{
assert_ptr(buf);
Init((byte*)buf, len);
_Buffer = (byte*)buf;
_Capacity = len;
_Position = 0;
_needFree = false;
_canWrite = false;
Length = len;
Little = true;
CanWrite = false;
}
// 使用字节数组初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream::Stream(ByteArray& bs)
{
_Buffer = bs.GetBuffer();
_Capacity = bs.Length();
_Position = 0;
_needFree = false;
_canWrite = true;
Length = bs.Length();
Little = true;
Init(bs.GetBuffer(), bs.Length());
}
Stream::Stream(const ByteArray& bs)
{
_Buffer = bs.GetBuffer();
_Capacity = bs.Length();
Init((byte*)bs.GetBuffer(), bs.Length());
CanWrite = false;
}
void Stream::Init(byte* buf, uint len)
{
assert_ptr(buf);
_Buffer = buf;
_Capacity = len;
_Position = 0;
_needFree = false;
_canWrite = false;
Length = bs.Length();
CanWrite = true;
Length = len;
Little = true;
}
// 销毁数据流
Stream::~Stream()
bool Stream::CheckRemain(uint count)
{
assert_ptr(this);
if(_needFree)
uint remain = _Capacity - _Position;
// 容量不够,需要扩容
if(count > remain)
{
if(_Buffer != _Arr) delete[] _Buffer;
_Buffer = NULL;
debug_printf("数据流 0x%08X 剩余容量 %d 不足 %d ,无法扩容!\r\n", this, remain, count);
assert_param(false);
return false;
}
return true;
}
// 数据流容量
@ -175,13 +143,12 @@ bool Stream::Write(const byte* buf, uint offset, uint count)
{
assert_param2(buf, "向数据流写入数据需要有效的缓冲区");
if(!_canWrite) return false;
if(!CanWrite) return false;
if(!CheckRemain(count)) return false;
memcpy(Current(), buf + offset, count);
_Position += count;
//Length += count;
// 内容长度不是累加,而是根据位置而扩大
if(_Position > Length) Length = _Position;
@ -191,7 +158,7 @@ bool Stream::Write(const byte* buf, uint offset, uint count)
// 写入7位压缩编码整数
uint Stream::WriteEncodeInt(uint value)
{
if(!_canWrite) return false;
if(!CanWrite) return false;
byte temp;
for( int i = 0 ; i < 4 ; i++ )
@ -212,7 +179,7 @@ uint Stream::WriteEncodeInt(uint value)
// 写入字符串,先写入压缩编码整数表示的长度
uint Stream::Write(const string str)
{
if(!_canWrite) return false;
if(!CanWrite) return false;
int len = 0;
if(str)
@ -252,37 +219,6 @@ int Stream::Peek() const
return *Current();
}
bool Stream::CheckRemain(uint count)
{
uint remain = _Capacity - _Position;
// 容量不够,需要扩容
if(count > remain)
{
if(!_needFree && _Buffer != _Arr)
{
debug_printf("数据流 0x%08X 剩余容量 %d 不足 %d ,而外部缓冲区无法扩容!\r\n", this, remain, count);
//assert_param(false);
return false;
}
// 原始容量成倍扩容
uint total = _Position + count;
uint size = _Capacity;
while(size < total) size <<= 1;
// 申请新的空间,并复制数据
byte* bufNew = new byte[size];
if(_Position > 0) memcpy(bufNew, _Buffer, _Position);
if(_Buffer != _Arr) delete[] _Buffer;
_Buffer = bufNew;
_Capacity = size;
}
return true;
}
// 从数据流读取变长数据到字节数组。以压缩整数开头表示长度
uint Stream::ReadArray(ByteArray& bs)
{
@ -366,8 +302,6 @@ byte Stream::ReadByte()
ushort Stream::ReadUInt16()
{
//byte* p = ReadBytes(2);
//ushort v = *(ushort*)p;
ushort v;
if(!Read((byte*)&v, 0, 2)) return 0;
if(!Little) v = __REV16(v);
@ -376,8 +310,6 @@ ushort Stream::ReadUInt16()
uint Stream::ReadUInt32()
{
//byte* p = ReadBytes(4);
//uint v = *(uint*)p;
uint v;
if(!Read((byte*)&v, 0, 4)) return 0;
if(!Little) v = __REV(v);
@ -386,8 +318,6 @@ uint Stream::ReadUInt32()
ulong Stream::ReadUInt64()
{
//byte* p = ReadBytes(8);
//ulong v = *(ulong*)p;
ulong v;
if(!Read((byte*)&v, 0, 8)) return 0;
if(!Little) v = __REV(v >> 32) | ((ulong)__REV(v & 0xFFFFFFFF) << 32);
@ -420,3 +350,56 @@ bool Stream::Write(ulong value)
return Write((byte*)&value, 0, 8);
}
MemoryStream::MemoryStream(uint len) : Stream(_Arr, ArrayLength(_Arr))
{
_needFree = false;
if(len > ArrayLength(_Arr))
{
byte* buf = new byte[len];
Init(buf, len);
_needFree = true;
}
}
// 销毁数据流
MemoryStream::~MemoryStream()
{
assert_ptr(this);
if(_needFree)
{
if(_Buffer != _Arr) delete[] _Buffer;
_Buffer = NULL;
}
}
bool MemoryStream::CheckRemain(uint count)
{
uint remain = _Capacity - _Position;
// 容量不够,需要扩容
if(count > remain)
{
if(!_needFree && _Buffer != _Arr)
{
debug_printf("数据流 0x%08X 剩余容量 %d 不足 %d ,而外部缓冲区无法扩容!\r\n", this, remain, count);
//assert_param(false);
return false;
}
// 原始容量成倍扩容
uint total = _Position + count;
uint size = _Capacity;
while(size < total) size <<= 1;
// 申请新的空间,并复制数据
byte* bufNew = new byte[size];
if(_Position > 0) memcpy(bufNew, _Buffer, _Position);
if(_Buffer != _Arr) delete[] _Buffer;
_Buffer = bufNew;
_Capacity = size;
}
return true;
}

View File

@ -4,40 +4,34 @@
#include <stddef.h>
#include "Sys.h"
// 内存数据流
// 数据流
// 数据流内有一个缓冲区,游标位置,数据长度。实际有效数据仅占用缓冲区中间部分,头尾都可能有剩余
class Stream
{
private:
protected:
byte* _Buffer; // 数据缓冲区。扩容后会重新分配缓冲区
uint _Capacity; // 缓冲区容量
uint _Position; // 游标位置
byte _Arr[64]; // 内部缓冲区。较小内存需要时,直接使用栈分配,提高性能。
bool _needFree; // 是否自动释放
bool _canWrite; // 是否可写
void Init(byte* buf, uint len);
virtual bool CheckRemain(uint count);
public:
bool Little; // 默认小字节序。仅影响数据读写操作
uint Length; // 数据长度
bool Little; // 默认小字节序。仅影响数据读写操作
bool CanWrite; // 是否可写
// 分配指定大小的数据流
Stream(uint len = 0);
// 使用缓冲区初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream(byte* buf, uint len);
Stream(const byte* buf, uint len);
// 使用字节数组初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream(ByteArray& bs);
Stream(const ByteArray& bs);
// 销毁数据流
~Stream();
// 数据流容量
uint Capacity() const;
void SetCapacity(uint len);
// 当前位置
uint Position() const;
void SetCapacity(uint len);
// 设置位置
bool SetPosition(int p);
// 余下的有效数据流长度。0表示已经到达终点
@ -102,52 +96,27 @@ public:
return pt;
}
/*// 常用读写整数方法
template<typename T>
T Read()
{
byte* p = Current();
if(!Seek(sizeof(T))) return 0;
// 检查地址对齐
if((uint)p % sizeof(T) == 0)
return *(T*)p;
T obj;
memcpy(&obj, p, sizeof(T));
return obj;
}
template<typename T>
bool Write(T value)
{
if(!_canWrite) return false;
if(!CheckRemain(sizeof(T))) return false;
byte* p = Current();
// 检查地址对齐
if((uint)p % sizeof(T) == 0)
*(T*)p = value;
else
memcpy(p, &value, sizeof(T));
// 移动游标
_Position += sizeof(T);
if(_Position > Length) Length = _Position;
return true;
}*/
// 读取指定长度的数据并返回首字节指针,移动数据流位置
byte* ReadBytes(int count = -1);
// 读取一个字节,不移动游标。如果没有可用数据,则返回-1
int Peek() const;
};
// 内存数据流。预分配空间,自动扩容
class MemoryStream : public Stream
{
private:
bool CheckRemain(uint count);
byte _Arr[0x40]; // 内部缓冲区。较小内存需要时,直接使用栈分配,提高性能。
bool _needFree; // 是否自动释放
virtual bool CheckRemain(uint count);
public:
// 分配指定大小的数据流
MemoryStream(uint len = 0);
// 销毁数据流
~MemoryStream();
};
#endif

View File

@ -402,7 +402,7 @@ bool Gateway::SendDeviceInfo(const Device* dv)
rs.Code = 0x25;
// 担心rs.Data内部默认缓冲区不够大这里直接使用数据流。必须小心ms生命结束以后它的缓冲区也将无法使用
//Stream ms(rs.Data, rs.Length);
Stream ms;
MemoryStream ms;
dv->Write(ms);