SmartOS/Core/Stream.h

120 lines
3.7 KiB
C++
Raw Permalink 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_
// 数据流
// 数据流内有一个缓冲区,游标位置,数据长度。实际有效数据仅占用缓冲区中间部分,头尾都可能有剩余
class Stream
{
protected:
byte* _Buffer; // 数据缓冲区。扩容后会重新分配缓冲区
int _Capacity; // 缓冲区容量
int _Position; // 游标位置
void Init(void* buf, int len);
virtual bool CheckRemain(int count);
public:
int Length; // 数据长度
bool Little; // 默认小字节序。仅影响数据读写操作
bool CanWrite; // 是否可写
bool CanResize; // 是否可以自动扩容
// 使用缓冲区初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream(void* buf, int len);
Stream(const void* buf, int len);
// 使用字节数组初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
explicit Stream(Buffer& bs);
explicit Stream(const Buffer& bs);
virtual ~Stream();
// 数据流容量
int Capacity() const;
void SetCapacity(int len);
// 当前位置
int Position() const;
// 设置位置
bool SetPosition(int p);
// 余下的有效数据流长度。0表示已经到达终点
int Remain() const;
// 尝试前后移动一段距离,返回成功或者失败。如果失败,不移动游标
bool Seek(int offset);
// 数据流指针。注意:扩容后指针会改变!
byte* GetBuffer() const;
// 数据流当前位置指针。注意:扩容后指针会改变!
byte* Current() const;
// 读取7位压缩编码整数
int ReadEncodeInt();
// 读取数据到字节数组,由字节数组指定大小。不包含长度前缀
int Read(Buffer& bs);
// 写入7位压缩编码整数
int WriteEncodeInt(int value);
// 把字节数组的数据写入到数据流。不包含长度前缀
bool Write(const Buffer& bs);
// 从数据流读取变长数据到字节数组。以压缩整数开头表示长度
int ReadArray(Buffer& bs);
ByteArray ReadArray(int count);
// 把字节数组作为变长数据写入到数据流。以压缩整数开头表示长度
bool WriteArray(const Buffer& bs);
ByteArray ReadArray();
String ReadString();
int ReadByte();
ushort ReadUInt16();
uint ReadUInt32();
UInt64 ReadUInt64();
bool Write(byte value);
bool Write(ushort value);
bool Write(uint value);
bool Write(UInt64 value);
//bool Write(sbyte value) { return Write((byte)value); }
bool Write(short value) { return Write((ushort)value); }
bool Write(int value) { return Write((uint)value); }
bool Write(Int64 value) { return Write((UInt64)value); }
// 取回指定结构体指针,并移动游标位置
template<typename T>
T* Retrieve(bool move = true)
{
int p = sizeof(T) + _Position;
// 允许移动到最后一个字节之后也就是Length
if(p < 0 || p > Length) return nullptr;
T* pt = (T*)Current();
if(move && !Seek(sizeof(T))) return nullptr;
return pt;
}
// 读取指定长度的数据并返回首字节指针,移动数据流位置
byte* ReadBytes(int count = -1);
// 读取一个字节,不移动游标。如果没有可用数据,则返回-1
int Peek() const;
};
// 内存数据流。预分配空间,自动扩容
class MemoryStream : public Stream
{
private:
byte _Arr[0x40]; // 内部缓冲区。较小内存需要时,直接使用栈分配,提高性能。
bool _needFree; // 是否自动释放
//bool _resize; // 是否可以自动扩容
virtual bool CheckRemain(int count);
public:
// 分配指定大小的数据流
MemoryStream(int len = 0);
// 使用缓冲区初始化数据流,支持自动扩容
MemoryStream(void* buf, int len);
// 销毁数据流
virtual ~MemoryStream();
};
#endif