(root)/
gettext-0.22.4/
gettext-tools/
gnulib-lib/
mbsrtowcs-impl.h
       1  /* Convert string to wide string.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2008.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  size_t
      19  FUNC (DCHAR_T *dest, const char **srcp, size_t len, mbstate_t *ps)
      20  {
      21    if (ps == NULL)
      22      ps = &INTERNAL_STATE;
      23    {
      24      const char *src = *srcp;
      25  
      26      if (dest != NULL)
      27        {
      28          DCHAR_T *destptr = dest;
      29  
      30          for (; len > 0; destptr++, len--)
      31            {
      32              size_t src_avail;
      33              size_t ret;
      34  
      35              /* An optimized variant of
      36                 src_avail = strnlen1 (src, MB_LEN_MAX);  */
      37              if (src[0] == '\0')
      38                src_avail = 1;
      39              else if (src[1] == '\0')
      40                src_avail = 2;
      41              else if (src[2] == '\0')
      42                src_avail = 3;
      43              else if (MB_LEN_MAX <= 4 || src[3] == '\0')
      44                src_avail = 4;
      45              else
      46                src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
      47  
      48              /* Parse the next multibyte character.  */
      49              ret = MBRTOWC (destptr, src, src_avail, ps);
      50  
      51              if (ret == (size_t)(-2))
      52                /* Encountered a multibyte character that extends past a '\0' byte
      53                   or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
      54                abort ();
      55  
      56              if (ret == (size_t)(-1))
      57                goto bad_input;
      58              if (ret == 0)
      59                {
      60                  src = NULL;
      61                  /* Here mbsinit (ps).  */
      62                  break;
      63                }
      64              if (!(USES_C32 && ret == (size_t)(-3)))
      65                src += ret;
      66            }
      67  
      68          *srcp = src;
      69          return destptr - dest;
      70        }
      71      else
      72        {
      73          /* Ignore dest and len, don't store *srcp at the end, and
      74             don't clobber *ps.  */
      75          mbstate_t state = *ps;
      76          size_t totalcount = 0;
      77  
      78          for (;; totalcount++)
      79            {
      80              size_t src_avail;
      81              size_t ret;
      82  
      83              /* An optimized variant of
      84                 src_avail = strnlen1 (src, MB_LEN_MAX);  */
      85              if (src[0] == '\0')
      86                src_avail = 1;
      87              else if (src[1] == '\0')
      88                src_avail = 2;
      89              else if (src[2] == '\0')
      90                src_avail = 3;
      91              else if (MB_LEN_MAX <= 4 || src[3] == '\0')
      92                src_avail = 4;
      93              else
      94                src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
      95  
      96              /* Parse the next multibyte character.  */
      97              ret = MBRTOWC (NULL, src, src_avail, &state);
      98  
      99              if (ret == (size_t)(-2))
     100                /* Encountered a multibyte character that extends past a '\0' byte
     101                   or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
     102                abort ();
     103  
     104              if (ret == (size_t)(-1))
     105                goto bad_input2;
     106              if (ret == 0)
     107                {
     108                  /* Here mbsinit (&state).  */
     109                  break;
     110                }
     111              src += ret;
     112            }
     113  
     114          return totalcount;
     115        }
     116  
     117     bad_input:
     118      *srcp = src;
     119     bad_input2:
     120      errno = EILSEQ;
     121      return (size_t)(-1);
     122    }
     123  }