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]>, const char **<[inbuf]>,
49 size_t *<[inbytesleft]>,
50 char **<[outbuf]>, size_t *<[outbytesleft]>),
52 iconv_t _iconv_open_r (struct _reent *<[rptr]>,
53 const char *<[to]>, const char *<[from]>);
54 int _iconv_close_r (struct _reent *<[rptr]>, iconv_t <[cd]>);
55 size_t _iconv_r (struct _reent *<[rptr]>,
56 iconv_t <[cd]>, const char **<[inbuf]>,
57 size_t *<[inbytesleft]>,
58 char **<[outbuf]>, size_t *<[outbytesleft]>),
62 size_t iconv (<[cd]>, <[in]>, <[inleft]>, <[out]>, <[outleft]>)
70 iconv_t iconv_open (<[to]>, <[from]>);
75 int iconv_close (<[cd]>);
79 size_t _iconv_r (<[rptr]>, <[cd]>, <[in]>, <[inleft]>, <[out]>, <[outleft]>)
80 struct _reent *<[rptr]>;
88 iconv_t _iconv_open_r (<[rptr]>, <[to]>, <[from]>);
89 struct _reent *<[rptr]>;
94 int iconv_close (<[rptr]>, <[cd]>);
95 struct _reent *<[rptr]>;
99 The function <<iconv>> converts characters from <[in]> which are in one
100 character set and converts them to characters of another character set,
101 outputting them to <[out]>. The value <[inleft]> specifies the number
102 of input bytes to convert whereas the value <[outleft]> specifies the
103 size remaining in the <[out]> buffer. The conversion descriptor <[cd]>
104 specifies the conversion being performed and is created via <<iconv_open>>.
106 An <<iconv>> conversion stops if: the input bytes are exhausted, the output
107 buffer is full, an invalid input character sequence occurs, or the
108 conversion specifier is invalid.
110 The function <<iconv_open>> is used to specify a conversion from one
111 character set: <[from]> to another: <[to]>. The result of the call is
112 to create a conversion specifier that can be used with <<iconv>>.
114 The function <<iconv_close>> is used to close a conversion specifier after
115 it is no longer needed.
117 The <<_iconv_r>>, <<_iconv_open_r>>, and <<_iconv_close_r>> functions are
118 reentrant versions of <<iconv>>, <<iconv_open>>, and <<iconv_close>>,
119 respectively. An additional reentrancy struct pointer: <[rptr]> is passed
120 to properly set <<errno>>.
123 The <<iconv>> function returns the number of non-identical conversions
124 performed. If an error occurs, (size_t)-1 is returned and <<errno>>
125 is set appropriately. The values of <[inleft]>, <[in]>, <[out]>,
126 and <[outleft]> are modified to indicate how much input was processed
127 and how much output was created.
129 The <<iconv_open>> function returns either a valid conversion specifier
130 or (iconv_t)-1 to indicate failure. If failure occurs, <<errno>> is set
133 The <<iconv_close>> function returns 0 on success or -1 on failure.
134 If failure occurs <<errno>> is set appropriately.
137 <<iconv>>, <<iconv_open>>, and <<iconv_close>> are non-ANSI and are specified
138 by the Single Unix specification.
140 No supporting OS subroutine calls are required.
144 #include <sys/types.h>
150 #include <sys/iconvnls.h>
156 * iconv interface functions as specified by Single Unix specification.
160 _DEFUN(iconv_open, (to, from),
164 return _iconv_open_r (_REENT, to, from);
169 _DEFUN(iconv, (cd, inbuf, inbytesleft, outbuf, outbytesleft),
171 _CONST char **inbuf _AND
172 size_t *inbytesleft _AND
174 size_t *outbytesleft)
176 return _iconv_r (_REENT, cd, inbuf, inbytesleft, outbuf, outbytesleft);
181 _DEFUN(iconv_close, (cd), iconv_t cd)
183 return _iconv_close_r (_REENT, cd);
189 _DEFUN(_iconv_open_r, (rptr, to, from),
190 struct _reent *rptr _AND
194 iconv_conversion_t *ic;
196 if (to == NULL || from == NULL || *to == '\0' || *from == '\0')
199 if ((to = (_CONST char *)_iconv_resolve_encoding_name (rptr, to)) == NULL)
202 if ((from = (_CONST char *)_iconv_resolve_encoding_name (rptr, from)) == NULL)
204 _free_r (rptr, (_VOID_PTR)to);
208 ic = (iconv_conversion_t *)_malloc_r (rptr, sizeof (iconv_conversion_t));
212 /* Select which conversion type to use */
213 if (strcmp (from, to) == 0)
215 /* Use null conversion */
216 ic->handlers = &_iconv_null_conversion_handlers;
217 ic->data = ic->handlers->open (rptr, to, from);
221 /* Use UCS-based conversion */
222 ic->handlers = &_iconv_ucs_conversion_handlers;
223 ic->data = ic->handlers->open (rptr, to, from);
226 _free_r (rptr, (_VOID_PTR)to);
227 _free_r (rptr, (_VOID_PTR)from);
229 if (ic->data == NULL)
231 _free_r (rptr, (_VOID_PTR)ic);
235 return (_VOID_PTR)ic;
240 _DEFUN(_iconv_r, (rptr, cd, inbuf, inbytesleft, outbuf, outbytesleft),
241 struct _reent *rptr _AND
243 _CONST char **inbuf _AND
244 size_t *inbytesleft _AND
246 size_t *outbytesleft)
248 iconv_conversion_t *ic = (iconv_conversion_t *)cd;
250 if ((_VOID_PTR)cd == NULL || cd == (iconv_t)-1 || ic->data == NULL
251 || (ic->handlers != &_iconv_null_conversion_handlers
252 && ic->handlers != &_iconv_ucs_conversion_handlers))
254 __errno_r (rptr) = EBADF;
258 if (inbuf == NULL || *inbuf == NULL)
260 mbstate_t state_null = ICONV_ZERO_MB_STATE_T;
262 if (!ic->handlers->is_stateful(ic->data, 1))
265 if (outbuf == NULL || *outbuf == NULL)
267 /* Reset shift state */
268 ic->handlers->set_state (ic->data, &state_null, 1);
273 if (outbytesleft != NULL)
275 mbstate_t state_save = ICONV_ZERO_MB_STATE_T;
277 /* Save current shift state */
278 ic->handlers->get_state (ic->data, &state_save, 1);
280 /* Reset shift state */
281 ic->handlers->set_state (ic->data, &state_null, 1);
283 /* Get initial shift state sequence and it's length */
284 ic->handlers->get_state (ic->data, &state_null, 1);
286 if (*outbytesleft >= state_null.__count)
288 memcpy ((_VOID_PTR)(*outbuf), (_VOID_PTR)&state_null, state_null.__count);
290 *outbuf += state_null.__count;
291 *outbytesleft -= state_null.__count;
296 /* Restore shift state if output buffer is too small */
297 ic->handlers->set_state (ic->data, &state_save, 1);
300 __errno_r (rptr) = E2BIG;
304 if (*inbytesleft == 0)
306 __errno_r (rptr) = EINVAL;
310 if (*outbytesleft == 0 || *outbuf == NULL)
312 __errno_r (rptr) = E2BIG;
316 return ic->handlers->convert (rptr,
318 (_CONST unsigned char**)inbuf,
320 (unsigned char**)outbuf,
327 _DEFUN(_iconv_close_r, (rptr, cd),
328 struct _reent *rptr _AND
332 iconv_conversion_t *ic = (iconv_conversion_t *)cd;
334 if ((_VOID_PTR)cd == NULL || cd == (iconv_t)-1 || ic->data == NULL
335 || (ic->handlers != &_iconv_null_conversion_handlers
336 && ic->handlers != &_iconv_ucs_conversion_handlers))
338 __errno_r (rptr) = EBADF;
342 res = (int)ic->handlers->close (rptr, ic->data);
344 _free_r (rptr, (_VOID_PTR)cd);
348 #endif /* !_REENT_ONLY */