(root)/
tar-1.35/
gnu/
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              src += ret;
      65            }
      66  
      67          *srcp = src;
      68          return destptr - dest;
      69        }
      70      else
      71        {
      72          /* Ignore dest and len, don't store *srcp at the end, and
      73             don't clobber *ps.  */
      74          mbstate_t state = *ps;
      75          size_t totalcount = 0;
      76  
      77          for (;; totalcount++)
      78            {
      79              size_t src_avail;
      80              size_t ret;
      81  
      82              /* An optimized variant of
      83                 src_avail = strnlen1 (src, MB_LEN_MAX);  */
      84              if (src[0] == '\0')
      85                src_avail = 1;
      86              else if (src[1] == '\0')
      87                src_avail = 2;
      88              else if (src[2] == '\0')
      89                src_avail = 3;
      90              else if (MB_LEN_MAX <= 4 || src[3] == '\0')
      91                src_avail = 4;
      92              else
      93                src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
      94  
      95              /* Parse the next multibyte character.  */
      96              ret = MBRTOWC (NULL, src, src_avail, &state);
      97  
      98              if (ret == (size_t)(-2))
      99                /* Encountered a multibyte character that extends past a '\0' byte
     100                   or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
     101                abort ();
     102  
     103              if (ret == (size_t)(-1))
     104                goto bad_input2;
     105              if (ret == 0)
     106                {
     107                  /* Here mbsinit (&state).  */
     108                  break;
     109                }
     110              src += ret;
     111            }
     112  
     113          return totalcount;
     114        }
     115  
     116     bad_input:
     117      *srcp = src;
     118     bad_input2:
     119      errno = EILSEQ;
     120      return (size_t)(-1);
     121    }
     122  }