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