diff options
Diffstat (limited to 'newlib/libc/iconv/lib/ces_euc.c')
-rw-r--r-- | newlib/libc/iconv/lib/ces_euc.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/newlib/libc/iconv/lib/ces_euc.c b/newlib/libc/iconv/lib/ces_euc.c new file mode 100644 index 000000000..dc5000c2d --- /dev/null +++ b/newlib/libc/iconv/lib/ces_euc.c @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 1999,2000 + * Konstantin Chuguev. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * iconv (Charset Conversion Library) v2.0 + */ +#ifdef ENABLE_ICONV + +#include "deps.h" +#include <_ansi.h> +#include <sys/types.h> +#include <stddef.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <wchar.h> +#include <reent.h> +#include "local.h" + +typedef struct { + int nccs; + struct iconv_ccs ccs[1]; +} iconv_ces_euc_state; + +int +_DEFUN(iconv_euc_init, (rptr, data, desc_data, num), + struct _reent *rptr _AND + _VOID_PTR *data _AND + _CONST _VOID_PTR desc_data _AND + size_t num) +{ + size_t stsz = sizeof(iconv_ces_euc_state) + + sizeof(struct iconv_ccs) * (num - 1); + int i; + iconv_ces_euc_state *state = (iconv_ces_euc_state *)_malloc_r(rptr, stsz); + + if (state == NULL) + return __errno_r(rptr); + for (i = 0; i < num; i++) { + int res = iconv_ccs_init(rptr, &(state->ccs[i]), + ((_CONST iconv_ces_euc_ccs *) desc_data)[i].name); + if (res) { + while (--i >= 0) + state->ccs[i].close(rptr, &(state->ccs[i])); + _free_r(rptr, state); + return res; + } + } + state->nccs = num; + (iconv_ces_euc_state *)*data = state; + return 0; +} + +int +_DEFUN(iconv_euc_close, (rptr, data), + struct _reent *rptr _AND + _VOID_PTR data) +{ +#define state ((iconv_ces_euc_state *)data) + int i, res = 0; + + for (i = 0; i < state->nccs; i++) + res = state->ccs[i].close(rptr, &(state->ccs[i])) || res; + _free_r(rptr, data); + return res; +#undef state +} + +#define is_7_14bit(data) ((data)->nbits & 7) +#define is_7bit(data) ((data)->nbits & 1) + +ssize_t +_DEFUN(iconv_euc_convert_from_ucs, (ces, in, outbuf, outbytesleft), + struct iconv_ces *ces _AND + ucs_t in _AND + unsigned char **outbuf _AND + size_t *outbytesleft) +{ + iconv_ces_euc_state *euc_state; + size_t bytes; + int i; + + if (in == UCS_CHAR_NONE) + return 1; /* No state reinitialization for table charsets */ + if (iconv_char32bit(in)) + return -1; + euc_state = (iconv_ces_euc_state *)(ces->data); + for (i = 0; i < euc_state->nccs; i++) { + _CONST iconv_ces_euc_ccs *ccsattr; + _CONST struct iconv_ccs *ccs = &(euc_state->ccs[i]); + ucs_t res = ICONV_CCS_CONVERT_FROM_UCS(ccs, in); + + if (res == UCS_CHAR_INVALID) + continue; + ccsattr = &(((_CONST iconv_ces_euc_ccs *)(ces->desc->data))[i]); + if (i) { + if (is_7_14bit(ccs)) + res |= is_7bit(ccs) ? 0x80 : 0x8080; + else if (!(res & 0x8080)) + continue; + } else if (res & 0x8080) + continue; + bytes = (res & 0xFF00 ? 2 : 1) + ccsattr->prefixlen; + if (*outbytesleft < bytes) + return 0; /* No space in the output buffer */ + if (ccsattr->prefixlen) { + memcpy(*outbuf, ccsattr->prefix, ccsattr->prefixlen); + (*outbuf) += ccsattr->prefixlen; + } + if (res & 0xFF00) + *(*outbuf)++ = (unsigned char)(res >> 8); + *(*outbuf)++ = (unsigned char)res; + *outbytesleft -= bytes; + return 1; + } + return -1; /* No character in output charset */ +} + +static ucs_t +_DEFUN(cvt2ucs, (ccs, inbuf, inbytesleft, hi_plane, bufptr), + struct iconv_ccs *ccs _AND + _CONST unsigned char *inbuf _AND + size_t inbytesleft _AND + int hi_plane _AND + _CONST unsigned char **bufptr) +{ + size_t bytes = ccs->nbits > 8 ? 2 : 1; + ucs_t ch = *(_CONST unsigned char *)inbuf++; + + if (inbytesleft < bytes) + return UCS_CHAR_NONE; /* Not enough bytes in the input buffer */ + if (bytes == 2) + ch = (ch << 8) | *(_CONST unsigned char *)inbuf++; + *bufptr = inbuf; + if (hi_plane) { + if (!(ch & 0x8080)) + return UCS_CHAR_INVALID; + if (is_7_14bit(ccs)) + ch &= 0x7F7F; + } else if (ch & 0x8080) + return UCS_CHAR_INVALID; + return ICONV_CCS_CONVERT_TO_UCS(ccs, ch); +} + +ucs_t +_DEFUN(iconv_euc_convert_to_ucs, (ces, inbuf, inbytesleft), + struct iconv_ces *ces _AND + _CONST unsigned char **inbuf _AND + size_t *inbytesleft) +{ + iconv_ces_euc_state *euc_state = + (iconv_ces_euc_state *)(ces->data); + ucs_t res = UCS_CHAR_INVALID; + _CONST unsigned char *ptr; + int i; + + if (**inbuf & 0x80) { + for (i = 1; i < euc_state->nccs; i++) { + _CONST iconv_ces_euc_ccs *ccsattr = + &(((_CONST iconv_ces_euc_ccs *) + (ces->desc->data))[i]); + if (ccsattr->prefixlen + 1 > *inbytesleft) + return UCS_CHAR_NONE; + if (ccsattr->prefixlen && + memcmp(*inbuf, ccsattr->prefix, ccsattr->prefixlen)) + continue; + res = cvt2ucs(&(euc_state->ccs[i]), + *inbuf + ccsattr->prefixlen, + *inbytesleft - ccsattr->prefixlen, + 1, &ptr); + if (res != UCS_CHAR_INVALID) + break; + } + if (res == UCS_CHAR_INVALID) + ptr = *inbuf + 1; + } else + res = cvt2ucs(euc_state->ccs, *inbuf, *inbytesleft, 0, &ptr); + if (res == UCS_CHAR_NONE) + return res; /* Not enough bytes in the input buffer */ + *inbytesleft -= ptr - *inbuf; + *inbuf = ptr; + return res; +} + +#endif /* #ifdef ENABLE_ICONV */ + |