mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-25 15:08:26 +02:00
LCL: Improve TStringHashList, prevents a PO file update crash. Issue #21685, patch from cobines
git-svn-id: trunk@36729 -
This commit is contained in:
parent
5ed7c19f7d
commit
17c60bd62e
@ -47,8 +47,10 @@ type
|
|||||||
FList: PStringHashItemList;
|
FList: PStringHashItemList;
|
||||||
FCount: Integer;
|
FCount: Integer;
|
||||||
fCaseSensitive: Boolean;
|
fCaseSensitive: Boolean;
|
||||||
|
function BinarySearch(HashValue: Cardinal): Integer;
|
||||||
function CompareString(const Value1, Value2: String): Boolean;
|
function CompareString(const Value1, Value2: String): Boolean;
|
||||||
function CompareValue(const Value1, Value2: Cardinal): Integer;
|
function CompareValue(const Value1, Value2: Cardinal): Integer;
|
||||||
|
procedure FindHashBoundaries(HashValue: Cardinal; StartFrom: Integer; out First, Last: Integer);
|
||||||
function GetData(const S: String): Pointer;
|
function GetData(const S: String): Pointer;
|
||||||
procedure SetCaseSensitive(const Value: Boolean);
|
procedure SetCaseSensitive(const Value: Boolean);
|
||||||
procedure Delete(Index: Integer);
|
procedure Delete(Index: Integer);
|
||||||
@ -63,7 +65,9 @@ type
|
|||||||
function Add(const S: String; ItemData: Pointer): Integer;
|
function Add(const S: String; ItemData: Pointer): Integer;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
function Find(const S: String): Integer;
|
function Find(const S: String): Integer;
|
||||||
|
function Find(const S: String; Data: Pointer): Integer;
|
||||||
function Remove(const S: String): Integer;
|
function Remove(const S: String): Integer;
|
||||||
|
function Remove(const S: String; Data: Pointer): Integer;
|
||||||
property CaseSensitive: Boolean read fCaseSensitive write SetCaseSensitive;
|
property CaseSensitive: Boolean read fCaseSensitive write SetCaseSensitive;
|
||||||
property Count: Integer read FCount;
|
property Count: Integer read FCount;
|
||||||
property Data[const S: String]: Pointer read GetData write SetData; default;
|
property Data[const S: String]: Pointer read GetData write SetData; default;
|
||||||
@ -125,6 +129,24 @@ begin
|
|||||||
Insert(Result,Item);
|
Insert(Result,Item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TStringHashList.BinarySearch(HashValue: Cardinal): Integer;
|
||||||
|
var
|
||||||
|
First, Last, Temp: Integer;
|
||||||
|
begin
|
||||||
|
Result:= -1;
|
||||||
|
First:= 0;
|
||||||
|
Last:= Count -1;
|
||||||
|
while First <= Last do
|
||||||
|
begin
|
||||||
|
Temp:= (First + Last) div 2;
|
||||||
|
case CompareValue(HashValue, FList[Temp]^.HashValue) of
|
||||||
|
1: First:= Temp + 1;
|
||||||
|
0: exit(Temp);
|
||||||
|
-1: Last:= Temp-1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TStringHashList.Clear;
|
procedure TStringHashList.Clear;
|
||||||
var
|
var
|
||||||
I: Integer;
|
I: Integer;
|
||||||
@ -216,43 +238,14 @@ end;
|
|||||||
function TStringHashList.Find(const S: String): Integer;
|
function TStringHashList.Find(const S: String): Integer;
|
||||||
var
|
var
|
||||||
Value: Cardinal;
|
Value: Cardinal;
|
||||||
First, Last, Temp, I: Integer;
|
First, Last, I: Integer;
|
||||||
begin
|
begin
|
||||||
Value:= HashOf(s);
|
Value:= HashOf(s);
|
||||||
Result:= -1;
|
Result:= BinarySearch(Value);
|
||||||
First:= 0;
|
if (Result <> -1) and not CompareString(S, FList[Result]^.Key) then
|
||||||
Last:= Count -1;
|
|
||||||
while First <= Last do
|
|
||||||
begin
|
|
||||||
Temp:= (First + Last) div 2;
|
|
||||||
case CompareValue(Value, FList[Temp]^.HashValue) of
|
|
||||||
1: First:= Temp + 1;
|
|
||||||
0:
|
|
||||||
begin
|
|
||||||
Result:= Temp;
|
|
||||||
if CompareString(S, FList[Temp]^.Key) then
|
|
||||||
exit
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
-1: Last:= Temp-1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
if Result <> -1 then
|
|
||||||
begin
|
begin
|
||||||
|
FindHashBoundaries(Value, Result, First, Last);
|
||||||
Result:= -1;
|
Result:= -1;
|
||||||
First:= Temp -1;
|
|
||||||
//Find first matching hash index
|
|
||||||
while (First >= 0) and (CompareValue(Value, FList[First]^.HashValue) = 0) do
|
|
||||||
dec(First);
|
|
||||||
if (First < 0) or ((CompareValue(Value, FList[First]^.HashValue) <> 0)) then
|
|
||||||
inc(First);
|
|
||||||
//Find the last matching hash index
|
|
||||||
Last:= Temp +1;
|
|
||||||
while (Last <= (FCount - 1)) and (CompareValue(Value, FList[Last]^.HashValue) = 0) do
|
|
||||||
inc(Last);
|
|
||||||
if (Last > (FCount - 1)) or (CompareValue(Value, FList[Last]^.HashValue) <> 0) then
|
|
||||||
dec(Last);
|
|
||||||
for I := First to Last do
|
for I := First to Last do
|
||||||
if CompareString(S, FList[I]^.Key) then
|
if CompareString(S, FList[I]^.Key) then
|
||||||
begin
|
begin
|
||||||
@ -262,6 +255,43 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TStringHashList.Find(const S: String; Data: Pointer): Integer;
|
||||||
|
var
|
||||||
|
Value: Cardinal;
|
||||||
|
First, Last, I: Integer;
|
||||||
|
begin
|
||||||
|
Value:= HashOf(s);
|
||||||
|
Result:= BinarySearch(Value);
|
||||||
|
if (Result <> -1) and
|
||||||
|
not (CompareString(S, FList[Result]^.Key) and (FList[Result]^.Data = Data)) then
|
||||||
|
begin
|
||||||
|
FindHashBoundaries(Value, Result, First, Last);
|
||||||
|
Result:= -1;
|
||||||
|
for I := First to Last do
|
||||||
|
if CompareString(S, FList[I]^.Key) and (FList[I]^.Data = Data) then
|
||||||
|
begin
|
||||||
|
Result:= I;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TStringHashList.FindHashBoundaries(HashValue: Cardinal; StartFrom: Integer; out First, Last: Integer);
|
||||||
|
begin
|
||||||
|
First:= StartFrom -1;
|
||||||
|
//Find first matching hash index
|
||||||
|
while (First >= 0) and (CompareValue(HashValue, FList[First]^.HashValue) = 0) do
|
||||||
|
dec(First);
|
||||||
|
if (First < 0) or ((CompareValue(HashValue, FList[First]^.HashValue) <> 0)) then
|
||||||
|
inc(First);
|
||||||
|
//Find the last matching hash index
|
||||||
|
Last:= StartFrom +1;
|
||||||
|
while (Last <= (FCount - 1)) and (CompareValue(HashValue, FList[Last]^.HashValue) = 0) do
|
||||||
|
inc(Last);
|
||||||
|
if (Last > (FCount - 1)) or (CompareValue(HashValue, FList[Last]^.HashValue) <> 0) then
|
||||||
|
dec(Last);
|
||||||
|
end;
|
||||||
|
|
||||||
function TStringHashList.HashOf(const Key: string): Cardinal;
|
function TStringHashList.HashOf(const Key: string): Cardinal;
|
||||||
var
|
var
|
||||||
P: PChar;
|
P: PChar;
|
||||||
@ -312,6 +342,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TStringHashList.Remove(const S: String; Data: Pointer): Integer;
|
||||||
|
begin
|
||||||
|
Result:= Find(S, Data);
|
||||||
|
if Result > -1 then
|
||||||
|
begin
|
||||||
|
Dispose(fList[Result]);
|
||||||
|
Delete(Result);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TStringHashList.SetCaseSensitive(const Value: Boolean);
|
procedure TStringHashList.SetCaseSensitive(const Value: Boolean);
|
||||||
begin
|
begin
|
||||||
if fCaseSensitive <> Value then
|
if fCaseSensitive <> Value then
|
||||||
|
@ -506,7 +506,7 @@ begin
|
|||||||
if (VItem=Item) then
|
if (VItem=Item) then
|
||||||
FIdentLowVarToItem.Remove(VarName);
|
FIdentLowVarToItem.Remove(VarName);
|
||||||
|
|
||||||
FOriginalToItem.Remove(Item.Original);
|
FOriginalToItem.Remove(Item.Original, Item);
|
||||||
FItems.Delete(i);
|
FItems.Delete(i);
|
||||||
Item.Free;
|
Item.Free;
|
||||||
end;
|
end;
|
||||||
@ -1041,7 +1041,7 @@ begin
|
|||||||
if Item.Tag<>aTag then
|
if Item.Tag<>aTag then
|
||||||
Continue;
|
Continue;
|
||||||
FIdentifierLowToItem.Remove(Item.IdentifierLow);
|
FIdentifierLowToItem.Remove(Item.IdentifierLow);
|
||||||
FOriginalToItem.Remove(Item.Original);
|
FOriginalToItem.Remove(Item.Original, Item);
|
||||||
FItems.Delete(i);
|
FItems.Delete(i);
|
||||||
Item.Free;
|
Item.Free;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user