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_MBSRTOWCS 15 #ifdef TRACE_MBSRTOWCS 16 # include <OS.h> 17 # define TRACE(x) debug_printf x 18 #else 19 # define TRACE(x) ; 20 #endif 21 22 23 using BPrivate::Libroot::GetCurrentLocaleBackend; 24 using BPrivate::Libroot::LocaleBackend; 25 26 27 extern "C" size_t 28 __mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len, 29 mbstate_t* ps) 30 { 31 LocaleBackend* backend = GetCurrentLocaleBackend(); 32 33 TRACE(("mbsnrtowcs(%p, %p, %lu, %lu) - lb:%p\n", dst, *src, nmc, len, 34 backend)); 35 36 if (ps == NULL) { 37 static mbstate_t internalMbState; 38 ps = &internalMbState; 39 } 40 41 if (backend == NULL) { 42 /* 43 * The POSIX locale is active. Since the POSIX locale only contains 44 * chars 0-127 and those ASCII chars are compatible with the UTF32 45 * values used in wint_t, we can just copy the bytes. 46 */ 47 size_t count = 0; 48 const char* srcEnd = *src + nmc; 49 if (dst == NULL) { 50 // only count number of required wide characters 51 const char* mbSrc = *src; 52 for (; mbSrc < srcEnd; ++mbSrc, ++count) { 53 if (*mbSrc < 0) { 54 // char is non-ASCII 55 __set_errno(EILSEQ); 56 count = (size_t)-1; 57 break; 58 } 59 if (*mbSrc == 0) { 60 memset(ps, 0, sizeof(mbstate_t)); 61 break; 62 } 63 } 64 } else { 65 // "convert" the characters 66 for (; *src < srcEnd && count < len; ++*src, ++count) { 67 if (**src < 0) { 68 // char is non-ASCII 69 __set_errno(EILSEQ); 70 count = (size_t)-1; 71 break; 72 } 73 *dst++ = (wchar_t)**src; 74 if (**src == 0) { 75 memset(ps, 0, sizeof(mbstate_t)); 76 *src = NULL; 77 break; 78 } 79 } 80 } 81 82 TRACE(("mbsnrtowcs returns %lx and src %p\n", count, *src)); 83 84 return count; 85 } 86 87 size_t result = 0; 88 status_t status = backend->MultibyteStringToWchar(dst, len, src, nmc, 89 ps, result); 90 91 if (status == B_BAD_DATA) { 92 TRACE(("mbsnrtowc(): setting errno to EILSEQ\n")); 93 __set_errno(EILSEQ); 94 result = (size_t)-1; 95 } else if (status != B_OK) { 96 TRACE(("mbsnrtowc(): setting errno to EINVAL (status: %lx)\n", status)); 97 __set_errno(EINVAL); 98 result = (size_t)-1; 99 } 100 101 TRACE(("mbsnrtowcs returns %lx and src %p\n", result, *src)); 102 103 return result; 104 } 105 106 107 B_DEFINE_WEAK_ALIAS(__mbsnrtowcs, mbsnrtowcs); 108 109 110 extern "C" size_t 111 __mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps) 112 { 113 if (ps == NULL) { 114 static mbstate_t internalMbState; 115 ps = &internalMbState; 116 } 117 118 LocaleBackend* backend = GetCurrentLocaleBackend(); 119 size_t srcLen = backend == NULL ? strlen(*src) + 1 : (size_t)-1; 120 121 return __mbsnrtowcs(dst, src, srcLen, len, ps); 122 } 123 124 125 B_DEFINE_WEAK_ALIAS(__mbsrtowcs, mbsrtowcs); 126