X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e3276230de335908f70232b2a5ede43665bd8d9d..62354609e69487e1066e1b1129c254c886cfa0fb:/src/common/strconv.cpp diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 31dc602f35..599048e9e2 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -57,7 +57,7 @@ #endif //def __DARWIN__ -#define TRACE_STRCONV _T("strconv") +#define TRACE_STRCONV wxT("strconv") // WC_UTF16 is defined only if sizeof(wchar_t) == 2, otherwise it's supposed to // be 4 bytes @@ -142,7 +142,7 @@ static wxUint32 wxDecodeSurrogate(const wxDecodeSurrogate_t **pSrc) { wxUint32 out; const size_t - n = decode_utf16(wx_reinterpret_cast(const wxUint16 *, *pSrc), out); + n = decode_utf16(reinterpret_cast(*pSrc), out); if ( n == wxCONV_FAILED ) *pSrc = NULL; else @@ -216,7 +216,7 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen, // all the complication come from the fact that this function, for // historical reasons, must behave in 2 subtly different ways when it's // called with a fixed number of characters and when it's called for the - // entire NUL-terminated string: in the former case (srcEnd == NULL) we + // entire NUL-terminated string: in the former case (srcEnd != NULL) we // must count all characters we convert, NUL or not; but in the latter we // do not count the trailing NUL -- but still count all the NULs inside the // string @@ -258,11 +258,13 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen, if ( !srcEnd ) { // we convert just one chunk in this case as this is the entire - // string anyhow + // string anyhow (and we don't count the trailing NUL in this case) break; } - // advance the input pointer past the end of this chunk + // advance the input pointer past the end of this chunk: notice that we + // will always stop before srcEnd because we know that the chunk is + // always properly NUL-terminated while ( NotAllNULs(src, nulLen) ) { // notice that we must skip over multiple bytes here as we suppose @@ -272,23 +274,20 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen, src += nulLen; } - src += nulLen; // skipping over its terminator as well + // if the buffer ends before this NUL, we shouldn't count it in our + // output so skip the code below + if ( src == srcEnd ) + break; + + // do count this terminator as it's inside the buffer we convert + dstWritten++; + if ( dst ) + dst++; + + src += nulLen; // skip the terminator itself - // note that ">=" (and not just "==") is needed here as the terminator - // we skipped just above could be inside or just after the buffer - // delimited by srcEnd if ( src >= srcEnd ) break; - - // if we got here then this wasn't the last chunk in this string and - // hence we must count an extra char for L'\0' even when converting a - // fixed number of characters - if ( srcEnd ) - { - dstWritten++; - if ( dst ) - dst++; - } } return dstWritten; @@ -324,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 ( 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 ) @@ -341,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 ( isNulTerminated ) + if ( chunkEnd < srcEnd ) dst += lenNul; } + + src = chunkEnd; } return dstWritten; @@ -490,6 +524,42 @@ wxMBConv::cWC2MB(const wchar_t *inBuff, size_t inLen, size_t *outLen) const return wxCharBuffer(); } +const wxWCharBuffer wxMBConv::cMB2WC(const wxScopedCharBuffer& buf) const +{ + const size_t srcLen = buf.length(); + if ( srcLen ) + { + const size_t dstLen = ToWChar(NULL, 0, buf, srcLen); + if ( dstLen != wxCONV_FAILED ) + { + wxWCharBuffer wbuf(dstLen); + wbuf.data()[dstLen] = L'\0'; + if ( ToWChar(wbuf.data(), dstLen, buf, srcLen) != wxCONV_FAILED ) + return wbuf; + } + } + + return wxWCharBuffer(); +} + +const wxCharBuffer wxMBConv::cWC2MB(const wxScopedWCharBuffer& wbuf) const +{ + const size_t srcLen = wbuf.length(); + if ( srcLen ) + { + const size_t dstLen = FromWChar(NULL, 0, wbuf, srcLen); + if ( dstLen != wxCONV_FAILED ) + { + wxCharBuffer buf(dstLen); + buf.data()[dstLen] = '\0'; + if ( FromWChar(buf.data(), dstLen, wbuf, srcLen) != wxCONV_FAILED ) + return buf; + } + } + + return wxCharBuffer(); +} + // ---------------------------------------------------------------------------- // wxMBConvLibc // ---------------------------------------------------------------------------- @@ -512,8 +582,8 @@ size_t wxMBConvLibc::WC2MB(char *buf, const wchar_t *psz, size_t n) const wxConvBrokenFileNames::wxConvBrokenFileNames(const wxString& charset) { - if ( wxStricmp(charset, _T("UTF-8")) == 0 || - wxStricmp(charset, _T("UTF8")) == 0 ) + if ( wxStricmp(charset, wxT("UTF-8")) == 0 || + wxStricmp(charset, wxT("UTF8")) == 0 ) m_conv = new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_PUA); else m_conv = new wxCSConv(charset); @@ -584,7 +654,7 @@ size_t wxMBConvUTF7::ToWChar(wchar_t *dst, size_t dstLen, } else // when working with partial strings we do use the shift state { - statePtr = wx_const_cast(DecoderState *, &m_stateDecoder); + statePtr = const_cast(&m_stateDecoder); // also save the old state to be able to rollback to it on error stateOrig = m_stateDecoder; @@ -771,7 +841,7 @@ size_t wxMBConvUTF7::FromWChar(char *dst, size_t dstLen, else // do use the mode we left the output in previously { stateOrig = m_stateEncoder; - statePtr = wx_const_cast(EncoderState *, &m_stateEncoder); + statePtr = const_cast(&m_stateEncoder); } EncoderState& state = *statePtr; @@ -1137,7 +1207,7 @@ wxMBConvStrictUTF8::FromWChar(char *dst, size_t dstLen, } else { - wxFAIL_MSG( _T("trying to encode undefined Unicode character") ); + wxFAIL_MSG( wxT("trying to encode undefined Unicode character") ); break; } @@ -1407,7 +1477,7 @@ size_t wxMBConvUTF16Base::GetLength(const char *src, size_t srcLen) if ( srcLen == wxNO_LEN ) { // count the number of bytes in input, including the trailing NULs - const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src); + const wxUint16 *inBuff = reinterpret_cast(src); for ( srcLen = 1; *inBuff++; srcLen++ ) ; @@ -1491,7 +1561,7 @@ wxMBConvUTF16swap::ToWChar(wchar_t *dst, size_t dstLen, if ( dstLen < srcLen ) return wxCONV_FAILED; - const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src); + const wxUint16 *inBuff = reinterpret_cast(src); for ( size_t n = 0; n < srcLen; n++, inBuff++ ) { *dst++ = wxUINT16_SWAP_ALWAYS(*inBuff); @@ -1515,7 +1585,7 @@ wxMBConvUTF16swap::FromWChar(char *dst, size_t dstLen, if ( dstLen < srcLen ) return wxCONV_FAILED; - wxUint16 *outBuff = wx_reinterpret_cast(wxUint16 *, dst); + wxUint16 *outBuff = reinterpret_cast(dst); for ( size_t n = 0; n < srcLen; n += BYTES_PER_CHAR, src++ ) { *outBuff++ = wxUINT16_SWAP_ALWAYS(*src); @@ -1549,7 +1619,7 @@ wxMBConvUTF16straight::ToWChar(wchar_t *dst, size_t dstLen, } size_t outLen = 0; - const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src); + const wxUint16 *inBuff = reinterpret_cast(src); for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; ) { const wxUint32 ch = wxDecodeSurrogate(&inBuff); @@ -1574,7 +1644,7 @@ wxMBConvUTF16straight::FromWChar(char *dst, size_t dstLen, srcLen = wxWcslen(src) + 1; size_t outLen = 0; - wxUint16 *outBuff = wx_reinterpret_cast(wxUint16 *, dst); + wxUint16 *outBuff = reinterpret_cast(dst); for ( size_t n = 0; n < srcLen; n++ ) { wxUint16 cc[2]; @@ -1622,7 +1692,7 @@ wxMBConvUTF16swap::ToWChar(wchar_t *dst, size_t dstLen, } size_t outLen = 0; - const wxUint16 *inBuff = wx_reinterpret_cast(const wxUint16 *, src); + const wxUint16 *inBuff = reinterpret_cast(src); for ( const wxUint16 * const inEnd = inBuff + inLen; inBuff < inEnd; ) { wxUint32 ch; @@ -1657,7 +1727,7 @@ wxMBConvUTF16swap::FromWChar(char *dst, size_t dstLen, srcLen = wxWcslen(src) + 1; size_t outLen = 0; - wxUint16 *outBuff = wx_reinterpret_cast(wxUint16 *, dst); + wxUint16 *outBuff = reinterpret_cast(dst); for ( const wchar_t *srcEnd = src + srcLen; src < srcEnd; src++ ) { wxUint16 cc[2]; @@ -1708,7 +1778,7 @@ size_t wxMBConvUTF32Base::GetLength(const char *src, size_t srcLen) if ( srcLen == wxNO_LEN ) { // count the number of bytes in input, including the trailing NULs - const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src); + const wxUint32 *inBuff = reinterpret_cast(src); for ( srcLen = 1; *inBuff++; srcLen++ ) ; @@ -1739,7 +1809,7 @@ wxMBConvUTF32straight::ToWChar(wchar_t *dst, size_t dstLen, if ( srcLen == wxNO_LEN ) return wxCONV_FAILED; - const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src); + const wxUint32 *inBuff = reinterpret_cast(src); const size_t inLen = srcLen / BYTES_PER_CHAR; size_t outLen = 0; for ( size_t n = 0; n < inLen; n++ ) @@ -1786,7 +1856,7 @@ wxMBConvUTF32straight::FromWChar(char *dst, size_t dstLen, return srcLen * BYTES_PER_CHAR; } - wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst); + wxUint32 *outBuff = reinterpret_cast(dst); size_t outLen = 0; for ( const wchar_t * const srcEnd = src + srcLen; src < srcEnd; ) { @@ -1817,7 +1887,7 @@ wxMBConvUTF32swap::ToWChar(wchar_t *dst, size_t dstLen, if ( srcLen == wxNO_LEN ) return wxCONV_FAILED; - const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src); + const wxUint32 *inBuff = reinterpret_cast(src); const size_t inLen = srcLen / BYTES_PER_CHAR; size_t outLen = 0; for ( size_t n = 0; n < inLen; n++, inBuff++ ) @@ -1864,7 +1934,7 @@ wxMBConvUTF32swap::FromWChar(char *dst, size_t dstLen, return srcLen*BYTES_PER_CHAR; } - wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst); + wxUint32 *outBuff = reinterpret_cast(dst); size_t outLen = 0; for ( const wchar_t * const srcEnd = src + srcLen; src < srcEnd; ) { @@ -1949,7 +2019,7 @@ wxMBConvUTF32swap::ToWChar(wchar_t *dst, size_t dstLen, if ( dstLen < srcLen ) return wxCONV_FAILED; - const wxUint32 *inBuff = wx_reinterpret_cast(const wxUint32 *, src); + const wxUint32 *inBuff = reinterpret_cast(src); for ( size_t n = 0; n < srcLen; n++, inBuff++ ) { *dst++ = wxUINT32_SWAP_ALWAYS(*inBuff); @@ -1973,7 +2043,7 @@ wxMBConvUTF32swap::FromWChar(char *dst, size_t dstLen, if ( dstLen < srcLen ) return wxCONV_FAILED; - wxUint32 *outBuff = wx_reinterpret_cast(wxUint32 *, dst); + wxUint32 *outBuff = reinterpret_cast(dst); for ( size_t n = 0; n < srcLen; n += BYTES_PER_CHAR, src++ ) { *outBuff++ = wxUINT32_SWAP_ALWAYS(*src); @@ -2106,21 +2176,21 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name) // check for charset that represents wchar_t: if ( ms_wcCharsetName.empty() ) { - wxLogTrace(TRACE_STRCONV, _T("Looking for wide char codeset:")); + 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 - _T("UCS-4"), + wxT("UCS-4"), #elif SIZEOF_WCHAR_T = 2 - _T("UCS-2"), + wxT("UCS-2"), #endif NULL }; - const wxChar **names = names_static; + const wxChar *const *names = names_static; #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP for ( ; *names && ms_wcCharsetName.empty(); ++names ) @@ -2131,19 +2201,19 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name) wxString nameXE(nameCS); #ifdef WORDS_BIGENDIAN - nameXE += _T("BE"); + nameXE += wxT("BE"); #else // little endian - nameXE += _T("LE"); + nameXE += wxT("LE"); #endif - wxLogTrace(TRACE_STRCONV, _T(" trying charset \"%s\""), + wxLogTrace(TRACE_STRCONV, wxT(" trying charset \"%s\""), nameXE.c_str()); m2w = iconv_open(nameXE.ToAscii(), name); if ( m2w == ICONV_T_INVALID ) { // try charset w/o bytesex info (e.g. "UCS4") - wxLogTrace(TRACE_STRCONV, _T(" trying charset \"%s\""), + wxLogTrace(TRACE_STRCONV, wxT(" trying charset \"%s\""), nameCS.c_str()); m2w = iconv_open(nameCS.ToAscii(), name); @@ -2190,8 +2260,8 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name) wxT("iconv wchar_t charset is \"%s\"%s"), ms_wcCharsetName.empty() ? wxString("") : ms_wcCharsetName, - ms_wcNeedsSwap ? _T(" (needs swap)") - : _T("")); + ms_wcNeedsSwap ? wxT(" (needs swap)") + : wxT("")); } else // we already have ms_wcCharsetName { @@ -2300,7 +2370,7 @@ wxMBConv_iconv::ToWChar(wchar_t *dst, size_t dstLen, else // no destination buffer { // convert using temp buffer to calculate the size of the buffer needed - wchar_t tbuf[8]; + wchar_t tbuf[256]; res = 0; do @@ -2347,13 +2417,12 @@ size_t wxMBConv_iconv::FromWChar(char *dst, size_t dstLen, if (ms_wcNeedsSwap) { // need to copy to temp buffer to switch endianness - // (doing WC_BSWAP twice on the original buffer won't help, as it + // (doing WC_BSWAP twice on the original buffer won't work, as it // could be in read-only memory, or be accessed in some other thread) - tmpbuf = (wchar_t *)malloc(inbuflen + SIZEOF_WCHAR_T); + tmpbuf = (wchar_t *)malloc(inbuflen); for ( size_t i = 0; i < srcLen; i++ ) tmpbuf[i] = WC_BSWAP(src[i]); - tmpbuf[srcLen] = L'\0'; src = tmpbuf; } @@ -2368,16 +2437,16 @@ size_t wxMBConv_iconv::FromWChar(char *dst, size_t dstLen, else // no destination buffer { // convert using temp buffer to calculate the size of the buffer needed - char tbuf[16]; + char tbuf[256]; res = 0; do { dst = tbuf; - outbuflen = 16; + outbuflen = WXSIZEOF(tbuf); cres = iconv(w2m, ICONV_CHAR_CAST(&inbuf), &inbuflen, &dst, &outbuflen); - res += 16 - outbuflen; + res += WXSIZEOF(tbuf) - outbuflen; } while ((cres == (size_t)-1) && (errno == E2BIG)); } @@ -2668,7 +2737,7 @@ public: switch ( len ) { default: - wxLogDebug(_T("Unexpected NUL length %d"), len); + wxLogDebug(wxT("Unexpected NUL length %d"), len); self->m_minMBCharWidth = (size_t)-1; break; @@ -2715,7 +2784,7 @@ private: break; } - wxASSERT_MSG( s_isWin98Or2k != -1, _T("should be set above") ); + wxASSERT_MSG( s_isWin98Or2k != -1, wxT("should be set above") ); } return s_isWin98Or2k == 1; @@ -2850,7 +2919,7 @@ private: // were we initialized successfully? bool m_ok; - DECLARE_NO_COPY_CLASS(wxMBConv_wxwin) + wxDECLARE_NO_COPY_CLASS(wxMBConv_wxwin); }; // make the constructors available for unit testing @@ -2909,7 +2978,7 @@ wxCSConv::wxCSConv(wxFontEncoding encoding) { if ( encoding == wxFONTENCODING_MAX || encoding == wxFONTENCODING_DEFAULT ) { - wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") ); + wxFAIL_MSG( wxT("invalid encoding value in wxCSConv ctor") ); encoding = wxFONTENCODING_SYSTEM; } @@ -3034,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 @@ -3057,7 +3126,7 @@ wxMBConv *wxCSConv::DoCreate() const delete conv; } - gs_nameCache[encoding] = _T(""); // cache the failure + gs_nameCache[encoding] = wxT(""); // cache the failure } } #endif // wxUSE_FONTMAP @@ -3147,31 +3216,12 @@ wxMBConv *wxCSConv::DoCreate() const delete conv; } -#endif // wxUSE_FONTMAP - // NB: This is a hack to prevent deadlock. What could otherwise happen - // in Unicode build: wxConvLocal creation ends up being here - // because of some failure and logs the error. But wxLog will try to - // attach a timestamp, for which it will need wxConvLocal (to convert - // time to char* and then wchar_t*), but that fails, tries to log the - // error, but wxLog has an (already locked) critical section that - // guards the static buffer. - static bool alreadyLoggingError = false; - if (!alreadyLoggingError) - { - alreadyLoggingError = true; - wxLogError(_("Cannot convert from the charset '%s'!"), - m_name ? m_name - : -#if wxUSE_FONTMAP - (const char*)wxFontMapperBase::GetEncodingDescription(m_encoding).ToAscii() -#else // !wxUSE_FONTMAP - (const char*)wxString::Format(_("encoding %i"), m_encoding).ToAscii() -#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP - ); - - alreadyLoggingError = false; - } + wxLogTrace(TRACE_STRCONV, + wxT("encoding \"%s\" is not supported by this system"), + (m_name ? wxString(m_name) + : wxFontMapperBase::GetEncodingName(m_encoding))); +#endif // wxUSE_FONTMAP return NULL; } @@ -3365,8 +3415,15 @@ wxCharBuffer wxSafeConvertWX2MB(const wchar_t *ws) #define WX_DEFINE_GLOBAL_CONV(klass, name, ctor_args) \ WX_DEFINE_GLOBAL_CONV2(klass, klass, name, ctor_args) +#ifdef __INTELC__ + // disable warning "variable 'xxx' was declared but never referenced" + #pragma warning(disable: 177) +#endif // Intel C++ + #ifdef __WINDOWS__ WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConv_win32, wxConvLibc, wxEMPTY_PARAMETER_VALUE); +#elif 0 // defined(__WXOSX__) + WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConv_cf, wxConvLibc, (wxFONTENCODING_UTF8)); #else WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConvLibc, wxConvLibc, wxEMPTY_PARAMETER_VALUE); #endif