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