The following program tries to use AnsiCompareStr/Text:
program Project5;
{$APPTYPE CONSOLE}
uses StrUtils, SysUtils;
begin
Writeln('Ord(''-'')=', Ord('-'));
Writeln('Ord(''_'')=', Ord('_'));
Writeln('AnsiCompareStr(''-'', ''_'')=', AnsiCompareStr('-', '_'));
Writeln('AnsiCompareText(''-'', ''_'')=', AnsiCompareText('-', '_'));
Writeln('WideCompareStr(''-'', ''_'')=', WideCompareStr('-', '_'));
Writeln('WideCompareText(''-'', ''_'')=', WideCompareText('-', '_'));
Writeln('CompareStr(''-'', ''_'')=', CompareStr('-', '_'));
Writeln('CompareText(''-'', ''_'')=', CompareText('-', '_'));
Readln;
end.
When compiled with Kylix, it outputs wrong results on CentOS 5/6 x64:
Ord('-')=45
Ord('_')=95
AnsiCompareStr('-', '_')=3 <--- should be negative
AnsiCompareText('-', '_')=3 <--- should be negative
WideCompareStr('-', '_')=3 <--- should be negative
WideCompareText('-', '_')=3 <--- should be negative
CompareStr('-', '_')=-50
CompareText('-', '_')=-50
I wonder why AnsiCompareStr/Text gives wrong results ?
PS: CompareStr is considered obsolete according to http://www.delphibasics.co.uk/RTL.asp?Name=CompareStr . AnsiCompareStr is considered to be the modern, Locale safe form of CompareStr according to http://www.delphibasics.co.uk/RTL.asp?Name=AnsiCompareStr .
PS: The locale is en_US.iso885915 and/or en_US.UTF8
PS: Kylix 3 (as Delphi 7 with CrossKylix)
function AnsiCompareStr(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), Length(S1),
PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
// glibc 2.1.2 / 2.1.3 implementations of strcoll() and strxfrm()
// have severe capacity limits. Comparing two 100k strings may
// exhaust the stack and kill the process.
// Fixed in glibc 2.1.91 and later.
Result := strcoll(PChar(S1), PChar(S2));
{$ENDIF}
end;
function AnsiCompareText(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1),
Length(S1), PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
Result := WideCompareText(S1, S2);
{$ENDIF}
end;
AnsiCompareStr/Text
are giving correct results. They reflect the ordering defined by the prevailing locale. For instanceAnsiCompareStr
is implemented with a simple call tostrcoll
from the glibc standard library.The problem is in your expectations. I'm not sure why you expect the results you do, but it's quite reasonable to expect that
glibc
implements collation correctly. The order implied bystrcoll
is the collation order for the prevailing locale, whatever that happens to be. You didn't state that in the question.Perhaps the clue is that you use the phrase locale safe. Well,
CompareXXX
are independent of locale,AnsiCompareXXX
depend upon the locale. If you are looking for locale invariant ordering thenAnsiCompareXXX
are the wrong choice.