⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commqueue.pas

📁 短信二次开发控件SMSComm
💻 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 + -