xref: /haiku/src/system/libroot/posix/wchar/mbrtowc.cpp (revision cc5eca75540f0750fbc325eab1f82c168564336b)
1*cc5eca75SOliver Tappe /*
2*cc5eca75SOliver Tappe ** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
3*cc5eca75SOliver Tappe ** Distributed under the terms of the Haiku License.
4*cc5eca75SOliver Tappe */
5*cc5eca75SOliver Tappe 
6*cc5eca75SOliver Tappe #include <errno.h>
7*cc5eca75SOliver Tappe #include <string.h>
8*cc5eca75SOliver Tappe #include <wchar.h>
9*cc5eca75SOliver Tappe 
10*cc5eca75SOliver Tappe #include "LocaleBackend.h"
11*cc5eca75SOliver Tappe 
12*cc5eca75SOliver Tappe 
13*cc5eca75SOliver Tappe using BPrivate::Libroot::gLocaleBackend;
14*cc5eca75SOliver Tappe 
15*cc5eca75SOliver Tappe 
16*cc5eca75SOliver Tappe extern "C" size_t
17*cc5eca75SOliver Tappe __mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps)
18*cc5eca75SOliver Tappe {
19*cc5eca75SOliver Tappe 	if (ps == NULL) {
20*cc5eca75SOliver Tappe 		static mbstate_t internalMbState;
21*cc5eca75SOliver Tappe 		ps = &internalMbState;
22*cc5eca75SOliver Tappe 	}
23*cc5eca75SOliver Tappe 
24*cc5eca75SOliver Tappe 	if (s == NULL)
25*cc5eca75SOliver Tappe 		return __mbrtowc(NULL, "", 1, ps);
26*cc5eca75SOliver Tappe 
27*cc5eca75SOliver Tappe 	if (gLocaleBackend == NULL) {
28*cc5eca75SOliver Tappe 		if (*s == '\0') {
29*cc5eca75SOliver Tappe 			memset(ps, 0, sizeof(mbstate_t));
30*cc5eca75SOliver Tappe 
31*cc5eca75SOliver Tappe 			if (pwc != NULL)
32*cc5eca75SOliver Tappe 				*pwc = 0;
33*cc5eca75SOliver Tappe 
34*cc5eca75SOliver Tappe 			return 0;
35*cc5eca75SOliver Tappe 		}
36*cc5eca75SOliver Tappe 
37*cc5eca75SOliver Tappe 		/*
38*cc5eca75SOliver Tappe 		 * The POSIX locale is active. Since the POSIX locale only contains
39*cc5eca75SOliver Tappe 		 * chars 0-127 and those ASCII chars are compatible with the UTF32
40*cc5eca75SOliver Tappe 		 * values used in wint_t, we can just return the byte.
41*cc5eca75SOliver Tappe 		 */
42*cc5eca75SOliver Tappe 
43*cc5eca75SOliver Tappe 		if (*s < 0) {
44*cc5eca75SOliver Tappe 			// char is non-ASCII
45*cc5eca75SOliver Tappe 			errno = EILSEQ;
46*cc5eca75SOliver Tappe 			return (size_t)-1;
47*cc5eca75SOliver Tappe 		}
48*cc5eca75SOliver Tappe 
49*cc5eca75SOliver Tappe 		if (pwc != NULL)
50*cc5eca75SOliver Tappe 			*pwc = *s;
51*cc5eca75SOliver Tappe 
52*cc5eca75SOliver Tappe 		return 1;
53*cc5eca75SOliver Tappe 	}
54*cc5eca75SOliver Tappe 
55*cc5eca75SOliver Tappe 	size_t lengthUsed;
56*cc5eca75SOliver Tappe 	status_t status
57*cc5eca75SOliver Tappe 		= gLocaleBackend->MultibyteToWchar(pwc, s, n, ps, lengthUsed);
58*cc5eca75SOliver Tappe 
59*cc5eca75SOliver Tappe 	if (status == B_BAD_INDEX)
60*cc5eca75SOliver Tappe 		return (size_t)-2;
61*cc5eca75SOliver Tappe 
62*cc5eca75SOliver Tappe 	if (status == B_BAD_DATA) {
63*cc5eca75SOliver Tappe 		errno = EILSEQ;
64*cc5eca75SOliver Tappe 		return (size_t)-1;
65*cc5eca75SOliver Tappe 	}
66*cc5eca75SOliver Tappe 
67*cc5eca75SOliver Tappe 	if (status != B_OK) {
68*cc5eca75SOliver Tappe 		errno = EINVAL;
69*cc5eca75SOliver Tappe 		return (size_t)-1;
70*cc5eca75SOliver Tappe 	}
71*cc5eca75SOliver Tappe 
72*cc5eca75SOliver Tappe 	return lengthUsed;
73*cc5eca75SOliver Tappe }
74*cc5eca75SOliver Tappe 
75*cc5eca75SOliver Tappe 
76*cc5eca75SOliver Tappe extern "C"
77*cc5eca75SOliver Tappe B_DEFINE_WEAK_ALIAS(__mbrtowc, mbrtowc);
78