// HRBuffers v0.3.1 (03.Aug.2000) // Simple buffer classes // by Colin A Ridgewell // // Copyright (C) 1999,2000 Hayden-R Ltd // http://www.haydenr.com // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along // with this program (gnu_license.htm); if not, write to the // // Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // To contact us via e-mail use the following addresses... // // bug@haydenr.u-net.com - to report a bug // support@haydenr.u-net.com - for general support // wishlist@haydenr.u-net.com - add new requirement to wish list // unit HRBuffers; interface uses Classes, SysUtils; type {Base buffer.} THRBuffer=class(TObject) private FBuffer:PChar; FSize:LongInt; procedure SetSize(Value:LongInt); procedure CreateBuffer(const Size:LongInt); procedure ResizeBuffer(const Size:LongInt); procedure FreeBuffer; protected function GetItems(Index:LongInt):Char; virtual; procedure SetItems(Index:LongInt;Value:Char); virtual; public constructor Create; virtual; destructor Destroy; override; property Buffer:PChar read FBuffer; property Size:Longint read FSize write SetSize; property Items[Index:LongInt]:Char read GetItems write SetItems; default; end; {Base buffer with EOB.} THRBufferEOB=class(THRBuffer) private protected function GetEOB:Boolean; virtual; public property EOB:Boolean read GetEOB; end; {Buffer for holding a series of char.} THRBufferChar=class(THRBufferEOB) private FEOB:Boolean; FPosition:Longint; protected function GetEOB:Boolean; override; function GetItems(Index:LongInt):Char; override; procedure SetItems(Index:LongInt;Value:Char); override; function GetAsPChar:PChar; procedure SetAsPChar(Value:PChar); function GetAsString:string; procedure SetAsString(Value:string); public constructor Create; override; destructor Destroy; override; property Buffer; property Position:Longint read FPosition write FPosition; procedure Write(const Value:Char); function Read:Char; procedure WritePChar(const Str:PChar); procedure WriteString(const Str:String); property AsPChar:PChar read GetAsPChar write SetAsPChar; property AsString:string read GetAsString write SetAsString; end; {Buffer for reading from a stream.} THRBufferStream=class(THRBufferEOB) private FEOB:Boolean; FStream:TStream; FStreamSize:Longint; FFirstPosInBuffer:LongInt; protected function GetEOB:Boolean; override; function GetItems(Index:LongInt):Char; override; procedure SetItems(Index:LongInt;Value:Char); override; procedure SetStream(Value:TStream); public constructor Create; override; destructor Destroy; override; property Stream:TStream read FStream write SetStream; end; {A buffer containing a list of smaller buffers in one piece of contiguous memory.} THRBufferList=class(THRBuffer) private function GetItemPos(const Index:Integer):Integer; function GetCount:Integer; function GetItemSize(Index:Integer):Integer; procedure SetItemSize(Index:Integer;Value:Integer); function GetItemBuffer(Index:Integer):PChar; public constructor Create; override; destructor Destroy; override; procedure Add(const Index,ItemSize:Integer); procedure Delete(const Index:Integer); property Count:Integer read GetCount; property ItemSize[Index:Integer]:Integer read GetItemSize write SetItemSize; property ItemBuffer[Index:Integer]:PChar read GetItemBuffer; end; implementation { T H R B u f f e r } constructor THRBuffer.Create; begin FBuffer:=nil; FSize:=0; end; destructor THRBuffer.Destroy; begin FreeBuffer; inherited Destroy; end; procedure THRBuffer.SetSize(Value:LongInt); begin if FBuffer=nil then CreateBuffer(Value) else if Value>0 then ResizeBuffer(Value) else FreeBuffer; end; function THRBuffer.GetItems(Index:LongInt):Char; begin Result:=#0; end; procedure THRBuffer.SetItems(Index:LongInt;Value:Char); begin end; procedure THRBuffer.CreateBuffer(const Size:LongInt); begin if FBuffer=nil then begin FSize:=Size; GetMem(FBuffer,FSize+1); {Null terminate end of buffer.} FBuffer[FSize]:=#0; end; end; procedure THRBuffer.ResizeBuffer(const Size:LongInt); var New:PChar; MoveSize:LongInt; begin if FBuffer<>nil then begin GetMem(New,Size+1); if FSize>Size then MoveSize:=Size else MoveSize:=FSize; Move(FBuffer[0],New[0],MoveSize); FreeMem(FBuffer,FSize+1); FBuffer:=New; FSize:=Size; FBuffer[FSize]:=#0; end; end; procedure THRBuffer.FreeBuffer; begin if FBuffer<>nil then begin FreeMem(FBuffer,FSize+1); FBuffer:=nil; FSize:=0; end; end; { T H R B u f f e r E O B } function THRBufferEOB.GetEOB:Boolean; begin Result:=True; end; { T H R B u f f e r C h a r } constructor THRBufferChar.Create; begin inherited Create; FEOB:=False; end; destructor THRBufferChar.Destroy; begin inherited Destroy; end; function THRBufferChar.GetEOB:Boolean; begin Result:=FEOB; end; function THRBufferChar.GetItems(Index:LongInt):Char; begin if IndexFStream then begin FStream:=Value; FStreamSize:=FStream.Size; FFirstPosInBuffer:=-1; end; end; function THRBufferStream.GetEOB:Boolean; begin Result:=FEOB; end; function THRBufferStream.GetItems(Index:LongInt):Char; begin if Index=FFirstPosInBuffer+FSize) or (Index index down buffer.} S:=Buffer+Pos+SizeOf(Integer)+ItemSize; D:=S+Diff; C:=Size-(Pos+SizeOf(Integer)+ItemSize); Move(S[0],D[0],C); {Dec buffer size} Size:=Size+Diff; end else begin {Grow buffer} OldSize:=Size; {Inc buffer size} Size:=Size+Diff; {Move items > index up buffer.} S:=Buffer+Pos+SizeOf(Integer)+ItemSize; D:=S+Diff; C:=OldSize-(Pos+SizeOf(Integer)+ItemSize); Move(S[0],D[0],C); end; {Set items new size.} PHRInteger(Buffer+Pos)^:=Value; end; function THRBufferList.GetItemBuffer(Index:Integer):PChar; begin Result:=Buffer+GetItemPos(Index)+SizeOf(Integer); end; procedure THRBufferList.Add(const Index,ItemSize:Integer); var PosIndex:Integer; Pos:Integer; PosItemSize:Integer; OldSize:Integer; S,D:PChar; C:Integer; begin {Step past count.} Pos:=SizeOf(Integer); {Step thought list until up to index or end list.} PosIndex:=0; while (PosIndex index up buffer.} if PosIndex<=PHRInteger(Buffer)^-1 then begin S:=Buffer+Pos; D:=Buffer+Pos+SizeOf(Integer)+ItemSize; C:=OldSize-Pos; Move(S[0],D[0],C); end; {Set size of item.} PHRInteger(Buffer+Pos)^:=ItemSize; {Inc count.} Inc(PHRInteger(Buffer)^); end; procedure THRBufferList.Delete(const Index:Integer); begin // find index // get size // move everthing > index down by sizeof(Integer) + index[size] // dec buffer size by sizeof(Integer) + index[size] // dec count end; end.