📄 commqueue.pas
字号:
unit CommQueue;
interface
uses Classes, SysUtils, Windows, Dialogs, StdCtrls;
type
ECommQueueError = class(Exception);
//OnDiscardEvent = procedure (Sender : TObject; Item : pointer) of object;
PCycleQueue = ^TCycleQueue;
TCycleQueue = array[0..MaxListSize-1] of Byte;
TCommQueue = class(TComponent)
private
FCycleQueue: PCycleQueue;
FCapacity: Integer; //队列的容量
FCycleQueueIndex: Integer; //队列中当前存储位置
FAddTimes: Cardinal;
protected
procedure SetCapacity(NewCapacity: Integer);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
class procedure Error(const Msg: string; Data: Integer); virtual;
function AddByByte(ReceiveByte: Byte): Boolean;
function AddByStr(InputStr: string): Boolean;
function GetByStr(var S: string; Offset: integer): Boolean;
function GetByStrFromIndex(var S: string; Position, Offset: Integer): Boolean;
procedure GetOneByte(var PByte: Byte; Offset: Integer);
function GetOneByteFromIndex(var PByte: Byte; Position, Offset: Integer): Boolean;
function GetAll(var S: string): Boolean;
procedure Reset;
property AddTimes: Cardinal read FAddTimes;
//property OnDiscard : OnDiscardEvent read FOnDiscard write FOnDiscard;}
published
property Capacity: Integer read FCapacity write SetCapacity default 1024;
end;
implementation
constructor TCommQueue.Create( AOwner: TComponent );
begin
inherited Create( AOwner );
FCycleQueueIndex := 0;
FCapacity := 1024;
FAddTimes := 0;
if not (csDesigning in ComponentState) then begin
FCycleQueue := AllocMem(FCapacity * SizeOf(Byte));
FillChar(FCycleQueue^, FCapacity, 0);//初始化
end;
end;
destructor TCommQueue.Destroy;
begin
if not (csDesigning in ComponentState) then
ReallocMem(FCycleQueue, 0); //释放内存,并置FCycleQueue为nil
inherited Destroy;
end;
procedure TCommQueue.Reset;
begin
FillChar(FCycleQueue^, FCapacity, 0);//初始化
FCycleQueueIndex := 0 ;
end;
//往通讯循环队列的中加入一个字符
function TCommQueue.AddByByte(ReceiveByte: Byte): Boolean;
begin
Result := False;
FCycleQueue^[FCycleQueueIndex] := ReceiveByte;
FCycleQueueIndex := (FCycleQueueIndex + 1) mod FCapacity;
FAddTimes := (FAddTimes + 1) mod High(Cardinal);
Result := True;
end;
//以字符串的形式往通讯循环队列添加
function TCommQueue.AddByStr(InputStr: string): Boolean;
var
i: integer;
begin
Result := False;
for i:=1 to Length(InputStr) do AddByByte(Byte(InputStr[i]));
Result := True;
end;
//读取通讯循环队列中的一个字符字符
//以FCycleQueueIndex为起始点,Offset为偏移量
procedure TCommQueue.GetOneByte(var PByte: Byte; Offset: Integer);
var
Index: integer;
begin
if (Offset>FCapacity-1) or (Offset<-FCapacity+1) then
raise ECommQueueError.Create('偏移量只能在' + IntToStr(-FCapacity+1)+'~' + IntToStr(FCapacity-1) + '之间');
Index := (FCycleQueueIndex-1+FCapacity) mod FCapacity;
Index := (Offset+Index+FCapacity) mod FCapacity;
PByte := FCycleQueue^[Index];
end;
//以字符串的形式返回通讯循环队列中的字符
//以FCycleQueueIndex为起始点,Offset为偏移量
function TCommQueue.GetByStr(var S: string; Offset: Integer): Boolean;
var
Index, StartIndex: integer;
Num: integer;
begin
Result := False;
if (Offset>FCapacity-1) or (Offset<-FCapacity+1) then
raise ECommQueueError.Create('偏移量只能在' + IntToStr(-FCapacity+1)+'~' + IntToStr(FCapacity-1) + '之间');
S := '';
if Offset<=0 then begin
Num := -Offset;
Offset := Offset - 1;
StartIndex := FCycleQueueIndex + FCapacity + Offset;
if StartIndex >= FCapacity then StartIndex := StartIndex - FCapacity;
end
else begin
Num := Offset;
StartIndex := FCycleQueueIndex-1;
if StartIndex<0 then StartIndex := FCapacity - 1;
end;
Index := StartIndex;
while Num>=0 do begin
S := S + Chr(FCycleQueue^[Index]);
Index := (Index + 1) mod FCapacity;
Num := Num - 1;
end;
Result := True;
end;
//返回通讯循环队列中指定起始和终止索引号的一个字节
function TCommQueue.GetOneByteFromIndex(var PByte: Byte; Position, Offset: Integer): Boolean;
var
Index: integer;
begin
Result := False;
if (Position<0) or (Position>=FCapacity) then
raise ECommQueueError.Create('起始索引号只能在0~' + IntToStr(FCapacity-1) + '之间');
if (Offset>FCapacity-1) or (Offset<-FCapacity+1) then
raise ECommQueueError.Create('偏移量只能在' + IntToStr(-FCapacity+1) + '~' + IntToStr(FCapacity-1) + '之间');
Index:= (Offset+Position+FCapacity) mod FCapacity;
PByte := FCycleQueue^[Index];
Result := True;
end;
//以字符串的形式返回通讯循环队列中所有字符
function TCommQueue.GetAll(var S: string): Boolean;
begin
if GetByStrFromIndex(S, 0, FCapacity-1) then Result:=True
else Result:=False;
end;
//以字符串的形式返回通讯循环队列中指定起始和终止索引号的字符
function TCommQueue.GetByStrFromIndex(var S: string; Position, Offset: Integer): Boolean;
var
Index, StartIndex: integer;
Num: integer;
begin
Result := False;
if (Position<0) or (Position>=FCapacity) then
raise ECommQueueError.Create('起始索引号只能在0~' + IntToStr(FCapacity-1) + '之间');
if (Offset>FCapacity-1) or (Offset<-FCapacity+1) then
raise ECommQueueError.Create('偏移量只能在' + IntToStr(-FCapacity+1) + '~' + IntToStr(FCapacity-1) + '之间');
S := '';
if Offset<=0 then begin
Num := -Offset;
StartIndex := Position + FCapacity + Offset;
if StartIndex >= FCapacity then StartIndex := StartIndex - FCapacity;
end
else begin
Num := Offset;
StartIndex := Position;
end;
Index := StartIndex;
while Num>=0 do begin
S := S + Chr(FCycleQueue^[Index]);
Index := (Index + 1) mod FCapacity;
Num := Num - 1;
end;
Result := True;
end;
class procedure TCommQueue.Error(const Msg: string; Data: Integer);
function ReturnAddr: Pointer;
asm
MOV EAX,[EBP+4]
end;
begin
raise EListError.CreateFmt(Msg, [Data]) at ReturnAddr;
end;
//设置通讯循环队列的长度
procedure TCommQueue.SetCapacity(NewCapacity: Integer);
begin
if (NewCapacity < 1) or (NewCapacity > 10000) then
raise ECommQueueError.Create('缓冲区大小应设置在1~10000之间');
if NewCapacity > FCapacity then
begin
if not (csDesigning in ComponentState) then
ReallocMem(FCycleQueue, NewCapacity * SizeOf(Byte));
FCapacity := NewCapacity;
end else
if NewCapacity < FCapacity then
begin
if not (csDesigning in ComponentState) then begin
MoveMemory(FCycleQueue, @(FCycleQueue[FCapacity - NewCapacity]),
(NewCapacity) * SizeOf(Byte));
ReallocMem(FCycleQueue, NewCapacity * SizeOf(Byte));
end;
FCapacity := NewCapacity;
//if FCapacity = 0 then FCycleQueue := nil;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -