2 * Copyright (c) 1999,2000
3 * 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
26 * iconv (Charset Conversion Library) v2.0
29 #include <sys/types.h>
41 struct iconv_ccs ccs[1];
42 } iconv_ces_euc_state_t;
45 _DEFUN(_iconv_euc_init, (rptr, data, desc_data, num),
46 struct _reent *rptr _AND
48 _CONST _VOID_PTR desc_data _AND
51 size_t stsz = sizeof(iconv_ces_euc_state_t) +
52 sizeof(struct iconv_ccs) * (num - 1);
54 iconv_ces_euc_state_t *state = (iconv_ces_euc_state_t *)_malloc_r(rptr, stsz);
57 return __errno_r(rptr);
58 for (i = 0; i < num; i++) {
59 int res = _iconv_ccs_init(rptr, &(state->ccs[i]),
60 ((_CONST iconv_ces_euc_ccs_t *) desc_data)[i].name);
63 state->ccs[i].close(rptr, &(state->ccs[i]));
69 (iconv_ces_euc_state_t *)*data = state;
74 _DEFUN(_iconv_euc_close, (rptr, data),
75 struct _reent *rptr _AND
78 #define state ((iconv_ces_euc_state_t *)data)
81 for (i = 0; i < state->nccs; i++)
82 res = state->ccs[i].close(rptr, &(state->ccs[i])) || res;
88 #define is_7_14bit(data) ((data)->nbits & 7)
89 #define is_7bit(data) ((data)->nbits & 1)
92 _DEFUN(_iconv_euc_convert_from_ucs, (ces, in, outbuf, outbytesleft),
93 struct iconv_ces *ces _AND
95 unsigned char **outbuf _AND
98 iconv_ces_euc_state_t *euc_state;
102 if (in == UCS_CHAR_NONE)
103 return 1; /* No state reinitialization for table charsets */
104 if (iconv_char32bit(in))
106 euc_state = (iconv_ces_euc_state_t *)(ces->data);
107 for (i = 0; i < euc_state->nccs; i++) {
108 _CONST iconv_ces_euc_ccs_t *ccsattr;
109 _CONST struct iconv_ccs *ccs = &(euc_state->ccs[i]);
110 ucs_t res = ICONV_CCS_CONVERT_FROM_UCS(ccs, in);
112 if (res == UCS_CHAR_INVALID)
114 ccsattr = &(((_CONST iconv_ces_euc_ccs_t *)(ces->desc->data))[i]);
117 res |= is_7bit(ccs) ? 0x80 : 0x8080;
118 else if (!(res & 0x8080))
120 } else if (res & 0x8080)
122 bytes = (res & 0xFF00 ? 2 : 1) + ccsattr->prefixlen;
123 if (*outbytesleft < bytes)
124 return 0; /* No space in the output buffer */
125 if (ccsattr->prefixlen) {
126 memcpy(*outbuf, ccsattr->prefix, ccsattr->prefixlen);
127 (*outbuf) += ccsattr->prefixlen;
130 *(*outbuf)++ = (unsigned char)(res >> 8);
131 *(*outbuf)++ = (unsigned char)res;
132 *outbytesleft -= bytes;
135 return -1; /* No character in output charset */
139 _DEFUN(cvt2ucs, (ccs, inbuf, inbytesleft, hi_plane, bufptr),
140 struct iconv_ccs *ccs _AND
141 _CONST unsigned char *inbuf _AND
142 size_t inbytesleft _AND
144 _CONST unsigned char **bufptr)
146 size_t bytes = ccs->nbits > 8 ? 2 : 1;
147 ucs_t ch = *(_CONST unsigned char *)inbuf++;
149 if (inbytesleft < bytes)
150 return UCS_CHAR_NONE; /* Not enough bytes in the input buffer */
152 ch = (ch << 8) | *(_CONST unsigned char *)inbuf++;
156 return UCS_CHAR_INVALID;
159 } else if (ch & 0x8080)
160 return UCS_CHAR_INVALID;
161 return ICONV_CCS_CONVERT_TO_UCS(ccs, ch);
165 _DEFUN(_iconv_euc_convert_to_ucs, (ces, inbuf, inbytesleft),
166 struct iconv_ces *ces _AND
167 _CONST unsigned char **inbuf _AND
170 iconv_ces_euc_state_t *euc_state =
171 (iconv_ces_euc_state_t *)(ces->data);
172 ucs_t res = UCS_CHAR_INVALID;
173 _CONST unsigned char *ptr;
176 if (**inbuf & 0x80) {
177 for (i = 1; i < euc_state->nccs; i++) {
178 _CONST iconv_ces_euc_ccs_t *ccsattr =
179 &(((_CONST iconv_ces_euc_ccs_t *)
180 (ces->desc->data))[i]);
181 if (ccsattr->prefixlen + 1 > *inbytesleft)
182 return UCS_CHAR_NONE;
183 if (ccsattr->prefixlen &&
184 memcmp(*inbuf, ccsattr->prefix, ccsattr->prefixlen))
186 res = cvt2ucs(&(euc_state->ccs[i]),
187 *inbuf + ccsattr->prefixlen,
188 *inbytesleft - ccsattr->prefixlen,
190 if (res != UCS_CHAR_INVALID)
193 if (res == UCS_CHAR_INVALID)
196 res = cvt2ucs(euc_state->ccs, *inbuf, *inbytesleft, 0, &ptr);
197 if (res == UCS_CHAR_NONE)
198 return res; /* Not enough bytes in the input buffer */
199 *inbytesleft -= ptr - *inbuf;