From 265d5cce058d11f3297d73b733e578ac2ad0dbe2 Mon Sep 17 00:00:00 2001 From: Ryan Norton Date: Thu, 7 Oct 2004 22:28:57 +0000 Subject: [PATCH] 1.10.2 and less mbtowc and wctomb HAVE THE COOTIEScd .. (they are just stubs and return 0 - we need our own, even in ANSIcd ..!)\n2.Finalize the null character changes in wxString - change mb_str and wc_str to not stop at null characters\n3.Add unit tests for the above git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29717 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/string.h | 6 ++-- include/wx/wxchar.h | 24 ++++++++------- src/common/string.cpp | 61 +++++++++++++++++++++++++++++++++++++++ src/common/wxchar.cpp | 2 +- tests/strings/strings.cpp | 27 +++++++++++++++++ 5 files changed, 104 insertions(+), 16 deletions(-) diff --git a/include/wx/string.h b/include/wx/string.h index f2ba5dfa68..30b903e322 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -819,8 +819,7 @@ public: // type differs because a function may either return pointer to the buffer // directly or have to use intermediate buffer for translation. #if wxUSE_UNICODE - const wxCharBuffer mb_str(wxMBConv& conv = wxConvLibc) const - { return conv.cWC2MB(c_str()); } + const wxCharBuffer mb_str(wxMBConv& conv = wxConvLibc) const; const wxWX2MBbuf mbc_str() const { return mb_str(*wxConvCurrent); } @@ -843,8 +842,7 @@ public: const wxWX2MBbuf mbc_str() const { return mb_str(); } #if wxUSE_WCHAR_T - const wxWCharBuffer wc_str(wxMBConv& conv) const - { return conv.cMB2WC(c_str()); } + const wxWCharBuffer wc_str(wxMBConv& conv) const; #endif // wxUSE_WCHAR_T const wxChar* fn_str() const { return c_str(); } diff --git a/include/wx/wxchar.h b/include/wx/wxchar.h index 515d80ddfe..e6f54b771e 100644 --- a/include/wx/wxchar.h +++ b/include/wx/wxchar.h @@ -362,13 +362,23 @@ #define wxCtime _tctime #else /* !TCHAR-aware compilers */ + #if __DARWIN__ && ( MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_2 ) && !defined(__MWERKS__) + /* even though they are defined and "implemented", they are bad and just + stubs so we need our own - we need these even in ANSI builds!! */ + #define mbstowcs wxInternalMbstowcs + #define wcstombs wxInternalWcstombs + + WXDLLIMPEXP_BASE size_t wxInternalMbstowcs (wchar_t *, const char *, size_t); + WXDLLIMPEXP_BASE size_t wxInternalWcstombs (char *, const wchar_t *, size_t); + #endif + /* No UNICODE in the c library except wchar_t typedef on mac OSX 10.2 and less - roll our own */ #if wxUSE_UNICODE && __DARWIN__ && ( MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_2 ) && !defined(__MWERKS__) - + /* we need everything! */ #define wxNEED_WX_STRING_H #define wxNEED_WX_CTYPE_H - + #define wxFgetchar(c) wxFgetc(c, stdin) #define wxFputc wxPutc #define wxFputchar(c) wxPutc(c, stdout) @@ -397,15 +407,7 @@ #define wxNEED_WX_STDIO_H #define wxNEED_WX_STDLIB_H #define wxNEED_WX_TIME_H - - /* even though they are defined and "implemented", they are bad and just - stubs so we need our own */ - #define mbstowcs wxInternalMbstowcs - #define wcstombs wxInternalWcstombs - - WXDLLIMPEXP_BASE size_t wxInternalMbstowcs (wchar_t *, const char *, size_t); - WXDLLIMPEXP_BASE size_t wxInternalWcstombs (char *, const wchar_t *, size_t); - + #elif wxUSE_UNICODE #include diff --git a/src/common/string.cpp b/src/common/string.cpp index 7532732646..f27e32da9b 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -1043,6 +1043,36 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) //else: the conversion failed -- leave the string empty (what else?) } } +} + +const wxCharBuffer wxString::mb_str(wxMBConv& conv) const +{ + const wxChar* szEnd = (*this).c_str() + length() + 1; + const wxChar* szPos = (*this).c_str(); + const wxChar* szStart = szPos; + + wxCharBuffer buffer(length() + 1); + + //Convert the string until the length() is reached, continuing the + //loop every time a null character is reached + while(szPos != szEnd) + { + size_t nLen = conv.WC2MB(NULL, szPos, 0); + + wxASSERT(nLen != (size_t)-1); //should not be true! If it is system wctomb could be bad + + if ( conv.WC2MB(&buffer.data()[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")); + buffer.data()[0] = '\0'; + return buffer; + } + + szPos += nLen + 1; + } + + return buffer; } #else // ANSI @@ -1101,6 +1131,37 @@ wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength) // leave empty } + +const wxWCharBuffer wxString::wc_str(wxMBConv& conv) const +{ + const wxChar* szEnd = (*this).c_str() + length() + 1; + const wxChar* szPos = (*this).c_str(); + const wxChar* szStart = szPos; + + wxWCharBuffer buffer(length() + 1); + + //Convert the string until the length() is reached, continuing the + //loop every time a null character is reached + while(szPos != szEnd) + { + size_t nLen = conv.MB2WC(NULL, szPos, 0); + + wxASSERT(nLen != (size_t)-1); //should not be true! If it is system mbtowc could be bad + + if ( conv.MB2WC(&buffer.data()[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")); + buffer.data()[0] = '\0'; + return buffer; + } + + szPos += nLen + 1; + } + + return buffer; +} + #endif // wxUSE_WCHAR_T #endif // Unicode/ANSI diff --git a/src/common/wxchar.cpp b/src/common/wxchar.cpp index 42d9449b8b..1aa8374a8c 100644 --- a/src/common/wxchar.cpp +++ b/src/common/wxchar.cpp @@ -1043,7 +1043,7 @@ WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)CharLower((LPTSTR)(ch)); } WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); } #endif -#if wxUSE_UNICODE && __DARWIN__ && ( MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_2 ) +#if __DARWIN__ && ( MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_2 ) WXDLLEXPORT size_t wxInternalMbstowcs (wchar_t * out, const char * in, size_t outlen) { diff --git a/tests/strings/strings.cpp b/tests/strings/strings.cpp index 83c1cc24a6..b27fbc79f1 100644 --- a/tests/strings/strings.cpp +++ b/tests/strings/strings.cpp @@ -43,6 +43,7 @@ private: #if wxUSE_WCHAR_T CPPUNIT_TEST( ConstructorsWithConversion ); #endif + CPPUNIT_TEST( Conversion ); CPPUNIT_TEST( Extraction ); CPPUNIT_TEST( Find ); CPPUNIT_TEST( Tokenizer ); @@ -60,6 +61,7 @@ private: #if wxUSE_WCHAR_T void ConstructorsWithConversion(); #endif + void Conversion(); void Extraction(); void Find(); void SingleTokenizerTest( wxChar *str, wxChar *delims, size_t count , wxStringTokenizerMode mode ); @@ -176,6 +178,31 @@ void StringTestCase::ConstructorsWithConversion() } #endif +void StringTestCase::Conversion() +{ +#if wxUSE_UNICODE + wxString szTheString(wxT("TheString")); + szTheString.insert(3, 1, '\0'); + wxCharBuffer theBuffer = szTheString.mb_str(); + + CPPUNIT_ASSERT( memcmp(theBuffer.data(), "The\0String", 11) == 0 ); +#else +# if wxUSE_WCHAR_T + wxString szTheString(wxT("TheString")); + szTheString.insert(3, 1, '\0'); + wxWCharBuffer theBuffer = szTheString.wc_str(wxConvLibc); + + CPPUNIT_ASSERT( memcmp(theBuffer.data(), L"The\0String", 11 * sizeof(wchar_t)) == 0 ); + + wxString szLocalTheString(wxT("TheString")); + szLocalTheString.insert(3, 1, '\0'); + wxWCharBuffer theLocalBuffer = szLocalTheString.wc_str(wxConvLocal); + + CPPUNIT_ASSERT( memcmp(theLocalBuffer.data(), L"The\0String", 11 * sizeof(wchar_t)) == 0 ); +# endif +#endif +} + void StringTestCase::Extraction() { wxString s(_T("Hello, world!")); -- 2.45.2