1 /* Convert multibyte character to 32-bit wide character.
2 Copyright (C) 2020 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program 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
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2020. */
29 # define FALLTHROUGH ((void) 0)
31 # define FALLTHROUGH __attribute__ ((__fallthrough__))
35 #if GNULIB_defined_mbstate_t /* AIX, IRIX */
36 /* Implement mbrtoc32() on top of mbtowc() for the non-UTF-8 locales
37 and directly for the UTF-8 locales. */
39 # if defined _WIN32 && !defined __CYGWIN__
41 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
44 # elif HAVE_PTHREAD_API
47 # if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
49 # pragma weak thrd_exit
50 # define c11_threads_in_use() (thrd_exit != NULL)
52 # define c11_threads_in_use() 0
62 # include "lc-charset-dispatch.h"
63 # include "mbtowc-lock.h"
65 verify (sizeof (mbstate_t) >= 4);
66 static char internal_state
[4];
69 mbrtoc32 (char32_t
*pwc
, const char *s
, size_t n
, mbstate_t *ps
)
71 # define FITS_IN_CHAR_TYPE(wc) 1
72 # include "mbrtowc-impl.h"
75 #else /* glibc, macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, MSVC, Minix, Android */
77 /* Implement mbrtoc32() based on the original mbrtoc32() or on mbrtowc(). */
81 # include "localcharset.h"
84 # if MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ
85 # include "hard-locale.h"
89 static mbstate_t internal_state
;
92 mbrtoc32 (char32_t
*pwc
, const char *s
, size_t n
, mbstate_t *ps
)
95 /* It's simpler to handle the case s == NULL upfront, than to worry about
96 this case later, before every test of pwc and n. */
104 # if MBRTOC32_EMPTY_INPUT_BUG || _GL_LARGE_CHAR32_T
110 ps
= &internal_state
;
112 # if HAVE_WORKING_MBRTOC32
113 /* mbrtoc32() may produce different values for wc than mbrtowc(). Therefore
116 # if defined _WIN32 && !defined __CYGWIN__
118 size_t ret
= mbrtoc32 (&wc
, s
, n
, ps
);
119 if (ret
< (size_t) -2 && pwc
!= NULL
)
122 size_t ret
= mbrtoc32 (pwc
, s
, n
, ps
);
125 # if MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ
126 if ((size_t) -2 <= ret
&& n
!= 0 && ! hard_locale (LC_CTYPE
))
129 *pwc
= (unsigned char) *s
;
136 # elif _GL_LARGE_CHAR32_T
138 /* Special-case all encodings that may produce wide character values
140 const char *encoding
= locale_charset ();
141 if (STREQ_OPT (encoding
, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
143 /* Special-case the UTF-8 encoding. Assume that the wide-character
144 encoding in a UTF-8 locale is UCS-2 or, equivalently, UTF-16. */
146 char *pstate
= (char *)ps
;
147 size_t nstate
= pstate
[0];
185 # define FITS_IN_CHAR_TYPE(wc) 1
186 # include "mbrtowc-impl-utf8.h"
190 if (nstate
>= (res
> 0 ? res
: 1))
193 /* Set *ps to the initial state. */
194 # if defined _WIN32 && !defined __CYGWIN__
195 /* Native Windows. */
196 /* MSVC defines 'mbstate_t' as an 8-byte struct; the first 4 bytes matter.
197 On mingw, 'mbstate_t' is sometimes defined as 'int', sometimes defined
198 as an 8-byte struct, of which the first 4 bytes matter. */
199 *(unsigned int *)pstate
= 0;
200 # elif defined __CYGWIN__
201 /* Cygwin defines 'mbstate_t' as an 8-byte struct; the first 4 bytes
212 /* Here 0 <= k < m < 4. */
228 /* The conversion state is undefined, says POSIX. */
234 size_t ret
= mbrtowc (&wc
, s
, n
, ps
);
235 if (ret
< (size_t) -2 && pwc
!= NULL
)
242 /* char32_t and wchar_t are equivalent. Use mbrtowc(). */
244 size_t ret
= mbrtowc (&wc
, s
, n
, ps
);
245 if (ret
< (size_t) -2 && pwc
!= NULL
)