Browse Source

+ Several improvements by Martin Schreiber

git-svn-id: trunk@4246 -
michael 19 years ago
parent
commit
497abf8f5d
1 changed files with 42 additions and 39 deletions
  1. 42 39
      rtl/unix/cwstring.pp

+ 42 - 39
rtl/unix/cwstring.pp

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