cbutils.pas

来自「本人买的<<VC++项目开发实例>>源代码配套光盘.」· PAS 代码 · 共 373 行

PAS
373
字号
{+-----------------------------------------------------------------------------+
 | Unit:        cbUtils
 | Created:     12.98
 | Last change: 1999-10-28
 | Author:      Cyrille de Brebisson [cyrille_de-brebisson@aus.hp.com]
 | Description: fast string list class implementation
 | Version:     0.52
 | Copyright (c) 1998 Cyrille de Brebisson
 | All rights reserved.
 |
 | Thanks to: Primoz Gabrijelcic
 |
 | Version history:
 |   up to 0.5: source maintained by the autor, version history unknown
 |   0.51:
 |     - Primoz Gabrijelcic
 |       - Fixed code to compile with Delphi 2 and 3 (pretty much untested). 
 +----------------------------------------------------------------------------+}

{$IFOPT R+} {$DEFINE SetR} {$ELSE} {$UNDEF SetR} {$ENDIF}

unit cbUtils;

{$I mwEdit.inc}

interface

uses classes;

const
  NbSubList = 128;

Type
  TSpeedStringList = class;

  TSpeedListObject = class
  protected
    FName: String;
    FSpeedList: TSpeedStringList;
    fobject: tobject;
    procedure SetName(const Value: String); virtual;
  public
    Property Name: String read FName write SetName;
    constructor create(name: string);
    destructor destroy; override;
    property SpeedList: TSpeedStringList read FSpeedList write FSpeedList;
    property pointer: tobject read fobject write fobject;
  end;

  PSpeedListObjects = ^TSpeedListObjects;
  TSpeedListObjects = array [0..0] of TSpeedListObject;

  TSpeedStringList = class
  private
    function GetText: string;
    procedure SetText(const Value: string);
    function GetInObject(Index: Integer): TObject;
    procedure SetInObject(Index: Integer; const Value: TObject);
  Protected
    FOnChange: TNotifyEvent;
    SumOfUsed: array [0..NbSubList-1] of integer;
    datasUsed: array [0..NbSubList-1] of integer;
    datas: array [0..NbSubList-1] of PSpeedListObjects;
    lengthDatas: array [0..NbSubList-1] of integer;
    procedure Changed; virtual;
    function Get(Index: Integer): string; virtual;
    function GetObject(Index: Integer): TSpeedListObject;
    function GetCount: integer;
    Function GetStringList: TStrings;
    Procedure SetStringList(const value: TStrings);
  public
    Procedure NameChange(const obj: TSpeedListObject; const NewName: String);
    Procedure ObjectDeleted(const obj: TSpeedListObject);

    destructor Destroy; override;
    constructor create;
{$IFDEF MWE_COMPILER_4_UP}
    function Add(const Value: TSpeedListObject): Integer; overload;
    function Add(const Value: String): TSpeedListObject; overload;
{$ELSE}
    function AddObj(const Value: TSpeedListObject): Integer;
    function Add(const Value: String): TSpeedListObject;
{$ENDIF}
    procedure Clear;
    function Find(const name: String): TSpeedListObject;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    property Objects[Index: Integer]: TSpeedListObject read GetObject;
    property inobject[Index: Integer]: TObject read GetInObject Write SetInObject;
    property Strings[Index: Integer]: string read Get; default;
    property count: integer read GetCount;
    Property StringList: TStrings read GetStringList write SetStringList;
    property text: string read GetText write SetText;
  end;

implementation

function StringCrc(S: string): integer;
var
  i :integer;
begin
  result:=0;
  for i:=1 to length(s) do
  begin
    result:= (result shr 4) xor (((result xor ord(s[i])) and $F) * $1081);
    result:= (result shr 4) xor (((result xor (ord(s[i]) shr 4)) and $F) * $1081);
  end;
end;

{ TSpeedListObject }

{$R-}

constructor TSpeedListObject.create(name: string);
begin
  inherited create;
  FName:= name;
end;

destructor TSpeedListObject.destroy;
begin
  if FSpeedList<>nil then
    FSpeedList.ObjectDeleted(Self);
  inherited destroy;
end;

procedure TSpeedListObject.SetName(const Value: String);
begin
  FName := Value;
  if FSpeedList<>nil then
    FSpeedList.NameChange(Self, Value);
end;

{ TSpeedStringList }

{$IFDEF MWE_COMPILER_4_UP}
function TSpeedStringList.Add(const Value: TSpeedListObject): Integer;
{$ELSE}
function TSpeedStringList.AddObj(const Value: TSpeedListObject): Integer;
{$ENDIF}
var
  crc: integer;
  i: integer;
begin
  crc:= StringCrc(Value.Name) mod High(Datas)+1;
  if DatasUsed[crc]=lengthDatas[crc] then begin
    ReallocMem(datas[crc], (lengthDatas[crc]*2+1)*SizeOf(datas[1][0]));
    lengthDatas[crc] := lengthDatas[crc]*2+1;
  end;
  Datas[crc][DatasUsed[crc]]:= Value;
  result:= SumOfUsed[crc]+DatasUsed[crc];
  inc(DatasUsed[crc]);
  for i:= crc+1 to High(SumOfUsed) do
    inc(SumOfUsed[i]);
  Value.SpeedList:= Self;
end;

function TSpeedStringList.Add(const Value: String): TSpeedListObject;
begin
  result:= TSpeedListObject.Create(value);
{$IFDEF MWE_COMPILER_4_UP}
  Add(Result);
{$ELSE}
  AddObj(Result);
{$ENDIF}
end;

procedure TSpeedStringList.Changed;
begin
  if Assigned(FOnChange) then
    FOnChange(Self);
end;

procedure TSpeedStringList.Clear;
var
  i, j: integer;
begin
  for i:= low(datas) to high(datas) do
  Begin
    for j:= 0{low(datas[i])} to DatasUsed[i]-1 do
      datas[i][j].free;
    datasUsed[i]:= 0;
    ReallocMem(datas[i],0);
    lengthDatas[i] := 0;
    SumOfUsed[i]:= 0;
  end;
  Changed;
end;

constructor TSpeedStringList.create;
var
  i: integer;
begin
  inherited Create;
  for i:= Low(Datas) to high(datas) do
  Begin
    SumOfUsed[i]:= 0;
    DatasUsed[i]:= 0;
    lengthDatas[i] := 0;
    datas[i] := nil;
  end;
end;

destructor TSpeedStringList.Destroy;
begin
  Clear;
  inherited destroy;
end;

function TSpeedStringList.Find(const name: String): TSpeedListObject;
var
  crc: integer;
  i: integer;
begin
  crc:= StringCrc(name) mod High(Datas)+1;
  for i:= 0 to DatasUsed[crc]-1 do
    if Datas[crc][i].name = name then
    Begin
      result:= Datas[crc][i];
      exit;
    end;
  result:= nil;
end;

function TSpeedStringList.Get(Index: Integer): string;
var
  i: integer;
begin
  for i:=low(SumOfUsed)+1 to High(SumOfUsed) do
    if Index>SumOfUsed[i] then
    Begin
      result:= Datas[i-1][Index-SumOfUsed[i-1]].name;
      exit;
    end;
  result:= '';
end;

function TSpeedStringList.GetCount: integer;
begin
  result:= SumOfUsed[High(datas)]+DatasUsed[High(Datas)];
end;

function TSpeedStringList.GetInObject(Index: Integer): TObject;
var
  i: integer;
begin
  for i:=low(SumOfUsed)+1 to High(SumOfUsed) do
    if Index>SumOfUSed[i] then
    Begin
      result:= Datas[i-1][Index-SumOfUsed[i-1]].pointer;
      exit;
    end;
  result:= nil;
end;

function TSpeedStringList.GetObject(Index: Integer): TSpeedListObject;
var
  i: integer;
begin
  for i:=low(SumOfUsed)+1 to High(SumOfUsed) do
    if Index>SumOfUSed[i] then
    Begin
      result:= Datas[i-1][Index-SumOfUsed[i-1]];
      exit;
    end;
  result:= nil;
end;

function TSpeedStringList.GetStringList: TStrings;
var
  i, j: integer;
begin
  result:= TStringList.Create;
  for i:= Low(Datas) to High(Datas) do
    for j:= 0{Low(Datas[i])} to DatasUsed[i]-1 do
      result.add(datas[i][j].name);
end;

function TSpeedStringList.GetText: string;
begin
  with StringList do
  Begin
    result:= Text;
    free;
  end;
end;

procedure TSpeedStringList.NameChange(const Obj: TSpeedListObject; const NewName: String);
var
  crc: integer;
  i: integer;
  j: integer;
begin
  crc:= StringCrc(obj.Name) mod High(Datas)+1;
  for i:= 0 to DatasUsed[crc]-1 do
    if Datas[crc][i] = Obj then
    Begin
      for j:= i+1 to DatasUsed[crc]-1 do
        Datas[i-1]:= Datas[i];
      for j:= crc+1 to High(Datas) do
        dec(SumOfUsed[j]);
      if DatasUsed[crc]<lengthDatas[crc] div 2 then begin
        ReallocMem(Datas[crc],DatasUsed[crc]*SizeOf(Datas[crc][0]));
        lengthDatas[crc] := DatasUsed[crc];
      end;
{$IFDEF MWE_COMPILER_4_UP}
  Add(Obj);
{$ELSE}
  AddObj(Obj);
{$ENDIF}
      exit;
    end;
end;

procedure TSpeedStringList.ObjectDeleted(const obj: TSpeedListObject);
var
  crc: integer;
  i: integer;
  j: integer;
begin
  crc:= StringCrc(obj.Name) mod High(Datas)+1;
  for i:= 0 to DatasUsed[crc]-1 do
    if Datas[crc][i] = Obj then
    Begin
      for j:= i+1 to DatasUsed[crc]-1 do
        Datas[i-1]:= Datas[i];
      for j:= crc+1 to High(Datas) do
        dec(SumOfUsed[j]);
      Obj.FSpeedList:= nil;
      exit;
    end;
end;

procedure TSpeedStringList.SetInObject(Index: Integer;
  const Value: TObject);
var
  i: integer;
begin
  for i:=low(SumOfUsed)+1 to High(SumOfUsed) do
    if Index>SumOfUSed[i] then
    Begin
      Datas[i-1][Index-SumOfUsed[i-1]].pointer:= value;
      exit;
    end;
end;

procedure TSpeedStringList.SetStringList(const value: TStrings);
var
  i: integer;
begin
  clear;
  for i:= 0 to Value.Count-1 do
{$IFDEF MWE_COMPILER_4_UP}
    Add(TSpeedListObject.Create(value[i]));
{$ELSE}
    AddObj(TSpeedListObject.Create(value[i]));
{$ENDIF}
end;

procedure TSpeedStringList.SetText(const Value: string);
var
  s: TStrings;
begin
  s:= TStringList.Create;
  try
    s.Text:= Value;
    StringList:= s;
  finally
    s.Free;
  end;
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?