Annotation of embedaddon/libiconv/extras/iconv_string.c, revision 1.1.1.1
1.1 misho 1: /* Copyright (C) 1999-2001, 2003 Bruno Haible.
2: This file is not part of the GNU LIBICONV Library.
3: This file is put into the public domain. */
4:
5: #include "iconv_string.h"
6: #include <iconv.h>
7: #include <errno.h>
8: #include <stdlib.h>
9: #include <string.h>
10:
11: #define tmpbufsize 4096
12:
13: int iconv_string (const char* tocode, const char* fromcode,
14: const char* start, const char* end,
15: char** resultp, size_t* lengthp)
16: {
17: iconv_t cd = iconv_open(tocode,fromcode);
18: size_t length;
19: char* result;
20: if (cd == (iconv_t)(-1)) {
21: if (errno != EINVAL)
22: return -1;
23: /* Unsupported fromcode or tocode. Check whether the caller requested
24: autodetection. */
25: if (!strcmp(fromcode,"autodetect_utf8")) {
26: int ret;
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))
31: return ret;
32: ret = iconv_string(tocode,"ISO-8859-1",start,end,resultp,lengthp);
33: return ret;
34: }
35: if (!strcmp(fromcode,"autodetect_jp")) {
36: int ret;
37: /* Try 7-bit encoding first. If the input contains bytes >= 0x80,
38: it will fail. */
39: ret = iconv_string(tocode,"ISO-2022-JP-2",start,end,resultp,lengthp);
40: if (!(ret < 0 && errno == EILSEQ))
41: return ret;
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
46: would not be good. */
47: ret = iconv_string(tocode,"EUC-JP",start,end,resultp,lengthp);
48: if (!(ret < 0 && errno == EILSEQ))
49: return ret;
50: /* Finally try SHIFT_JIS. */
51: ret = iconv_string(tocode,"SHIFT_JIS",start,end,resultp,lengthp);
52: return ret;
53: }
54: if (!strcmp(fromcode,"autodetect_kr")) {
55: int ret;
56: /* Try 7-bit encoding first. If the input contains bytes >= 0x80,
57: it will fail. */
58: ret = iconv_string(tocode,"ISO-2022-KR",start,end,resultp,lengthp);
59: if (!(ret < 0 && errno == EILSEQ))
60: return ret;
61: /* Finally try EUC-KR. */
62: ret = iconv_string(tocode,"EUC-KR",start,end,resultp,lengthp);
63: return ret;
64: }
65: errno = EINVAL;
66: return -1;
67: }
68: /* Determine the length we need. */
69: {
70: size_t count = 0;
71: char tmpbuf[tmpbufsize];
72: const char* inptr = start;
73: size_t insize = end-start;
74: while (insize > 0) {
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) && errno != E2BIG) {
79: if (errno == EINVAL)
80: break;
81: else {
82: int saved_errno = errno;
83: iconv_close(cd);
84: errno = saved_errno;
85: return -1;
86: }
87: }
88: count += outptr-tmpbuf;
89: }
90: {
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;
96: iconv_close(cd);
97: errno = saved_errno;
98: return -1;
99: }
100: count += outptr-tmpbuf;
101: }
102: length = count;
103: }
104: if (lengthp != NULL)
105: *lengthp = length;
106: if (resultp == NULL) {
107: iconv_close(cd);
108: return 0;
109: }
110: result = (*resultp == NULL ? malloc(length) : realloc(*resultp,length));
111: *resultp = result;
112: if (length == 0) {
113: iconv_close(cd);
114: return 0;
115: }
116: if (result == NULL) {
117: iconv_close(cd);
118: errno = ENOMEM;
119: return -1;
120: }
121: iconv(cd,NULL,NULL,NULL,NULL); /* return to the initial state */
122: /* Do the conversion for real. */
123: {
124: const char* inptr = start;
125: size_t insize = end-start;
126: char* outptr = result;
127: size_t outsize = length;
128: while (insize > 0) {
129: size_t res = iconv(cd,&inptr,&insize,&outptr,&outsize);
130: if (res == (size_t)(-1)) {
131: if (errno == EINVAL)
132: break;
133: else {
134: int saved_errno = errno;
135: iconv_close(cd);
136: errno = saved_errno;
137: return -1;
138: }
139: }
140: }
141: {
142: size_t res = iconv(cd,NULL,NULL,&outptr,&outsize);
143: if (res == (size_t)(-1)) {
144: int saved_errno = errno;
145: iconv_close(cd);
146: errno = saved_errno;
147: return -1;
148: }
149: }
150: if (outsize != 0) abort();
151: }
152: iconv_close(cd);
153: return 0;
154: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>