X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bbb0ff36dbb57461c3086c6e729aa3acf7a559ec..ccc3a25d878ae0797c2f689f5ef6a8b727786f83:/src/common/strconv.cpp diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 7ad34c9ccf..599048e9e2 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -323,16 +323,22 @@ wxMBConv::FromWChar(char *dst, size_t dstLen, const size_t lenNul = GetMBNulLen(); for ( const wchar_t * const srcEnd = src + srcLen; src < srcEnd; - src += wxWcslen(src) + 1 /* skip L'\0' too */ ) + src++ /* skip L'\0' too */ ) { // try to convert the current chunk size_t lenChunk = WC2MB(NULL, src, 0); - if ( lenChunk == wxCONV_FAILED ) return wxCONV_FAILED; dstWritten += lenChunk; - if ( src + lenChunk < srcEnd || isNulTerminated ) + + const wchar_t * const + chunkEnd = isNulTerminated ? srcEnd - 1 : src + wxWcslen(src); + + // our return value accounts for the trailing NUL(s), unlike that of + // WC2MB(), however don't do it for the last NUL we artificially added + // ourselves above + if ( chunkEnd < srcEnd ) dstWritten += lenNul; if ( dst ) @@ -340,13 +346,42 @@ wxMBConv::FromWChar(char *dst, size_t dstLen, if ( dstWritten > dstLen ) return wxCONV_FAILED; - if ( WC2MB(dst, src, lenChunk + lenNul) == wxCONV_FAILED ) + // if we know that there is enough space in the destination buffer + // (because we accounted for lenNul in dstWritten above), we can + // convert directly in place -- but otherwise we need another + // temporary buffer to ensure that we don't overwrite the output + wxCharBuffer dstBuf; + char *dstTmp; + if ( chunkEnd == srcEnd ) + { + dstBuf = wxCharBuffer(lenChunk + lenNul - 1); + dstTmp = dstBuf.data(); + } + else + { + dstTmp = dst; + } + + if ( WC2MB(dstTmp, src, lenChunk + lenNul) == wxCONV_FAILED ) return wxCONV_FAILED; + if ( dstTmp != dst ) + { + // copy everything up to but excluding the terminating NUL(s) + // into the real output buffer + memcpy(dst, dstTmp, lenChunk); + + // micro-optimization: if dstTmp != dst it means that chunkEnd + // == srcEnd and so we're done, no need to update anything below + break; + } + dst += lenChunk; - if ( src + lenChunk < srcEnd || isNulTerminated ) + if ( chunkEnd < srcEnd ) dst += lenNul; } + + src = chunkEnd; } return dstWritten; @@ -2144,9 +2179,9 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name) wxLogTrace(TRACE_STRCONV, wxT("Looking for wide char codeset:")); #if wxUSE_FONTMAP - const wxChar **names = wxFontMapperBase::GetAllEncodingNames(WC_ENC); + const wxChar *const *names = wxFontMapperBase::GetAllEncodingNames(WC_ENC); #else // !wxUSE_FONTMAP - static const wxChar *names_static[] = + static const wxChar *const names_static[] = { #if SIZEOF_WCHAR_T == 4 wxT("UCS-4"), @@ -2155,7 +2190,7 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name) #endif NULL }; - const wxChar **names = names_static; + const wxChar *const *names = names_static; #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP for ( ; *names && ms_wcCharsetName.empty(); ++names ) @@ -3068,7 +3103,7 @@ wxMBConv *wxCSConv::DoCreate() const delete conv; } - const wxChar** names = wxFontMapperBase::GetAllEncodingNames(encoding); + const wxChar* const* names = wxFontMapperBase::GetAllEncodingNames(encoding); // CS : in case this does not return valid names (eg for MacRoman) // encoding got a 'failure' entry in the cache all the same, // although it just has to be created using a different method, so