1 /* Copyright (C) 2011-2022 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
c16rtomb(char * s,char16_t c16,mbstate_t * ps)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 }
67