xref: /haiku/src/system/libroot/posix/wchar/wcrtomb.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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_WCRTOMB
15 #ifdef TRACE_WCRTOMB
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 __wcrtomb(char* s, wchar_t wc, mbstate_t* ps)
29 {
30 	LocaleBackend* backend = GetCurrentLocaleBackend();
31 
32 	if (ps == NULL) {
33 		static mbstate_t internalMbState;
34 		ps = &internalMbState;
35 	}
36 
37 	if (s == NULL)
38 		wc = 0;
39 
40 	if (backend == NULL) {
41 		/*
42 		 * The POSIX locale is active. Since the POSIX locale only contains
43 		 * chars 0-127 and those ASCII chars are compatible with the UTF32
44 		 * values used in wint_t, we can just return the byte.
45 		 */
46 
47 		if (wc > 127) {
48 			// char is non-ASCII
49 			__set_errno(EILSEQ);
50 			return (size_t)-1;
51 		}
52 
53 		if (s != NULL)
54 			*s = char(wc);
55 
56 		return 1;
57 	}
58 
59 	size_t lengthUsed;
60 	status_t status = backend->WcharToMultibyte(s, wc, ps, lengthUsed);
61 
62 	if (status == B_BAD_INDEX)
63 		return (size_t)-2;
64 
65 	if (status == B_BAD_DATA) {
66 		TRACE(("mbrtowc(): setting errno to EILSEQ\n"));
67 		__set_errno(EILSEQ);
68 		return (size_t)-1;
69 	}
70 
71 	if (status != B_OK) {
72 		TRACE(("wcrtomb(): setting errno to EINVAL (status: %lx)\n", status));
73 		__set_errno(EINVAL);
74 		return (size_t)-1;
75 	}
76 
77 	return lengthUsed;
78 }
79 
80 
81 B_DEFINE_WEAK_ALIAS(__wcrtomb, wcrtomb);
82