Delphi XE2 AnsiFormat() and ANSI String constants
Asked Answered
F

2

5

Is there a handy Format() function that works only on Ansi strings? Because everytime I use an AnsiString with Format() I get a warning. And no, I don't want Delphi to convert my AnsiStrings back and forth between Wide and Ansi strings. That is just making things awfully slower. Also, is there a way to force a string constant to be Ansi? check this out

function SomeStrFunc(S: AnsiString): AnsiString; overload;
function SomeStrFunc(S: String): String; overload;

and then when I use SomeStrFunc('ABC') it will call the wide string version. What if I want to use the Ansi version and force Delphi to store 'ABC' constant in AnsiChars.

Fluoridate answered 7/10, 2011 at 3:58 Comment(6)
Why do you want to use AnsiString? You mention performance. Is it really significantly slower to use Unicode? How did you time that? Are you aware that the Ansi Windows API functions are slower than the native Unicode versions?Extraction
Because AnsiStrings take half the space needed by UnicodeStrings, which would be pretty important if you're working on a professional-scale application. Think about an application that is being run by hundreds of people at the same time, all over the world, sending hundreds of log messages to a logging server (only warnings, errors not to mention info, debug msgs) thru internet. Think if it's running thru a 3G connection. And I can name tens of other scenarios where UnicodeStrings could be totally useless and moreover would be a waste of time and space and money.Fluoridate
Ansi not much use with international programs. For space saving UTF8 is an option. If you are constrained by bandwidth use compression.Extraction
And yes, it is really slower to mix Unicode and Ansi. (I'm not talking about using only Unicode for the reasons I mentioned above). Every conversion between Ansi and Unicode involves the call of internal UStrFromLStr() function, which goes thru InternalUStrFromPCharLen() which calls WCharFromChar() which calls UnicodeFromLocaleChars() which calls WinAPI function MultiByteToWideChar() where you could say you're no longer in Kansas anymore and say goodbye to your precious clock ticks. And think about making these conversions hundreds of times in a sec. So, yes it is awfully slow.Fluoridate
Compression is not an option if you think about calling a function more than 10 times a sec IMHO. And UTF8 is also slower than plain Ansi.Fluoridate
When you are bandwidth limited compression is faster. That's standard with communication protocols. If you are using ANSI then you can only rely on ASCII, in which case UTF8 is identical. If you are happy with ASCII then fine. If you have to support international audience then ASCII gets pretty limiting.Extraction
H
11

There is Ansi version of Format function in System.AnsiStrings unit

Hennebery answered 7/10, 2011 at 6:17 Comment(3)
Thanks, I needed that one. Do you know if there is a solution for the Delphi XE case?Bratislava
@Ritsaert - Yes, AnsiStrings unit exists in all Unicode Delphi's (2009 and above).Hennebery
Thanks @Serg. System.AnsiStrings unit turned out to be a treasure chest.Fluoridate
V
7

Serg answered your question about an AnsiString version of Format(). I'll answer your other question.

String literals are encoded based on the context they are used, so to force a literal to a particular encoding, you have to tell the compiler which encoding it needs to use, eg:

SomeStrFunc(AnsiString('ABC'));

Or

const
  cABC: AnsiString = 'ABC';

SomeStrFunc(cABC);
Vitavitaceous answered 7/10, 2011 at 6:36 Comment(3)
You don't need to tell the compiler how to store a literal unless you assign it to a variable of a different string type. If you assign the same literal to both a string and an AnsiString variable, the compiler will store both versions in the exe. This I am sure of (#4293111). Not sure whether the compiler has the same behaviour for passing a literal value to string/AnsiString parameter.Rectangle
It does have the same behavior, @Marjan. An untyped string constant could assume many different types within a single program, including AnsiString, UnicodeString, PChar, and Char.Polloch
I actually was afraid to be have to use the second approach, which is pretty cumbersome. And the first way is definitely not the way I'd like to use but still, that does the job. I was kinda hoping something like 'ABC'A (like the way to make numeric constants long in C/C++) but I guess I can typedef AS = AnsiString; and then just use AS('ABC')Fluoridate

© 2022 - 2024 — McMap. All rights reserved.