📄 pfiblists.pas
字号:
{***************************************************************}
{ FIBPlus - component library for direct access to Firebird and }
{ InterBase databases }
{ }
{ FIBPlus is based in part on the product }
{ Free IB Components, written by Gregory H. Deatz for }
{ Hoagland, Longo, Moran, Dunst & Doukas Company. }
{ mailto:gdeatz@hlmdd.com }
{ }
{ Copyright (c) 1998-2007 Devrace Ltd. }
{ Written by Serge Buzadzhy (buzz@devrace.com) }
{ }
{ ------------------------------------------------------------- }
{ FIBPlus home page: http://www.fibplus.com/ }
{ FIBPlus support : http://www.devrace.com/support/ }
{ ------------------------------------------------------------- }
{ }
{ Please see the file License.txt for full license information }
{***************************************************************}
unit pFIBLists;
interface
uses SysUtils,Classes
{$IFNDEF LINUX} ,Windows {$ENDIF}
;
{$I FIBPlus.inc}
type
TCallObject = class
public
constructor Create; virtual;
end;
TCallClass= class of TCallObject;
TObjStringList= class
private
FOwner:TObject;
FList :TStringList;
FHashList:TList;
FUseHash:boolean;
function GetObject(const Index:integer):TObject;
function GetCount: integer;
function GetItem(const Index: integer): string;
function HashFunc(Str: PChar): Integer;
function FindInHash(const Search: string; var Hash,Index: Integer): Boolean;
public
constructor Create(Owner:TObject;aUseHash:boolean);
destructor Destroy ; override;
procedure FullClear;
function FindObject(const ObjName:string;ObjClass:TCallClass; var InitRes:boolean):integer;
function Find(const S: string; var Index: Integer): Boolean;
function AddObject(const S: string; AObject: TObject): Integer;
procedure Remove(const S: string);
procedure Delete(Index:integer);
property Objects[const Index:integer]:TObject read GetObject;
property Count:integer read GetCount;
property Item[const Index:integer]:string read GetItem; default;
property UseHash:boolean read FUseHash;
end;
TSortedList=class(TObject)
// Note : Only for Items compatibled with Integer
private
FList:TList;
FTag :integer;
function GetItem(const Index:integer):integer;
function GetCount:integer;
protected
public
constructor Create;
destructor Destroy; override;
procedure IncValuesDiapazon(FromValue,ToValue:integer; Distance:integer);
procedure IncValues(FromValue:integer; Distance:integer);
function Add(const Item):integer;
function Find(const Item; var Index:integer):boolean ;
function IndexOf(const Item ):integer;
procedure Delete(const Index:integer);
procedure Remove(const Item);
procedure Clear;
function LastItem:integer;
property Item[const Index :integer]:integer read GetItem;default;
property Count:integer read GetCount;
property Tag :integer read FTag write FTag;
end;
TStringCollection = class
private
FData :array of array of string;
FHighBounds:integer;
FCount :integer;
FCapacity :integer;
procedure Grow;
procedure SetCapacity(NewCapacity:integer);
function GetValue(X, Y: integer): string;
procedure SetValue(X, Y: integer; const Value: string);
function GetPValue(X, Y: integer): PString;
public
constructor Create(aHighBounds:integer);
destructor Destroy; override;
function Add:integer;
procedure Clear;
procedure Insert(Index: Integer);
procedure Delete(Index: Integer);
procedure Exchange(X1,X2:integer);
procedure SetPCharValue(X, Y: integer; const Value: PChar;Len:integer);
property PValue[X,Y:integer]:PString read GetPValue;
property Value[X,Y:integer]:string read GetValue write SetValue; default;
property HighX:integer read FHighBounds;
property CountY:integer read FCount;
property Capacity :integer read FCapacity write SetCapacity;
end;
implementation
uses StdFuncs,StrUtil;
{ TCallObject }
constructor TCallObject.Create;
begin
inherited Create;
end;
{ TObjStringList }
function TObjStringList.AddObject(const S: string;
AObject: TObject): Integer;
var Hash:integer;
begin
if not UseHash then
Result:=FList.AddObject(S,AObject)
else
begin
if not FindInHash(S,Hash,Result) then
begin
FList.InsertObject(Result,S,AObject);
FHashList.Insert(Result,Pointer(Hash))
end;
end;
end;
procedure TObjStringList.Remove(const S: string);
var Index:integer;
Hash :integer;
begin
if not UseHash then
begin
Index:=FList.IndexOf(S);
if Index>-1 then
FList.Delete(Index);
end
else
begin
if FindInHash(S,Hash,Index) then
begin
FList.Delete(Index);
FHashList.Delete(Index);
end;
end;
end;
constructor TObjStringList.Create(Owner:TObject;aUseHash:boolean);
begin
inherited Create;
FOwner:=Owner;
FList :=TStringList.Create;
if not aUseHash then
with FList do
begin
Sorted :=true;
Duplicates:=dupIgnore;
FHashList:=nil
end
else
begin
FHashList:=TList.Create;
FUseHash := aUseHash
end;
end;
destructor TObjStringList.Destroy;
begin
FullClear;
FList.Free;
FHashList.Free;
inherited Destroy;
end;
function TObjStringList.Find(const S: string; var Index: Integer): Boolean;
var Hash:integer;
begin
if not UseHash then
Result:=FList.Find(S,Index)
else
Result:=FindInHash(S,Hash,Index)
end;
function TObjStringList.FindInHash(const Search: string; var Hash,
Index: Integer): Boolean;
var
L, H, I, C: Integer;
begin
with FList do
begin
Result := False;
L := 0;
H := Count - 1;
Hash:=HashFunc(PChar(Search));
while (L <= H) do
begin
I := (L + H) shr 1;
C := Signum(Integer(FHashList[I]) - Hash);
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
begin
Result :=EquelNames(False,Search,FList[I]);
if not Result then
begin
while (I>=0) and (Hash=Integer(FHashList[I])) do Dec(I);
Inc(I);
Result :=EquelNames(False,Search,FList[I]);
end;
while not Result and (Hash=Integer(FHashList[I])) do
begin
Inc(I);
if i<FList.Count then
Result := EquelNames(False,Search,FList[I])
else
begin
Index := I;
Exit;
end;
end;
if Result then
begin
Index := I;
Exit;
end;
end;
end;
end;
Index := L;
end;
end;
function TObjStringList.
FindObject(const ObjName:string;ObjClass:TCallClass; var InitRes:boolean):integer;
var Hash:integer;
begin
if not UseHash then
begin
with FList do
if not Find(ObjName,Result) then
begin
InitRes:=true;
Result:= AddObject(ObjName,ObjClass.Create);
end
else
InitRes:=false;
end
else
if not FindInHash(ObjName,Hash,Result) then
begin
InitRes:=true;
FList.InsertObject(Result,ObjName,ObjClass.Create);
FHashList.Insert(Result,Pointer(Hash))
end
else
InitRes:=false;
end;
procedure TObjStringList.FullClear;
var i:integer;
begin
with FList do
begin
for i:=0 to Pred(Count) do Objects[i].Free;
Clear
end
end;
function TObjStringList.GetCount: integer;
begin
result:=FList.Count
end;
function TObjStringList.GetItem(const Index: integer): string;
begin
Result:=FList[Index]
end;
function TObjStringList.GetObject(const Index: integer): TObject;
begin
Result:=FList.Objects[Index]
end;
function TObjStringList.HashFunc(Str: PChar): Integer;
var
Off, Len, Skip, I: Integer;
begin
Result := 0;
Off := 1;
Len := Q_StrLen(Str);
if Len < 16 then
for I := (Len - 1) downto 0 do
begin
Result := Result * 37 + Ord(Str[Off])-32;
Inc(Off);
end
else
begin
{ Only sample some characters }
Skip := Len div 8;
I := Len - 1;
while I >= 0 do
begin
Result := Result * 39+ Ord(Str[Off]) -32;
Dec(I, Skip);
Inc(Off, Skip);
end;
end;
end;
procedure TObjStringList.Delete(Index: integer);
begin
FList.Delete(Index);
if FUseHash then FHashList.Delete(Index);
end;
{ TSortedList }
constructor TSortedList.Create;
begin
inherited Create;
FList:=TList.Create;
end;
function TSortedList.Add(const Item): integer;
begin
if not Find(Item,Result) then
FList.Insert(Result,Pointer(Item));
end;
procedure TSortedList.Delete(const Index: integer);
begin
FList.Delete(Index);
end;
destructor TSortedList.Destroy;
begin
FList.Free;
inherited Destroy;
end;
procedure TSortedList.IncValuesDiapazon(FromValue,ToValue:integer; Distance:integer);
var
i :integer;
Index :integer;
Index1:integer;
MaxValue:integer;
MinValue:integer;
begin
if FList.Count=0 then Exit;
if FromValue>ToValue then
begin
MaxValue:=FromValue;
MinValue:=ToValue;
end
else
begin
MaxValue:=ToValue;
MinValue:=FromValue;
end;
Find(MinValue, Index);
Find(MaxValue, Index1);
if Index1>=FList.Count then Index1:=FList.Count-1;
if MaxValue<Integer(FList.List^[Index1]) then Dec(Index1);
for i:=Index1 downto Index do
FList.List^[i]:=Pointer(Integer(FList.List^[i])+Distance)
end;
procedure TSortedList.IncValues(FromValue:integer; Distance:integer);
var
i:integer;
Index:integer;
begin
Find(FromValue, Index);
for i:=FList.Count-1 downto Index do
FList.List^[i]:=Pointer(Integer(FList.List^[i])+Distance)
end;
function TSortedList.Find(const Item; var Index: integer): boolean;
var
L, H, I, C: Integer;
function Compare(I,I1:integer):integer;
begin
if I=I1 then Result:=0 else
if I>I1 then Result:=1 else Result:=-1;
end;
begin
Result := False;
L := 0;
H := FList.Count - 1;
while L <= H do
begin
I := (L + H) shr 1;
C:=Compare(Integer(FList.List^[I]),Integer(Item));
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
Result := True;
end;
end;
Index := L;
end;
function TSortedList.IndexOf(const Item): integer;
begin
if not Find(Item,Result) then
Result:=-1
end;
procedure TSortedList.Remove(const Item);
var Index:integer;
begin
if Find(Item,Index) then
FList.Delete(Index);
end;
function TSortedList.GetItem(const Index: integer): integer;
begin
Result:=Integer(FList.List^[Index]);
end;
function TSortedList.GetCount: integer;
begin
Result:=FList.Count
end;
procedure TSortedList.Clear;
begin
FList.Clear
end;
function TSortedList.LastItem: integer;
begin
if Count=0 then
Result := -1
else
Result :=Integer(FList.List^[FList.Count-1])
end;
{ TStringCollection }
function TStringCollection.Add: integer;
var
i:integer;
c:integer;
begin
if FCapacity=FCount then
Grow;
c:=Pred(FHighBounds);
for i:=0 to c do
Pointer(FData[i][FCount]) := nil;
Inc(FCount);
Result:=FCount
end;
procedure TStringCollection.Clear;
begin
Finalize(FData[0],FHighBounds);
FCount := 0;
FCapacity := 0;
end;
constructor TStringCollection.Create(aHighBounds: integer);
begin
inherited Create;
FHighBounds:=aHighBounds;
SetLength(FData,aHighBounds);
FCount :=0;
FCapacity :=0;
end;
procedure TStringCollection.Delete(Index: Integer);
var
i:integer;
begin
for i:=0 to Pred(FHighBounds) do
begin
Finalize(FData[i][Index]);
if Index<FCount-1 then
Move(FData[i][Index+1], FData[i][Index],(FCount - Index) * SizeOf(string));
end;
Dec(FCount);
end;
destructor TStringCollection.Destroy;
begin
Clear;
SetLength(FData,0);
inherited;
end;
procedure TStringCollection.Exchange(X1, X2: integer);
var
i:integer;
p:Pointer;
begin
for i:=0 to Pred(FHighBounds) do
begin
p:=Pointer(FData[i][X1]);
Pointer(FData[i][X1]):=Pointer(FData[i][X2]);
Pointer(FData[i][X2]):=p
end;
end;
function TStringCollection.GetPValue(X, Y: integer): PString;
begin
Assert(X<=FHighBounds,'Can''t read value to StrCollection. Bad X-Index');
Assert(Y<FCount,'Can''t read value to StrCollection. Bad Y-Index');
Result:=@(FData[X][Y])
end;
function TStringCollection.GetValue(X, Y: integer): string;
begin
Assert(X<=FHighBounds,'Can''t read value to StrCollection. Bad X-Index');
Assert(Y<FCount,'Can''t read value to StrCollection. Bad Y-Index');
Result:=FData[X][Y]
end;
procedure TStringCollection.Grow;
begin
if FCapacity=0 then
SetCapacity(128)
else
SetCapacity(FCapacity + (FCapacity shr 1));
end;
procedure TStringCollection.Insert(Index: Integer);
var
i:integer;
begin
if FCount = FCapacity then
Grow;
if Index < FCount then
for i:=0 to Pred(FHighBounds) do
begin
Move(FData[i][Index], FData[i][Index + 1],(FCount - Index) * SizeOf(string));
Pointer(FData[i][Index]):=nil;
end;
Inc(FCount);
end;
procedure TStringCollection.SetCapacity(NewCapacity:integer);
var
i:integer;
begin
for i := 0 to FHighBounds - 1 do
SetLength(FData[i],NewCapacity);
// SetLength(PStrArray(@FData)^,NewCapacity*FHighBounds);
FCapacity := NewCapacity;
end;
procedure TStringCollection.SetValue(X, Y: integer; const Value: string);
var
Len:Integer;
begin
Assert(X<=FHighBounds,'Can''t write value to StrCollection. Bad X-Index');
Assert(Y<FCount,'Can''t write value to StrCollection. Bad Y-Index');
Len:=Length(Value);
if Len=0 then
FData[X][Y]:=''
else
SetString(FData[X][Y],PChar(@Value[1]),Length(Value));
end;
procedure TStringCollection.SetPCharValue(X, Y: integer; const Value: PChar;Len:integer);
begin
Assert(X<=FHighBounds,'Can''t write value to StrCollection. Bad X-Index');
Assert(Y<FCount,'Can''t write value to StrCollection. Bad Y-Index');
if Len<0 then
SetString(FData[X][Y],Value,Q_StrLen(Value))
else
if Len=0 then
FData[X][Y]:=''
else
begin
SetString(FData[X][Y],Value,Len)
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -