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