xref: /haiku/src/system/libroot/posix/wchar/mbrtowc.cpp (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
1 /*
2 ** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
3 ** Distributed under the terms of the MIT 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::GetCurrentLocaleBackend;
24 using BPrivate::Libroot::LocaleBackend;
25 
26 
27 extern "C" size_t
28 __mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps)
29 {
30 	if (ps == NULL) {
31 		static mbstate_t internalMbState;
32 		ps = &internalMbState;
33 	}
34 
35 	if (s == NULL)
36 		return __mbrtowc(NULL, "", 1, ps);
37 	if (n == 0)
38 		return (size_t)-2;
39 
40 	LocaleBackend* backend = GetCurrentLocaleBackend();
41 
42 	if (backend == NULL) {
43 		if (*s == '\0') {
44 			memset(ps, 0, sizeof(mbstate_t));
45 
46 			if (pwc != NULL)
47 				*pwc = 0;
48 
49 			return 0;
50 		}
51 
52 		/*
53 		 * The POSIX locale is active. Since the POSIX locale only contains
54 		 * chars 0-127 and those ASCII chars are compatible with the UTF32
55 		 * values used in wint_t, we can just return the byte.
56 		 */
57 
58 		if (*s < 0) {
59 			// char is non-ASCII
60 			__set_errno(EILSEQ);
61 			return (size_t)-1;
62 		}
63 
64 		if (pwc != NULL)
65 			*pwc = *s;
66 
67 		return 1;
68 	}
69 
70 	size_t lengthUsed;
71 	status_t status = backend->MultibyteToWchar(pwc, s, n, ps, lengthUsed);
72 
73 	if (status == B_BAD_INDEX)
74 		return (size_t)-2;
75 
76 	if (status == B_BAD_DATA) {
77 		TRACE(("mbrtowc(): setting errno to EILSEQ\n"));
78 		__set_errno(EILSEQ);
79 		return (size_t)-1;
80 	}
81 
82 	if (status != B_OK) {
83 		TRACE(("mbrtowc(): setting errno to EINVAL (status: %lx)\n", status));
84 		__set_errno(EINVAL);
85 		return (size_t)-1;
86 	}
87 
88 	return lengthUsed;
89 }
90 
91 
92 B_DEFINE_WEAK_ALIAS(__mbrtowc, mbrtowc);
93