X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/852dcba5286b2b423d7cb21799d11df7efcbd0e6..8f4745feeb2850f3bebb3af45407e164550d541a:/src/common/strconv.cpp?ds=inline diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 5d19539fc5..41ca712cdf 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -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 @@ -160,11 +160,15 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen, const char *src, size_t srcLen) const { // although new conversion classes are supposed to implement this function - // directly, the existins ones only implement the old MB2WC() and so, to + // directly, the existing ones only implement the old MB2WC() and so, to // avoid to have to rewrite all conversion classes at once, we provide a // default (but not efficient) implementation of this one in terms of the // old function by copying the input to ensure that it's NUL-terminated and // then using MB2WC() to convert it + // + // moreover, some conversion classes simply can't implement ToWChar() + // directly, the primary example is wxConvLibc: mbstowcs() only handles + // NUL-terminated strings // the number of chars [which would be] written to dst [if it were not NULL] size_t dstWritten = 0; @@ -205,6 +209,21 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen, srcEnd = NULL; } + // the idea of this code is straightforward: it converts a NUL-terminated + // chunk of the string during each iteration and updates the output buffer + // with the result + // + // 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 + // 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 + // + // so for the (simple) former case we just always count the trailing NUL, + // but for the latter we need to wait until we see if there is going to be + // another loop iteration and only count it then for ( ;; ) { // try to convert the current chunk @@ -257,9 +276,19 @@ wxMBConv::ToWChar(wchar_t *dst, size_t dstLen, // 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 inEnd + // 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; @@ -304,7 +333,7 @@ wxMBConv::FromWChar(char *dst, size_t dstLen, return wxCONV_FAILED; dstWritten += lenChunk; - if ( isNulTerminated ) + if ( src+lenChunk < srcEnd || isNulTerminated ) dstWritten += lenNul; if ( dst ) @@ -316,7 +345,7 @@ wxMBConv::FromWChar(char *dst, size_t dstLen, return wxCONV_FAILED; dst += lenChunk; - if ( isNulTerminated ) + if ( src+lenChunk < srcEnd || isNulTerminated ) dst += lenNul; } } @@ -536,7 +565,7 @@ static const unsigned char utf7unb64[] = 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; size_t wxMBConvUTF7::ToWChar(wchar_t *dst, size_t dstLen, @@ -555,7 +584,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; @@ -580,11 +609,19 @@ size_t wxMBConvUTF7::ToWChar(wchar_t *dst, size_t dstLen, const unsigned char dc = utf7unb64[cc]; if ( dc == 0xff ) { - // end of encoded part, check that nothing was left: the bit - // field cycles through 0,6,4,2 sequence so check that we're at - // the end of it - if ( state.bit != 2 ) + // end of encoded part, check that nothing was left: there can + // be up to 4 bits of 0 padding but nothing else (we also need + // to check isLSB as we count bits modulo 8 while a valid UTF-7 + // encoded sequence must contain an integral number of UTF-16 + // characters) + if ( state.isLSB || state.bit > 4 || + (state.accum & ((1 << state.bit) - 1)) ) + { + if ( !len ) + state = stateOrig; + return wxCONV_FAILED; + } state.ToDirect(); @@ -637,7 +674,15 @@ size_t wxMBConvUTF7::ToWChar(wchar_t *dst, size_t dstLen, len++; src++; } - else + else if ( utf7unb64[(unsigned)*src] == 0xff ) + { + // empty encoded chunks are not allowed + if ( !len ) + state = stateOrig; + + return wxCONV_FAILED; + } + else // base-64 encoded chunk follows { state.ToShifted(); } @@ -726,7 +771,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; @@ -1362,7 +1407,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++ ) ; @@ -1446,7 +1491,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); @@ -1470,7 +1515,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); @@ -1504,7 +1549,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); @@ -1529,7 +1574,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]; @@ -1577,7 +1622,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; @@ -1612,7 +1657,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]; @@ -1663,7 +1708,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++ ) ; @@ -1694,7 +1739,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++ ) @@ -1741,7 +1786,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; ) { @@ -1772,7 +1817,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++ ) @@ -1819,7 +1864,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; ) { @@ -1904,7 +1949,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); @@ -1928,7 +1973,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); @@ -2255,7 +2300,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 @@ -2302,13 +2347,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; } @@ -2323,16 +2367,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)); } @@ -2805,7 +2849,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 @@ -2845,6 +2889,16 @@ wxCSConv::wxCSConv(const wxString& charset) #if wxUSE_FONTMAP m_encoding = wxFontMapperBase::GetEncodingFromName(charset); + if ( m_encoding == wxFONTENCODING_MAX ) + { + // set to unknown/invalid value + m_encoding = wxFONTENCODING_SYSTEM; + } + else if ( m_encoding == wxFONTENCODING_DEFAULT ) + { + // wxFONTENCODING_DEFAULT is same as US-ASCII in this context + m_encoding = wxFONTENCODING_ISO8859_1; + } #else m_encoding = wxFONTENCODING_SYSTEM; #endif @@ -3092,31 +3146,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; } @@ -3310,8 +3345,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