* extended TFPGMap so that it's possible to add a custom compare function for data. Default compare function is binary compare.

git-svn-id: trunk@14888 -
This commit is contained in:
ivost 2010-02-11 20:45:14 +00:00
parent 83fc2dd1ea
commit 0637586076

View File

@ -197,16 +197,20 @@ type
FDataSize: Integer; FDataSize: Integer;
FDuplicates: TDuplicates; FDuplicates: TDuplicates;
FSorted: Boolean; FSorted: Boolean;
FOnPtrCompare: TFPSListCompareFunc; FOnKeyPtrCompare: TFPSListCompareFunc;
FOnDataPtrCompare: TFPSListCompareFunc;
procedure SetSorted(Value: Boolean); procedure SetSorted(Value: Boolean);
protected protected
function BinaryCompare(Key1, Key2: Pointer): Integer; function BinaryCompareKey(Key1, Key2: Pointer): Integer;
function BinaryCompareData(Data1, Data2: Pointer): Integer;
procedure SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
procedure SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
procedure InitOnPtrCompare; virtual;
procedure CopyKey(Src, Dest: Pointer); virtual; procedure CopyKey(Src, Dest: Pointer); virtual;
procedure CopyData(Src, Dest: Pointer); virtual; procedure CopyData(Src, Dest: Pointer); virtual;
function GetKey(Index: Integer): Pointer; function GetKey(Index: Integer): Pointer;
function GetKeyData(AKey: Pointer): Pointer; function GetKeyData(AKey: Pointer): Pointer;
function GetData(Index: Integer): Pointer; function GetData(Index: Integer): Pointer;
procedure InitOnPtrCompare; virtual;
function LinearIndexOf(AKey: Pointer): Integer; function LinearIndexOf(AKey: Pointer): Integer;
procedure PutKey(Index: Integer; AKey: Pointer); procedure PutKey(Index: Integer; AKey: Pointer);
procedure PutKeyData(AKey: Pointer; NewData: Pointer); procedure PutKeyData(AKey: Pointer; NewData: Pointer);
@ -232,18 +236,22 @@ type
property Data[Index: Integer]: Pointer read GetData write PutData; property Data[Index: Integer]: Pointer read GetData write PutData;
property KeyData[Key: Pointer]: Pointer read GetKeyData write PutKeyData; default; property KeyData[Key: Pointer]: Pointer read GetKeyData write PutKeyData; default;
property Sorted: Boolean read FSorted write SetSorted; property Sorted: Boolean read FSorted write SetSorted;
property OnPtrCompare: TFPSListCompareFunc read FOnPtrCompare write FOnPtrCompare; //property OnPtrCompare: TFPSListCompareFunc read FOnKeyCompareFunc write FOnKeyCompareFunc; deprecated;
property OnKeyPtrCompare: TFPSListCompareFunc read FOnKeyPtrCompare write SetOnKeyPtrCompare;
property OnDataPtrCompare: TFPSListCompareFunc read FOnDataPtrCompare write SetOnDataPtrCompare;
end; end;
{$ifndef VER2_0} {$ifndef VER2_0}
generic TFPGMap<TKey, TData> = class(TFPSMap) generic TFPGMap<TKey, TData> = class(TFPSMap)
type public type public
TCompareFunc = function(const Key1, Key2: TKey): Integer; TKeyCompareFunc = function(const Key1, Key2: TKey): Integer;
TDataCompareFunc = function(const Data1, Data2: TData): Integer;
PKey = ^TKey; PKey = ^TKey;
PData = ^TData; PData = ^TData;
var protected var protected
FOnCompare: TCompareFunc; FOnKeyCompare: TKeyCompareFunc;
FOnDataCompare: TDataCompareFunc;
procedure CopyItem(Src, Dest: Pointer); override; procedure CopyItem(Src, Dest: Pointer); override;
procedure CopyKey(Src, Dest: Pointer); override; procedure CopyKey(Src, Dest: Pointer); override;
procedure CopyData(Src, Dest: Pointer); override; procedure CopyData(Src, Dest: Pointer); override;
@ -254,10 +262,13 @@ type
function GetData(Index: Integer): TData; {$ifdef CLASSESINLINE} inline; {$endif} function GetData(Index: Integer): TData; {$ifdef CLASSESINLINE} inline; {$endif}
function KeyCompare(Key1, Key2: Pointer): Integer; function KeyCompare(Key1, Key2: Pointer): Integer;
function KeyCustomCompare(Key1, Key2: Pointer): Integer; function KeyCustomCompare(Key1, Key2: Pointer): Integer;
//function DataCompare(Data1, Data2: Pointer): Integer;
function DataCustomCompare(Data1, Data2: Pointer): Integer;
procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef CLASSESINLINE} inline; {$endif} procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef CLASSESINLINE} inline; {$endif}
procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif} procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
procedure PutData(Index: Integer; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif} procedure PutData(Index: Integer; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
procedure SetOnCompare(NewCompare: TCompareFunc); procedure SetOnKeyCompare(NewCompare: TKeyCompareFunc);
procedure SetOnDataCompare(NewCompare: TDataCompareFunc);
public public
constructor Create; constructor Create;
function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef CLASSESINLINE} inline; {$endif} function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
@ -271,7 +282,9 @@ type
property Keys[Index: Integer]: TKey read GetKey write PutKey; property Keys[Index: Integer]: TKey read GetKey write PutKey;
property Data[Index: Integer]: TData read GetData write PutData; property Data[Index: Integer]: TData read GetData write PutData;
property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default; property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default;
property OnCompare: TCompareFunc read FOnCompare write SetOnCompare; //property OnCompare: TCompareFunc read FOnKeyCompare write SetOnKeyCompare;
property OnKeyCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare;
property OnDataCompare: TDataCompareFunc read FOnDataCompare write SetOnDataCompare;
end; end;
{$endif} {$endif}
@ -967,11 +980,6 @@ begin
System.Move(Src^, Dest^, FDataSize); System.Move(Src^, Dest^, FDataSize);
end; end;
function TFPSMap.BinaryCompare(Key1, Key2: Pointer): Integer;
begin
Result := CompareByte(Key1^, Key2^, FKeySize);
end;
function TFPSMap.GetKey(Index: Integer): Pointer; function TFPSMap.GetKey(Index: Integer): Pointer;
begin begin
Result := Items[Index]; Result := Items[Index];
@ -993,9 +1001,36 @@ begin
Error(SMapKeyError, PtrUInt(AKey)); Error(SMapKeyError, PtrUInt(AKey));
end; end;
function TFPSMap.BinaryCompareKey(Key1, Key2: Pointer): Integer;
begin
Result := CompareByte(Key1^, Key2^, FKeySize);
end;
function TFPSMap.BinaryCompareData(Data1, Data2: Pointer): Integer;
begin
Result := CompareByte(Data1^, Data1^, FDataSize);
end;
procedure TFPSMap.SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
begin
if Proc <> nil then
FOnKeyPtrCompare := Proc
else
FOnKeyPtrCompare := @BinaryCompareKey;
end;
procedure TFPSMap.SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
begin
if Proc <> nil then
FOnDataPtrCompare := Proc
else
FOnDataPtrCompare := @BinaryCompareData;
end;
procedure TFPSMap.InitOnPtrCompare; procedure TFPSMap.InitOnPtrCompare;
begin begin
FOnPtrCompare := @BinaryCompare; SetOnKeyPtrCompare(nil);
SetOnDataPtrCompare(nil);
end; end;
procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer); procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer);
@ -1061,7 +1096,7 @@ begin
while L<=R do while L<=R do
begin begin
I := (L+R) div 2; I := (L+R) div 2;
Dir := FOnPtrCompare(Items[I], AKey); Dir := FOnKeyPtrCompare(Items[I], AKey);
if Dir < 0 then if Dir < 0 then
L := I+1 L := I+1
else begin else begin
@ -1083,7 +1118,7 @@ var
begin begin
Result := 0; Result := 0;
ListItem := First; ListItem := First;
while (Result < FCount) and (FOnPtrCompare(ListItem, AKey) <> 0) do while (Result < FCount) and (FOnKeyPtrCompare(ListItem, AKey) <> 0) do
begin begin
Inc(Result); Inc(Result);
ListItem := PByte(ListItem)+FItemSize; ListItem := PByte(ListItem)+FItemSize;
@ -1107,7 +1142,7 @@ var
begin begin
Result := 0; Result := 0;
ListItem := First+FKeySize; ListItem := First+FKeySize;
while (Result < FCount) and (CompareByte(ListItem^, AData^, FDataSize) <> 0) do while (Result < FCount) and (FOnDataPtrCompare(ListItem, AData) <> 0) do
begin begin
Inc(Result); Inc(Result);
ListItem := PByte(ListItem)+FItemSize; ListItem := PByte(ListItem)+FItemSize;
@ -1151,7 +1186,7 @@ end;
procedure TFPSMap.Sort; procedure TFPSMap.Sort;
begin begin
inherited Sort(FOnPtrCompare); inherited Sort(FOnKeyPtrCompare);
end; end;
{**************************************************************************** {****************************************************************************
@ -1202,11 +1237,6 @@ begin
Result := TData(inherited GetKeyData(@AKey)^); Result := TData(inherited GetKeyData(@AKey)^);
end; end;
procedure TFPGMap.InitOnPtrCompare;
begin
OnPtrCompare := @KeyCompare;
end;
function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer; function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
begin begin
if PKey(Key1)^ < PKey(Key2)^ then if PKey(Key1)^ < PKey(Key2)^ then
@ -1217,9 +1247,48 @@ begin
Result := 0; Result := 0;
end; end;
{function TFPGMap.DataCompare(Data1, Data2: Pointer): Integer;
begin
if PData(Data1)^ < PData(Data2)^ then
Result := -1
else if PData(Data1)^ > PData(Data2)^ then
Result := 1
else
Result := 0;
end;}
function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer; function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
begin begin
Result := FOnCompare(TKey(Key1^), TKey(Key2^)); Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
end;
function TFPGMap.DataCustomCompare(Data1, Data2: Pointer): Integer;
begin
Result := FOnDataCompare(TData(Data1^), TData(Data2^));
end;
procedure TFPGMap.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
begin
FOnKeyCompare := NewCompare;
if NewCompare <> nil then
OnKeyPtrCompare := @KeyCustomCompare
else
OnKeyPtrCompare := @KeyCompare;
end;
procedure TFPGMap.SetOnDataCompare(NewCompare: TDataCompareFunc);
begin
FOnDataCompare := NewCompare;
if NewCompare <> nil then
OnDataPtrCompare := @DataCustomCompare
else
OnDataPtrCompare := nil;
end;
procedure TFPGMap.InitOnPtrCompare;
begin
SetOnKeyCompare(nil);
SetOnDataCompare(nil);
end; end;
procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey); procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
@ -1237,15 +1306,6 @@ begin
inherited PutKeyData(@AKey, @NewData); inherited PutKeyData(@AKey, @NewData);
end; end;
procedure TFPGMap.SetOnCompare(NewCompare: TCompareFunc);
begin
FOnCompare := NewCompare;
if NewCompare <> nil then
OnPtrCompare := @KeyCustomCompare
else
InitOnPtrCompare;
end;
function TFPGMap.Add(const AKey: TKey): Integer; function TFPGMap.Add(const AKey: TKey): Integer;
begin begin
Result := inherited Add(@AKey); Result := inherited Add(@AKey);