2 * Copyright (c) 2003-2004, Artem B. Bityuckiy
3 * Copyright (c) 1999,2000, Konstantin Chuguev. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 <<iconv>>, <<iconv_open>>, <<iconv_close>>---charset conversion routines
46 iconv_t iconv_open (const char *<[to]>, const char *<[from]>);
47 int iconv_close (iconv_t <[cd]>);
48 size_t iconv (iconv_t <[cd]>, char **restrict <[inbuf]>,
49 size_t *restrict <[inbytesleft]>,
50 char **restrict <[outbuf]>,
51 size_t *restrict <[outbytesleft]>);
53 iconv_t _iconv_open_r (struct _reent *<[rptr]>,
54 const char *<[to]>, const char *<[from]>);
55 int _iconv_close_r (struct _reent *<[rptr]>, iconv_t <[cd]>);
56 size_t _iconv_r (struct _reent *<[rptr]>,
57 iconv_t <[cd]>, const char **<[inbuf]>,
58 size_t *<[inbytesleft]>,
59 char **<[outbuf]>, size_t *<[outbytesleft]>);
62 The function <<iconv>> converts characters from <[in]> which are in one
63 encoding to characters of another encoding, outputting them to <[out]>.
64 The value <[inleft]> specifies the number of input bytes to convert whereas
65 the value <[outleft]> specifies the size remaining in the <[out]> buffer.
66 The conversion descriptor <[cd]> specifies the conversion being performed
67 and is created via <<iconv_open>>.
69 An <<iconv>> conversion stops if: the input bytes are exhausted, the output
70 buffer is full, an invalid input character sequence occurs, or the
71 conversion specifier is invalid.
73 The function <<iconv_open>> is used to specify a conversion from one
74 encoding: <[from]> to another: <[to]>. The result of the call is
75 to create a conversion specifier that can be used with <<iconv>>.
77 The function <<iconv_close>> is used to close a conversion specifier after
78 it is no longer needed.
80 The <<_iconv_r>>, <<_iconv_open_r>>, and <<_iconv_close_r>> functions are
81 reentrant versions of <<iconv>>, <<iconv_open>>, and <<iconv_close>>,
82 respectively. An additional reentrancy struct pointer: <[rptr]> is passed
83 to properly set <<errno>>.
86 The <<iconv>> function returns the number of non-identical conversions
87 performed. If an error occurs, (size_t)-1 is returned and <<errno>>
88 is set appropriately. The values of <[inleft]>, <[in]>, <[out]>,
89 and <[outleft]> are modified to indicate how much input was processed
90 and how much output was created.
92 The <<iconv_open>> function returns either a valid conversion specifier
93 or (iconv_t)-1 to indicate failure. If failure occurs, <<errno>> is set
96 The <<iconv_close>> function returns 0 on success or -1 on failure.
97 If failure occurs <<errno>> is set appropriately.
100 <<iconv>>, <<iconv_open>>, and <<iconv_close>> are non-ANSI and are specified
101 by the Single Unix specification.
103 No supporting OS subroutine calls are required.
107 #include <sys/types.h>
113 #include <sys/iconvnls.h>
119 * iconv interface functions as specified by Single Unix specification.
123 iconv_open (const char *to
,
126 return _iconv_open_r (_REENT
, to
, from
);
132 char **__restrict inbuf
,
133 size_t *__restrict inbytesleft
,
134 char **__restrict outbuf
,
135 size_t *__restrict outbytesleft
)
137 return _iconv_r (_REENT
, cd
, (const char **) inbuf
, inbytesleft
,
138 outbuf
, outbytesleft
);
143 iconv_close (iconv_t cd
)
145 return _iconv_close_r (_REENT
, cd
);
151 _iconv_open_r (struct _reent
*rptr
,
155 iconv_conversion_t
*ic
;
157 if (to
== NULL
|| from
== NULL
|| *to
== '\0' || *from
== '\0')
160 if ((to
= (const char *)_iconv_resolve_encoding_name (rptr
, to
)) == NULL
)
163 if ((from
= (const char *)_iconv_resolve_encoding_name (rptr
, from
)) == NULL
)
165 _free_r (rptr
, (void *)to
);
169 ic
= (iconv_conversion_t
*)_malloc_r (rptr
, sizeof (iconv_conversion_t
));
173 /* Select which conversion type to use */
174 if (strcmp (from
, to
) == 0)
176 /* Use null conversion */
177 ic
->handlers
= &_iconv_null_conversion_handlers
;
178 ic
->data
= ic
->handlers
->open (rptr
, to
, from
);
182 /* Use UCS-based conversion */
183 ic
->handlers
= &_iconv_ucs_conversion_handlers
;
184 ic
->data
= ic
->handlers
->open (rptr
, to
, from
);
187 _free_r (rptr
, (void *)to
);
188 _free_r (rptr
, (void *)from
);
190 if (ic
->data
== NULL
)
192 _free_r (rptr
, (void *)ic
);
201 _iconv_r (struct _reent
*rptr
,
206 size_t *outbytesleft
)
208 iconv_conversion_t
*ic
= (iconv_conversion_t
*)cd
;
210 if ((void *)cd
== NULL
|| cd
== (iconv_t
)-1 || ic
->data
== NULL
211 || (ic
->handlers
!= &_iconv_null_conversion_handlers
212 && ic
->handlers
!= &_iconv_ucs_conversion_handlers
))
214 _REENT_ERRNO (rptr
) = EBADF
;
218 if (inbuf
== NULL
|| *inbuf
== NULL
)
220 mbstate_t state_null
= ICONV_ZERO_MB_STATE_T
;
222 if (!ic
->handlers
->is_stateful(ic
->data
, 1))
225 if (outbuf
== NULL
|| *outbuf
== NULL
)
227 /* Reset shift state */
228 ic
->handlers
->set_state (ic
->data
, &state_null
, 1);
233 if (outbytesleft
!= NULL
)
235 mbstate_t state_save
= ICONV_ZERO_MB_STATE_T
;
237 /* Save current shift state */
238 ic
->handlers
->get_state (ic
->data
, &state_save
, 1);
240 /* Reset shift state */
241 ic
->handlers
->set_state (ic
->data
, &state_null
, 1);
243 /* Get initial shift state sequence and it's length */
244 ic
->handlers
->get_state (ic
->data
, &state_null
, 1);
246 if (*outbytesleft
>= state_null
.__count
)
248 memcpy ((void *)(*outbuf
), (void *)&state_null
, state_null
.__count
);
250 *outbuf
+= state_null
.__count
;
251 *outbytesleft
-= state_null
.__count
;
256 /* Restore shift state if output buffer is too small */
257 ic
->handlers
->set_state (ic
->data
, &state_save
, 1);
260 _REENT_ERRNO (rptr
) = E2BIG
;
264 if (*inbytesleft
== 0)
266 _REENT_ERRNO (rptr
) = EINVAL
;
270 if (*outbytesleft
== 0 || *outbuf
== NULL
)
272 _REENT_ERRNO (rptr
) = E2BIG
;
276 return ic
->handlers
->convert (rptr
,
278 (const unsigned char**)inbuf
,
280 (unsigned char**)outbuf
,
287 _iconv_close_r (struct _reent
*rptr
,
291 iconv_conversion_t
*ic
= (iconv_conversion_t
*)cd
;
293 if ((void *)cd
== NULL
|| cd
== (iconv_t
)-1 || ic
->data
== NULL
294 || (ic
->handlers
!= &_iconv_null_conversion_handlers
295 && ic
->handlers
!= &_iconv_ucs_conversion_handlers
))
297 _REENT_ERRNO (rptr
) = EBADF
;
301 res
= (int)ic
->handlers
->close (rptr
, ic
->data
);
303 _free_r (rptr
, (void *)cd
);
307 #endif /* !_REENT_ONLY */