Reputation: 11435
For my purposes, I'm actually truly using ASCII character data (for submitting ASCII text files to the state), so just using unicodestring won't help the end result (I'd still have to convert something).
I've got the option to convert a StrComp function in Delphi 2009 that went from comparing a AnsiString and an PAnsiChar to a UnicodeString and an PAnsiChar.
Val : PAnsiChar
Mask : TEditMask;
....
this is my original code, it's not good
StrComp(PAnsiChar(Mask.EditText), Val);
....
so, I can change it to this:
StrComp(PAnsiChar(AnsiString(MAskEdit.EditText), Val);
or, I can change it to this (extra conversions for 'clarity'):
StrComp(PChar(MAskEdit.EditText), PChar(String(AnsiString(Val))));
I remember Marco Cantu saying, don't do one of these in a loop, I just don't remember which one or why.
Upvotes: 1
Views: 1773
Reputation: 43023
If you compile this:
StrComp(PAnsiChar(Mask.EditText), Val);
There is an implicit conversion from the Mask.EditText
as UnicodeString
into a temporary AnsiString
in order to allow the type cast to PAnsiChar
. That is your 2nd line:
StrComp(PAnsiChar(AnsiString(MAskEdit.EditText), Val);
But writing
StrComp(PChar(MAskEdit.EditText), PChar(String(AnsiString(Val))));
will let PChar(MAskEdit.EditText)
return a PChar
, that is a PWideChar
, so it will use the other overloaded StrComp
function.
In fact, there are two overloaded functions defined since Delphi 2009 in SysUtils.pas:
function StrComp(const Str1, Str2: PAnsiChar): Integer; overload;
function StrComp(const Str1, Str2: PWideChar): Integer; overload;
Both functions won't call the windows API, but will compare the characters one by one, with case sensitivity.
So my advice is that you simply do not use any pointer in your code, but rely on plain string
= UnicodeString
variables everywhere in your code, and use this function instead:
function CompareStr(const S1, S2: string): Integer;
The comparison will be the same, and there will be no hidden conversion. The issue with having WideChar
instead of AnsiChar
(i.e. having two times more memory) is nothing compared with the conversion (two WinAPI calls) between unicode and current ansi page. To quote your title, conversion direction does not matter: it is always much slower than no conversion.
If you search about speed, I suspect that Mask.EditText
is definitively the bottleneck in your code. This method will send a GDI message, wait for the response of the component, then affect a string
with the text. You should better use a temporary variable on stack, if, as I suspect, you are using this Mask.EditText
expression in a loop.
Upvotes: 5
Reputation: 595402
The real question is - why are you comparing a UnicodeString
to a PAnsiChar
instead of updating the PAnsiChar
data to Unicode? You should use AnsiChar/AnsiString at the boundaries that interact with legacy data, network connections, etc. All internal processing should be using a single string encoding to avoid these kinds of issues. Convert legacy/network data from Ansi to Unicode when loading the data. Convert from Unicode to Ansi when saving legacy data, sending network data, etc.
Upvotes: 2