2 * Copyright (c) 2003-2004, Artem B. Bityuckiy
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/types.h>
31 #include <sys/iconvnls.h>
45 * _iconv_nls_construct_filename -- constructs full file name.
48 * struct _reent *rptr - reent structure of current thread/process.
49 * const char *file - the name of file.
50 * const char *dir - the name of subdirectory;
51 * const char *ext - file extension.
54 * Function constructs patch to icionv-related file.
55 * 'file' shouldn't be NULL. Doesn't use extension if 'ext' is NULL.
58 * The pointer to file name if success, In case of error returns NULL
59 * and sets current thread's/process's errno.
62 _iconv_nls_construct_filename (struct _reent
*rptr
,
70 int dirlen
= strlen (dir
);
72 if ((path
= _getenv_r (rptr
, NLS_ENVVAR_NAME
)) == NULL
|| *path
== '\0')
73 path
= ICONV_DEFAULT_NLSPATH
;
79 if ((p
= _malloc_r (rptr
, len1
+ dirlen
+ len2
+ len3
+ 3)) == NULL
)
80 return (const char *)NULL
;
82 memcpy (p
, path
, len1
);
83 if (p
[len1
- 1] != '/')
85 memcpy (p
+ len1
, dir
, dirlen
);
88 memcpy (p
+ len1
, file
, len2
);
92 memcpy (p
+ len1
, ext
, len3
);
97 return (const char *)p
;
103 * _iconv_nls_get_mb_cur_max -- return encoding's maximum length
104 * of a multi-byte character.
107 * iconv_t cd - opened iconv conversion descriptor;
108 * int direction - "from encoding" or "to encoding" direction.
111 * Return maximum length of a multi-byte character in one of 'cd's
112 * encoding. Return "from" encoding's value if 'direction' is 0 and
113 * "to" encoding's value if 'direction' isn't 0.
116 _iconv_nls_get_mb_cur_max (iconv_t cd
,
119 iconv_conversion_t
*ic
= (iconv_conversion_t
*)cd
;
121 return ic
->handlers
->get_mb_cur_max (ic
->data
, direction
);
125 * _iconv_nls_is_stateful -- is encoding stateful?
128 * iconv_t cd - opened iconv conversion descriptor;
129 * int direction - "from encoding" or "to encoding" direction.
132 * Returns 0 if encoding is stateless or 1 if stateful.
133 * Tests "from" encoding if 'direction' is 0 and
134 * "to" encoding's value if 'direction' isn't 0.
138 _iconv_nls_is_stateful (iconv_t cd
,
141 iconv_conversion_t
*ic
= (iconv_conversion_t
*)cd
;
143 return ic
->handlers
->is_stateful (ic
->data
, direction
);
147 * _iconv_nls_conv - special version of iconv for NLS.
153 * Function behaves as _iconv_r but:
154 * 1. Don't handle reset/return shift states queries
155 * (like iconv does when 'inbuf' == NULL, etc);
156 * 2. Don't save result if 'outbuf' == NULL or
158 * 3. Don't perform default conversion if there is no character
159 * in "to" encoding that corresponds to character from "from"
166 _iconv_nls_conv (struct _reent
*rptr
,
171 size_t *outbytesleft
)
173 iconv_conversion_t
*ic
= (iconv_conversion_t
*)cd
;
174 int flags
= ICONV_FAIL_BIT
;
176 if ((void *)cd
== NULL
|| cd
== (iconv_t
)-1 || ic
->data
== NULL
177 || (ic
->handlers
!= &_iconv_null_conversion_handlers
178 && ic
->handlers
!= &_iconv_ucs_conversion_handlers
))
180 _REENT_ERRNO (rptr
) = EBADF
;
184 if (inbytesleft
== NULL
|| *inbytesleft
== 0)
187 if (outbuf
== NULL
|| *outbuf
== NULL
)
188 flags
|= ICONV_DONT_SAVE_BIT
;
190 if (outbytesleft
== NULL
|| *outbytesleft
== 0)
192 _REENT_ERRNO (rptr
) = E2BIG
;
196 return ic
->handlers
->convert (rptr
,
198 (const unsigned char**)inbuf
,
200 (unsigned char**)outbuf
,
206 * _iconv_nls_get_state -- get encoding's current shift state value.
209 * iconv_t cd - iconv descriptor;
210 * mbstate_t *ps - where to save shift state;
211 * int direction - "from" encoding if 0, "to" encoding if 1.
214 * Save encoding's current shift state to 'ps'. Save "from" encoding's
215 * shift state if 'direction' is 0 and "to" encodings's shift state
216 * if 'direction' isn't 0.
219 _iconv_nls_get_state (iconv_t cd
,
223 iconv_conversion_t
*ic
= (iconv_conversion_t
*)cd
;
225 ic
->handlers
->get_state (ic
->data
, ps
, direction
);
231 * _iconv_nls_set_state -- set encoding's current shift state value.
234 * iconv_t cd - iconv descriptor;
235 * mbstate_t *ps - where to save shift state.
236 * int direction - "from" encoding if 0, "to" encoding if 1.
239 * Set encoding's current shift state.
242 * 0 if success, -1 if failure.
245 _iconv_nls_set_state (iconv_t cd
,
249 iconv_conversion_t
*ic
= (iconv_conversion_t
*)cd
;
251 return ic
->handlers
->set_state (ic
->data
, ps
, direction
);
254 /* Same as iconv_open() but don't perform name resolving */
256 iconv_open1 (struct _reent
*rptr
,
260 iconv_conversion_t
*ic
;
262 if (to
== NULL
|| from
== NULL
|| *to
== '\0' || *from
== '\0')
265 ic
= (iconv_conversion_t
*)_malloc_r (rptr
, sizeof (iconv_conversion_t
));
269 /* Select which conversion type to use */
270 if (strcmp (from
, to
) == 0)
272 /* Use null conversion */
273 ic
->handlers
= &_iconv_null_conversion_handlers
;
274 ic
->data
= ic
->handlers
->open (rptr
, to
, from
);
278 /* Use UCS-based conversion */
279 ic
->handlers
= &_iconv_ucs_conversion_handlers
;
280 ic
->data
= ic
->handlers
->open (rptr
, to
, from
);
283 if (ic
->data
== NULL
)
285 _free_r (rptr
, (void *)ic
);
293 * _iconv_nls_open - open iconv descriptors for NLS.
296 * struct _reent *rptr - process's reent structure;
297 * const char *encoding - encoding name;
298 * iconv_t *tomb - wchar -> encoding iconv descriptor pointer;
299 * iconv_t *towc - encoding -> wchar iconv descriptor pointer;
300 * int flag - perform encoding name resolving flag.
303 * Opens two iconv descriptors for 'encoding' -> wchar and
304 * wchar -> 'encoding' iconv conversions. Function is used when locale or
305 * wide-oriented stream is opened. If 'flag' is 0, don't perform encoding
306 * name resolving ('encoding' must not be alias in this case).
309 * If successful - return 0, else set errno and return -1.
312 _iconv_nls_open (struct _reent
*rptr
,
313 const char *encoding
,
318 const char *wchar_encoding
;
320 if (sizeof (wchar_t) > 2 && WCHAR_MAX
> 0xFFFF)
321 wchar_encoding
= "ucs_4_internal";
322 else if (sizeof (wchar_t) > 1 && WCHAR_MAX
> 0xFF)
323 wchar_encoding
= "ucs_2_internal";
325 wchar_encoding
= ""; /* This shuldn't happen */
329 if ((*towc
= _iconv_open_r (rptr
, wchar_encoding
, encoding
)) == (iconv_t
)-1)
332 if ((*tomb
= _iconv_open_r (rptr
, encoding
, wchar_encoding
)) == (iconv_t
)-1)
334 _iconv_close_r (rptr
, *towc
);
340 if ((*towc
= iconv_open1 (rptr
, wchar_encoding
, encoding
)) == (iconv_t
)-1)
343 if ((*tomb
= iconv_open1 (rptr
, encoding
, wchar_encoding
)) == (iconv_t
)-1)
345 _iconv_close_r (rptr
, *towc
);
353 #endif /* _MB_CAPABLE */