1119998Sgad/* 2119998Sgad** Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved. 3119998Sgad** Distributed under the terms of the MIT License. 4119998Sgad*/ 5119998Sgad 6119998Sgad#include <errno.h> 7119998Sgad#include <string.h> 8119998Sgad#include <wchar.h> 9119998Sgad 10119998Sgad#include <errno_private.h> 11119998Sgad#include <LocaleBackend.h> 12119998Sgad 13119998Sgad 14119998Sgad//#define TRACE_MBRTOWC 15119998Sgad#ifdef TRACE_MBRTOWC 16119998Sgad# include <OS.h> 17119998Sgad# define TRACE(x) debug_printf x 18119998Sgad#else 19119998Sgad# define TRACE(x) ; 20119998Sgad#endif 21119998Sgad 22119998Sgad 23119998Sgadusing BPrivate::Libroot::GetCurrentLocaleBackend; 24119998Sgadusing BPrivate::Libroot::LocaleBackend; 25119998Sgad 26119998Sgad 27119998Sgadextern "C" size_t 28119998Sgad__mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps) 29119998Sgad{ 30119998Sgad if (ps == NULL) { 31119998Sgad static mbstate_t internalMbState; 32119998Sgad ps = &internalMbState; 33119998Sgad } 34119998Sgad 35119998Sgad if (s == NULL) 36119998Sgad return __mbrtowc(NULL, "", 1, ps); 37120361Sgad if (n == 0) 38120361Sgad return (size_t)-2; 39120361Sgad 40120361Sgad LocaleBackend* backend = GetCurrentLocaleBackend(); 41119998Sgad 42119998Sgad if (backend == NULL) { 43119998Sgad if (*s == '\0') { 44119998Sgad memset(ps, 0, sizeof(mbstate_t)); 45119998Sgad 46119998Sgad if (pwc != NULL) 47119998Sgad *pwc = 0; 48119998Sgad 49119998Sgad return 0; 50120361Sgad } 51119998Sgad 52119998Sgad /* 53119998Sgad * The POSIX locale is active. Since the POSIX locale only contains 54119998Sgad * chars 0-127 and those ASCII chars are compatible with the UTF32 55120361Sgad * values used in wint_t, we can just return the byte. 56120361Sgad */ 57120361Sgad 58120361Sgad if (*s < 0) { 59120361Sgad // char is non-ASCII 60120361Sgad __set_errno(EILSEQ); 61120361Sgad return (size_t)-1; 62120361Sgad } 63120361Sgad 64120361Sgad if (pwc != NULL) 65120361Sgad *pwc = *s; 66120361Sgad 67120361Sgad return 1; 68120361Sgad } 69120361Sgad 70120361Sgad size_t lengthUsed; 71120361Sgad status_t status = backend->MultibyteToWchar(pwc, s, n, ps, lengthUsed); 72120361Sgad 73120361Sgad if (status == B_BAD_INDEX) 74120361Sgad return (size_t)-2; 75120361Sgad 76120361Sgad if (status == B_BAD_DATA) { 77120361Sgad TRACE(("mbrtowc(): setting errno to EILSEQ\n")); 78120361Sgad __set_errno(EILSEQ); 79120361Sgad return (size_t)-1; 80120361Sgad } 81120361Sgad 82120046Sgad if (status != B_OK) { 83120361Sgad TRACE(("mbrtowc(): setting errno to EINVAL (status: %lx)\n", status)); 84120361Sgad __set_errno(EINVAL); 85120046Sgad return (size_t)-1; 86120046Sgad } 87120046Sgad 88120046Sgad return lengthUsed; 89120046Sgad} 90120046Sgad 91120046Sgad 92120046SgadB_DEFINE_WEAK_ALIAS(__mbrtowc, mbrtowc); 93120046Sgad