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
23using BPrivate::Libroot::GetCurrentLocaleBackend;
24using BPrivate::Libroot::LocaleBackend;
25
26
27extern "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
81B_DEFINE_WEAK_ALIAS(__wcrtomb, wcrtomb);
82