From: Václav Slavík Date: Fri, 30 Mar 2007 20:09:02 +0000 (+0000) Subject: added char_str() and wchar_str() methods to wxString for obtaining char*/wchar_t... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/ef0f138756ebe8f7cd7f3212377bef9d65e8e920?ds=sidebyside added char_str() and wchar_str() methods to wxString for obtaining char*/wchar_t* pointers git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45175 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index dc0d82cff7..708b7023a5 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -30,6 +30,12 @@ Changes in behaviour which may result in compilation errors in vast majority of cases because of conversion operators, but it can break code that depends on the result being wxChar. +- The value returned by wxString::c_str() cannot be casted to non-const char* + or wchar_t* anymore. The solution is to use newly added wxString methods + char_str() (which returns a buffer convertible to char*) or wchar_str() + (which returns a buffer convertible to wchar_t*). These methods are + available in wxWidgets 2.8 series beginning with 2.8.4 as well. + - The value returned by wxString::operator[] or wxString::iterator cannot be used in switch statements anymore, because it's a class instance. Code like this won't compile: diff --git a/docs/latex/wx/wxstring.tex b/docs/latex/wx/wxstring.tex index 5384dd46b1..60bbd04123 100644 --- a/docs/latex/wx/wxstring.tex +++ b/docs/latex/wx/wxstring.tex @@ -573,10 +573,32 @@ Returns the empty string if {\it ch} is not found. Returns a pointer to the string data ({\tt const char*} in ANSI build, {\tt const wchar\_t*} in Unicode build). +Note that the returned value is not convertible to {\tt char*} or +{\tt wchar\_t*}, use \helpref{char\_str}{wxstringcharstr} or +\helpref{wchar\_string}{wxstringwcharstr} if you need to pass string value +to a function expecting non-const pointer. + +\wxheading{See also} + +\helpref{mb\_str}{wxstringmbstr}, \helpref{wc\_str}{wxstringwcstr}, +\helpref{fn\_str}{wxstringfnstr}, \helpref{char\_str}{wxstringcharstr}, +\helpref{wchar\_string}{wxstringwcharstr} + +\membersection{wxString::char\_str}\label{wxstringcharstr} + +\constfunc{wxWritableCharBuffer}{char\_str}{\void} + +Returns an object with string data that is implicitly convertible to +{\tt char*} pointer. Note that any change to the returned buffer is lost and so +this function is only usable for passing strings to legacy libraries that +don't have const-correct API. Use \helpref{wxStringBuffer}{wxstringbuffer} if +you want to modify the string. + \wxheading{See also} \helpref{mb\_str}{wxstringmbstr}, \helpref{wc\_str}{wxstringwcstr}, -\helpref{fn\_str}{wxstringfnstr} +\helpref{fn\_str}{wxstringfnstr}, \helpref{c\_str}{wxstringcstr}, +\helpref{wchar\_str}{wxstringwcharstr} \membersection{wxString::Clear}\label{wxstringclear} @@ -941,7 +963,7 @@ The macro wxWX2MBbuf is defined as the correct return type (without const). \helpref{wxMBConv}{wxmbconv}, \helpref{c\_str}{wxstringcstr}, \helpref{wc\_str}{wxstringwcstr}, -\helpref{fn\_str}{wxstringfnstr} +\helpref{fn\_str}{wxstringfnstr}, \helpref{char\_str}{wxstringcharstr} \membersection{wxString::Mid}\label{wxstringmid} @@ -1272,7 +1294,23 @@ The macro wxWX2WCbuf is defined as the correct return type (without const). \helpref{wxMBConv}{wxmbconv}, \helpref{c\_str}{wxstringcstr}, \helpref{mb\_str}{wxstringwcstr}, -\helpref{fn\_str}{wxstringfnstr} +\helpref{fn\_str}{wxstringfnstr}, \helpref{wchar\_str}{wxstringwcharstr} + +\membersection{wxString::wchar\_str}\label{wxstringwcharstr} + +\constfunc{wxWritableWCharBuffer}{wchar\_str}{\void} + +Returns an object with string data that is implicitly convertible to +{\tt char*} pointer. Note that any change to the returned buffer is lost and so +this function is only usable for passing strings to legacy libraries that +don't have const-correct API. Use \helpref{wxStringBuffer}{wxstringbuffer} if +you want to modify the string. + +\wxheading{See also} + +\helpref{mb\_str}{wxstringmbstr}, \helpref{wc\_str}{wxstringwcstr}, +\helpref{fn\_str}{wxstringfnstr}, \helpref{c\_str}{wxstringcstr}, +\helpref{char\_str}{wxstringcharstr} \membersection{wxString::operator!}\label{wxstringoperatornot} diff --git a/include/wx/buffer.h b/include/wx/buffer.h index c9232820fe..a0c2786ef4 100644 --- a/include/wx/buffer.h +++ b/include/wx/buffer.h @@ -146,6 +146,27 @@ public: }; #endif // wxUSE_WCHAR_T +// wxCharTypeBuffer implicitly convertible to T* +template +class wxWritableCharTypeBuffer : wxCharTypeBuffer +{ +public: + typedef typename wxCharTypeBuffer::CharType CharType; + + wxWritableCharTypeBuffer(const wxCharTypeBuffer& src) + : wxCharTypeBuffer(src) {} + // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to + // always return a buffer + wxWritableCharTypeBuffer(const CharType *str = NULL) + : wxCharTypeBuffer(str) {} + + operator CharType*() { return this->data(); } +}; + +typedef wxWritableCharTypeBuffer wxWritableCharBuffer; +typedef wxWritableCharTypeBuffer wxWritableWCharBuffer; + + #if wxUSE_UNICODE #define wxWxCharBuffer wxWCharBuffer diff --git a/include/wx/string.h b/include/wx/string.h index e0f58918e8..4ff1d97591 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -923,6 +923,12 @@ public: // wchar_t*, UTF-8-encoded char*, depending on the build): const_pointer wx_str() const { return m_impl.c_str(); } + // conversion to *non-const* multibyte or widestring buffer; modifying + // returned buffer won't affect the string, these methods are only useful + // for passing values to const-incorrect functions + wxWritableCharBuffer char_str() const { return mb_str(); } + wxWritableWCharBuffer wchar_str() const { return wc_str(); } + // conversion to/from plain (i.e. 7 bit) ASCII: this is useful for // converting numbers or strings which are certain not to contain special // chars (typically system functions, X atoms, environment variables etc.) @@ -972,7 +978,7 @@ public: const wxWX2MBbuf mbc_str() const { return mb_str(); } #if wxUSE_WCHAR_T - const wxWCharBuffer wc_str(const wxMBConv& conv) const; + const wxWCharBuffer wc_str(const wxMBConv& conv = wxConvLibc) const; #endif // wxUSE_WCHAR_T #ifdef __WXOSX__ const wxCharBuffer fn_str() const { return wxConvFile.cWC2WX( wc_str( wxConvLocal ) ); } diff --git a/tests/strings/strings.cpp b/tests/strings/strings.cpp index b486a32142..7198b0cb7c 100644 --- a/tests/strings/strings.cpp +++ b/tests/strings/strings.cpp @@ -53,7 +53,9 @@ private: #endif // wxLongLong_t CPPUNIT_TEST( ToDouble ); CPPUNIT_TEST( WriteBuf ); - CPPUNIT_TEST( CStrData ); + CPPUNIT_TEST( CStrDataTernaryOperator ); + CPPUNIT_TEST( CStrDataImplicitConversion ); + CPPUNIT_TEST( ExplicitConversion ); CPPUNIT_TEST_SUITE_END(); void String(); @@ -77,8 +79,10 @@ private: #endif // wxLongLong_t void ToDouble(); void WriteBuf(); - void CStrData(); - void DoCStrData(bool cond); + void CStrDataTernaryOperator(); + void DoCStrDataTernaryOperator(bool cond); + void CStrDataImplicitConversion(); + void ExplicitConversion(); DECLARE_NO_COPY_CLASS(StringTestCase) }; @@ -657,10 +661,10 @@ void StringTestCase::WriteBuf() -void StringTestCase::CStrData() +void StringTestCase::CStrDataTernaryOperator() { - DoCStrData(true); - DoCStrData(false); + DoCStrDataTernaryOperator(true); + DoCStrDataTernaryOperator(false); } template bool CheckStr(const wxString& expected, T s) @@ -668,7 +672,7 @@ template bool CheckStr(const wxString& expected, T s) return expected == wxString(s); } -void StringTestCase::DoCStrData(bool cond) +void StringTestCase::DoCStrDataTernaryOperator(bool cond) { // test compilation of wxCStrData when used with operator?: (the asserts // are not very important, we're testing if the code compiles at all): @@ -691,3 +695,40 @@ void StringTestCase::DoCStrData(bool cond) CPPUNIT_ASSERT( CheckStr(s, (cond ? "foo" : s.c_str())) ); #endif } + +bool CheckStrChar(const wxString& expected, char *s) + { return CheckStr(expected, s); } +bool CheckStrWChar(const wxString& expected, wchar_t *s) + { return CheckStr(expected, s); } +bool CheckStrConstChar(const wxString& expected, const char *s) + { return CheckStr(expected, s); } +bool CheckStrConstWChar(const wxString& expected, const wchar_t *s) + { return CheckStr(expected, s); } + +void StringTestCase::CStrDataImplicitConversion() +{ + wxString s("foo"); + + // FIXME-UTF8: when wxCStrData can handle both conversions, this should + // be changed to always test all versions, both MB and WC +#if wxUSE_UNICODE + CPPUNIT_ASSERT( CheckStrConstWChar(s, s.c_str()) ); + CPPUNIT_ASSERT( CheckStrConstWChar(s, s) ); +#else + CPPUNIT_ASSERT( CheckStrConstChar(s, s.c_str()) ); + CPPUNIT_ASSERT( CheckStrConstChar(s, s) ); +#endif +} + +void StringTestCase::ExplicitConversion() +{ + wxString s("foo"); + + CPPUNIT_ASSERT( CheckStr(s, s.mb_str()) ); + CPPUNIT_ASSERT( CheckStrConstChar(s, s.mb_str()) ); + CPPUNIT_ASSERT( CheckStrChar(s, s.char_str()) ); + + CPPUNIT_ASSERT( CheckStr(s, s.wc_str()) ); + CPPUNIT_ASSERT( CheckStrConstWChar(s, s.wc_str()) ); + CPPUNIT_ASSERT( CheckStrWChar(s, s.wchar_str()) ); +}