From 497abf8f5d2d32a417f90b7f7e7d951fbd7b03be Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 17 Jul 2006 19:52:00 +0000 Subject: [PATCH] + Several improvements by Martin Schreiber git-svn-id: trunk@4246 - --- rtl/unix/cwstring.pp | 81 +++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/rtl/unix/cwstring.pp b/rtl/unix/cwstring.pp index 7d628caa30..9beec283f8 100644 --- a/rtl/unix/cwstring.pp +++ b/rtl/unix/cwstring.pp @@ -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;