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
23using BPrivate::Libroot::gLocaleBackend;
24
25
26extern "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
88extern "C"
89B_DEFINE_WEAK_ALIAS(__mbrtowc, mbrtowc);
90