(root)/
glibc-2.38/
wcsmbs/
c16rtomb.c
       1  /* Copyright (C) 2011-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <uchar.h>
      19  #include <wchar.h>
      20  
      21  
      22  /* This is the private state used if PS is NULL.  */
      23  static mbstate_t state;
      24  
      25  size_t
      26  c16rtomb (char *s, char16_t c16, mbstate_t *ps)
      27  {
      28    wchar_t wc = c16;
      29  
      30    if (ps == NULL)
      31      ps = &state;
      32  
      33    if (s == NULL)
      34      {
      35        /* Reset any state relating to surrogate pairs.  */
      36        ps->__count &= 0x7fffffff;
      37        ps->__value.__wch = 0;
      38        wc = 0;
      39      }
      40  
      41    if (ps->__count & 0x80000000)
      42      {
      43        /* The previous call passed in the first surrogate of a
      44  	 surrogate pair.  */
      45        ps->__count &= 0x7fffffff;
      46        if (wc >= 0xdc00 && wc < 0xe000)
      47  	wc = (0x10000
      48  	      + ((ps->__value.__wch & 0x3ff) << 10)
      49  	      + (wc & 0x3ff));
      50        else
      51  	/* This is not a low surrogate; ensure an EILSEQ error by
      52  	   trying to decode the high surrogate as a wide character on
      53  	   its own.  */
      54  	wc = ps->__value.__wch;
      55        ps->__value.__wch = 0;
      56      }
      57    else if (wc >= 0xd800 && wc < 0xdc00)
      58      {
      59        /* The high part of a surrogate pair.  */
      60        ps->__count |= 0x80000000;
      61        ps->__value.__wch = wc;
      62        return 0;
      63      }
      64  
      65    return wcrtomb (s, wc, ps);
      66  }