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