|
@@ -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;
|