lazutils: UTF8CompareStr: made 64bit safe, added fast PChar versions

git-svn-id: trunk@38103 -
This commit is contained in:
mattias 2012-08-01 10:50:19 +00:00
parent ecfb0f4478
commit b240df36a1
3 changed files with 95 additions and 6 deletions

View File

@ -271,9 +271,9 @@ type
function CompareCTDirectoryCaches(Data1, Data2: Pointer): integer;
function CompareAnsiStringAndDirectoryCache(Dir, Cache: Pointer): integer;
function ComparePCharFirstCaseInsAThenCase(Data1, Data2: Pointer): integer;
function ComparePCharCaseInsensitiveA(Data1, Data2: Pointer): integer;
function ComparePCharCaseSensitive(Data1, Data2: Pointer): integer;
function ComparePCharFirstCaseInsAThenCase(Data1, Data2: Pointer): integer; // insensitive ASCII then byte wise
function ComparePCharCaseInsensitiveA(Data1, Data2: Pointer): integer; // insensitive ASCII
function ComparePCharCaseSensitive(Data1, Data2: Pointer): integer; // byte wise
// unit links
function SearchUnitInUnitLinks(const UnitLinks, TheUnitName: string;

View File

@ -25,6 +25,10 @@ function CompareFileExt(const Filename, Ext: string;
function CompareFilenameStarts(const Filename1, Filename2: string): integer;
function CompareFilenames(Filename1: PChar; Len1: integer;
Filename2: PChar; Len2: integer): integer;
function CompareFilenamesP(Filename1, Filename2: PChar;
IgnoreCase: boolean = false // false = use default
): integer;
function DirPathExists(DirectoryName: string): boolean;
function DirectoryIsWritable(const DirectoryName: string): boolean;
function ExtractFileNameOnly(const AFilename: string): string;
@ -362,6 +366,65 @@ begin
{$ENDIF}
end;
function CompareFilenamesP(Filename1, Filename2: PChar;
IgnoreCase: boolean = false): integer;
var
{$IFDEF darwin}
F1: CFStringRef;
F2: CFStringRef;
Flags: CFStringCompareFlags;
{$ELSE}
File1, File2: string;
Len1: SizeInt;
Len2: SizeInt;
{$ENDIF}
begin
if (Filename1=nil) or (Filename1^=#0) then begin
if (Filename2=nil) or (Filename2^=#0) then begin
// both empty
exit(0);
end else begin
// filename1 empty, filename2 not empty
exit(-1);
end;
end else if (Filename2=nil) or (Filename2^=#0) then begin
// filename1 not empty, filename2 empty
exit(1);
end;
{$IFDEF CaseInsensitiveFilenames}
// this platform is by default case insensitive
IgnoreCase:=true;
{$ENDIF}
{$IFDEF darwin}
F1:=CFStringCreateWithCString(nil,Pointer(Filename1),kCFStringEncodingUTF8);
F2:=CFStringCreateWithCString(nil,Pointer(Filename2),kCFStringEncodingUTF8);
Flags:=kCFCompareNonliteral;
if IgnoreCase then Flags+=kCFCompareCaseInsensitive;
Result:=CFStringCompare(F1,F2,Flags);
CFRelease(F1);
CFRelease(F2);
{$ELSE}
if IgnoreCase then begin
// compare case insensitive
Len1:=StrLen(Filename1);
SetLength(File1,Len1);
System.Move(Filename1^,File1[1],Len1);
Len2:=StrLen(Filename2);
SetLength(File2,Len2);
System.Move(Filename2^,File2[1],Len2);
Result:=UTF8CompareText(File1,File2);
end else begin
// compare literally
while (Filename1^=Filename2^) and (Filename1^<>#0) do begin
inc(Filename1);
Inc(Filename2);
end;
Result:=ord(Filename1^)-ord(Filename2^);
end;
{$ENDIF}
end;
function DirPathExists(DirectoryName: string): boolean;
begin
Result:=DirectoryExistsUTF8(ChompPathDelim(DirectoryName));

View File

@ -88,6 +88,8 @@ procedure AssignUTF8ListToAnsi(UTF8List, AnsiList: TStrings);
//compare functions
function UTF8CompareStr(const S1, S2: string): Integer; inline;
function UTF8CompareStrP(S1, S2: PChar): Integer;
function UTF8CompareStr(S1: PChar; Count1: SizeInt; S2: PChar; Count2: SizeInt): Integer;
function UTF8CompareText(const S1, S2: string): Integer;
function CompareStrListUTF8LowerCase(List: TStringList; Index1, Index2: Integer): Integer;
@ -2500,12 +2502,36 @@ end;
Params: S1, S2 - UTF8 encoded strings
Returns: < 0 if S1 < S2, 0 if S1 = S2, > 0 if S2 > S1.
Compare 2 UTF8 encoded strings, case sensitive.
Note: Use this function instead of AnsiCompareStr.
This function guarantees proper collation on all supported platforms.
------------------------------------------------------------------------------}
function UTF8CompareStr(const S1, S2: string): Integer;
begin
Result := SysUtils.CompareStr(S1, S2);
Result := UTF8CompareStr(PChar(Pointer(S1)),length(S1),
PChar(Pointer(S2)),length(S2));
end;
function UTF8CompareStrP(S1, S2: PChar): Integer;
begin
Result:=UTF8CompareStr(S1,StrLen(S1),S2,StrLen(S2));
end;
function UTF8CompareStr(S1: PChar; Count1: SizeInt; S2: PChar; Count2: SizeInt
): Integer;
var
Count: SizeInt;
begin
Result := 0;
if Count1>Count2 then
Count:=Count2
else
Count:=Count1;
Result := CompareMemRange(Pointer(S1),Pointer(S2), Count); // Note: CompareMemRange can handle nil if Count=0
if Result<>0 then exit;
if Count1>Count2 then
Result:=1
else if Count1<Count2 then
Result:=-1
else
Result:=0;
end;
{------------------------------------------------------------------------------