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
28 #include <sys/types.h>
39 find_encoding_name (const char *searchee
,
44 * UCS-based conversion interface functions implementation.
48 ucs_based_conversion_open (struct _reent
*rptr
,
52 iconv_ucs_conversion_t
*uc
;
53 const iconv_to_ucs_ces_t
*to_ucs_bices
;
54 const iconv_from_ucs_ces_t
*from_ucs_bices
;
56 uc
= (iconv_ucs_conversion_t
*)
57 _calloc_r (rptr
, 1, sizeof (iconv_ucs_conversion_t
));
62 * Find CES converter for "from" encoding ("from" source encoding corresponds
63 * to "to_ucs" CES converter).
65 for (to_ucs_bices
= &_iconv_to_ucs_ces
[0];
66 to_ucs_bices
->names
!= NULL
;
69 if (find_encoding_name (from
, to_ucs_bices
->names
) == 0)
74 * Find CES converter for "to" encoding ("to" source encoding corresponds
75 * to "from_ucs" CES converter).
77 for (from_ucs_bices
= &_iconv_from_ucs_ces
[0];
78 from_ucs_bices
->names
!= NULL
;
81 if (find_encoding_name (to
, from_ucs_bices
->names
) == 0)
85 if (to_ucs_bices
->names
== NULL
|| from_ucs_bices
->names
== NULL
)
88 uc
->to_ucs
.handlers
= to_ucs_bices
->handlers
;
89 uc
->from_ucs
.handlers
= from_ucs_bices
->handlers
;
91 /* Initialize "to UCS" CES converter */
92 if (to_ucs_bices
->handlers
->init
!= NULL
)
94 uc
->to_ucs
.data
= to_ucs_bices
->handlers
->init (rptr
, from
);
95 if (uc
->to_ucs
.data
== NULL
)
99 uc
->to_ucs
.data
= (void *)&fake_data
;
102 /* Initialize "from UCS" CES converter */
103 if (from_ucs_bices
->handlers
->init
!= NULL
)
105 uc
->from_ucs
.data
= from_ucs_bices
->handlers
->init (rptr
, to
);
106 if (uc
->from_ucs
.data
== NULL
)
110 uc
->from_ucs
.data
= (void *)&fake_data
;
115 if (uc
->to_ucs
.data
!= NULL
&& uc
->to_ucs
.handlers
->close
!= NULL
)
116 uc
->to_ucs
.handlers
->close (rptr
, uc
->to_ucs
.data
);
118 _free_r (rptr
, (void *)uc
);
125 ucs_based_conversion_close (struct _reent
*rptr
,
128 iconv_ucs_conversion_t
*uc
;
131 uc
= (iconv_ucs_conversion_t
*)data
;
133 if (uc
->from_ucs
.handlers
->close
!= NULL
)
134 res
= uc
->from_ucs
.handlers
->close (rptr
, uc
->from_ucs
.data
);
135 if (uc
->to_ucs
.handlers
->close
!= NULL
)
136 res
|= uc
->to_ucs
.handlers
->close (rptr
, uc
->to_ucs
.data
);
138 _free_r (rptr
, (void *)data
);
145 ucs_based_conversion_convert (struct _reent
*rptr
,
147 const unsigned char **inbuf
,
149 unsigned char **outbuf
,
150 size_t *outbytesleft
,
153 unsigned char outbuf1
[ICONV_MB_LEN_MAX
];
154 unsigned char *poutbuf1
;
156 iconv_ucs_conversion_t
*uc
= (iconv_ucs_conversion_t
*)data
;
158 while (*inbytesleft
> 0)
160 register size_t bytes
;
162 const unsigned char *inbuf_save
= *inbuf
;
163 size_t inbyteslef_save
= *inbytesleft
;
165 if (*outbytesleft
== 0)
167 _REENT_ERRNO (rptr
) = E2BIG
;
171 ch
= uc
->to_ucs
.handlers
->convert_to_ucs (uc
->to_ucs
.data
,
174 if (ch
== (ucs4_t
)ICONV_CES_BAD_SEQUENCE
)
176 _REENT_ERRNO (rptr
) = EINVAL
;
180 if (ch
== (ucs4_t
)ICONV_CES_INVALID_CHARACTER
)
182 _REENT_ERRNO (rptr
) = EILSEQ
;
186 if (flags
& ICONV_DONT_SAVE_BIT
)
188 poutbuf1
= &outbuf1
[0];
192 bytes
= uc
->from_ucs
.handlers
->convert_from_ucs (uc
->from_ucs
.data
, ch
,
193 outbuf
, outbytesleft
);
195 if (bytes
== (size_t)ICONV_CES_NOSPACE
)
198 *inbytesleft
= inbyteslef_save
;
199 _REENT_ERRNO (rptr
) = E2BIG
;
202 else if (bytes
== (size_t)ICONV_CES_INVALID_CHARACTER
)
204 if (flags
& ICONV_FAIL_BIT
)
207 _REENT_ERRNO (rptr
) = EILSEQ
;
211 * For this case SUSv3 stands: "if iconv() encounters a character in the
212 * input buffer that is valid, but for which an identical character does
213 * not exist in the target encoding, iconv() shall perform an
214 * implementation-defined conversion on this character".
215 * Don't generate error, just write default character.
217 bytes
= uc
->from_ucs
.handlers
->convert_from_ucs (
219 (ucs4_t
)DEFAULT_CHARACTER
,
222 if ((__int32_t
)bytes
< 0)
224 _REENT_ERRNO (rptr
) = E2BIG
;
237 ucs_based_conversion_get_mb_cur_max (void *data
,
240 iconv_ucs_conversion_t
*uc
= (iconv_ucs_conversion_t
*)data
;
243 return uc
->to_ucs
.handlers
->get_mb_cur_max (uc
->to_ucs
.data
);
245 return uc
->from_ucs
.handlers
->get_mb_cur_max (uc
->from_ucs
.data
);
250 ucs_based_conversion_get_state (void *data
,
254 iconv_ucs_conversion_t
*uc
= (iconv_ucs_conversion_t
*)data
;
255 mbstate_t nullstate
= ICONV_ZERO_MB_STATE_T
;
259 if (uc
->to_ucs
.handlers
->get_state
!= NULL
)
260 uc
->to_ucs
.handlers
->get_state (uc
->to_ucs
.data
, state
);
262 *state
= nullstate
; /* internal copy */
266 if (uc
->from_ucs
.handlers
->get_state
!= NULL
)
267 uc
->from_ucs
.handlers
->get_state (uc
->from_ucs
.data
, state
);
269 *state
= nullstate
; /* internal copy */
277 ucs_based_conversion_set_state (void *data
,
281 iconv_ucs_conversion_t
*uc
= (iconv_ucs_conversion_t
*)data
;
285 if (uc
->to_ucs
.handlers
->set_state
!= NULL
)
286 return uc
->to_ucs
.handlers
->set_state (uc
->to_ucs
.data
, state
);
290 if (uc
->from_ucs
.handlers
->set_state
!= NULL
)
291 return uc
->from_ucs
.handlers
->set_state (uc
->from_ucs
.data
, state
);
298 ucs_based_conversion_is_stateful (void *data
,
301 iconv_ucs_conversion_t
*uc
= (iconv_ucs_conversion_t
*)data
;
305 if (uc
->to_ucs
.handlers
->is_stateful
!= NULL
)
306 return uc
->to_ucs
.handlers
->is_stateful (uc
->to_ucs
.data
);
310 if (uc
->from_ucs
.handlers
->is_stateful
!= NULL
)
311 return uc
->from_ucs
.handlers
->is_stateful (uc
->from_ucs
.data
);
318 /* UCS-based conversion definition object */
319 const iconv_conversion_handlers_t
320 _iconv_ucs_conversion_handlers
=
322 ucs_based_conversion_open
,
323 ucs_based_conversion_close
,
324 ucs_based_conversion_convert
,
325 ucs_based_conversion_get_state
,
326 ucs_based_conversion_set_state
,
327 ucs_based_conversion_get_mb_cur_max
,
328 ucs_based_conversion_is_stateful
333 * Supplementary functions.
337 find_encoding_name (const char *searchee
,
342 for (p
= *names
; p
!= NULL
; p
= *(names
++))
343 if (strcmp (p
, searchee
) == 0)