xref: /aosp_15_r20/external/musl/src/multibyte/mbrtoc16.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #include <uchar.h>
2*c9945492SAndroid Build Coastguard Worker #include <wchar.h>
3*c9945492SAndroid Build Coastguard Worker 
mbrtoc16(char16_t * restrict pc16,const char * restrict s,size_t n,mbstate_t * restrict ps)4*c9945492SAndroid Build Coastguard Worker size_t mbrtoc16(char16_t *restrict pc16, const char *restrict s, size_t n, mbstate_t *restrict ps)
5*c9945492SAndroid Build Coastguard Worker {
6*c9945492SAndroid Build Coastguard Worker 	static unsigned internal_state;
7*c9945492SAndroid Build Coastguard Worker 	if (!ps) ps = (void *)&internal_state;
8*c9945492SAndroid Build Coastguard Worker 	unsigned *pending = (unsigned *)ps;
9*c9945492SAndroid Build Coastguard Worker 
10*c9945492SAndroid Build Coastguard Worker 	if (!s) return mbrtoc16(0, "", 1, ps);
11*c9945492SAndroid Build Coastguard Worker 
12*c9945492SAndroid Build Coastguard Worker 	/* mbrtowc states for partial UTF-8 characters have the high bit set;
13*c9945492SAndroid Build Coastguard Worker 	 * we use nonzero states without high bit for pending surrogates. */
14*c9945492SAndroid Build Coastguard Worker 	if ((int)*pending > 0) {
15*c9945492SAndroid Build Coastguard Worker  		if (pc16) *pc16 = *pending;
16*c9945492SAndroid Build Coastguard Worker 		*pending = 0;
17*c9945492SAndroid Build Coastguard Worker 		return -3;
18*c9945492SAndroid Build Coastguard Worker 	}
19*c9945492SAndroid Build Coastguard Worker 
20*c9945492SAndroid Build Coastguard Worker 	wchar_t wc;
21*c9945492SAndroid Build Coastguard Worker 	size_t ret = mbrtowc(&wc, s, n, ps);
22*c9945492SAndroid Build Coastguard Worker 	if (ret <= 4) {
23*c9945492SAndroid Build Coastguard Worker 		if (wc >= 0x10000) {
24*c9945492SAndroid Build Coastguard Worker 			*pending = (wc & 0x3ff) + 0xdc00;
25*c9945492SAndroid Build Coastguard Worker 			wc = 0xd7c0 + (wc >> 10);
26*c9945492SAndroid Build Coastguard Worker 		}
27*c9945492SAndroid Build Coastguard Worker 		if (pc16) *pc16 = wc;
28*c9945492SAndroid Build Coastguard Worker 	}
29*c9945492SAndroid Build Coastguard Worker 	return ret;
30*c9945492SAndroid Build Coastguard Worker }
31