1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #include <stddef.h>
23: #include <errno.h>
24: #include <iconv.h>
25:
26: #include <gconv_int.h>
27:
28: #include <assert.h>
29:
30:
31: size_t
32: iconv (iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf,
33: size_t *outbytesleft)
34: {
35: __gconv_t gcd = (__gconv_t) cd;
36: char *outstart = outbuf ? *outbuf : NULL;
37: size_t irreversible;
38: int result;
39:
40: if (__builtin_expect (inbuf == NULL || *inbuf == NULL, 0))
41: {
42: if (outbuf == NULL || *outbuf == NULL)
43: result = __gconv (gcd, NULL, NULL, NULL, NULL, &irreversible);
44: else
45: result = __gconv (gcd, NULL, NULL, (unsigned char **) outbuf,
46: (unsigned char *) (outstart + *outbytesleft),
47: &irreversible);
48: }
49: else
50: {
51: const char *instart = *inbuf;
52:
53: result = __gconv (gcd, (const unsigned char **) inbuf,
54: (const unsigned char *) (*inbuf + *inbytesleft),
55: (unsigned char **) outbuf,
56: (unsigned char *) (*outbuf + *outbytesleft),
57: &irreversible);
58:
59: *inbytesleft -= *inbuf - instart;
60: }
61: if (outstart != NULL)
62: *outbytesleft -= *outbuf - outstart;
63:
64: switch (__builtin_expect (result, __GCONV_OK))
65: {
66: case __GCONV_ILLEGAL_DESCRIPTOR:
67: __set_errno (EBADF);
68: irreversible = (size_t) -1L;
69: break;
70:
71: case __GCONV_ILLEGAL_INPUT:
72: __set_errno (EILSEQ);
73: irreversible = (size_t) -1L;
74: break;
75:
76: case __GCONV_FULL_OUTPUT:
77: __set_errno (E2BIG);
78: irreversible = (size_t) -1L;
79: break;
80:
81: case __GCONV_INCOMPLETE_INPUT:
82: __set_errno (EINVAL);
83: irreversible = (size_t) -1L;
84: break;
85:
86: case __GCONV_EMPTY_INPUT:
87: case __GCONV_OK:
88:
89: break;
90:
91: default:
92: assert (!"Nothing like this should happen");
93: }
94:
95: return irreversible;
96: }