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