SmartOS/Stream.h

125 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _Stream_H_
#define _Stream_H_
#include <stddef.h>
#include "Sys.h"
// 内存数据流
// 数据流内有一个缓冲区,游标位置,数据长度。实际有效数据仅占用缓冲区中间部分,头尾都可能有剩余
class Stream
{
private:
byte* _Buffer; // 数据缓冲区。扩容后会重新分配缓冲区
uint _Capacity; // 缓冲区容量
//bool _needFree; // 是否自动释放
// 又是头疼的对齐问题
uint _needFree; // 是否自动释放
uint _Position; // 游标位置
byte _Arr[64]; // 内部缓冲区。较小内存需要时,直接使用栈分配,提高性能。
public:
uint Length; // 数据长度
// 分配指定大小的数据流
Stream(uint len = 0);
// 使用缓冲区初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream(byte* buf, uint len);
// 使用字节数组初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream(ByteArray& bs);
// 销毁数据流
~Stream();
// 数据流容量
uint Capacity();
// 当前位置
uint Position();
// 设置位置
void SetPosition(uint p);
// 余下的有效数据流长度。0表示已经到达终点
uint Remain();
// 尝试前后移动一段距离,返回成功或者失败。如果失败,不移动游标
bool Seek(int offset);
// 数据流指针。注意:扩容后指针会改变!
byte* GetBuffer();
// 数据流当前位置指针。注意:扩容后指针会改变!
byte* Current();
// 从当前位置读取数据
uint Read(byte* buf, uint offset = 0, int count = -1);
uint ReadEncodeInt();
// 把数据写入当前位置
void Write(byte* buf, uint offset, uint count);
uint WriteEncodeInt(uint value);
// 写入字符串,先写入压缩编码整数表示的长度
uint Write(string str);
void Write(ByteArray& bs);
uint ReadArray(ByteArray& bs);
void WriteArray(ByteArray& bs);
uint ReadString(String& str);
void WriteString(String& str);
// 取回指定结构体指针,并移动游标位置
template<typename T>
T* Retrieve(bool move = true)
{
int p = sizeof(T) + _Position;
// 允许移动到最后一个字节之后也就是Length
if(p < 0 || p > Length) return NULL;
T* pt = (T*)Current();
if(move && !Seek(sizeof(T))) return NULL;
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>
void Write(T value)
{
if(!CheckCapacity(sizeof(T))) return;
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;
}
byte* ReadBytes(int count = -1);
// 读取一个字节,不移动游标。如果没有可用数据,则返回-1
int Peek();
private:
bool CheckCapacity(uint count);
};
#endif