From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/iconv/lib/loop_wchar.h | 458 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 jni/iconv/lib/loop_wchar.h (limited to 'jni/iconv/lib/loop_wchar.h') diff --git a/jni/iconv/lib/loop_wchar.h b/jni/iconv/lib/loop_wchar.h new file mode 100644 index 0000000..30d5dbd --- /dev/null +++ b/jni/iconv/lib/loop_wchar.h @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2000-2002, 2005-2006, 2008 Free Software Foundation, Inc. + * This file is part of the GNU LIBICONV Library. + * + * The GNU LIBICONV Library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * The GNU LIBICONV Library is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU LIBICONV Library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* This file defines three conversion loops: + - from wchar_t to anything else, + - from anything else to wchar_t, + - from wchar_t to wchar_t. + */ + +#if HAVE_WCRTOMB || HAVE_MBRTOWC +# include +# define BUF_SIZE 64 /* assume MB_LEN_MAX <= 64 */ + /* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ + extern size_t mbrtowc (); +# ifdef mbstate_t +# define mbrtowc(pwc, s, n, ps) (mbrtowc)(pwc, s, n, 0) +# define mbsinit(ps) 1 +# endif +# ifndef mbsinit +# if !HAVE_MBSINIT +# define mbsinit(ps) 1 +# endif +# endif +#endif + +/* + * The first two conversion loops have an extended conversion descriptor. + */ +struct wchar_conv_struct { + struct conv_struct parent; +#if HAVE_WCRTOMB || HAVE_MBRTOWC + mbstate_t state; +#endif +}; + + +#if HAVE_WCRTOMB + +/* From wchar_t to anything else. */ + +#ifndef LIBICONV_PLUG + +#if 0 + +struct wc_to_mb_fallback_locals { + struct wchar_conv_struct * l_wcd; + char* l_outbuf; + size_t l_outbytesleft; + int l_errno; +}; + +/* A callback that writes a string given in the locale encoding. */ +static void wc_to_mb_write_replacement (const char *buf, size_t buflen, + void* callback_arg) +{ + struct wc_to_mb_fallback_locals * plocals = + (struct wc_to_mb_fallback_locals *) callback_arg; + /* Do nothing if already encountered an error in a previous call. */ + if (plocals->l_errno == 0) { + /* Attempt to convert the passed buffer to the target encoding. + Here we don't support characters split across multiple calls. */ + const char* bufptr = buf; + size_t bufleft = buflen; + size_t res = unicode_loop_convert(&plocals->l_wcd->parent, + &bufptr,&bufleft, + &plocals->l_outbuf,&plocals->l_outbytesleft); + if (res == (size_t)(-1)) { + if (errno == EILSEQ || errno == EINVAL) + /* Invalid buf contents. */ + plocals->l_errno = EILSEQ; + else if (errno == E2BIG) + /* Output buffer too small. */ + plocals->l_errno = E2BIG; + else + abort(); + } else { + /* Successful conversion. */ + if (bufleft > 0) + abort(); + } + } +} + +#else + +struct wc_to_mb_fallback_locals { + char* l_outbuf; + size_t l_outbytesleft; + int l_errno; +}; + +/* A callback that writes a string given in the target encoding. */ +static void wc_to_mb_write_replacement (const char *buf, size_t buflen, + void* callback_arg) +{ + struct wc_to_mb_fallback_locals * plocals = + (struct wc_to_mb_fallback_locals *) callback_arg; + /* Do nothing if already encountered an error in a previous call. */ + if (plocals->l_errno == 0) { + /* Attempt to copy the passed buffer to the output buffer. */ + if (plocals->l_outbytesleft < buflen) + plocals->l_errno = E2BIG; + else { + memcpy(plocals->l_outbuf, buf, buflen); + plocals->l_outbuf += buflen; + plocals->l_outbytesleft -= buflen; + } + } +} + +#endif + +#endif /* !LIBICONV_PLUG */ + +static size_t wchar_from_loop_convert (iconv_t icd, + const char* * inbuf, size_t *inbytesleft, + char* * outbuf, size_t *outbytesleft) +{ + struct wchar_conv_struct * wcd = (struct wchar_conv_struct *) icd; + size_t result = 0; + while (*inbytesleft >= sizeof(wchar_t)) { + const wchar_t * inptr = (const wchar_t *) *inbuf; + size_t inleft = *inbytesleft; + char buf[BUF_SIZE]; + mbstate_t state = wcd->state; + size_t bufcount = 0; + while (inleft >= sizeof(wchar_t)) { + /* Convert one wchar_t to multibyte representation. */ + size_t count = wcrtomb(buf+bufcount,*inptr,&state); + if (count == (size_t)(-1)) { + /* Invalid input. */ + if (wcd->parent.discard_ilseq) { + count = 0; + } + #ifndef LIBICONV_PLUG + else if (wcd->parent.fallbacks.wc_to_mb_fallback != NULL) { + /* Drop the contents of buf[] accumulated so far, and instead + pass all queued wide characters to the fallback handler. */ + struct wc_to_mb_fallback_locals locals; + const wchar_t * fallback_inptr; + #if 0 + locals.l_wcd = wcd; + #endif + locals.l_outbuf = *outbuf; + locals.l_outbytesleft = *outbytesleft; + locals.l_errno = 0; + for (fallback_inptr = (const wchar_t *) *inbuf; + fallback_inptr <= inptr; + fallback_inptr++) + wcd->parent.fallbacks.wc_to_mb_fallback(*fallback_inptr, + wc_to_mb_write_replacement, + &locals, + wcd->parent.fallbacks.data); + if (locals.l_errno != 0) { + errno = locals.l_errno; + return -1; + } + wcd->state = state; + *inbuf = (const char *) (inptr + 1); + *inbytesleft = inleft - sizeof(wchar_t); + *outbuf = locals.l_outbuf; + *outbytesleft = locals.l_outbytesleft; + result += 1; + break; + } + #endif + else { + errno = EILSEQ; + return -1; + } + } + inptr++; + inleft -= sizeof(wchar_t); + bufcount += count; + if (count == 0) { + /* Continue, append next wchar_t. */ + } else { + /* Attempt to convert the accumulated multibyte representations + to the target encoding. */ + const char* bufptr = buf; + size_t bufleft = bufcount; + char* outptr = *outbuf; + size_t outleft = *outbytesleft; + size_t res = unicode_loop_convert(&wcd->parent, + &bufptr,&bufleft, + &outptr,&outleft); + if (res == (size_t)(-1)) { + if (errno == EILSEQ) + /* Invalid input. */ + return -1; + else if (errno == E2BIG) + /* Output buffer too small. */ + return -1; + else if (errno == EINVAL) { + /* Continue, append next wchar_t, but avoid buffer overrun. */ + if (bufcount + MB_CUR_MAX > BUF_SIZE) + abort(); + } else + abort(); + } else { + /* Successful conversion. */ + wcd->state = state; + *inbuf = (const char *) inptr; + *inbytesleft = inleft; + *outbuf = outptr; + *outbytesleft = outleft; + result += res; + break; + } + } + } + } + return result; +} + +static size_t wchar_from_loop_reset (iconv_t icd, + char* * outbuf, size_t *outbytesleft) +{ + struct wchar_conv_struct * wcd = (struct wchar_conv_struct *) icd; + if (outbuf == NULL || *outbuf == NULL) { + /* Reset the states. */ + memset(&wcd->state,'\0',sizeof(mbstate_t)); + return unicode_loop_reset(&wcd->parent,NULL,NULL); + } else { + if (!mbsinit(&wcd->state)) { + mbstate_t state = wcd->state; + char buf[BUF_SIZE]; + size_t bufcount = wcrtomb(buf,(wchar_t)0,&state); + if (bufcount == (size_t)(-1) || bufcount == 0 || buf[bufcount-1] != '\0') + abort(); + else { + const char* bufptr = buf; + size_t bufleft = bufcount-1; + char* outptr = *outbuf; + size_t outleft = *outbytesleft; + size_t res = unicode_loop_convert(&wcd->parent, + &bufptr,&bufleft, + &outptr,&outleft); + if (res == (size_t)(-1)) { + if (errno == E2BIG) + return -1; + else + abort(); + } else { + res = unicode_loop_reset(&wcd->parent,&outptr,&outleft); + if (res == (size_t)(-1)) + return res; + else { + /* Successful. */ + wcd->state = state; + *outbuf = outptr; + *outbytesleft = outleft; + return 0; + } + } + } + } else + return unicode_loop_reset(&wcd->parent,outbuf,outbytesleft); + } +} + +#endif + + +#if HAVE_MBRTOWC + +/* From anything else to wchar_t. */ + +#ifndef LIBICONV_PLUG + +struct mb_to_wc_fallback_locals { + char* l_outbuf; + size_t l_outbytesleft; + int l_errno; +}; + +static void mb_to_wc_write_replacement (const wchar_t *buf, size_t buflen, + void* callback_arg) +{ + struct mb_to_wc_fallback_locals * plocals = + (struct mb_to_wc_fallback_locals *) callback_arg; + /* Do nothing if already encountered an error in a previous call. */ + if (plocals->l_errno == 0) { + /* Attempt to copy the passed buffer to the output buffer. */ + if (plocals->l_outbytesleft < sizeof(wchar_t)*buflen) + plocals->l_errno = E2BIG; + else { + for (; buflen > 0; buf++, buflen--) { + *(wchar_t*) plocals->l_outbuf = *buf; + plocals->l_outbuf += sizeof(wchar_t); + plocals->l_outbytesleft -= sizeof(wchar_t); + } + } + } +} + +#endif /* !LIBICONV_PLUG */ + +static size_t wchar_to_loop_convert (iconv_t icd, + const char* * inbuf, size_t *inbytesleft, + char* * outbuf, size_t *outbytesleft) +{ + struct wchar_conv_struct * wcd = (struct wchar_conv_struct *) icd; + size_t result = 0; + while (*inbytesleft > 0) { + size_t incount; + for (incount = 1; incount <= *inbytesleft; incount++) { + char buf[BUF_SIZE]; + const char* inptr = *inbuf; + size_t inleft = incount; + char* bufptr = buf; + size_t bufleft = BUF_SIZE; + size_t res = unicode_loop_convert(&wcd->parent, + &inptr,&inleft, + &bufptr,&bufleft); + if (res == (size_t)(-1)) { + if (errno == EILSEQ) + /* Invalid input. */ + return -1; + else if (errno == EINVAL) { + /* Incomplete input. Next try with one more input byte. */ + } else + /* E2BIG shouldn't occur. */ + abort(); + } else { + /* Successful conversion. */ + size_t bufcount = bufptr-buf; /* = BUF_SIZE-bufleft */ + mbstate_t state = wcd->state; + wchar_t wc; + res = mbrtowc(&wc,buf,bufcount,&state); + if (res == (size_t)(-2)) { + /* Next try with one more input byte. */ + } else { + if (res == (size_t)(-1)) { + /* Invalid input. */ + if (wcd->parent.discard_ilseq) { + } + #ifndef LIBICONV_PLUG + else if (wcd->parent.fallbacks.mb_to_wc_fallback != NULL) { + /* Drop the contents of buf[] accumulated so far, and instead + pass all queued chars to the fallback handler. */ + struct mb_to_wc_fallback_locals locals; + locals.l_outbuf = *outbuf; + locals.l_outbytesleft = *outbytesleft; + locals.l_errno = 0; + wcd->parent.fallbacks.mb_to_wc_fallback(*inbuf, incount, + mb_to_wc_write_replacement, + &locals, + wcd->parent.fallbacks.data); + if (locals.l_errno != 0) { + errno = locals.l_errno; + return -1; + } + /* Restoring the state is not needed because it is the initial + state anyway: For all known locale encodings, the multibyte + to wchar_t conversion doesn't have shift state, and we have + excluded partial accumulated characters. */ + /* wcd->state = state; */ + *inbuf += incount; + *inbytesleft -= incount; + *outbuf = locals.l_outbuf; + *outbytesleft = locals.l_outbytesleft; + result += 1; + break; + } + #endif + else + return -1; + } else { + if (*outbytesleft < sizeof(wchar_t)) { + errno = E2BIG; + return -1; + } + *(wchar_t*) *outbuf = wc; + /* Restoring the state is not needed because it is the initial + state anyway: For all known locale encodings, the multibyte + to wchar_t conversion doesn't have shift state, and we have + excluded partial accumulated characters. */ + /* wcd->state = state; */ + *outbuf += sizeof(wchar_t); + *outbytesleft -= sizeof(wchar_t); + } + *inbuf += incount; + *inbytesleft -= incount; + result += res; + break; + } + } + } + } + return result; +} + +static size_t wchar_to_loop_reset (iconv_t icd, + char* * outbuf, size_t *outbytesleft) +{ + struct wchar_conv_struct * wcd = (struct wchar_conv_struct *) icd; + size_t res = unicode_loop_reset(&wcd->parent,outbuf,outbytesleft); + if (res == (size_t)(-1)) + return res; + memset(&wcd->state,0,sizeof(mbstate_t)); + return 0; +} + +#endif + + +/* From wchar_t to wchar_t. */ + +static size_t wchar_id_loop_convert (iconv_t icd, + const char* * inbuf, size_t *inbytesleft, + char* * outbuf, size_t *outbytesleft) +{ + struct conv_struct * cd = (struct conv_struct *) icd; + const wchar_t* inptr = (const wchar_t*) *inbuf; + size_t inleft = *inbytesleft / sizeof(wchar_t); + wchar_t* outptr = (wchar_t*) *outbuf; + size_t outleft = *outbytesleft / sizeof(wchar_t); + size_t count = (inleft <= outleft ? inleft : outleft); + if (count > 0) { + *inbytesleft -= count * sizeof(wchar_t); + *outbytesleft -= count * sizeof(wchar_t); + do { + wchar_t wc = *inptr++; + *outptr++ = wc; + #ifndef LIBICONV_PLUG + if (cd->hooks.wc_hook) + (*cd->hooks.wc_hook)(wc, cd->hooks.data); + #endif + } while (--count > 0); + *inbuf = (const char*) inptr; + *outbuf = (char*) outptr; + } + return 0; +} + +static size_t wchar_id_loop_reset (iconv_t icd, + char* * outbuf, size_t *outbytesleft) +{ + return 0; +} -- cgit v1.2.3