* Optimize case insensitive comparison in Locate/Lookup by encoding the key before hand and by using the ansi functions

* Rename the comparison functions variables to make clear what is encoded in ansi or utf8

git-svn-id: trunk@13431 -
This commit is contained in:
blikblum 2009-07-23 22:10:59 +00:00
parent 5b58c9aea6
commit ba45ced9bf

View File

@ -976,65 +976,66 @@ type
CompFunction: TLocateCompareFunction;
end;
function CompInsensitivePartial(Value: PChar; const Key: String): Boolean;
function CompInsensitivePartial(UTF8Value: PChar; const AnsiKey: String): Boolean;
var
AnsiKey, AnsiValue: AnsiString;
AnsiValue: AnsiString;
begin
//see comments of CompInsensitive and CompInsensitiveWild functions
if Value <> nil then
if UTF8Value <> nil then
begin
AnsiKey := UTF8Decode(Key);
AnsiValue := UTF8Decode(Value);
AnsiValue := UTF8Decode(UTF8Value);
Result := AnsiStrLIComp(PChar(AnsiValue), PChar(AnsiKey), Length(AnsiKey)) = 0;
end
else
Result := False;
end;
function CompSensitivePartial(Value: PChar; const Key: String): Boolean;
function CompSensitivePartial(UTF8Value: PChar; const UTF8Key: String): Boolean;
begin
if Value <> nil then
Result := StrLComp(Value, PChar(Key), Length(Key)) = 0
if UTF8Value <> nil then
Result := StrLComp(UTF8Value, PChar(UTF8Key), Length(UTF8Key)) = 0
else
Result := False;
end;
function CompInsensitive(Value: PChar; const Key: String): Boolean;
function CompInsensitive(UTF8Value: PChar; const AnsiKey: String): Boolean;
begin
//fpc does not provide a function to compare UTF8 directly, so use a temporary
//widestring here. In unix systems with UTF8 encoding this would not be necessary
//but there's no direct way to check that
//fpc does not provide a function to compare UTF8 directly, so convert the
//UTF8Value string to ansi through a temporary widestring and compare with the
//AnsiKey (already encoded in the system ansi encoding).
//In unix systems where UTF8 is the system ansi encoding this would not be
//necessary but there's no direct way to check that
//todo: change this code when fpc has better support for unicode
if Value <> nil then
Result := WideCompareText(UTF8Decode(Value), UTF8Decode(Key)) = 0
if UTF8Value <> nil then
Result := AnsiCompareText(UTF8Decode(UTF8Value), AnsiKey) = 0
else
Result := False;
end;
function CompSensitive(Value: PChar; const Key: String): Boolean;
function CompSensitive(UTF8Value: PChar; const UTF8Key: String): Boolean;
begin
if Value <> nil then
Result := StrComp(Value, PChar(Key)) = 0
if UTF8Value <> nil then
Result := StrComp(UTF8Value, PChar(UTF8Key)) = 0
else
Result := False;
end;
function CompSensitiveWild(Value: PChar; const Key: String): Boolean;
function CompSensitiveWild(UTF8Value: PChar; const UTF8Key: String): Boolean;
begin
if Value <> nil then
Result := IsWild(String(Value), Key, False)
if UTF8Value <> nil then
Result := IsWild(String(UTF8Value), UTF8Key, False)
else
Result := False;
end;
function CompInsensitiveWild(Value: PChar; const Key: String): Boolean;
function CompInsensitiveWild(UTF8Value: PChar; const AnsiKey: String): Boolean;
begin
//IsWild is not unicode aware and fpc does not provide functions to properly
//uppercase UTF8 strings, so convert to a temporary WideString and uppercase it
//(that will be implicitely converted back to the system encoding)
//IsWild does not work with UTF8 encoded strings for case insensitive searches,
//so convert UTF8Value to the system ansi encoding before passing to IsWild.
//AnsiKey is already encoded in ansi
//todo: change this code when fpc has better support for unicode
if Value <> nil then
Result := IsWild(WideUpperCase(UTF8Decode(Value)), WideUpperCase(UTF8Decode(Key)), False)
if UTF8Value <> nil then
Result := IsWild(UTF8Decode(UTF8Value), AnsiKey, True)
else
Result := False;
end;
@ -1107,6 +1108,9 @@ begin
LocateFields[i].Key := VarToStr(KeyValues[i])
else
LocateFields[i].Key := VarToStr(KeyValues);
//store Key encoded as the system ansi encoding
if loCaseInsensitive in LocateOptions then
LocateFields[i].Key := UTF8Decode(LocateFields[i].Key);
end
else
begin