(*
* Unit owner: 不得闲, d10.天地弦
* blog: http://www.cnblogs.com/dksoft
* homePage: www.diocp.org
*
*
* 1. 2015年7月17日 15:01:12
* TBufferLink添加函数
* ///
* /// 从当前位置开始搜索Buffer
* /// 返回搜索到subBuf的起始位置
* /// 如果搜索不到返回-1
* ///
* function SearchBuffer(subBuf:PAnsiChar; subBufLen:Cardinal): Integer;
*
* 2 . 修正TDiocpExTcpServer和TDiocpExTcpClient的一处解码严重bug(谢谢 沈阳-想 14667479反馈和提供有缺陷的DEMO)
* 修正了SearchBuffer中用于搜索数据的函数SearchPointer bug,
* 由于没有赋值j = pvStartIndex导致判断 j < sourcelen时,会出现超越内存块搜寻。导致搜寻了无效的数据。
* 2015-08-28 14:06:14
* 3. 修正SearchBuffer中的一严重bug(只比较了前两位字符的匹配性)
2015-09-11 09:08:22
*
*)
unit utils_buffer;
/// 2014年2月26日 11:33:38
/// 杨茂丰
/// inline
//{$IF defined(FPC) or defined(VER170) or defined(VER180) or defined(VER190) or defined(VER200) or defined(VER210)}
// {$DEFINE HAVE_INLINE}
//{$IFEND}
{$if CompilerVersion > 18}
{$DEFINE HAVE_INLINE}
{$ifend}
interface
uses
Windows, SyncObjs, SysUtils, Classes;
// 25:XE5
{$IF CompilerVersion<=25}
type
NativeUInt = Cardinal;
IntPtr = Cardinal;
{$ifend}
type
TDxMemBlockType = (MB_Small,MB_Normal,MB_Big,MB_SpBig,MB_Large,MB_SPLarge,MB_Max,MB_MaxBlock); //内存块模式
PMemoryBlock = ^TMemoryBlock;
TMemoryBlock = record
Memory: Pointer;
Next: PMemoryBlock;
Prev: PMemoryBlock;
NextEx: PMemoryBlock;
PrevEx: PMemoryBlock;
BlockType: TDxMemBlockType;
DataLen: NativeUInt;
end;
//内存池
TDxMemoryPool = class
private
FCs: TCriticalSection;
FBlockSize: Integer;
FMaxFreeBlocks: Integer;
FUseHead: PMemoryBlock; //使用的节点的皆点头
FUseLast: PMemoryBlock; //最后一个
FUnUseHead: PMemoryBlock; //未使用的皆点头
FUnUseLast: PMemoryBlock;
FUseCount: Integer;
FFreeCount: Integer;
FBlockType: TDxMemBlockType;
protected
function InnerCreateBlock: PMemoryBlock;
public
constructor Create(BlockSize: Integer;InitCount: Integer;BlockType: TDxMemBlockType;MaxFreeBlocks: Integer=50);
destructor Destroy;override;
procedure Lock; {$IFDEF HAVE_INLINE} inline;{$ENDIF}
procedure Unlock; {$IFDEF HAVE_INLINE} inline;{$ENDIF}
function GetMemory(Zero: Boolean): Pointer;deprecated;
procedure FreeMemory(P: Pointer);deprecated;
function GetMemoryBlock: PMemoryBlock;
procedure FreeMemoryBlock(p: PMemoryBlock);
procedure Clear;
end;
TBufferLink = class;
//依附于内存池的内存流对象
TDxMemoryStream = class(TStream)
private
FHead: PMemoryBlock;
FLast: PMemoryBlock;
FCurBlock: PMemoryBlock;
FCurBlockPos: Integer;
FMarkBlock: PMemoryBlock;
FMarkBlokPos: Integer;
FSize, FPosition,FCapacity: Longint;
FMemBlockType: TDxMemBlockType;
FMemBlockCount: Integer;
procedure SetMemBlockType(const Value: TDxMemBlockType);
function GetBlockSize: DWORD;
protected
function GetSize: Int64; override;
public
constructor Create(const MemType: TDxMemBlockType = MB_Small);
destructor Destroy;override;
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
procedure SaveToStream(Stream: TStream);
procedure SaveToFile(const FileName: string);
procedure LoadFromStream(Stream: TStream);
procedure LoadFromFile(const FileName: string);
procedure SwapStreamLink(Stream: TDxMemoryStream);
procedure SetSize(NewSize: Longint); override;
procedure SaveCurBlock;
procedure RestoreCurBlock;
procedure LinkToBufferList(BufList: TBufferLink);
procedure ReadToBufferList(BufList: TBufferLink;Len: Integer);
procedure SwapBufferBlock(Stream: TDxMemoryStream); //交换内部连接
procedure LoadFromBufferList(BufList: TBufferLink;const DataLen: Integer);
procedure WriteStream(Stream: TStream;Len: Integer);
procedure ReadStream(Stream: TStream;len: Integer);
procedure Clear;
property Head: PMemoryBlock read FHead;
property Last: PMemoryBlock read FLast;
property BlockSize: DWORD read GetBlockSize;
property MemBlockType: TDxMemBlockType read FMemBlockType write SetMemBlockType; //小内存流
end;
///
/// 内部分配内存时是使用的内存池
///
TBufferLink = class
private
FHead: PMemoryBlock; //头部
FLast: PMemoryBlock; //最后一个可用的内存块位
FRead: PMemoryBlock; //当前读到的Buffer
FReadPosition: Cardinal; //当前读到的Buffer位置
FMark: PMemoryBlock; //标记的内存块
FMarkPosition: Cardinal; //标记的内存块位置
function InnerReadBuf(const pvBufRecord: PMemoryBlock; pvStartPostion: Cardinal;
buf: PAnsiChar; len: Cardinal): Cardinal;
public
constructor Create;
destructor Destroy; override;
procedure markReaderIndex;
procedure restoreReaderIndex;
procedure AddBuffer(buf:PAnsiChar; len:Cardinal);
procedure AddMemBlockLink(MemBlockLink: PMemoryBlock);
function readBuffer(const buf: PAnsiChar; len: Cardinal): Cardinal;
///
/// 跳过一段
///
function Skip(len:Cardinal): Cardinal;
///
/// 从当前位置开始搜索Buffer
/// 返回搜索到subBuf的起始位置到当前读取位置直接的字符个数
/// 如果搜索不到返回-1
/// searchbuffer('12', '1234') = 0;
///
function SearchBuffer(subBuf:PAnsiChar; subBufLen:Cardinal): Integer;
procedure clearBuffer;
procedure clearHaveReadBuffer;
function validCount: Integer;
function GetCurBlock: PMemoryBlock;
function FirstBlock: PMemoryBlock;
procedure RemoveBlock(Block: PMemoryBlock;const FreeBlock: Boolean = False);
end;
TDxObjectPool = class;
TOnCreateObject = procedure(Pool: TDxObjectPool;var Obj: TObject) of Object;
TDxObjectPool = class
private
FUses,FUnUses: TList;
FObjClass: TClass;
FMaxObjCount: Integer;
FLocker: TCriticalSection;
FOnCreateObject: TOnCreateObject;
public
constructor Create(AMaxCount: Integer);overload;
constructor Create(AMaxCount: Integer;ObjClass: TClass);overload;
destructor Destroy;override;
function GetObject: TObject;
procedure FreeObject(Obj: TObject);
property OnCreateObject: TOnCreateObject read FOnCreateObject write FOnCreateObject;
end;
//环形缓冲流
TDxRingStream = class(TStream)
private
FReadBlock: PMemoryBlock; //读取的块
FReadBlockPos: Integer;
FMemBlockType: TDxMemBlockType;
FWriteBlock: PMemoryBlock;
FWriteBlockPos: Integer;
FSize, FCapacity: Longint;
FMemBlockCount: Integer;
FHead: PMemoryBlock;
FLast: PMemoryBlock;
FReadPosition: Integer;
FWritePosition: Integer;
FMarkRead,FMarkWrite: PMemoryBlock; //标记的内存块
FMarkReadPosition,FMarkWritePosition: Cardinal; //标记的内存块位置
procedure SetReadPosition(const Value: Integer);
procedure SetWritePostion(const Value: Integer);
function SeekReadWrite(Offset: Longint; Origin: TSeekOrigin;SeekRead: Boolean): Longint;
function GetCanWriteSize: Integer;
function GetDataSize: Integer;
protected
function GetSize: Int64; override;
public
constructor Create(const RingBufferSize: DWORD; const MemType: TDxMemBlockType = MB_Small);
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
procedure ReadBuffer(var Buffer; Count: Longint);
procedure WriteBuffer(const Buffer; Count: Longint);
procedure markReaderIndex;
procedure restoreReaderIndex;
procedure markWriterIndex;
procedure restoreWriterIndex;
function Write(const Buffer; Count: Longint): Longint; override;
procedure SetSize(NewSize: Longint); override;
property ReadPosition: Integer read FReadPosition write SetReadPosition;
property WritePosition: Integer read FWritePosition write SetWritePostion;
property CanWriteSize: Integer read GetCanWriteSize; //能写入的数据长度
property DataSize: Integer read GetDataSize; //能读取的数据长度
end;
const
MAX_SEND_BLOCK_SIZE: Integer= 1460*44;
procedure FreeMemBlock(Block: PMemoryBlock);
function GetMemBlock(BlockType: TDxMemBlockType): PMemoryBlock;
function CalcMemType(MemSize: Integer): TDxMemBlockType;
implementation
var
NormalMPool: TDxMemoryPool = nil;
SmallMPool: TDxMemoryPool = nil; //小内存块内存池
BigMPool: TDxMemoryPool = nil; //大内存块内存池
SuperBigMPool: TDxMemoryPool = nil; //超级大内存块内存池
LargeMPool: TDxMemoryPool = nil;
SPLargeMPool: TDxMemoryPool = nil;
MaxMPool: TDxMemoryPool = nil;
FMaxBlockMPool: TDxMemoryPool = nil;
///
/// 来自于utils_strings
/// 查找PSub在P中出现的第一个位置
///
///
/// 如果找到, 返回指向第一个pvSub的位置
/// 找不到返回 Nil
///
/// 数据
/// 数据长度
/// 开始位置0开始
/// 查找的数据
/// 查找的数据长度
function SearchPointer(pvSource: Pointer; pvSourceLen, pvStartIndex: Integer;
pvSub: Pointer; pvSubLen: Integer): Pointer;
var
I, j: Integer;
lvTempP, lvTempPSub, lvTempP2, lvTempPSub2:PAnsiChar;
begin
if (pvSub = nil) then
Result := nil
else
begin
Result := nil;
j := pvStartIndex;
lvTempP := PAnsiChar(pvSource);
Inc(lvTempP, pvStartIndex);
lvTempPSub := PAnsiChar(pvSub);
while j 1024 * 128 then
Result := MB_Max
else if MemSize >= MAX_SEND_BLOCK_SIZE then
Result := MB_MaxBlock
else if MemSize > 4096*4 then
Result := MB_SPLarge
else if MemSize > 2048 then
Result := MB_Large
else if MemSize > 640 then
Result := MB_Big
else if MemSize > 256 then
Result := MB_Normal
else Result := MB_Small;
end;
function SuperMemoryPool: TDxMemoryPool;
begin
if SuperBigMPool = nil then
SuperBigMPool := TDxMemoryPool.Create(2048,30,MB_SpBig,100);
Result := SuperBigMPool;
end;
function MaxMemoryPool: TDxMemoryPool;
begin
if MaxMPool = nil then
MaxMPool := TDxMemoryPool.Create(1024 * 128,30,MB_Max,100);
Result := MaxMPool;
end;
function LargeMemoryPool: TDxMemoryPool;
begin
if LargeMPool = nil then
LargeMPool := TDxMemoryPool.Create(4096,30,MB_Large,100);
Result := LargeMPool;
end;
function SuperLargeMemoryPool: TDxMemoryPool;
begin
if SPLargeMPool = nil then
SPLargeMPool := TDxMemoryPool.Create(4096*4,30,MB_SpLarge,100); //16KB
Result := SPLargeMPool;
end;
function MaxBlockMPool: TDxMemoryPool;
begin
if FMaxBlockMPool = nil then
FMaxBlockMPool := TDxMemoryPool.Create(MAX_SEND_BLOCK_SIZE,30,MB_MaxBlock,100);
Result := FMaxBlockMPool;
end;
function MemoryPool: TDxMemoryPool;
begin
if NormalMPool = nil then
NormalMPool := TDxMemoryPool.Create(640,30,MB_Normal,100);
Result := NormalMPool;
end;
function SmallMemoryPool: TDxMemoryPool;
begin
if SmallMPool = nil then
SmallMPool := TDxMemoryPool.Create(128,30,MB_Small,100); //小内存块
Result := SmallMPool;
end;
function BigMemoryPool: TDxMemoryPool;
begin
if BigMPool = nil then
BigMPool := TDxMemoryPool.Create(1024,30,MB_Big,100); //大内存块
Result := BigMPool;
end;
function GetMemBlock(BlockType: TDxMemBlockType): PMemoryBlock;
begin
case BlockType of
MB_Small: Result := SmallMemoryPool.GetMemoryBlock;
MB_Normal: Result := MemoryPool.GetMemoryBlock;
MB_Big: Result := BigMemoryPool.GetMemoryBlock;
MB_SpBig: Result := SuperMemoryPool.GetMemoryBlock;
MB_Large: Result := LargeMemoryPool.GetMemoryBlock;
MB_SPLarge: Result := SuperLargeMemoryPool.GetMemoryBlock;
MB_Max: Result := MaxMemoryPool.GetMemoryBlock;
MB_MaxBlock: Result := MaxBlockMPool.GetMemoryBlock;
else Result := nil;
end;
end;
{ TDxMemoryPool }
procedure TDxMemoryPool.Clear;
var
P,tmp: PMemoryBlock;
begin
Lock;
try
p := FUseHead;
while p <> nil do
begin
tmp := p^.Next;
FreeMem(p^.Memory);
FreeMem(p);
p := tmp;
end;
p := FUnUseHead;
while p <> nil do
begin
tmp := p^.Next;
FreeMem(p^.Memory,FBlockSize);
FreeMem(p,SizeOf(TMemoryBlock));
p := tmp;
end;
FUnUseHead := nil;
FUnUseLast := nil;
FUseHead := nil;
FUseLast := nil;
finally
Unlock;
end;
end;
constructor TDxMemoryPool.Create(BlockSize, InitCount: integer;BlockType: TDxMemBlockType;MaxFreeBlocks: Integer = 50);
var
p: PMemoryBlock;
begin
FBlockType := BlockType;
// 块大小以64字节对齐,这样的执行效率最高
if (BlockSize mod 64 = 0) then
FBlockSize := BlockSize
else
FBlockSize := (BlockSize div 64) * 64 + 64;
FMaxFreeBlocks := MaxFreeBlocks;
FCS := TCriticalSection.Create;
FMaxFreeBlocks := MaxFreeBlocks;
FUseCount := 0;
FFreeCount := InitCount;
while InitCount > 0 do
begin
GetMem(p,SizeOf(TMemoryBlock));
GetMem(p^.Memory,FBlockSize);
p^.BlockType := FBlockType;
if FUnUseHead = nil then
begin
FUnUseHead := p;
FUnUseHead^.Next := nil;
FUnUseHead.Prev := nil;
FUnUseLast := FUnUseHead;
end
else
begin
p.Prev := FUnUseLast;
p.Next := nil;
FUnUseLast.Next := p;
FUnUseLast := p;
end;
Dec(InitCount);
end;
end;
destructor TDxMemoryPool.Destroy;
begin
Clear;
FCS.Free;
inherited;
end;
procedure TDxMemoryPool.FreeMemory(P: Pointer);
var
pBlock: PMemoryBlock;
begin
if P = nil then Exit;
Lock;
try
pBlock := FUseHead;
while true do
begin
if PBlock^.Memory = p then
begin
//先判定是否是头
if pBlock = FUseHead then
begin
FUseHead := pBlock^.Next;
if FUseHead <> nil then
FUseHead^.Prev := nil;
end;
if PBlock^.Prev <> nil then
PBlock^.Prev^.Next := PBlock^.Next;
if FUseLast = pBlock then
FUseLast := FUseLast^.Prev;
if FUnUseHead = nil then
begin
FUnUseHead := pBlock;
pBlock^.Prev := nil;
FUnUseLast := pBlock;
end
else if FFreeCount + 1 < FMaxFreeBlocks then
begin
pBlock^.Prev := FUnUseLast;
FUnUseLast^.Next := pBlock;
FUnUseLast := pBlock;
end
else //直接释放
begin
FreeMem(PBlock^.Memory);
FreeMem(pBlock);
pBlock := nil;
end;
if pBlock <> nil then
begin
Inc(FFreeCount);
PBlock^.Next := nil;
end;
Dec(FUseCount);
if FUseLast = nil then
FUseHead := nil;
Break;
end;
pBlock := pBlock^.Next;
if pBlock = nil then
break;
end;
finally
Unlock;
end;
end;
procedure TDxMemoryPool.FreeMemoryBlock(p: PMemoryBlock);
begin
if p = nil then
Exit;
Lock;
try
if p^.PrevEx <> nil then
p^.PrevEx^.NextEx := p^.NextEx;//连接指向下一个
if p^.NextEx <> nil then
p^.NextEx^.PrevEx := p^.PrevEx;
//从Use列表中断开,Use列表指向P的节点的下一个
if p^.Prev <> nil then
p^.Prev^.Next := p^.Next;
if p^.Next <> nil then
p^.Next^.Prev := p^.Prev;
p^.NextEx := nil;
p^.PrevEx := nil;
if FUseLast = p then
FUseLast := FUseLast^.Prev;
if FUnUseHead = nil then
begin
FUnUseHead := p;
FUnUseHead^.Prev := nil;
FUnUseLast := p;
end
else if FFreeCount + 1 <= FMaxFreeBlocks then
begin
p^.Prev := FUnUseLast;
FUnUseLast^.Next := p;
FUnUseLast := p;
end
else
begin
FreeMem(P^.Memory);
FreeMem(P);
p := nil;
end;
Dec(FUseCount);
if p <> nil then
begin
Inc(FFreeCount);
p^.Next := nil;
end;
if FUseLast = nil then
FUseHead := nil;
finally
Unlock;
end;
end;
function TDxMemoryPool.GetMemory(Zero: Boolean): Pointer;
var
p: PMemoryBlock;
begin
Lock;
try
if FUnUseHead = nil then
begin
GetMem(p,SizeOf(TMemoryBlock));
GetMem(p^.Memory,FBlockSize);
P^.BlockType := FBlockType;
end
else //直接从链表中取
begin
p := FUnUseHead;
FUnUseHead := FUnUseHead.Next;
Dec(FFreeCount);
end;
Inc(FUseCount);
p.Next := nil;
if FUseHead = nil then
begin
FUseHead := p;
p.Prev := nil;
FUseLast := p;
end
else
begin
p.Prev := FUseLast;
FUseLast.Next := p;
FUseLast := p;
end;
Result := p^.Memory;
if Zero then
ZeroMemory(Result,FBlockSize);
finally
Unlock;
end;
end;
function TDxMemoryPool.GetMemoryBlock: PMemoryBlock;
begin
Lock;
try
if FUnUseHead = nil then
begin
GetMem(Result,SizeOf(TMemoryBlock));
GetMem(Result^.Memory,FBlockSize);
Result^.BlockType := FBlockType;
end
else //直接从链表中取
begin
Result := FUnUseHead;
FUnUseHead := FUnUseHead.Next;
Dec(FFreeCount);
end;
Inc(FUseCount);
Result.Next := nil;
result.NextEx := nil;
result.PrevEx := nil;
if FUseHead = nil then
begin
FUseHead := Result;
Result.Prev := nil;
FUseLast := FUseHead;
end
else
begin
Result.Prev := FUseLast;
FUseLast.Next := Result;
FUseLast := Result;
end;
finally
Unlock;
end;
end;
function TDxMemoryPool.InnerCreateBlock: PMemoryBlock;
begin
GetMem(Result,SizeOf(TMemoryBlock));
GetMem(result^.Memory,FBlockSize);
Result^.BlockType := FBlockType;
end;
procedure TDxMemoryPool.Lock;
begin
FCs.Enter;
end;
procedure TDxMemoryPool.Unlock;
begin
FCs.Leave;
end;
{ TDxMemoryStream }
procedure TDxMemoryStream.Clear;
begin
SetSize(0);
end;
constructor TDxMemoryStream.Create(const MemType: TDxMemBlockType = MB_Small);
begin
inherited Create;
FMemBlockType := MemType;
end;
destructor TDxMemoryStream.Destroy;
begin
SetSize(0);
inherited;
end;
function TDxMemoryStream.GetBlockSize: DWORD;
begin
case FMemBlockType of
MB_Small: Result := SmallMemoryPool.FBlockSize;
MB_Normal: Result := MemoryPool.FBlockSize;
MB_Big: Result := BigMemoryPool.FBlockSize;
MB_SpBig: Result := SuperMemoryPool.FBlockSize;
MB_Large: Result := LargeMemoryPool.FBlockSize;
MB_SPLarge: Result := SuperLargeMemoryPool.FBlockSize;
MB_Max: Result := MaxMemoryPool.FBlockSize;
MB_MaxBlock: Result := MaxBlockMPool.FBlockSize;
else Result := 0;
end;
end;
function TDxMemoryStream.GetSize: Int64;
begin
Result := FSize;
end;
procedure TDxMemoryStream.LinkToBufferList(BufList: TBufferLink);
var
tmp: PMemoryBlock;
BSize: integer;
begin
if FHead <> nil then
begin
if BufList.FHead = nil then
BufList.FHead := FHead
else
begin
FHead.PrevEx := BufList.FLast;
BufList.FLast^.NextEx := FHead;
end;
BufList.FLast := FLast;
tmp := FHead;
case FMemBlockType of
MB_Small: BSize := SmallMemoryPool.FBlockSize;
MB_Normal: BSize := MemoryPool.FBlockSize;
MB_SpBig: BSize := SuperMemoryPool.FBlockSize;
MB_Large: BSize := LargeMemoryPool.FBlockSize;
MB_SPLarge: BSize := SuperLargeMemoryPool.FBlockSize;
MB_Max: BSize := MaxMemoryPool.FBlockSize;
MB_MaxBlock: BSize := MaxBlockMPool.FBlockSize;
else BSize := BigMemoryPool.FBlockSize;
end;
while tmp <> FLast do
begin
tmp^.DataLen := BSize;
tmp := tmp^.NextEx;
end;
FLast^.DataLen := BSize - (FCapacity - FSize);
//连接到连接缓存区,就相当于本流清空
FHead := nil;
FLast := nil;
FMarkBlokPos := 0;
FPosition := 0;
FMarkBlock := nil;
FSize := 0;
FCapacity := 0;
FMemBlockCount := 0;
FCurBlockPos := 0;
FCurBlock := nil;
end;
end;
procedure TDxMemoryStream.LoadFromBufferList(BufList: TBufferLink;const DataLen: Integer);
var
Windex: Integer;
tmpBlock: PMemoryBlock;
MPool: TDxMemoryPool;
begin
SetSize(DataLen);
if FSize <> 0 then
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
tmpBlock := FHead;
for Windex := 0 to FMemBlockCount - 1 do
begin
if tmpBlock = nil then
Break;
if Windex = FMemBlockCount - 1 then
BufList.ReadBuffer(tmpBlock^.Memory,MPool.FBlockSize - (FCapacity - FSize))
else BufList.readBuffer(tmpBlock^.Memory,MPool.FBlockSize);
tmpBlock := tmpBlock^.NextEx;
end;
FPosition := 0;
FCurBlock := FHead;
FCurBlockPos := 0;
end;
end;
procedure TDxMemoryStream.LoadFromFile(const FileName: string);
var
F: TFileStream;
begin
F := TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(F);
finally
F.Free;
end;
end;
procedure TDxMemoryStream.LoadFromStream(Stream: TStream);
var
Windex: Integer;
tmpBlock: PMemoryBlock;
MPool: TDxMemoryPool;
begin
Stream.Position := 0;
SetSize(Stream.Size);
if FSize <> 0 then
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
tmpBlock := FHead;
for Windex := 0 to FMemBlockCount - 1 do
begin
if Windex = FMemBlockCount - 1 then
begin
Stream.ReadBuffer(tmpBlock^.Memory^,MPool.FBlockSize - (FCapacity - FSize));
end
else Stream.ReadBuffer(tmpBlock^.Memory^,MPool.FBlockSize);
tmpBlock := tmpBlock^.NextEx;
end;
FPosition := 0;
FCurBlock := FHead;
FCurBlockPos := 0;
end;
end;
function TDxMemoryStream.Read(var Buffer; Count: Integer): Longint;
var
p: PAnsiChar;
MPool: TDxMemoryPool;
pBuf: Pointer;
begin
if FCurBlock = nil then
Result := 0
else
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
if FPosition + Count > FSize then
Count := FSize - FPosition;
if Count = 0 then
begin
result := 0;
Exit;
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
if FCurBlock = nil then
begin
result := 0;
Exit;
end;
Result := Count;
p := @Buffer;
//先读取当前块剩下的区域
pBuf := Pointer(NativeUInt(FCurBlock^.Memory) + DWORD(FCurBlockPos));
if Count <= MPool.FBlockSize - FCurBlockPos then //足够写了
begin
Move(PBuf^,buffer,Count);
Inc(FPosition,Count);
inc(FCurBlockPos,Count);
Count := 0;
end
else
begin
Move(PBuf^,Buffer,MPool.FBlockSize - FCurBlockPos);
Dec(Count,MPool.FBlockSize - FCurBlockPos);
Inc(FPosition,MPool.FBlockSize - FCurBlockPos);
Inc(p,MPool.FBlockSize - FCurBlockPos);
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
while Count > 0 do
begin
if Count > MPool.FBlockSize then
begin
Move(FCurBlock^.Memory^,p^,MPool.FBlockSize);
Dec(Count,MPool.FBlockSize);
FCurBlockPos := MPool.FBlockSize;
Inc(FPosition,MPool.FBlockSize);
Inc(p,MPool.FBlockSize);
end
else
begin
Move(FCurBlock^.Memory^,p^,Count);
Inc(FPosition,Count);
Inc(p,Count);
FCurBlockPos := Count;
Count := 0;
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
end;
end;
end;
procedure TDxMemoryStream.ReadStream(Stream: TStream; len: Integer);
var
MPool: TDxMemoryPool;
pBuf: Pointer;
begin
if FCurBlock <> nil then
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
if FPosition + Len > FSize then
Len := FSize - FPosition;
//先读取当前块剩下的区域
pBuf := Pointer(NativeUInt(FCurBlock^.Memory) + DWORD(FCurBlockPos));
if Len <= MPool.FBlockSize - FCurBlockPos then //足够写了
begin
Stream.WriteBuffer(PBuf^,Len);
Inc(FPosition,Len);
inc(FCurBlockPos,Len);
Len := 0;
end
else
begin
Stream.WriteBuffer(PBuf^,MPool.FBlockSize - FCurBlockPos);
Dec(Len,MPool.FBlockSize - FCurBlockPos);
Inc(FPosition,MPool.FBlockSize - FCurBlockPos);
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
while Len > 0 do
begin
if Len > MPool.FBlockSize then
begin
Stream.WriteBuffer(FCurBlock^.Memory^,MPool.FBlockSize);
Dec(Len,MPool.FBlockSize);
FCurBlockPos := MPool.FBlockSize;
Inc(FPosition,MPool.FBlockSize);
end
else
begin
Stream.WriteBuffer(FCurBlock^.Memory^,Len);
Inc(FPosition,Len);
FCurBlockPos := Len;
Len := 0;
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
end;
end;
end;
procedure TDxMemoryStream.ReadToBufferList(BufList: TBufferLink; Len: Integer);
var
MPool: TDxMemoryPool;
pBuf: Pointer;
begin
if FCurBlock <> nil then
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
if FPosition + Len > FSize then
Len := FSize - FPosition;
//先读取当前块剩下的区域
pBuf := Pointer(NativeUInt(FCurBlock^.Memory) + DWORD(FCurBlockPos));
if Len <= MPool.FBlockSize - FCurBlockPos then //足够写了
begin
BufList.AddBuffer(PBuf,Len);
Inc(FPosition,Len);
inc(FCurBlockPos,Len);
Len := 0;
end
else
begin
BufList.AddBuffer(PBuf,MPool.FBlockSize - FCurBlockPos);
Dec(Len,MPool.FBlockSize - FCurBlockPos);
Inc(FPosition,MPool.FBlockSize - FCurBlockPos);
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
if FCurBlock = FLast then
begin
if Len > MPool.FBlockSize then//最后一块,并且超过了块大小
SetSize(FPosition + Len)
else if FPosition + Len > FSize then
FSize := FPosition + Len;
end;
end;
while Len > 0 do
begin
if Len > MPool.FBlockSize then
begin
BufList.AddBuffer(FCurBlock^.Memory,MPool.FBlockSize);
Dec(Len,MPool.FBlockSize);
FCurBlockPos := MPool.FBlockSize;
Inc(FPosition,MPool.FBlockSize);
end
else
begin
BufList.AddBuffer(FCurBlock^.Memory,Len);
Inc(FPosition,Len);
FCurBlockPos := Len;
Len := 0;
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
end;
end;
end;
procedure TDxMemoryStream.RestoreCurBlock;
begin
FCurBlock := FMarkBlock;
FCurBlockPos := FMarkBlokPos;
end;
procedure TDxMemoryStream.SaveCurBlock;
begin
FMarkBlock := FCurBlock;
FMarkBlokPos := FCurBlockPos;
end;
procedure TDxMemoryStream.SaveToFile(const FileName: string);
var
FStream: TFileStream;
begin
if FHead <> nil then
begin
FStream := TFileStream.Create(FileName,fmCreate);
try
SaveToStream(FStream);
finally
FStream.Free;
end;
end;
end;
procedure TDxMemoryStream.SaveToStream(Stream: TStream);
var
tmp: PMemoryBlock;
MPool: TDxMemoryPool;
begin
if FHead <> nil then
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
tmp := FHead;
while tmp <> nil do
begin
if tmp <> FLast then
Stream.WriteBuffer(tmp^.Memory^,MPool.FBlockSize)
else Stream.WriteBuffer(tmp^.Memory^,MPool.FBlockSize - FCapacity + FSize);
tmp := tmp^.NextEx;
end;
end;
end;
function TDxMemoryStream.Seek(Offset: Integer; Origin: Word): Longint;
var
MPool: TDxMemoryPool;
BIndex: integer;
FLastSize: Integer;
begin
if FHead <> nil then
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
case TSeekOrigin(Origin) of
soBeginning:
begin
if Offset < 0 then
Offset := 0;
if Offset <= FSize then
begin
FCurBlockPos := Offset mod MPool.FBlockSize;
BIndex := Offset div MPool.FBlockSize;
FCurBlock := FHead;
FPosition := FCurBlockPos;
if BIndex > 0 then
repeat
Inc(FPosition,MPool.FBlockSize);
Dec(Bindex);
FCurBlock := FCurBlock^.NextEx;
until (BIndex = 0) or (FCurBlock = nil);
end
else
begin
FCurBlock := FLast;
FCurBlockPos := FCapacity - FSize;
FPosition := Size;
end;
end;
soCurrent:
begin
if Offset > 0 then
begin
BIndex := (FCurBlockPos + Offset) div MPool.FBlockSize;
Inc(FPosition,MPool.FBlockSize - FCurBlockPos);
FCurBlockPos := (FCurBlockPos + Offset) mod MPool.FBlockSize;
Inc(FPosition,FCurBlockPos);
while BIndex > 0 do
begin
FCurBlock := FCurBlock^.NextEx;
Dec(BIndex);
if BIndex > 0 then
Inc(FPosition,MPool.FBlockSize);
end;
end
else
begin
if Offset + FCurBlockPos >= 0 then
begin
Inc(FPosition,offset);
Inc(FCurBlockPos,offset);
end
else
begin
FCurBlock := FCurBlock^.PrevEx;
if FCurBlock = nil then
begin
FCurBlockPos := 0;
FCurBlock := FHead;
end
else
begin
inc(offset,FCurBlockPos);
Dec(FPosition,FCurBlockPos);
FCurBlockPos := MPool.FBlockSize;
Seek(Offset,soCurrent);
end;
end;
end;
end;
soEnd:
begin
if Offset < 0 then
Offset := -offset;
if Offset < FSize then
begin
FLastSize := MPool.FBlockSize - FCapacity + FSize; //最后一个大小
if Offset <= FLastSize then
begin
FCurBlockPos := FLastSize - Offset;
FCurBlock := FLast;
FPosition := FSize - Offset;
end
else
begin
FCurBlock := FLast^.PrevEx;
Dec(Offset,FLastSize);
FPosition := FSize - FLastSize;
BIndex := Offset div MPool.FBlockSize;
Offset := Offset mod MPool.FBlockSize;
FCurBlockPos := MPool.FBlockSize - Offset;
Dec(FPosition,MPool.FBlockSize - FCurBlockPos);
while BIndex > 0 do
begin
FCurBlock := FCurBlock^.PrevEx;
Dec(BIndex);
Dec(FPosition,MPool.FBlockSize);
end;
end;
end
else
begin
FPosition := 0;
FCurBlockPos := 0;
FCurBlock := FHead;
end;
end;
end;
Result := FPosition;
end
else Result := 0;
end;
procedure TDxMemoryStream.SetMemBlockType(const Value: TDxMemBlockType);
begin
if FMemBlockType <> Value then
begin
Clear;
FMemBlockType := Value;
end;
end;
procedure TDxMemoryStream.SetSize(NewSize: Integer);
var
CurCount: integer;
mBlock: PMemoryBlock;
MPool: TDxMemoryPool;
begin
if FSize <> NewSize then
begin
FSize := NewSize;
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
CurCount := FCapacity div MPool.FBlockSize;
FMemBlockCount := NewSize div MPool.FBlockSize;
if NewSize mod MPool.FBlockSize <> 0 then
Inc(FMemBlockCount);
if CurCount <> FMemBlockCount then
begin
while CurCount > FMemBlockCount do
begin //内存回收
mBlock := FLast;
FLast := FLast^.PrevEx;
MPool.FreeMemoryBlock(mBlock);
Dec(CurCount);
end;
while CurCount < FMemBlockCount do
begin
mBlock := MPool.GetMemoryBlock;
mBlock.NextEx := nil;
mBlock.PrevEx := nil;
if FHead = nil then
begin
FHead := mBlock;
FLast := mBlock;
FHead.NextEx := nil;
FHead.PrevEx := nil;
end
else
begin
FLast^.NextEx := mBlock;
mBlock^.PrevEx := FLast;
FLast := mBlock;
end;
Inc(CurCount);
end;
FCapacity := MPool.FBlockSize * FMemBlockCount;
end;
if NewSize = 0 then
begin
FPosition := 0;
FCurBlock := nil;
FHead := nil;
FLast := nil;
FMarkBlokPos := 0;
FMarkBlock := nil;
FCurBlockPos := 0;
end
else
begin
if FPosition > NewSize then
Position := NewSize;
if FCurBlock = nil then
begin
FCurBlock := FHead;
FCurBlockPos := 0;
end;
end;
end;
end;
procedure TDxMemoryStream.SwapBufferBlock(Stream: TDxMemoryStream);
begin
end;
procedure TDxMemoryStream.SwapStreamLink(Stream: TDxMemoryStream);
var
OldHead,OldLast: PMemoryBlock;
OldSize,OldBlockCount: DWORD;
OldMtype: TDxMemBlockType;
OldFCapacity: LongInt;
begin
FMarkBlokPos := 0;
FMarkBlock := nil;
OldBlockCount := FMemBlockCount;
FMemBlockCount := Stream.FMemBlockCount;
OldMtype := FMemBlockType;
FMemBlockType := Stream.FMemBlockType;
OldFCapacity := FCapacity;
FCapacity := Stream.FCapacity;
OldHead := FHead;
FHead := Stream.FHead;
OldLast := FLast;
FLast := Stream.FLast;
OldSize := FSize;
FSize := Stream.Size;
FCurBlock := nil;
FCurBlockPos := 0;
FPosition := 0;
Stream.FHead := OldHead;
Stream.FLast := OldLast;
Stream.FMarkBlock := nil;
Stream.FMarkBlokPos := 0;
Stream.FMarkBlock := nil;
Stream.FCurBlock := nil;
Stream.FCurBlockPos := 0;
Stream.FMemBlockCount := OldBlockCount;
Stream.FCapacity := OldFCapacity;
Stream.FPosition := 0;
Stream.FSize := OldSize;
Stream.FMemBlockType := OldMtype;
end;
function TDxMemoryStream.Write(const Buffer; Count: Integer): Longint;
var
MPool: TDxMemoryPool;
pBuf: Pointer;
tmpBuf: PByte;
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
if FCurBlock = nil then
SetSize(Count)
else if FCurBlock = FLast then
begin
if FCurBlockPos + Count > MPool.FBlockSize then
SetSize(FSize + Count)
else if FPosition + Count > FSize then
Inc(FSize,Count);
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
end;
Result := Count;
tmpBuf := @Buffer;
//先写满当前未写满的内存块空间
pBuf := Pointer(NativeUInt(FCurBlock^.Memory) + DWORD(FCurBlockPos));
if Count <= MPool.FBlockSize - FCurBlockPos then //足够写了
begin
Move(Buffer,pBuf^,Count);
inc(FCurBlockPos,Count);
Inc(FPosition,Count);
Count := 0;
end
else
begin
Move(Buffer,PBuf^,MPool.FBlockSize - FCurBlockPos);
Dec(Count,MPool.FBlockSize - FCurBlockPos);
Inc(tmpBuf,MPool.FBlockSize - FCurBlockPos);
Inc(FPosition,MPool.FBlockSize - FCurBlockPos);
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
if FCurBlock = FLast then
begin
if Count > MPool.FBlockSize then//最后一块,并且超过了块大小
SetSize(FPosition + Count)
else if FPosition + Count > FSize then
FSize := FPosition + Count;
end;
end;
while Count > 0 do
begin
if Count > MPool.FBlockSize then
begin
Move(tmpBuf^,FCurBlock^.Memory^,MPool.FBlockSize);
Inc(tmpBuf,MPool.FBlockSize);
Dec(Count,MPool.FBlockSize);
FCurBlockPos := MPool.FBlockSize;
Inc(FPosition,MPool.FBlockSize);
end
else
begin
Move(tmpBuf^,FCurBlock^.Memory^,Count);
Inc(FPosition,Count);
Inc(tmpBuf,Count);
FCurBlockPos := Count;
Count := 0;
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
if FCurBlock = FLast then
begin
if Count > MPool.FBlockSize then//最后一块,并且超过了块大小
SetSize(FPosition + Count)
else if FPosition + Count > FSize then
FSize := FPosition + Count;
end;
end;
end;
if FCurBlock = nil then //为空,表示所有数据全部刚刚写完,需要重新分配一个内存
begin
FCurBlockPos := MPool.FBlockSize;
FCurBlock := FLast;
end;
end;
procedure TDxMemoryStream.WriteStream(Stream: TStream; Len: Integer);
var
MPool: TDxMemoryPool;
pBuf: Pointer;
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
if FCurBlock = nil then
SetSize(Len)
else if FCurBlock = FLast then
begin
if FCurBlockPos + Len > MPool.FBlockSize then
SetSize(Len+FSize)
else if FPosition + Len > FSize then
Inc(FSize,Len);
end;
//先写满当前未写满的内存块空间
pBuf := Pointer(NativeUInt(FCurBlock^.Memory) + DWORD(FCurBlockPos));
if Len <= MPool.FBlockSize - FCurBlockPos then //足够写了
begin
Stream.ReadBuffer(PBuf^,Len);
inc(FCurBlockPos,Len);
Inc(FPosition,Len);
Len := 0;
end
else
begin
Stream.ReadBuffer(PBuf^,MPool.FBlockSize - FCurBlockPos);
Dec(Len,MPool.FBlockSize - FCurBlockPos);
Inc(FPosition,MPool.FBlockSize - FCurBlockPos);
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
if FCurBlock = FLast then
begin
if Len > MPool.FBlockSize then//最后一块了,并且超过了块大小
SetSize(FPosition + Len)
else if FPosition + Len > FSize then
FSize := FPosition + Len;
end;
end;
while Len > 0 do
begin
if Len > MPool.FBlockSize then
begin
Stream.ReadBuffer(FCurBlock^.Memory^,MPool.FBlockSize);
Dec(Len,MPool.FBlockSize);
FCurBlockPos := MPool.FBlockSize;
Inc(FPosition,MPool.FBlockSize);
end
else
begin
Stream.ReadBuffer(FCurBlock^.Memory^,Len);
Inc(FPosition,Len);
FCurBlockPos := Len;
Len := 0;
end;
if FCurBlockPos = MPool.FBlockSize then
begin
FCurBlock := FCurBlock^.NextEx;
FCurBlockPos := 0;
if FCurBlock = FLast then
begin
if Len > MPool.FBlockSize then//最后一块了,并且超过了块大小
SetSize(FPosition + Len)
else if FPosition + Len > FSize then
FSize := FPosition + Len;
end;
end;
end;
end;
{ TBufferLink }
procedure TBufferLink.AddBuffer(buf: PAnsiChar; len: Cardinal);
var
MemBlock: PMemoryBlock;
BlockSize,WSize: NativeUInt;
pBuf: PAnsiChar;
MPool: TDxMemoryPool;
begin
if FLast <> nil then
begin
//先写入空白内容数据
case FLast^.BlockType of
MB_Small: BlockSize := SmallMemoryPool.FBlockSize;
MB_Normal: BlockSize := MemoryPool.FBlockSize;
MB_SpBig: BlockSize := SuperMemoryPool.FBlockSize;
MB_Large: BlockSize := LargeMemoryPool.FBlockSize;
MB_SPLarge: BlockSize := SuperLargeMemoryPool.FBlockSize;
MB_Max: BlockSize := MaxMemoryPool.FBlockSize;
MB_MaxBlock: BlockSize := MaxBlockMPool.FBlockSize;
else BlockSize := BigMemoryPool.FBlockSize;
end;
if (FLast^.DataLen <> BlockSize) then
begin
WSize := BlockSize - FLast^.DataLen;
pBuf := FLast^.Memory;
Inc(PBuf,FLast^.DataLen);
if WSize >= len then
begin
Move(buf^,PBuf^,len);
Inc(FLast^.DataLen,len);
len := 0;
end
else
begin
Move(buf^,PBuf^,WSize);
Dec(len,WSize);
Inc(buf,WSize);
FLast^.DataLen := BlockSize;
end;
end;
end;
if len = 0 then
Exit;
if len <= DWORD(SmallMemoryPool.FBlockSize) then
MPool := SmallMemoryPool
else if len <= DWORD(MemoryPool.FBlockSize) then
MPool := MemoryPool
else if len <= DWORD(BigMemoryPool.FBlockSize) then
MPool := BigMemoryPool
else if len <= DWORD(SuperMemoryPool.FBlockSize) then
MPool := SuperMemoryPool
else if len <= DWORD(LargeMemoryPool.FBlockSize) then
MPool := LargeMemoryPool
else if len <= DWORD(SuperLargeMemoryPool.FBlockSize) then
MPool := SuperLargeMemoryPool
else if len <= MaxBlockMPool.FBlockSize then
MPool := MaxBlockMPool
else
MPool := nil;
if MPool <> nil then
begin
MemBlock := MPool.GetMemoryBlock;
MemBlock^.DataLen := len;
MemBlock^.NextEx := nil;
MemBlock^.PrevEx := nil;
Move(buf^,MemBlock^.Memory^,len);
if FHead = nil then
FHead := MemBlock;
if FLast = nil then
FLast := MemBlock
else
begin
FLast^.NextEx := MemBlock;
MemBlock^.PrevEx := FLast;
FLast := MemBlock;
end;
end
else
begin
MemBlock := MaxMemoryPool.GetMemoryBlock;
MemBlock^.NextEx := nil;
MemBlock^.PrevEx := nil;
if MaxMemoryPool.FBlockSize <= Len then
begin
MemBlock^.DataLen := MaxMemoryPool.FBlockSize;
Move(buf^,MemBlock^.Memory^,MemBlock^.DataLen)
end
else
begin
MemBlock^.DataLen := Len;
Move(buf^,MemBlock^.Memory^,len);
end;
if FHead = nil then
FHead := MemBlock;
if FLast = nil then
FLast := MemBlock
else
begin
FLast^.NextEx := MemBlock;
MemBlock^.PrevEx := FLast;
FLast := MemBlock;
end;
Dec(len,MemBlock^.DataLen);
Inc(buf,MemBlock^.DataLen);
if Len > 0 then
AddBuffer(buf,len);
end;
end;
procedure TBufferLink.AddMemBlockLink(MemBlockLink: PMemoryBlock);
begin
MemBlockLink^.NextEx := nil;
MemBlockLink^.PrevEx := nil;
if FHead = nil then
FHead := MemBlockLink;
if FLast = nil then
FLast := MemBlockLink
else
begin
FLast^.NextEx := MemBlockLink;
MemBlockLink^.PrevEx := FLast;
FLast := MemBlockLink;
end;
end;
procedure TBufferLink.clearBuffer;
var
lvBuf, lvFreeBuf: PMemoryBlock;
begin
lvBuf := FLast;
while lvBuf <> nil do
begin
lvFreeBuf := lvBuf;
lvBuf := lvBuf.PrevEx;
case lvFreeBuf^.BlockType of
MB_Small: SmallMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_Normal: MemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_SpBig: SuperMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_Large: LargeMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_SPLarge: SuperLargeMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_Max: MaxMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_MaxBlock: MaxBlockMPool.FreeMemoryBlock(lvFreeBuf);
else BigMemoryPool.FreeMemoryBlock(lvFreeBuf);
end;
end;
FHead := nil;
FLast := nil;
FRead := nil;
FReadPosition := 0;
FMark := nil;
FMarkPosition := 0;
end;
procedure TBufferLink.clearHaveReadBuffer;
var
lvBuf, lvFreeBuf: PMemoryBlock;
begin
if FRead = nil then exit;
lvBuf := FRead.PrevEx;
while lvBuf <> nil do
begin
lvFreeBuf :=lvBuf;
lvBuf := lvBuf.PrevEx;
case lvFreeBuf^.BlockType of
MB_Small: SmallMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_Normal: MemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_SpBig: SuperMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_Large: LargeMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_SPLarge: SuperLargeMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_Max: MaxMemoryPool.FreeMemoryBlock(lvFreeBuf);
MB_MaxBlock: MaxBlockMPool.FreeMemoryBlock(lvFreeBuf);
else BigMemoryPool.FreeMemoryBlock(lvFreeBuf);
end;
end;
//之前都被清理
FRead.PrevEx := nil;
FHead := FRead;
end;
constructor TBufferLink.Create;
begin
inherited Create;
FReadPosition := 0;
end;
destructor TBufferLink.Destroy;
begin
clearBuffer;
inherited;
end;
function TBufferLink.FirstBlock: PMemoryBlock;
begin
Result := FHead;
end;
function TBufferLink.GetCurBlock: PMemoryBlock;
begin
Result := FRead;
if Result = nil then
Result := FHead;
end;
function TBufferLink.InnerReadBuf(const pvBufRecord: PMemoryBlock;
pvStartPostion: Cardinal; buf: PAnsiChar; len: Cardinal): Cardinal;
var
lvValidCount:Cardinal;
begin
Result := 0;
if pvBufRecord <> nil then
begin
lvValidCount := pvBufRecord.Datalen - pvStartPostion;//本块内存还剩下的内存数据
if lvValidCount <= 0 then
Result := 0
else
begin
if len <= lvValidCount then //数据全部在本块内存中获取到
begin
CopyMemory(buf, Pointer(NativeUInt(pvBufRecord.Memory) + pvStartPostion), len);
Result := len;
end
else
begin
CopyMemory(buf, Pointer(NativeUInt(pvBufRecord.Memory) + pvStartPostion), lvValidCount);
Result := lvValidCount; //本块内存中获取的内存数据不够,返回本块读取的剩下的数据,需要到下一块内存继续读取
end;
end;
end;
end;
function TBufferLink.readBuffer(const buf: PAnsiChar;
len: Cardinal): Cardinal;
var
lvBuf: PMemoryBlock;
lvPosition, l, lvReadCount, lvRemain:Cardinal;
begin
lvReadCount := 0;
lvBuf := FRead;
lvPosition := FReadPosition;
if lvBuf = nil then
begin
lvBuf := FHead;
lvPosition := 0;
end;
if lvBuf <> nil then
begin
lvRemain := len;
while lvBuf <> nil do
begin
l := InnerReadBuf(lvBuf, lvPosition, Pointer(NativeUInt(buf) + lvReadCount), lvRemain);
if l = lvRemain then
begin
//读完
inc(lvReadCount, l);
Inc(lvPosition, l);
FReadPosition := lvPosition;
FRead := lvBuf;
Break;
end
else if l < lvRemain then //读取的比需要读的长度小
begin
lvRemain := lvRemain - l;
inc(lvReadCount, l);
Inc(lvPosition, l);
FReadPosition := lvPosition;
FRead := lvBuf;
lvBuf := lvBuf.NextEx;
if lvBuf <> nil then //读下一个
begin
FRead := lvBuf;
FReadPosition := 0;
lvPosition := 0;
end;
end;
end;
Result := lvReadCount;
end
else Result := 0;
end;
procedure TBufferLink.RemoveBlock(Block: PMemoryBlock;const FreeBlock: Boolean = False);
begin
if Block^.NextEx <> nil then
Block^.NextEx^.PrevEx := Block^.PrevEx;
if Block^.PrevEx <> nil then
Block^.PrevEx^.NextEx := Block^.NextEx;
if Block = FHead then
FHead := Block^.NextEx;
if Block = FLast then
FLast := Block^.PrevEx;
if FreeBlock then
FreeMemBlock(Block);
end;
procedure TBufferLink.restoreReaderIndex;
begin
FRead := FMark;
FReadPosition := FMarkPosition;
end;
procedure TBufferLink.markReaderIndex;
begin
FMark := FRead;
FMarkPosition := FReadPosition;
end;
function TBufferLink.SearchBuffer(subBuf:PAnsiChar; subBufLen:Cardinal):
Integer;
var
lvBufBlock: PMemoryBlock;
LCompLen,HasCompLen:Cardinal;
SearchStart,SubPointer,search1,LLast: PAnsiChar;
LPosition,BlockSize,LResult,HasRead:Integer;
FHasFound: Boolean;
BlockIndex: Integer;
begin
Result := -1;
lvBufBlock := FRead;
if lvBufBlock = nil then
begin // 从头开始
lvBufBlock := FHead;
end;
BlockIndex := 0;
HasRead := 0;
if lvBufBlock <> nil then
begin
FHasFound := False;
SubPointer := subBuf;
Result := FReadPosition;
LPosition := FReadPosition;
HasCompLen := 0;
while lvBufBlock <> nil do
begin
case lvBufBlock.BlockType of
MB_Small: BlockSize := SmallMemoryPool.FBlockSize;
MB_Normal: BlockSize := MemoryPool.FBlockSize;
MB_SpBig: BlockSize := SuperMemoryPool.FBlockSize;
MB_Large: BlockSize := LargeMemoryPool.FBlockSize;
MB_SPLarge: BlockSize := SuperLargeMemoryPool.FBlockSize;
MB_Max: BlockSize := MaxMemoryPool.FBlockSize;
MB_MaxBlock: BlockSize := MaxBlockMPool.FBlockSize;
else BlockSize := BigMemoryPool.FBlockSize;
end;
SearchStart := PAnsiChar(lvBufBlock.Memory);
LLast := SearchStart;
Inc(LLast,BlockSize);
inc(SearchStart,LPosition);
while LPosition < BlockSize do
begin
if SearchStart^ = SubPointer^ then //匹配到,匹配后面的
begin
LCompLen := 1 + HasCompLen;
search1 := SearchStart;
if BlockIndex = 0 then
LResult := Integer(search1)- Integer(PAnsiChar(lvBufBlock.Memory)) - FReadPosition
else LResult := Integer(search1)- Integer(PAnsiChar(lvBufBlock.Memory));
Inc(search1);
Inc(SubPointer);
while LCompLen < subBufLen do
begin
if Integer(search1) = integer(LLast) then //已经匹配到末尾
begin
HasCompLen := LCompLen;
Break;
end
else if search1^ = subPointer^ then
begin
Inc(search1);
Inc(SubPointer);
Inc(LCompLen);
Inc(LResult);
end
else
begin
if Integer(search1) <> integer(LLast) then
begin
SubPointer := subBuf;
HasCompLen := 0;
end
else HasCompLen := LCompLen;
Break;
end;
end;
FHasFound := LCompLen = subBufLen;
if FHasFound then
begin
Result := HasRead + LResult - subBufLen + 1;
Break;
end;
end;
Inc(LPosition);
Inc(SearchStart);
end;
if FHasFound then
Break
else Result := -1; // 感谢[杭州]军 444356747反馈
if BlockIndex = 0 then
HasRead := BlockSize - FReadPosition
else Inc(HasRead,BlockSize);
Inc(BlockIndex);
lvBufBlock := lvBufBlock^.NextEx;
LPosition := 0;
//
{lvPRes := SearchPointer(lvBufBlock.Memory, lvBufBlock.DataLen, lvPosition, subBuf, subBufLen);
if lvPRes <> nil then
begin
x := PAnsiChar(lvPRes) - PAnsiChar(lvBufBlock.Memory) - lvPosition;
Result := l + x;
Break;
end
else
begin
l := l + lvBufBlock.DataLen - lvPosition;
// 查找下一块
lvBufBlock := lvBufBlock.NextEx;
lvPosition := 0;
end;}
end;
end;
end;
function TBufferLink.validCount: Integer;
var
lvNext: PMemoryBlock;
begin
Result := 0;
if FRead = nil then
lvNext:= FHead
else
begin
Result := FRead.DataLen - FReadPosition;
lvNext := FRead.NextEx;
end;
while lvNext <> nil do
begin
Inc(Result, lvNext.DataLen);
lvNext := lvNext.NextEx;
end;
end;
function TBufferLink.Skip(len: Cardinal): Cardinal;
var
lvBuf: PMemoryBlock;
lvPosition, l, lvReadCount, lvRemain:Cardinal;
begin
lvReadCount := 0;
lvBuf := FRead;
lvPosition := FReadPosition;
if lvBuf = nil then
begin
lvBuf := FHead;
lvPosition := 0;
end;
if lvBuf <> nil then
begin
lvRemain := len;
while lvBuf <> nil do
begin
l := lvBuf.Datalen - lvPosition;//本块内存还剩下的内存数据;
if l >= lvRemain then
begin
//读完
inc(lvReadCount, lvRemain);
Inc(lvPosition, lvRemain);
FReadPosition := lvPosition;
FRead := lvBuf;
Break;
end
else if l < lvRemain then //读取的比需要读的长度小
begin
lvRemain := lvRemain - l;
inc(lvReadCount, l);
Inc(lvPosition, l);
FReadPosition := lvPosition;
FRead := lvBuf;
lvBuf := lvBuf.NextEx;
if lvBuf <> nil then //读下一个
begin
FRead := lvBuf;
FReadPosition := 0;
lvPosition := 0;
end;
end;
end;
Result := lvReadCount;
end
else Result := 0;
end;
{ TDxObjectPool }
constructor TDxObjectPool.Create(AMaxCount: Integer);
begin
FUses := TList.Create;
FUnUses := TList.Create;
FMaxObjCount := AMaxCount;
FLocker := TCriticalSection.Create;
end;
constructor TDxObjectPool.Create(AMaxCount: Integer; ObjClass: TClass);
begin
Create(AMaxCount);
FObjClass := ObjClass;
end;
destructor TDxObjectPool.Destroy;
begin
FLocker.Free;
while FUses.Count > 0 do
begin
TObject(FUses[FUses.Count - 1]).Free;
FUses.Delete(FUses.Count - 1);
end;
while FUnUses.Count > 0 do
begin
TObject(FUnUses[FUnUses.Count - 1]).Free;
FUnUses.Delete(FUnUses.Count - 1);
end;
FUses.Free;
FUnUses.Free;
inherited;
end;
procedure TDxObjectPool.FreeObject(Obj: TObject);
begin
FLocker.Enter;
try
FUses.Remove(obj);
if FUnUses.Count + 1 > FMaxObjCount then
obj.Free
else FUnUses.Add(Obj);
finally
FLocker.Leave;
end;
end;
function TDxObjectPool.GetObject: TObject;
begin
FLocker.Enter;
try
if FUnUses.Count = 0 then
begin
if Assigned(FOnCreateObject) then
FOnCreateObject(self,Result)
else if FObjClass.InheritsFrom(TComponent) then
Result := TComponentClass(FObjClass).Create(nil)
else Result := FObjClass.Create;
if Result <> nil then
FUses.Add(Result);
end
else
begin
Result := TObject(FUnUses[FUnUses.Count - 1]);
FUnUses.Delete(FUnUses.Count - 1);
FUses.Add(Result)
end;
finally
FLocker.Leave;
end;
end;
procedure FreeObjPool;
begin
if NormalMPool <> nil then
NormalMPool.Free;
if SmallMPool <> nil then
SmallMPool.Free;
if BigMPool <> nil then
BigMPool.Free;
if SuperBigMPool <> nil then
SuperBigMPool.Free;
if LargeMPool <> nil then
LargeMPool.Free;
if SPLargeMPool <> nil then
SPLargeMPool.Free;
if MaxMPool <> nil then
MaxMPool.Free;
if FMaxBlockMPool <>nil then
FMaxBlockMPool.Free;
end;
{ TDxRingStream }
constructor TDxRingStream.Create(const RingBufferSize: DWORD;
const MemType: TDxMemBlockType);
begin
inherited Create;
FMemBlockType := MemType;
if RingBufferSize <> 0 then
SetSize(RingBufferSize);
end;
function TDxRingStream.GetCanWriteSize: Integer;
begin
if FWritePosition > FReadPosition then
Result := FSize - FWritePosition + FReadPosition
else if FWritePosition < FReadPosition then
Result := FReadPosition - FWritePosition
else if FReadPosition = 0 then
Result := FSize
else Result := 0;
end;
function TDxRingStream.GetDataSize: Integer;
begin
if FWritePosition > FReadPosition then
Result := FWritePosition - FReadPosition
else if FWritePosition < FReadPosition then
Result := FWritePosition + FSize - FReadPosition
else if FWritePosition = 0 then
Result := 0
else Result := FSize;
end;
function TDxRingStream.GetSize: Int64;
begin
Result := FSize;
end;
procedure TDxRingStream.markReaderIndex;
begin
FMarkRead := FReadBlock;
FMarkReadPosition := FReadBlockPos;
end;
procedure TDxRingStream.markWriterIndex;
begin
FMarkWrite := FWriteBlock;
FMarkWritePosition := FWriteBlockPos;
end;
function TDxRingStream.Read(var Buffer; Count: Integer): Longint;
var
p: PAnsiChar;
MPool: TDxMemoryPool;
pBuf: Pointer;
CanReadSize: Integer;
begin
if FReadBlock = nil then
Result := 0
else
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
CanReadSize := DataSize;
if Count > CanReadSize then
Count := CanReadSize;
if Count = 0 then
begin
result := 0;
Exit;
end;
if FReadBlockPos = MPool.FBlockSize then
begin
FReadBlock := FReadBlock^.NextEx;
FReadBlockPos := 0;
end;
if FReadBlock = nil then
begin
result := 0;
Exit;
end;
Result := Count;
p := @Buffer;
//先读取当前块剩下的区域
pBuf := Pointer(NativeUInt(FReadBlock^.Memory) + DWORD(FReadBlockPos));
if Count <= MPool.FBlockSize - FReadBlockPos then //足够写了
begin
Move(PBuf^,buffer,Count);
Inc(FReadPosition,Count);
inc(FReadBlockPos,Count);
Count := 0;
end
else
begin
Move(PBuf^,Buffer,MPool.FBlockSize - FReadBlockPos);
Dec(Count,MPool.FBlockSize - FReadBlockPos);
Inc(FReadPosition,MPool.FBlockSize - FReadBlockPos);
Inc(p,MPool.FBlockSize - FReadBlockPos);
FReadBlock := FReadBlock^.NextEx;
FReadBlockPos := 0;
end;
if FReadBlockPos = MPool.FBlockSize then
begin
FReadBlock := FReadBlock^.NextEx;
FReadBlockPos := 0;
end;
while Count > 0 do
begin
if Count > MPool.FBlockSize then
begin
Move(FReadBlock^.Memory^,p^,MPool.FBlockSize);
Dec(Count,MPool.FBlockSize);
FReadBlockPos := MPool.FBlockSize;
Inc(FReadPosition,MPool.FBlockSize);
Inc(p,MPool.FBlockSize);
end
else
begin
Move(FReadBlock^.Memory^,p^,Count);
Inc(FReadPosition,Count);
Inc(p,Count);
FReadBlockPos := Count;
Count := 0;
end;
if FReadBlockPos = MPool.FBlockSize then
begin
FReadBlock := FReadBlock^.NextEx;
FReadBlockPos := 0;
end;
end;
end;
end;
procedure TDxRingStream.ReadBuffer(var Buffer; Count: Integer);
begin
read(buffer,Count);
end;
procedure TDxRingStream.restoreReaderIndex;
begin
FReadBlock := FMarkRead;
FReadBlockPos := FMarkReadPosition;
end;
procedure TDxRingStream.restoreWriterIndex;
begin
FWriteBlock := FMarkWrite;
FWriteBlockPos := FMarkWritePosition;
end;
function TDxRingStream.Seek(Offset: Integer; Origin: Word): Longint;
begin
Result := 0;
end;
function TDxRingStream.SeekReadWrite(Offset: Integer; Origin: TSeekOrigin;
SeekRead: Boolean): Longint;
var
MPool: TDxMemoryPool;
BIndex: integer;
FLastSize: Integer;
begin
if FHead <> nil then
begin
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
case TSeekOrigin(Origin) of
soBeginning:
begin
if Offset < 0 then
Offset := 0;
if Offset <= FSize then
begin
BIndex := Offset div MPool.FBlockSize;
if SeekRead then
begin
FReadBlockPos := Offset mod MPool.FBlockSize;
FReadBlock := FHead;
FReadPosition := FReadBlockPos;
end
else
begin
FWriteBlockPos := Offset mod MPool.FBlockSize;
FWriteBlock := FHead;
FWritePosition := FWriteBlockPos;
end;
if BIndex > 0 then
begin
if SeekRead then
repeat
Inc(FReadPosition,MPool.FBlockSize);
Dec(Bindex);
FReadBlock := FReadBlock^.NextEx;
until (BIndex = 0) or (FReadBlock = nil)
else
repeat
Inc(FWritePosition,MPool.FBlockSize);
Dec(Bindex);
FWriteBlock := FWriteBlock^.NextEx;
until (BIndex = 0) or (FWriteBlock = nil)
end;
end
else
begin
if SeekRead then
begin
FReadBlock := FLast;
FReadBlockPos := FCapacity - FSize;
FReadPosition := Size;
end
else
begin
FWriteBlock := FLast;
FWriteBlockPos := FCapacity - FSize;
FWritePosition := Size;
end;
end;
end;
soCurrent:
begin
if Offset > 0 then
begin
if SeekRead then
begin
BIndex := (FReadBlockPos + Offset) div MPool.FBlockSize;
Inc(FReadPosition,MPool.FBlockSize - FReadBlockPos);
FReadBlockPos := (FReadBlockPos + Offset) mod MPool.FBlockSize;
Inc(FReadPosition,FReadBlockPos);
while BIndex > 0 do
begin
FReadBlock := FReadBlock^.NextEx;
Dec(BIndex);
if BIndex > 0 then
Inc(FReadPosition,MPool.FBlockSize);
end;
end
else
begin
BIndex := (FWriteBlockPos + Offset) div MPool.FBlockSize;
Inc(FWritePosition,MPool.FBlockSize - FWriteBlockPos);
FWriteBlockPos := (FWriteBlockPos + Offset) mod MPool.FBlockSize;
Inc(FWritePosition,FWriteBlockPos);
while BIndex > 0 do
begin
FWRiteBlock := FWRiteBlock^.NextEx;
Dec(BIndex);
if BIndex > 0 then
Inc(FWritePosition,MPool.FBlockSize);
end;
end;
end
else
begin
if SeekRead then
begin
if Offset + FReadBlockPos >= 0 then
begin
Inc(FReadPosition,offset);
Inc(FReadBlockPos,offset);
end
else
begin
FReadBlock := FReadBlock^.PrevEx;
if FReadBlock = nil then
begin
FReadBlockPos := 0;
FReadBlock := FHead;
end
else
begin
inc(offset,FReadBlockPos);
Dec(FReadPosition,FReadBlockPos);
FReadBlockPos := MPool.FBlockSize;
SeekReadWrite(Offset,soCurrent,SeekRead);
end;
end;
end
else
begin
if Offset + FWriteBlockPos >= 0 then
begin
Inc(FWritePosition,offset);
Inc(FWriteBlockPos,offset);
end
else
begin
FWriteBlock := FWriteBlock^.PrevEx;
if FWriteBlock = nil then
begin
FWriteBlockPos := 0;
FWriteBlock := FHead;
end
else
begin
inc(offset,FWriteBlockPos);
Dec(FWritePosition,FWriteBlockPos);
FWriteBlockPos := MPool.FBlockSize;
SeekReadWrite(Offset,soCurrent,SeekRead);
end;
end;
end;
end;
end;
soEnd:
begin
if Offset < 0 then
Offset := -offset;
if Offset < FSize then
begin
FLastSize := MPool.FBlockSize - FCapacity + FSize; //最后一个大小
if Offset <= FLastSize then
begin
if SeekRead then
begin
FReadBlockPos := FLastSize - Offset;
FReadBlock := FLast;
FReadPosition := FSize - Offset;
end
else
begin
FWriteBlockPos := FLastSize - Offset;
FWriteBlock := FLast;
FWritePosition := FSize - Offset;
end;
end
else
begin
Dec(Offset,FLastSize);
if SeekRead then
begin
FReadBlock := FLast^.PrevEx;
FReadPosition := FSize - FLastSize;
end
else
begin
FWriteBlock := FLast^.PrevEx;
FWritePosition := FSize - FLastSize;
end;
BIndex := Offset div MPool.FBlockSize;
Offset := Offset mod MPool.FBlockSize;
if SeekRead then
begin
FReadBlockPos := MPool.FBlockSize - Offset;
Dec(FReadPosition,MPool.FBlockSize - FReadBlockPos);
while BIndex > 0 do
begin
FReadBlock := FReadBlock^.PrevEx;
Dec(BIndex);
Dec(FReadPosition,MPool.FBlockSize);
end;
end
else
begin
FWriteBlockPos := MPool.FBlockSize - Offset;
Dec(FWritePosition,MPool.FBlockSize - FWriteBlockPos);
while BIndex > 0 do
begin
FWriteBlock := FWriteBlock^.PrevEx;
Dec(BIndex);
Dec(FWritePosition,MPool.FBlockSize);
end;
end;
end;
end
else if SeekRead then
begin
FReadPosition := 0;
FReadBlockPos := 0;
FReadBlock := FHead;
end
else
begin
FWritePosition := 0;
FWriteBlockPos := 0;
FWriteBlock := FHead;
end;
end;
end;
if SeekRead then
Result := FReadPosition
else Result := FWritePosition;
end
else Result := 0;
end;
procedure TDxRingStream.SetReadPosition(const Value: Integer);
begin
SeekReadWrite(Value, soBeginning,true);
end;
procedure TDxRingStream.SetSize(NewSize: Integer);
var
CurCount: integer;
mBlock: PMemoryBlock;
MPool: TDxMemoryPool;
begin
if FSize <> NewSize then
begin
FSize := NewSize;
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
CurCount := FCapacity div MPool.FBlockSize;
FMemBlockCount := NewSize div MPool.FBlockSize;
if NewSize mod MPool.FBlockSize <> 0 then
Inc(FMemBlockCount);
if CurCount <> FMemBlockCount then
begin
while CurCount > FMemBlockCount do
begin //内存回收
mBlock := FLast;
FLast := FLast^.PrevEx;
MPool.FreeMemoryBlock(mBlock);
Dec(CurCount);
end;
while CurCount < FMemBlockCount do
begin
mBlock := MPool.GetMemoryBlock;
mBlock.NextEx := nil;
mBlock.PrevEx := nil;
if FHead = nil then
begin
FHead := mBlock;
FLast := mBlock;
FHead.NextEx := nil;
FHead.PrevEx := nil;
end
else
begin
FLast^.NextEx := mBlock;
mBlock^.PrevEx := FLast;
FLast := mBlock;
end;
Inc(CurCount);
end;
FCapacity := MPool.FBlockSize * FMemBlockCount;
if FLast <> nil then //指向头部形成一个环形
FLast.NextEx := FHead;
end;
if NewSize = 0 then
begin
FReadBlock := nil;
FWriteBlock := nil;
FHead := nil;
FLast := nil;
FWriteBlockPos := 0;
FReadBlockPos := 0;
end
else
begin
if FReadPosition > NewSize then
ReadPosition := NewSize;
if FReadBlock = nil then
begin
FReadBlock := FHead;
FReadBlockPos := 0;
FReadPosition := 0;
end;
if FWritePosition > NewSize then
WritePosition := NewSize;
if FWriteBlock = nil then
begin
FWriteBlock := FHead;
FWriteBlockPos := 0;
FWritePosition := 0;
end;
end;
end;
end;
procedure TDxRingStream.SetWritePostion(const Value: Integer);
begin
SeekReadWrite(Value, soBeginning,False);
end;
function TDxRingStream.Write(const Buffer; Count: Integer): Longint;
var
MPool: TDxMemoryPool;
pBuf: Pointer;
tmpBuf: PByte;
CSize: Integer;
begin
CSize := CanWriteSize;
if CSize = 0 then
begin
Result := 0;
Exit;
end
else if Count > CSize then
Count := CSize;
case FMemBlockType of
MB_Small: MPool := SmallMemoryPool;
MB_Normal: MPool := MemoryPool;
MB_SpBig: MPool := SuperMemoryPool;
MB_Large: MPool := LargeMemoryPool;
MB_SPLarge: MPool := SuperLargeMemoryPool;
MB_Max: MPool := MaxMemoryPool;
MB_MaxBlock: MPool := MaxBlockMPool;
else MPool := BigMemoryPool;
end;
if FWriteBlockPos = MPool.FBlockSize then
begin
FWriteBlock := FWriteBlock^.NextEx;
FWriteBlockPos := 0;
end;
Result := Count;
tmpBuf := @Buffer;
//先写满当前未写满的内存块空间
pBuf := Pointer(NativeUInt(FWriteBlock^.Memory) + DWORD(FWriteBlockPos));
if Count <= MPool.FBlockSize - FWriteBlockPos then //足够写了
begin
Move(Buffer,pBuf^,Count);
inc(FWriteBlockPos,Count);
Inc(FWritePosition,Count);
Count := 0;
end
else
begin
Move(Buffer,PBuf^,MPool.FBlockSize - FWriteBlockPos);
Dec(Count,MPool.FBlockSize - FWriteBlockPos);
Inc(tmpBuf,MPool.FBlockSize - FWriteBlockPos);
Inc(FWritePosition,MPool.FBlockSize - FWriteBlockPos);
FWriteBlock := FWriteBlock^.NextEx;
FWriteBlockPos := 0;
end;
while Count > 0 do
begin
if Count > MPool.FBlockSize then
begin
Move(tmpBuf^,FWriteBlock^.Memory^,MPool.FBlockSize);
Inc(tmpBuf,MPool.FBlockSize);
Dec(Count,MPool.FBlockSize);
FWriteBlockPos := MPool.FBlockSize;
Inc(FWritePosition,MPool.FBlockSize);
end
else
begin
Move(tmpBuf^,FWriteBlock^.Memory^,Count);
Inc(FWritePosition,Count);
Inc(tmpBuf,Count);
FWriteBlockPos := Count;
Count := 0;
end;
if FWriteBlockPos = MPool.FBlockSize then
begin
FWriteBlock := FWriteBlock^.NextEx;
FWriteBlockPos := 0;
end;
end;
end;
procedure TDxRingStream.WriteBuffer(const Buffer; Count: Integer);
begin
Write(Buffer,Count)
end;
procedure FreeMemBlock(Block: PMemoryBlock);
begin
case Block^.BlockType of
MB_Small: SmallMemoryPool.FreeMemoryBlock(Block);
MB_Normal: MemoryPool.FreeMemoryBlock(Block);
MB_SpBig: SuperMemoryPool.FreeMemoryBlock(Block);
MB_Large: LargeMemoryPool.FreeMemoryBlock(Block);
MB_SPLarge: SuperLargeMemoryPool.FreeMemoryBlock(Block);
MB_Max: MaxMemoryPool.FreeMemoryBlock(Block);
MB_MaxBlock: MaxBlockMPool.FreeMemoryBlock(Block);
else BigMemoryPool.FreeMemoryBlock(Block);
end;
end;
initialization
finalization
FreeObjPool;
end.