SmartOS/Core/Stream.cpp

387 lines
7.9 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.

#include <stddef.h>
#include "_Core.h"
#include "ByteArray.h"
#include "SString.h"
#include "Stream.h"
extern ushort _REV16(ushort);
extern uint _REV(uint);
// 使用缓冲区初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream::Stream(void* buf, int len)
{
Init(buf, len);
}
Stream::Stream(const void* buf, int len)
{
Init((void*)buf, len);
CanWrite = false;
}
// 使用字节数组初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
Stream::Stream(Buffer& bs)
{
Init(bs.GetBuffer(), bs.Length());
}
Stream::Stream(const Buffer& bs)
{
Init((void*)bs.GetBuffer(), bs.Length());
CanWrite = false;
}
Stream::~Stream() { }
void Stream::Init(void* buf, int len)
{
assert(buf, "buf");
_Buffer = (byte*)buf;
_Capacity = len;
_Position = 0;
CanWrite = true;
CanResize = true;
Length = len;
Little = true;
}
bool Stream::CheckRemain(int count)
{
int remain = _Capacity - _Position;
// 容量不够,需要扩容
if (count > remain)
{
if (CanResize)
debug_printf("数据流 0x%p 剩余容量 (%d - %d) = %d 不足 %d ,无法扩容!\r\n", this, _Capacity, _Position, remain, count);
else
assert(false, "无法扩容");
return false;
}
return true;
}
// 数据流容量
int Stream::Capacity() const { return _Capacity; }
void Stream::SetCapacity(int len) { CheckRemain(len - _Position); }
// 当前位置
int Stream::Position() const { return _Position; }
// 设置位置
bool Stream::SetPosition(int p)
{
// 允许移动到最后一个字节之后也就是Length
//assert(p <= Length, "设置的位置超出长度");
if (p < 0 && p > Length)
{
debug_printf("设置的位置 %d 超出长度 %d\r\n", p, Length);
return false;
}
_Position = p;
return true;
}
// 余下的有效数据流长度。0表示已经到达终点
int Stream::Remain() const { return Length - _Position; };
// 尝试前后移动一段距离,返回成功或者失败。如果失败,不移动游标
bool Stream::Seek(int offset)
{
if (offset == 0) return true;
return SetPosition(offset + _Position);
}
// 数据流指针。注意:扩容后指针会改变!
byte* Stream::GetBuffer() const { return _Buffer; }
// 数据流当前位置指针。注意:扩容后指针会改变!
byte* Stream::Current() const { return &_Buffer[_Position]; }
// 读取7位压缩编码整数
int Stream::ReadEncodeInt()
{
int value = 0;
// 同时计算最大4字节避免无限读取错误数据
for (int i = 0, k = 0; i < 4; i++, k += 7)
{
int temp = ReadByte();
if (temp < 0) break;
value |= (temp & 0x7F) << k;
if ((temp & 0x80) == 0) break;
}
return value;
}
// 读取数据到字节数组,由字节数组指定大小。不包含长度前缀
int Stream::Read(Buffer& bs)
{
if (bs.Length() == 0) return 0;
Buffer ss(_Buffer, Length);
int count = bs.Copy(0, ss, _Position, bs.Length());
// 游标移动
_Position += count;
bs.SetLength(count);
return count;
}
// 写入7位压缩编码整数
int Stream::WriteEncodeInt(int value)
{
if (!CanWrite) return 0;
byte buf[8];
int k = 0;
for (int i = 0; i < 4 && value >= 0x80; i++)
{
buf[k++] = (byte)(value | 0x80);
value >>= 7;
}
{
buf[k++] = (byte)value;
}
return Write(Buffer(buf, k));
}
// 把字节数组的数据写入到数据流。不包含长度前缀
bool Stream::Write(const Buffer& bs)
{
int count = bs.Length();
if (count == 0) return true;
if (!CanWrite) return false;
if (!CheckRemain(count)) return false;
Buffer ss(_Buffer, _Capacity);
count = ss.Copy(_Position, bs, 0, count);
_Position += count;
// 内容长度不是累加,而是根据位置而扩大
if (_Position > Length) Length = _Position;
return true;
}
// 读取指定长度的数据并返回首字节指针,移动数据流位置
byte* Stream::ReadBytes(int count)
{
// 默认小于0时读取全部数据
if (count < 0) count = Remain();
byte* p = Current();
if (!Seek(count)) return nullptr;
return p;
}
// 读取一个字节,不移动游标。如果没有可用数据,则返回-1
int Stream::Peek() const
{
if (!Remain()) return -1;
return *Current();
}
// 从数据流读取变长数据到字节数组。以压缩整数开头表示长度
int Stream::ReadArray(Buffer& bs)
{
int len = ReadEncodeInt();
if (!len)
{
bs.SetLength(0);
return 0;
}
if (len > bs.Length() && !bs.SetLength(len))
{
// 在设计时,如果取得的长度超级大,可能是设计错误
//if(len > 0x40)
{
debug_printf("Stream::ReadArray 缓冲区大小不足 读 %d > %d ", len, bs.Length());
//assert(len <= bs.Capacity(), "缓冲区大小不足");
}
return 0;
}
return Read(bs);
}
ByteArray Stream::ReadArray(int count)
{
ByteArray bs;
bs.SetLength(count);
Read(bs);
return bs;
}
// 读取字节数组返回。不用担心有临时变量的构造和析构RVO会为我们排忧解难
ByteArray Stream::ReadArray()
{
ByteArray bs;
ReadArray(bs);
return bs;
}
// 把字节数组作为变长数据写入到数据流。以压缩整数开头表示长度
bool Stream::WriteArray(const Buffer& bs)
{
WriteEncodeInt(bs.Length());
return Write(bs);
}
String Stream::ReadString()
{
String str;
ReadArray(str);
return str;
}
int Stream::ReadByte()
{
if (Length == _Position) return -1;
byte* p = Current();
if (!Seek(1)) return 0;
return *p;
}
ushort Stream::ReadUInt16()
{
ushort v;
Buffer bs(&v, sizeof(v));
if (!Read(bs)) return 0;
if (!Little) v = _REV16(v);
return v;
}
uint Stream::ReadUInt32()
{
uint v;
Buffer bs(&v, sizeof(v));
if (!Read(bs)) return 0;
if (!Little) v = _REV(v);
return v;
}
UInt64 Stream::ReadUInt64()
{
UInt64 v;
Buffer bs(&v, sizeof(v));
if (!Read(bs)) return 0;
if (!Little) v = _REV(v >> 32) | ((UInt64)_REV(v & 0xFFFFFFFF) << 32);
return v;
}
bool Stream::Write(byte value)
{
return Write(Buffer(&value, sizeof(value)));
}
bool Stream::Write(ushort value)
{
if (!Little) value = _REV16(value);
return Write(Buffer(&value, sizeof(value)));
}
bool Stream::Write(uint value)
{
if (!Little) value = _REV(value);
return Write(Buffer(&value, sizeof(value)));
}
bool Stream::Write(UInt64 value)
{
if (!Little) value = _REV(value >> 32) | ((UInt64)_REV(value & 0xFFFFFFFF) << 32);
return Write(Buffer(&value, sizeof(value)));
}
/******************************** MemoryStream ********************************/
MemoryStream::MemoryStream(int len) : Stream(_Arr, ArrayLength(_Arr))
{
Length = 0;
_needFree = false;
if (len > ArrayLength(_Arr))
{
byte* buf = new byte[len];
Init(buf, len);
_needFree = true;
}
}
MemoryStream::MemoryStream(void* buf, int len) : Stream(buf, len)
{
_needFree = false;
}
// 销毁数据流
MemoryStream::~MemoryStream()
{
if (_needFree)
{
if (_Buffer != _Arr) delete[] _Buffer;
_Buffer = nullptr;
}
}
bool MemoryStream::CheckRemain(int count)
{
int remain = _Capacity - _Position;
// 容量不够,需要扩容
if (count > remain)
{
if (!CanResize) return Stream::CheckRemain(count);
// 原始容量成倍扩容
int total = _Position + count;
int size = _Capacity;
if (size < 0x10) size = 0x10;
while (size < total) size <<= 1;
// 申请新的空间,并复制数据
byte* bufNew = new byte[size];
if (Length > 0) Buffer(_Buffer, Length).CopyTo(0, bufNew, -1);
if (_Buffer != _Arr && _needFree == true) delete[] _Buffer;
_Buffer = bufNew;
_Capacity = size;
_needFree = true;
}
return true;
}
WEAK ushort _REV16(ushort value)
{
return (ushort)((value << 8) | (value >> 8));
}
WEAK uint _REV(uint value)
{
return (_REV16(value & 0xFFFF) << 16) | (_REV16(value >> 16));
}