(root)/
glibc-2.38/
iconv/
gconv.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 <assert.h>
      21  #include <dlfcn.h>
      22  #include <stddef.h>
      23  #include <sys/param.h>
      24  
      25  #include <gconv_int.h>
      26  #include <pointer_guard.h>
      27  
      28  
      29  int
      30  __gconv (__gconv_t cd, const unsigned char **inbuf,
      31  	 const unsigned char *inbufend, unsigned char **outbuf,
      32  	 unsigned char *outbufend, size_t *irreversible)
      33  {
      34    size_t last_step;
      35    int result;
      36  
      37    if (cd == (__gconv_t) -1L)
      38      return __GCONV_ILLEGAL_DESCRIPTOR;
      39  
      40    last_step = cd->__nsteps - 1;
      41  
      42    assert (irreversible != NULL);
      43    *irreversible = 0;
      44  
      45    cd->__data[last_step].__outbuf = outbuf != NULL ? *outbuf : NULL;
      46    cd->__data[last_step].__outbufend = outbufend;
      47  
      48    __gconv_fct fct = cd->__steps->__fct;
      49    if (cd->__steps->__shlib_handle != NULL)
      50      PTR_DEMANGLE (fct);
      51  
      52    if (inbuf == NULL || *inbuf == NULL)
      53      {
      54        /* We just flush.  */
      55        result = DL_CALL_FCT (fct,
      56  			    (cd->__steps, cd->__data, NULL, NULL, NULL,
      57  			     irreversible,
      58  			     cd->__data[last_step].__outbuf == NULL ? 2 : 1,
      59  			     0));
      60  
      61        /* If the flush was successful clear the rest of the state.  */
      62        if (result == __GCONV_OK)
      63  	for (size_t cnt = 0; cnt <= last_step; ++cnt)
      64  	  cd->__data[cnt].__invocation_counter = 0;
      65      }
      66    else
      67      {
      68        const unsigned char *last_start;
      69  
      70        assert (outbuf != NULL && *outbuf != NULL);
      71  
      72        do
      73  	{
      74  	  last_start = *inbuf;
      75  	  result = DL_CALL_FCT (fct,
      76  				(cd->__steps, cd->__data, inbuf, inbufend,
      77  				 NULL, irreversible, 0, 0));
      78  	}
      79        while (result == __GCONV_EMPTY_INPUT && last_start != *inbuf
      80  	     && *inbuf + cd->__steps->__min_needed_from <= inbufend);
      81      }
      82  
      83    if (outbuf != NULL && *outbuf != NULL)
      84      *outbuf = cd->__data[last_step].__outbuf;
      85  
      86    return result;
      87  }