(root)/
glibc-2.38/
iconv/
iconv.c
       1  /* Convert characters in input buffer using conversion descriptor to
       2     output buffer.
       3     Copyright (C) 1997-2023 Free Software Foundation, Inc.
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  #include <stddef.h> /* for NULL */
      21  #include <errno.h>
      22  #include <iconv.h>
      23  
      24  #include <gconv_int.h>
      25  
      26  #include <assert.h>
      27  
      28  
      29  size_t
      30  iconv (iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf,
      31         size_t *outbytesleft)
      32  {
      33    __gconv_t gcd = (__gconv_t) cd;
      34    char *outstart = outbuf ? *outbuf : NULL;
      35    size_t irreversible;
      36    int result;
      37  
      38    if (__glibc_unlikely (inbuf == NULL || *inbuf == NULL))
      39      {
      40        if (outbuf == NULL || *outbuf == NULL)
      41  	result = __gconv (gcd, NULL, NULL, NULL, NULL, &irreversible);
      42        else
      43  	result = __gconv (gcd, NULL, NULL, (unsigned char **) outbuf,
      44  			  (unsigned char *) (outstart + *outbytesleft),
      45  			  &irreversible);
      46      }
      47    else
      48      {
      49        const char *instart = *inbuf;
      50  
      51        result = __gconv (gcd, (const unsigned char **) inbuf,
      52  			(const unsigned char *)  (*inbuf + *inbytesleft),
      53  			(unsigned char **) outbuf,
      54  			(unsigned char *) (*outbuf + *outbytesleft),
      55  			&irreversible);
      56  
      57        *inbytesleft -= *inbuf - instart;
      58      }
      59    if (outstart != NULL)
      60      *outbytesleft -= *outbuf - outstart;
      61  
      62    switch (__builtin_expect (result, __GCONV_OK))
      63      {
      64      case __GCONV_ILLEGAL_DESCRIPTOR:
      65        __set_errno (EBADF);
      66        irreversible = (size_t) -1L;
      67        break;
      68  
      69      case __GCONV_ILLEGAL_INPUT:
      70        __set_errno (EILSEQ);
      71        irreversible = (size_t) -1L;
      72        break;
      73  
      74      case __GCONV_FULL_OUTPUT:
      75        __set_errno (E2BIG);
      76        irreversible = (size_t) -1L;
      77        break;
      78  
      79      case __GCONV_INCOMPLETE_INPUT:
      80        __set_errno (EINVAL);
      81        irreversible = (size_t) -1L;
      82        break;
      83  
      84      case __GCONV_EMPTY_INPUT:
      85      case __GCONV_OK:
      86        /* Nothing.  */
      87        break;
      88  
      89      default:
      90        assert (!"Nothing like this should happen");
      91      }
      92  
      93    return irreversible;
      94  }