+ Several improvements by Martin Schreiber

git-svn-id: trunk@4246 -
This commit is contained in:
michael 2006-07-17 19:52:00 +00:00
parent d3896e0661
commit 497abf8f5d

View File

@ -27,11 +27,9 @@ implementation
{$ifndef linux} // Linux (and maybe glibc platforms in general), have iconv in glibc.
{$ifndef FreeBSD5}
{$ifndef SunOS}
{$linklib iconv}
{$define useiconv}
{$endif}
{$endif}
{$endif linux}
Uses
@ -44,7 +42,7 @@ Uses
Const
{$ifndef useiconv}
libiconvname='c'; // is in libc for several OSes
libiconvname='c'; // is in libc under Linux.
{$else}
libiconvname='iconv';
{$endif}
@ -74,16 +72,12 @@ const
{$ifdef darwin}
CODESET = 0;
{$else darwin}
{$ifdef solaris}
CODESET = 0;
{$else solaris}
{$ifdef FreeBSD} // actually FreeBSD5. internationalisation is afaik not default on 4.
CODESET = 0;
{$else freebsd}
{$error lookup the value of CODESET in /usr/include/langinfo.h for your OS }
// and while doing it, check if iconv is in libc, and if the symbols are prefixed with iconv_ or libiconv_
{$endif FreeBSD}
{$endif solaris}
{$endif darwin}
{$endif linux}
@ -115,7 +109,25 @@ var
iconv_ucs42ansi,
iconv_ansi2wide,
iconv_wide2ansi : iconv_t;
lock_ansi2ucs4 : integer = -1;
lock_ucs42ansi : integer = -1;
lock_ansi2wide : integer = -1;
lock_wide2ansi : integer = -1;
procedure lockiconv(var lockcount: integer);
begin
while interlockedincrement(lockcount) <> 0 do begin
interlockeddecrement(lockcount);
sleep(0);
end;
end;
procedure unlockiconv(var lockcount: integer);
begin
interlockeddecrement(lockcount);
end;
procedure Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
var
outlength,
@ -126,13 +138,7 @@ procedure Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
destpos: pchar;
mynil : pchar;
my0 : size_t;
conv : iconv_t;
begin
{ conversion descriptors aren't thread safe }
if IsMultithread then
conv:=iconv_open(nl_langinfo(CODESET),unicode_encoding)
else
conv:=iconv_wide2ansi;
mynil:=nil;
my0:=0;
{ rought estimation }
@ -142,7 +148,8 @@ procedure Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
srcpos:=source;
destpos:=pchar(dest);
outleft:=outlength;
while iconv(conv,@srcpos,@srclen,@destpos,@outleft)=size_t(-1) do
lockiconv(lock_wide2ansi);
while iconv(iconv_wide2ansi,@srcpos,@srclen,@destpos,@outleft)=size_t(-1) do
begin
case fpgetCerrno of
ESysEILSEQ:
@ -154,7 +161,7 @@ procedure Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
inc(destpos);
dec(outleft);
{ reset }
iconv(conv,@mynil,@my0,@mynil,@my0);
iconv(iconv_wide2ansi,@mynil,@my0,@mynil,@my0);
end;
ESysE2BIG:
begin
@ -167,13 +174,15 @@ procedure Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
destpos:=pchar(dest)+outoffset;
end;
else
raise EConvertError.Create('iconv error '+IntToStr(fpgetCerrno));
begin
unlockiconv(lock_wide2ansi);
raise EConvertError.Create('iconv error '+IntToStr(fpgetCerrno));
end;
end;
end;
unlockiconv(lock_wide2ansi);
// truncate string
setlength(dest,length(dest)-outleft);
if IsMultithread then
iconv_close(conv);
end;
@ -186,13 +195,7 @@ procedure Ansi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
destpos: pchar;
mynil : pchar;
my0 : size_t;
conv : iconv_t;
begin
{ conversion descriptors aren't thread safe }
if IsMultithread then
conv:=iconv_open(unicode_encoding,nl_langinfo(CODESET))
else
conv:=iconv_ansi2wide;
mynil:=nil;
my0:=0;
// extra space
@ -202,7 +205,8 @@ procedure Ansi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
srcpos:=source;
destpos:=pchar(dest);
outleft:=outlength*2;
while iconv(conv,@srcpos,@len,@destpos,@outleft)=size_t(-1) do
lockiconv(lock_ansi2wide);
while iconv(iconv_ansi2wide,@srcpos,@len,@destpos,@outleft)=size_t(-1) do
begin
case fpgetCerrno of
ESysEILSEQ:
@ -213,7 +217,7 @@ procedure Ansi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
inc(destpos,2);
dec(outleft,2);
{ reset }
iconv(conv,@mynil,@my0,@mynil,@my0);
iconv(iconv_wide2ansi,@mynil,@my0,@mynil,@my0);
end;
ESysE2BIG:
begin
@ -226,13 +230,15 @@ procedure Ansi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
destpos:=pchar(dest)+outoffset;
end;
else
raise EConvertError.Create('iconv error '+IntToStr(fpgetCerrno));
begin
unlockiconv(lock_ansi2wide);
raise EConvertError.Create('iconv error '+IntToStr(fpgetCerrno));
end;
end;
end;
unlockiconv(lock_ansi2wide);
// truncate string
setlength(dest,length(dest)-outleft div 2);
if IsMultithread then
iconv_close(conv);
end;
@ -265,13 +271,7 @@ procedure Ansi2UCS4Move(source:pchar;var dest:UCS4String;len:SizeInt);
destpos: pchar;
mynil : pchar;
my0 : size_t;
conv : iconv_t;
begin
{ conversion descriptors aren't thread safe }
if IsMultithread then
conv:=iconv_open('UCS4',nl_langinfo(CODESET))
else
conv:=iconv_ansi2ucs4;
mynil:=nil;
my0:=0;
// extra space
@ -281,7 +281,8 @@ procedure Ansi2UCS4Move(source:pchar;var dest:UCS4String;len:SizeInt);
srcpos:=source;
destpos:=pchar(dest);
outleft:=outlength*4;
while iconv(conv,@srcpos,@len,@destpos,@outleft)=size_t(-1) do
lockiconv(lock_ansi2ucs4);
while iconv(iconv_ansi2ucs4,@srcpos,@len,@destpos,@outleft)=size_t(-1) do
begin
case fpgetCerrno of
ESysE2BIG:
@ -295,13 +296,15 @@ procedure Ansi2UCS4Move(source:pchar;var dest:UCS4String;len:SizeInt);
destpos:=pchar(dest)+outoffset;
end;
else
raise EConvertError.Create('iconv error '+IntToStr(fpgetCerrno));
begin
unlockiconv(lock_ansi2ucs4);
raise EConvertError.Create('iconv error '+IntToStr(fpgetCerrno));
end;
end;
end;
unlockiconv(lock_ansi2ucs4);
// truncate string
setlength(dest,length(dest)-outleft div 4);
if IsMultithread then
iconv_close(conv);
end;