1 /* Copyright (C) 1999-2001 Bruno Haible.
2 This file is not part of the GNU LIBICONV Library.
3 This file is put into the public domain. */
5 #include "iconv_string.h"
11 #define tmpbufsize 4096
13 int iconv_string (const char* tocode
, const char* fromcode
,
14 const char* start
, const char* end
,
15 char** resultp
, size_t* lengthp
)
17 iconv_t cd
= iconv_open(tocode
,fromcode
);
20 if (cd
== (iconv_t
)(-1)) {
23 /* Unsupported fromcode or tocode. Check whether the caller requested
25 if (!strcmp(fromcode
,"autodetect_utf8")) {
27 /* Try UTF-8 first. There are very few ISO-8859-1 inputs that would
28 be valid UTF-8, but many UTF-8 inputs are valid ISO-8859-1. */
29 ret
= iconv_string(tocode
,"UTF-8",start
,end
,resultp
,lengthp
);
30 if (!(ret
< 0 && errno
== EILSEQ
))
32 ret
= iconv_string(tocode
,"ISO-8859-1",start
,end
,resultp
,lengthp
);
35 if (!strcmp(fromcode
,"autodetect_jp")) {
37 /* Try 7-bit encoding first. If the input contains bytes >= 0x80,
39 ret
= iconv_string(tocode
,"ISO-2022-JP-2",start
,end
,resultp
,lengthp
);
40 if (!(ret
< 0 && errno
== EILSEQ
))
42 /* Try EUC-JP next. Short SHIFT_JIS inputs may come out wrong. This
43 is unavoidable. People will condemn SHIFT_JIS.
44 If we tried SHIFT_JIS first, then some short EUC-JP inputs would
45 come out wrong, and people would condemn EUC-JP and Unix, which
47 ret
= iconv_string(tocode
,"EUC-JP",start
,end
,resultp
,lengthp
);
48 if (!(ret
< 0 && errno
== EILSEQ
))
50 /* Finally try SHIFT_JIS. */
51 ret
= iconv_string(tocode
,"SHIFT_JIS",start
,end
,resultp
,lengthp
);
54 if (!strcmp(fromcode
,"autodetect_kr")) {
56 /* Try 7-bit encoding first. If the input contains bytes >= 0x80,
58 ret
= iconv_string(tocode
,"ISO-2022-KR",start
,end
,resultp
,lengthp
);
59 if (!(ret
< 0 && errno
== EILSEQ
))
61 /* Finally try EUC-KR. */
62 ret
= iconv_string(tocode
,"EUC-KR",start
,end
,resultp
,lengthp
);
68 /* Determine the length we need. */
71 char tmpbuf
[tmpbufsize
];
72 const char* inptr
= start
;
73 size_t insize
= end
-start
;
75 char* outptr
= tmpbuf
;
76 size_t outsize
= tmpbufsize
;
77 size_t res
= iconv(cd
,&inptr
,&insize
,&outptr
,&outsize
);
78 if (res
== (size_t)(-1)) {
82 int saved_errno
= errno
;
88 count
+= outptr
-tmpbuf
;
91 char* outptr
= tmpbuf
;
92 size_t outsize
= tmpbufsize
;
93 size_t res
= iconv(cd
,NULL
,NULL
,&outptr
,&outsize
);
94 if (res
== (size_t)(-1)) {
95 int saved_errno
= errno
;
100 count
+= outptr
-tmpbuf
;
106 if (resultp
== NULL
) {
110 result
= (*resultp
== NULL
? malloc(length
) : realloc(*resultp
,length
));
116 if (result
== NULL
) {
121 iconv(cd
,NULL
,NULL
,NULL
,NULL
); /* return to the initial state */
122 /* Do the conversion for real. */
124 const char* inptr
= start
;
125 size_t insize
= end
-start
;
126 char* outptr
= result
;
127 size_t outsize
= length
;
129 size_t res
= iconv(cd
,&inptr
,&insize
,&outptr
,&outsize
);
130 if (res
== (size_t)(-1)) {
134 int saved_errno
= errno
;
142 size_t res
= iconv(cd
,NULL
,NULL
,&outptr
,&outsize
);
143 if (res
== (size_t)(-1)) {
144 int saved_errno
= errno
;
150 if (outsize
!= 0) abort();