Blame lib/mbsrtowcs-impl.h

Packit Service a2489d
/* Convert string to wide string.
Packit Service a2489d
   Copyright (C) 2008-2018 Free Software Foundation, Inc.
Packit Service a2489d
   Written by Bruno Haible <bruno@clisp.org>, 2008.
Packit Service a2489d
Packit Service a2489d
   This program is free software: you can redistribute it and/or modify
Packit Service a2489d
   it under the terms of the GNU General Public License as published by
Packit Service a2489d
   the Free Software Foundation; either version 3 of the License, or
Packit Service a2489d
   (at your option) any later version.
Packit Service a2489d
Packit Service a2489d
   This program is distributed in the hope that it will be useful,
Packit Service a2489d
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a2489d
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service a2489d
   GNU General Public License for more details.
Packit Service a2489d
Packit Service a2489d
   You should have received a copy of the GNU General Public License
Packit Service a2489d
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit Service a2489d
Packit Service a2489d
size_t
Packit Service a2489d
mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps)
Packit Service a2489d
{
Packit Service a2489d
  if (ps == NULL)
Packit Service a2489d
    ps = &_gl_mbsrtowcs_state;
Packit Service a2489d
  {
Packit Service a2489d
    const char *src = *srcp;
Packit Service a2489d
Packit Service a2489d
    if (dest != NULL)
Packit Service a2489d
      {
Packit Service a2489d
        wchar_t *destptr = dest;
Packit Service a2489d
Packit Service a2489d
        for (; len > 0; destptr++, len--)
Packit Service a2489d
          {
Packit Service a2489d
            size_t src_avail;
Packit Service a2489d
            size_t ret;
Packit Service a2489d
Packit Service a2489d
            /* An optimized variant of
Packit Service a2489d
               src_avail = strnlen1 (src, MB_LEN_MAX);  */
Packit Service a2489d
            if (src[0] == '\0')
Packit Service a2489d
              src_avail = 1;
Packit Service a2489d
            else if (src[1] == '\0')
Packit Service a2489d
              src_avail = 2;
Packit Service a2489d
            else if (src[2] == '\0')
Packit Service a2489d
              src_avail = 3;
Packit Service a2489d
            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
Packit Service a2489d
              src_avail = 4;
Packit Service a2489d
            else
Packit Service a2489d
              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
Packit Service a2489d
Packit Service a2489d
            /* Parse the next multibyte character.  */
Packit Service a2489d
            ret = mbrtowc (destptr, src, src_avail, ps);
Packit Service a2489d
Packit Service a2489d
            if (ret == (size_t)(-2))
Packit Service a2489d
              /* Encountered a multibyte character that extends past a '\0' byte
Packit Service a2489d
                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
Packit Service a2489d
              abort ();
Packit Service a2489d
Packit Service a2489d
            if (ret == (size_t)(-1))
Packit Service a2489d
              goto bad_input;
Packit Service a2489d
            if (ret == 0)
Packit Service a2489d
              {
Packit Service a2489d
                src = NULL;
Packit Service a2489d
                /* Here mbsinit (ps).  */
Packit Service a2489d
                break;
Packit Service a2489d
              }
Packit Service a2489d
            src += ret;
Packit Service a2489d
          }
Packit Service a2489d
Packit Service a2489d
        *srcp = src;
Packit Service a2489d
        return destptr - dest;
Packit Service a2489d
      }
Packit Service a2489d
    else
Packit Service a2489d
      {
Packit Service a2489d
        /* Ignore dest and len, don't store *srcp at the end, and
Packit Service a2489d
           don't clobber *ps.  */
Packit Service a2489d
        mbstate_t state = *ps;
Packit Service a2489d
        size_t totalcount = 0;
Packit Service a2489d
Packit Service a2489d
        for (;; totalcount++)
Packit Service a2489d
          {
Packit Service a2489d
            size_t src_avail;
Packit Service a2489d
            size_t ret;
Packit Service a2489d
Packit Service a2489d
            /* An optimized variant of
Packit Service a2489d
               src_avail = strnlen1 (src, MB_LEN_MAX);  */
Packit Service a2489d
            if (src[0] == '\0')
Packit Service a2489d
              src_avail = 1;
Packit Service a2489d
            else if (src[1] == '\0')
Packit Service a2489d
              src_avail = 2;
Packit Service a2489d
            else if (src[2] == '\0')
Packit Service a2489d
              src_avail = 3;
Packit Service a2489d
            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
Packit Service a2489d
              src_avail = 4;
Packit Service a2489d
            else
Packit Service a2489d
              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
Packit Service a2489d
Packit Service a2489d
            /* Parse the next multibyte character.  */
Packit Service a2489d
            ret = mbrtowc (NULL, src, src_avail, &state);
Packit Service a2489d
Packit Service a2489d
            if (ret == (size_t)(-2))
Packit Service a2489d
              /* Encountered a multibyte character that extends past a '\0' byte
Packit Service a2489d
                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
Packit Service a2489d
              abort ();
Packit Service a2489d
Packit Service a2489d
            if (ret == (size_t)(-1))
Packit Service a2489d
              goto bad_input2;
Packit Service a2489d
            if (ret == 0)
Packit Service a2489d
              {
Packit Service a2489d
                /* Here mbsinit (&state).  */
Packit Service a2489d
                break;
Packit Service a2489d
              }
Packit Service a2489d
            src += ret;
Packit Service a2489d
          }
Packit Service a2489d
Packit Service a2489d
        return totalcount;
Packit Service a2489d
      }
Packit Service a2489d
Packit Service a2489d
   bad_input:
Packit Service a2489d
    *srcp = src;
Packit Service a2489d
   bad_input2:
Packit Service a2489d
    errno = EILSEQ;
Packit Service a2489d
    return (size_t)(-1);
Packit Service a2489d
  }
Packit Service a2489d
}