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