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
23using BPrivate::Libroot::GetCurrentLocaleBackend;
24using BPrivate::Libroot::LocaleBackend;
25
26
27extern "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
92B_DEFINE_WEAK_ALIAS(__mbrtowc, mbrtowc);
93