size_t wcsftime_l(wchar_t *wcs, size_t maxsize, const wchar_t *format, const struct tm *timeptr, locale_t loc) { char *dst, *dstp, *sformat; size_t n, sflen; int sverrno; sformat = dst = NULL; /* * Convert the supplied format string to a multibyte representation * for strftime(), which only handles single-byte characters. */ sflen = wcstombs_l(NULL, format, 0, loc); if (sflen == (size_t)-1) goto error; if ((sformat = malloc(sflen + 1)) == NULL) goto error; wcstombs_l(sformat, format, sflen + 1, loc); /* * Allocate memory for longest multibyte sequence that will fit * into the caller's buffer and call strftime() to fill it. * Then, copy and convert the result back into wide characters in * the caller's buffer. */ if (SIZE_T_MAX / MB_CUR_MAX_L(loc) <= maxsize) { /* maxsize is preposterously large - avoid int. overflow. */ errno = EINVAL; goto error; } dst = malloc(maxsize * MB_CUR_MAX_L(loc)); if (dst == NULL) goto error; if (strftime_l(dst, maxsize, sformat, timeptr, loc) == 0) goto error; dstp = dst; n = mbstowcs_l(wcs, dstp, maxsize, loc); if (n == (size_t)-2 || n == (size_t)-1) goto error; free(sformat); free(dst); return n; error: sverrno = errno; free(sformat); free(dst); errno = sverrno; return 0; }
/* * wchar2char --- convert wide characters to multibyte format * * This has the same API as the standard wcstombs_l() function; in particular, * tolen is the maximum number of bytes to store at *to, and *from must be * zero-terminated. The output will be zero-terminated iff there is room. */ size_t wchar2char(char *to, const wchar_t *from, size_t tolen, pg_locale_t locale) { size_t result; if (tolen == 0) return 0; #ifdef WIN32 /* * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and * for some reason mbstowcs and wcstombs won't do this for us, so we use * MultiByteToWideChar(). */ if (GetDatabaseEncoding() == PG_UTF8) { result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen, NULL, NULL); /* A zero return is failure */ if (result <= 0) result = -1; else { Assert(result <= tolen); /* Microsoft counts the zero terminator in the result */ result--; } } else #endif /* WIN32 */ if (locale == (pg_locale_t) 0) { /* Use wcstombs directly for the default locale */ result = wcstombs(to, from, tolen); } else { #ifdef HAVE_LOCALE_T #ifdef HAVE_WCSTOMBS_L /* Use wcstombs_l for nondefault locales */ result = wcstombs_l(to, from, tolen, locale); #else /* !HAVE_WCSTOMBS_L */ /* We have to temporarily set the locale as current ... ugh */ locale_t save_locale = uselocale(locale); result = wcstombs(to, from, tolen); uselocale(save_locale); #endif /* HAVE_WCSTOMBS_L */ #else /* !HAVE_LOCALE_T */ /* Can't have locale != 0 without HAVE_LOCALE_T */ elog(ERROR, "wcstombs_l is not available"); result = 0; /* keep compiler quiet */ #endif /* HAVE_LOCALE_T */ } return result; }
int UTF8::FromUnicode(const wchar_t *wstr, int wlen, char *str, int *len) { #if defined(WIN32) || defined(_WINDOWS_) wlen = WideCharToMultiByte(CP_UTF8, 0, wstr, wlen, str, wlen * 4, NULL, NULL); #else if (!m_UTF8_locale) m_UTF8_locale = _create_locale(LC_ALL, "en_US.UTF-8"); wlen = wcstombs_l(str, wstr, wlen, m_UTF8_locale); #endif if (len != NULL) *len = wlen; return (errno = 0); }