xref: /third_party/musl/src/stdio/fgetwc.c (revision 570af302)
1#include "stdio_impl.h"
2#include "locale_impl.h"
3#include <wchar.h>
4#include <errno.h>
5
6static wint_t __fgetwc_unlocked_internal(FILE *f)
7{
8	wchar_t wc;
9	int c;
10	size_t l;
11
12	/* Convert character from buffer if possible */
13	if (f->rpos != f->rend) {
14		l = mbtowc(&wc, (void *)f->rpos, f->rend - f->rpos);
15		if (l+1 >= 1) {
16			f->rpos += l + !l; /* l==0 means 1 byte, null */
17			return wc;
18		}
19	}
20
21	/* Convert character byte-by-byte */
22	mbstate_t st = { 0 };
23	unsigned char b;
24	int first = 1;
25	do {
26		b = c = getc_unlocked(f);
27		if (c < 0) {
28			if (!first) {
29				f->flags |= F_ERR;
30				errno = EILSEQ;
31			}
32			return WEOF;
33		}
34		l = mbrtowc(&wc, (void *)&b, 1, &st);
35		if (l == -1) {
36			if (!first) {
37				f->flags |= F_ERR;
38				ungetc(b, f);
39			}
40			return WEOF;
41		}
42		first = 0;
43	} while (l == -2);
44
45	return wc;
46}
47
48wint_t __fgetwc_unlocked(FILE *f)
49{
50	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
51	if (f->mode <= 0) fwide(f, 1);
52	*ploc = f->locale;
53	wchar_t wc = __fgetwc_unlocked_internal(f);
54	*ploc = loc;
55	return wc;
56}
57
58wint_t fgetwc(FILE *f)
59{
60	wint_t c;
61	FLOCK(f);
62	c = __fgetwc_unlocked(f);
63	FUNLOCK(f);
64	return c;
65}
66
67weak_alias(__fgetwc_unlocked, fgetwc_unlocked);
68weak_alias(__fgetwc_unlocked, getwc_unlocked);
69