#include <errno.h>
#include <string.h>
#include <wchar.h>
#include <errno_private.h>
#include <LocaleBackend.h>
#ifdef TRACE_MBSRTOWCS
# include <OS.h>
# define TRACE(x) debug_printf x
#else
# define TRACE(x) ;
#endif
using BPrivate::Libroot::GetCurrentLocaleBackend;
using BPrivate::Libroot::LocaleBackend;
extern "C" size_t
__mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len,
mbstate_t* ps)
{
LocaleBackend* backend = GetCurrentLocaleBackend();
TRACE(("mbsnrtowcs(%p, %p, %lu, %lu) - lb:%p\n", dst, *src, nmc, len,
backend));
if (ps == NULL) {
static mbstate_t internalMbState;
ps = &internalMbState;
}
if (backend == NULL) {
size_t count = 0;
const char* srcEnd = *src + nmc;
if (dst == NULL) {
const char* mbSrc = *src;
for (; mbSrc < srcEnd; ++mbSrc, ++count) {
if (*mbSrc < 0) {
__set_errno(EILSEQ);
count = (size_t)-1;
break;
}
if (*mbSrc == 0) {
memset(ps, 0, sizeof(mbstate_t));
break;
}
}
} else {
for (; *src < srcEnd && count < len; ++*src, ++count) {
if (**src < 0) {
__set_errno(EILSEQ);
count = (size_t)-1;
break;
}
*dst++ = (wchar_t)**src;
if (**src == 0) {
memset(ps, 0, sizeof(mbstate_t));
*src = NULL;
break;
}
}
}
TRACE(("mbsnrtowcs returns %lx and src %p\n", count, *src));
return count;
}
size_t result = 0;
status_t status = backend->MultibyteStringToWchar(dst, len, src, nmc,
ps, result);
if (status == B_BAD_DATA) {
TRACE(("mbsnrtowc(): setting errno to EILSEQ\n"));
__set_errno(EILSEQ);
result = (size_t)-1;
} else if (status != B_OK) {
TRACE(("mbsnrtowc(): setting errno to EINVAL (status: %lx)\n", status));
__set_errno(EINVAL);
result = (size_t)-1;
}
TRACE(("mbsnrtowcs returns %lx and src %p\n", result, *src));
return result;
}
B_DEFINE_WEAK_ALIAS(__mbsnrtowcs, mbsnrtowcs);
extern "C" size_t
__mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps)
{
if (ps == NULL) {
static mbstate_t internalMbState;
ps = &internalMbState;
}
LocaleBackend* backend = GetCurrentLocaleBackend();
size_t srcLen = backend == NULL ? strlen(*src) + 1 : (size_t)-1;
return __mbsnrtowcs(dst, src, srcLen, len, ps);
}
B_DEFINE_WEAK_ALIAS(__mbsrtowcs, mbsrtowcs);