From: Ryan Norton Date: Sat, 30 Oct 2004 20:16:25 +0000 (+0000) Subject: solution to wxMBConv stuff - make a seperate XX2XX for strings of a specified length... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/e4e3bbb44783c651ac51665794a7ffcb8dff7eb6 solution to wxMBConv stuff - make a seperate XX2XX for strings of a specified length, use this in wxString instead of previous worst-case method git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30186 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/strconv.h b/include/wx/strconv.h index 59aefd6a5c..a28fe448eb 100644 --- a/include/wx/strconv.h +++ b/include/wx/strconv.h @@ -41,11 +41,18 @@ class WXDLLIMPEXP_BASE wxMBConv public: // the actual conversion takes place here // - // note that n is the size of the output buffer, not the length of input + // note that outputSize is the size of the output buffer, not the length of input // (the latter is always supposed to be NUL-terminated) virtual size_t MB2WC(wchar_t *outputBuf, const char *psz, size_t outputSize) const = 0; virtual size_t WC2MB(char *outputBuf, const wchar_t *psz, size_t outputSize) const = 0; + // actual conversion for strings with embedded null characters + // + // outputSize is the size of the output buffer + // pszLen is the length of the input string (including all but last null character) + size_t MB2WC(wchar_t *outputBuf, const char *psz, size_t outputSize, size_t pszLen) const; + size_t WC2MB(char *outputBuf, const wchar_t *psz, size_t outputSize, size_t pszLen) const; + // MB <-> WC const wxWCharBuffer cMB2WC(const char *psz) const; const wxCharBuffer cWC2MB(const wchar_t *psz) const; diff --git a/include/wx/string.h b/include/wx/string.h index 2bc8b54afd..309b27820a 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -1077,9 +1077,6 @@ public: // the same as above, but takes a va_list static wxString FormatV(const wxChar *pszFormat, va_list argptr); - // returns the highest possible memory allocation for encoding - static size_t WorstEncodingCase(size_t len, const wxMBConv& conv); - // raw access to string memory // ensure that string has space for at least nLen characters // only works if the data of this string is not shared diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 83c06de9c6..06ec99a71e 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -217,6 +217,94 @@ const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *pwz) const return buf; } +size_t wxMBConv::MB2WC(wchar_t* szBuffer, const char* szString, + size_t outsize, size_t nStringLen) const +{ + const char* szEnd = szString + nStringLen + 1; + const char* szPos = szString; + const char* szStart = szPos; + + size_t nActualLength = 0; + + //Convert the string until the length() is reached, continuing the + //loop every time a null character is reached + while(szPos != szEnd) + { + wxASSERT(szPos < szEnd); //something is _really_ screwed up if this rings true + + //Get the length of the current (sub)string + size_t nLen = MB2WC(NULL, szPos, 0); + + //Invalid conversion? + if( nLen == (size_t)-1 ) + return nLen; + + //Increase the actual length (+1 for current null character) + nActualLength += nLen + 1; + + //Only copy data in if buffer size is big enough + if (szBuffer != NULL && + nActualLength <= outsize) + { + //Convert the current (sub)string + if ( MB2WC(&szBuffer[szPos - szStart], szPos, nLen + 1) == (size_t)-1 ) + return (size_t)-1; + } + + //Increment to next (sub)string + //Note that we have to use strlen here instead of nLen + //here because XX2XX gives us the size of the output buffer, + //not neccessarly the length of the string + szPos += strlen(szPos) + 1; + } + + return nActualLength - 1; //success - return actual length +} + +size_t wxMBConv::WC2MB(char* szBuffer, const wchar_t* szString, + size_t outsize, size_t nStringLen) const +{ + const wchar_t* szEnd = szString + nStringLen + 1; + const wchar_t* szPos = szString; + const wchar_t* szStart = szPos; + + size_t nActualLength = 0; + + //Convert the string until the length() is reached, continuing the + //loop every time a null character is reached + while(szPos != szEnd) + { + wxASSERT(szPos < szEnd); //something is _really_ screwed up if this rings true + + //Get the length of the current (sub)string + size_t nLen = WC2MB(NULL, szPos, 0); + + //Invalid conversion? + if( nLen == (size_t)-1 ) + return nLen; + + //Increase the actual length (+1 for current null character) + nActualLength += nLen + 1; + + //Only copy data in if buffer size is big enough + if (szBuffer != NULL && + nActualLength <= outsize) + { + //Convert the current (sub)string + if(WC2MB(&szBuffer[szPos - szStart], szPos, nLen + 1) == (size_t)-1 ) + return (size_t)-1; + } + + //Increment to next (sub)string + //Note that we have to use wxWcslen here instead of nLen + //here because XX2XX gives us the size of the output buffer, + //not neccessarly the length of the string + szPos += wxWcslen(szPos) + 1; + } + + return nActualLength - 1; //success - return actual length +} + // ---------------------------------------------------------------------------- // wxMBConvLibc // ---------------------------------------------------------------------------- @@ -2080,7 +2168,7 @@ public: if (szOut == NULL) { // worst case - nRealOutSize = wxString::WorstEncodingCase(nBufSize - 1, *this)+1 ; + nRealOutSize = ((nBufSize - 1) * 8) +1 ; szBuffer = new char[ nRealOutSize ] ; } else @@ -2257,7 +2345,7 @@ public: if (buf == NULL) { // worst case - n = wxString::WorstEncodingCase(byteInLen / SIZEOF_WCHAR_T, *this) + SIZEOF_WCHAR_T; + n = ((byteInLen / SIZEOF_WCHAR_T) * 8) + SIZEOF_WCHAR_T; tbuf = (char*) malloc( n ) ; } diff --git a/src/common/string.cpp b/src/common/string.cpp index f6b388e45b..eb2d9d442d 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -984,126 +984,6 @@ int STRINGCLASS::compare(size_t nStart, size_t nLen, // wxString class core // =========================================================================== -// --------------------------------------------------------------------------- -// common conversion routines -// --------------------------------------------------------------------------- - -size_t wxString::WorstEncodingCase(size_t len, const wxMBConv& WXUNUSED(conv)) -{ - //Worst case for UTF7 - return len * 5; -} - -#if wxUSE_WCHAR_T - -//Convert a wide character string of a specified length -//to a multi-byte character string, ignoring intermittent null characters -//returns the actual length of the string -inline size_t wxMbstr(char* szBuffer, const wchar_t* szString, - size_t nStringLen, wxMBConv& conv) -{ - const wchar_t* szEnd = szString + nStringLen + 1; - const wchar_t* szPos = szString; - const wchar_t* szStart = szPos; - - size_t nActualLength = 0; - - //Convert the string until the length() is reached, continuing the - //loop every time a null character is reached - while(szPos != szEnd) - { - wxASSERT(szPos < szEnd); //something is _really_ screwed up if this rings true - - //Get the length of the current (sub)string - size_t nLen = conv.WC2MB(NULL, szPos, 0); - - //Invalid conversion? - if( nLen == (size_t)-1 ) - { - szBuffer[0] = '\0'; - return 0; - } - - //Increase the actual length (+1 for current null character) - nActualLength += nLen + 1; - - //If this is true it means buffer overflow - wxASSERT( nActualLength <= wxString::WorstEncodingCase(nStringLen, conv) + 1 ); - - //Convert the current (sub)string - if(conv.WC2MB(&szBuffer[szPos - szStart], szPos, nLen + 1) == (size_t)-1 ) - { - //error - return empty buffer - wxFAIL_MSG(wxT("Error converting wide-character string to a multi-byte string")); - szBuffer[0] = '\0'; - return 0; - } - - //Increment to next (sub)string - //Note that we have to use wxWcslen here instead of nLen - //here because XX2XX gives us the size of the output buffer, - //not neccessarly the length of the string - szPos += wxWcslen(szPos) + 1; - } - - return nActualLength - 1; //success - return actual length -} - -//Convert a multi-byte character string of a specified length -//to a wide character string, ignoring intermittent null characters -//returns the actual length -inline size_t wxWcstr( wchar_t* szBuffer, const char* szString, - size_t nStringLen, wxMBConv& conv) -{ - const char* szEnd = szString + nStringLen + 1; - const char* szPos = szString; - const char* szStart = szPos; - - size_t nActualLength = 0; - - //Convert the string until the length() is reached, continuing the - //loop every time a null character is reached - while(szPos != szEnd) - { - wxASSERT(szPos < szEnd); //something is _really_ screwed up if this rings true - - //Get the length of the current (sub)string - size_t nLen = conv.MB2WC(NULL, szPos, 0); - - //Invalid conversion? - if( nLen == (size_t)-1 ) - { - szBuffer[0] = '\0'; - return 0; - } - - //Increase the actual length (+1 for current null character) - nActualLength += nLen + 1; - - //If this is true it means buffer overflow - wxASSERT(nActualLength <= nStringLen + 1); - - //Convert the current (sub)string - if ( conv.MB2WC(&szBuffer[szPos - szStart], szPos, nLen + 1) == (size_t)-1 ) - { - //error - return empty buffer - wxFAIL_MSG(wxT("Error converting multi-byte string to a wide-character string")); - szBuffer[0] = '\0'; - return 0; - } - - //Increment to next (sub)string - //Note that we have to use strlen here instead of nLen - //here because XX2XX gives us the size of the output buffer, - //not neccessarly the length of the string - szPos += strlen(szPos) + 1; - } - - return nActualLength - 1; //success - return actual length -} - -#endif //wxUSE_WCHAR_T - // --------------------------------------------------------------------------- // construction and conversion // --------------------------------------------------------------------------- @@ -1143,28 +1023,48 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) nLen = 0; } + // anything to do? if ( (nLen != 0) && (nLen != (size_t)-1) ) { - //When converting mb->wc it never inflates to more characters than the length - wxStringBufferLength internalBuffer(*this, nLen + 1); + //Get length of converted string + size_t dwConvLen = conv.MB2WC(NULL, psz, 0, nLen); + + //if valid, do the conversion + if (dwConvLen != (size_t) -1) + { + //Get internal buffer + wxStringBufferLength internalBuffer(*this, dwConvLen + 1); - //Do the actual conversion & Set the length of the buffer - internalBuffer.SetLength( - wxWcstr(internalBuffer, psz, nLen, conv) - ); + //Do the actual conversion & Set the length of the buffer + internalBuffer.SetLength( + conv.MB2WC(internalBuffer, psz, dwConvLen + 1, nLen) + ); + } } } //Convert wxString in Unicode mode to a multi-byte string const wxCharBuffer wxString::mb_str(wxMBConv& conv) const { - //Create the buffer - wxCharBuffer buffer( wxString::WorstEncodingCase(length(), conv) + 1); + //Get length of converted string + size_t dwConvLen = conv.WC2MB(NULL, (*this).c_str(), 0, length()); + + //if valid, do the conversion + if (dwConvLen != (size_t) -1) + { + //Create good buffer + wxCharBuffer buffer(dwConvLen + 1); + + //Do the actual conversion + conv.WC2MB(buffer.data(), (*this).c_str(), dwConvLen + 1, length()); - //Do the actual conversion (will return a blank string on error) - wxMbstr(buffer.data(), (*this).c_str(), length(), conv); + return buffer; + } + //create bogus buffer + wxCharBuffer buffer(1); + buffer.data()[0u] = 0; return buffer; } @@ -1207,14 +1107,20 @@ wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength) // anything to do? if ( (nLen != 0) && (nLen != (size_t)-1) ) { - //Create a wxStringBufferLength which will access the internal - //C char pointer in non-stl mode - wxStringBufferLength internalBuffer(*this, wxString::WorstEncodingCase(nLen, conv) + 1); + //Get length of converted string + size_t dwConvLen = conv.WC2MB(NULL, pwz, 0, nLen); + + //if valid, do the conversion + if (dwConvLen != (size_t) -1) + { + //Get internal buffer + wxStringBufferLength internalBuffer(*this, dwConvLen + 1); - //Do the actual conversion & Set the length of the buffer - internalBuffer.SetLength( - wxMbstr(internalBuffer, pwz, nLen, conv) - ); + //Do the actual conversion & Set the length of the buffer + internalBuffer.SetLength( + conv.WC2MB(*this, pwz, dwConvLen + 1, nLen) + ); + } } } @@ -1222,12 +1128,24 @@ wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength) //mode is not enabled and wxUSE_WCHAR_T is enabled const wxWCharBuffer wxString::wc_str(wxMBConv& conv) const { - //mb->wc never inflates to more than the length - wxWCharBuffer buffer(length() + 1); + //Get length of converted string + size_t dwConvLen = conv.MB2WC(NULL, (*this).c_str(), 0, length()); - //Do the actual conversion (will return a blank string on error) - wxWcstr(buffer.data(), (*this).c_str(), length(), conv); + //if valid, do the conversion + if (dwConvLen != (size_t) -1) + { + //Create good buffer + wxWCharBuffer buffer(dwConvLen + 1); + + //Do the actual conversion + conv.MB2WC(buffer.data(), (*this).c_str(), dwConvLen + 1, length()); + + return buffer; + } + //create bogus buffer + wxWCharBuffer buffer(1); + buffer.data()[0u] = 0; return buffer; }