Răsfoiți Sursa

* initial windows iconv support based on PHP code. See Mantis #15171

git-svn-id: trunk@17727 -
marco 14 ani în urmă
părinte
comite
5b741f3acc
1 a modificat fișierele cu 45 adăugiri și 6 ștergeri
  1. 45 6
      packages/iconvenc/src/iconvert.inc

+ 45 - 6
packages/iconvenc/src/iconvert.inc

@@ -1,3 +1,8 @@
+
+{$ifndef Unix}
+ {$define noerrnoiconv}
+{$endif}
+
 function Iconvert(S: string; var Res: string; FromEncoding, ToEncoding: string): cint;
 var
   InLen, OutLen, Offset: size_t;
@@ -14,12 +19,40 @@ begin
   end;
 
   try
-    SetLength(Res, Length(S));
-    InLen := Length(S);
-    OutLen := Length(Res);
+    InLen:=Length(s);
+    {$ifdef noerrnoiconv}
+      // guestimate based on http://svn.php.net/viewvc/php/php-src/trunk/ext/iconv/iconv.c?revision=280602&view=markup
+      outlen:=InLen*Sizeof(longint) + 15;
+    {$else}
+      outlen:=InLen;
+    {$endif}
+    setlength(res,outlen);
+
     Src := PChar(S);
     Dst := PChar(Res);
 
+
+    {$ifdef noerrnoiconv}
+      iconvres := iconv(H, @Src, @InLen, @Dst, @OutLen);
+      if iconvres = size_t(-1) then
+        begin
+          res:=s;
+          exit(-1);
+        end;
+       if outlen<8 then    // From PHP, URL above, see also  PHP bug 55042 (they didn't recalc their "dest")
+        begin
+          Offset:=Dst-PChar(Res);
+          SetLength(Res, Length(Res)+8); // 5 is minimally one utf-8 char
+          Dst:=PChar(Res)+Offset;
+          OutLen:=Length(Res)-Offset;
+        end;
+       iconvres:=iconv(H, nil, nil, @Dst, @Outlen);
+       if iconvres = size_t(-1) then
+         begin
+           res:=s;
+           exit(-1);
+         end;
+    {$else}    
     while InLen > 0 do
     begin
       iconvres := iconv(H, @Src, @InLen, @Dst, @OutLen);
@@ -46,7 +79,7 @@ begin
             exit(-1)
       end;
     end;
-
+   
     // iconv has a buffer that needs flushing, specially if the last char is not #0
     iconv(H, nil, nil, @Dst, @Outlen);
     lerr:=cerrno;
@@ -58,11 +91,17 @@ begin
         OutLen:=Length(Res)-Offset;
         iconv(H, nil, nil, @Dst, @Outlen);
       end;
+   {$endif}
     // trim output buffer
     SetLength(Res, Length(Res) - Outlen);
-  finally
+  finally Offset:=Dst-PChar(Res);
+        SetLength(Res, Length(Res)+InLen*2+5); // 5 is minimally one utf-8 char
+        Dst:=PChar(Res)+Offset;
+        OutLen:=Length(Res)-Offset;
+        iconv(H, nil, nil, @Dst, @Outlen);
+
     iconv_close(H);
   end;
-
+  
   Result := 0;
 end;