My environment is Ubuntu 12.04 Linux on i386. I can see that only UTF-8 locales are installed (in /var/lib/locales/supported.d/local):
de_DE.UTF-8 UTF-8
en_US.UTF-8 UTF-8
~
Now the problem:
TIdIOHandler.InitComponent calls TIdTextEncoding.Default which in turn calls TIdMBCSEncoding.Create(‘ASCII’).
And there, the line
FMaxCharSize := GetByteCount(PWideChar(@cValue[0]), 2);
is executed, and GetByteCount returns zero – which should not happen (the expected value is 1 because ASCII is a single-byte encoding).
The place which returns the zero value is line 2288 in IdGlobal:
if iconv(FFromUTF16, @LCharsPtr, @LCharCount, @LBytesPtr, {$IFNDEF KYLIX}@{$ENDIF}LByteCount) = size_t(-1) then
begin
Result := 0;
Exit;
end;
Could this be caused by a missing UTF-16 locale? (I did not succeed installing UTF-16 support in my first attempt and maybe this problem has been seen by other Indy users on Linux too)
Indy does not currently do adequate handling of
iconv()errors becauseiconv()relies on platform-specificerrnovariables that are hard to implement in Indy across multiple platforms (this would not have been a problem ificonv()has been implemented to return its own error codes direcgtly). Not alliconv()errors are real failures, but Indy does not know that yet, so it treats all errors as failures (as for whyGetByteCount()returns 0 on failure instead of raising an exception, this is becauseTIdTextEncodingis modeled after Embarcadero’sSysUtils.TEncodingclass and thus has to be API-compatible with it. This will change in Indy 11).ICONV is supposed to implement its charsets natively, so it shouldn’t matter what locates are installed in the OS. In this case, I suspect that
iconv()is failing to convert codepoint$10FFFDfrom UTF-16 to ASCII inTIdMBCSEncoding.Create()since it is outside the ASCII range, and this is one of those cases where Indy needs to look aterrnoto diffrentiate between a failure and partial conversion, but currently is not doing so.As a workaround, you can edit IdGlobal.pas to have the
TIdTextEncoding.Defaultproperty getter use theTIdASCIIEncodingclass instead of theTIdMBCSEncodingclass, since Indy has its own ASCII implementation that is not dependant on ICONV.