initialize wxStringBuffer with the original contents of wxString it was created from for better compatibility with the old, non-STL, build (this avoids problems such as ticket #4845); add wxString::tchar_buf() to help with the implementation
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@53995 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -65,6 +65,11 @@ class WXDLLIMPEXP_FWD_BASE wxString;
|
||||
#define WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER 1
|
||||
#endif
|
||||
|
||||
namespace wxPrivate
|
||||
{
|
||||
template <typename T> struct wxStringAsBufHelper;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// macros
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1211,6 +1216,30 @@ public:
|
||||
{ return mb_str(conv); }
|
||||
wxWritableWCharBuffer wchar_str() const { return wc_str(); }
|
||||
|
||||
// conversion to the buffer of the given type T (= char or wchar_t) and
|
||||
// also optionally return the buffer length
|
||||
//
|
||||
// this is mostly/only useful for the template functions
|
||||
//
|
||||
// FIXME-VC6: the second argument only exists for VC6 which doesn't support
|
||||
// explicit template function selection, do not use it unless
|
||||
// you must support VC6!
|
||||
template <typename T>
|
||||
wxCharTypeBuffer<T> tchar_str(size_t *len = NULL,
|
||||
T * WXUNUSED(dummy) = NULL) const
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
// we need a helper dispatcher depending on type
|
||||
return wxPrivate::wxStringAsBufHelper<T>::Get(*this, len);
|
||||
#else // ANSI
|
||||
// T can only be char in ANSI build
|
||||
if ( len )
|
||||
*len = length();
|
||||
|
||||
return wxCharTypeBuffer<T>::CreateNonOwned(wx_str());
|
||||
#endif // Unicode build kind
|
||||
}
|
||||
|
||||
// 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.)
|
||||
@@ -1259,6 +1288,10 @@ public:
|
||||
}
|
||||
const char* utf8_str() const { return wx_str(); }
|
||||
const char* ToUTF8() const { return wx_str(); }
|
||||
|
||||
// this function exists in UTF-8 build only and returns the length of the
|
||||
// internal UTF-8 representation
|
||||
size_t utf8_length() const { return m_impl.length(); }
|
||||
#elif wxUSE_UNICODE_WCHAR
|
||||
static wxString FromUTF8(const char *utf8)
|
||||
{ return wxString(utf8, wxMBConvUTF8()); }
|
||||
@@ -2715,6 +2748,67 @@ inline wxString operator+(wchar_t ch, const wxString& string)
|
||||
|
||||
#define wxGetEmptyString() wxString()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// helper functions which couldn't be defined inline
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace wxPrivate
|
||||
{
|
||||
|
||||
#if wxUSE_UNICODE_WCHAR
|
||||
|
||||
template <>
|
||||
struct wxStringAsBufHelper<char>
|
||||
{
|
||||
static wxCharBuffer Get(const wxString& s, size_t *len)
|
||||
{
|
||||
wxCharBuffer buf(s.mb_str());
|
||||
if ( len )
|
||||
*len = buf ? strlen(buf) : 0;
|
||||
return buf;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct wxStringAsBufHelper<wchar_t>
|
||||
{
|
||||
static wxWCharBuffer Get(const wxString& s, size_t *len)
|
||||
{
|
||||
if ( len )
|
||||
*len = s.length();
|
||||
return wxWCharBuffer::CreateNonOwned(s.wx_str());
|
||||
}
|
||||
};
|
||||
|
||||
#elif wxUSE_UNICODE_UTF8
|
||||
|
||||
template <>
|
||||
struct wxStringAsBufHelper<char>
|
||||
{
|
||||
static wxCharBuffer Get(const wxString& s, size_t *len)
|
||||
{
|
||||
if ( len )
|
||||
*len = s.utf8_length();
|
||||
return wxCharBuffer::CreateNonOwned(s.wx_str());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct wxStringAsBufHelper<wchar_t>
|
||||
{
|
||||
static wxWCharBuffer Get(const wxString& s, size_t *len)
|
||||
{
|
||||
wxWCharBuffer wbuf(s.wc_str());
|
||||
if ( len )
|
||||
*len = wxWcslen(wbuf);
|
||||
return wbuf;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // Unicode build kind
|
||||
|
||||
} // namespace wxPrivate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxStringBuffer: a tiny class allowing to get a writable pointer into string
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -2782,8 +2876,30 @@ public:
|
||||
|
||||
wxStringTypeBufferBase(wxString& str, size_t lenWanted = 1024)
|
||||
: m_str(str), m_buf(lenWanted)
|
||||
{ }
|
||||
{
|
||||
// for compatibility with old wxStringBuffer which provided direct
|
||||
// access to wxString internal buffer, initialize ourselves with the
|
||||
// string initial contents
|
||||
|
||||
// FIXME-VC6: remove the ugly (CharType *)NULL and use normal
|
||||
// tchar_str<CharType>
|
||||
size_t len;
|
||||
const wxCharTypeBuffer<CharType> buf(str.tchar_str(&len, (CharType *)NULL));
|
||||
if ( buf )
|
||||
{
|
||||
if ( len > lenWanted )
|
||||
{
|
||||
// in this case there is not enough space for terminating NUL,
|
||||
// ensure that we still put it there
|
||||
m_buf.data()[lenWanted] = 0;
|
||||
len = lenWanted - 1;
|
||||
}
|
||||
|
||||
wxTmemcpy(m_buf.data(), buf, len + 1);
|
||||
}
|
||||
//else: conversion failed, this can happen when trying to get Unicode
|
||||
// string contents into a char string
|
||||
}
|
||||
|
||||
operator CharType*() { return m_buf.data(); }
|
||||
|
||||
@@ -2794,20 +2910,23 @@ protected:
|
||||
|
||||
template<typename T>
|
||||
class WXDLLIMPEXP_BASE wxStringTypeBufferLengthBase
|
||||
: public wxStringTypeBufferBase<T>
|
||||
{
|
||||
public:
|
||||
typedef T CharType;
|
||||
|
||||
wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024)
|
||||
: m_str(str), m_buf(lenWanted), m_len(0), m_lenSet(false)
|
||||
: wxStringTypeBufferBase<T>(str, lenWanted),
|
||||
m_len(0),
|
||||
m_lenSet(false)
|
||||
{ }
|
||||
|
||||
operator CharType*() { return m_buf.data(); }
|
||||
~wxStringTypeBufferLengthBase()
|
||||
{
|
||||
wxASSERT_MSG( this->m_lenSet, "forgot to call SetLength()" );
|
||||
}
|
||||
|
||||
void SetLength(size_t length) { m_len = length; m_lenSet = true; }
|
||||
|
||||
protected:
|
||||
wxString& m_str;
|
||||
wxCharTypeBuffer<CharType> m_buf;
|
||||
size_t m_len;
|
||||
bool m_lenSet;
|
||||
};
|
||||
@@ -2817,7 +2936,9 @@ class wxStringTypeBuffer : public wxStringTypeBufferBase<T>
|
||||
{
|
||||
public:
|
||||
wxStringTypeBuffer(wxString& str, size_t lenWanted = 1024)
|
||||
: wxStringTypeBufferBase<T>(str, lenWanted) {}
|
||||
: wxStringTypeBufferBase<T>(str, lenWanted)
|
||||
{ }
|
||||
|
||||
~wxStringTypeBuffer()
|
||||
{
|
||||
this->m_str.assign(this->m_buf.data());
|
||||
@@ -2831,11 +2952,11 @@ class wxStringTypeBufferLength : public wxStringTypeBufferLengthBase<T>
|
||||
{
|
||||
public:
|
||||
wxStringTypeBufferLength(wxString& str, size_t lenWanted = 1024)
|
||||
: wxStringTypeBufferLengthBase<T>(str, lenWanted) {}
|
||||
: wxStringTypeBufferLengthBase<T>(str, lenWanted)
|
||||
{ }
|
||||
|
||||
~wxStringTypeBufferLength()
|
||||
{
|
||||
wxASSERT(this->m_lenSet);
|
||||
this->m_str.assign(this->m_buf.data(), this->m_len);
|
||||
}
|
||||
|
||||
@@ -2869,12 +2990,12 @@ public:
|
||||
|
||||
~wxStringInternalBufferLength()
|
||||
{
|
||||
wxASSERT(m_lenSet);
|
||||
m_str.m_impl.assign(m_buf.data(), m_len);
|
||||
}
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxStringInternalBufferLength)
|
||||
};
|
||||
|
||||
#endif // wxUSE_STL_BASED_WXSTRING
|
||||
|
||||
|
||||
|
@@ -1026,6 +1026,29 @@ public:
|
||||
*/
|
||||
wxWritableCharBuffer char_str(const wxMBConv& conv = wxConvLibc) const;
|
||||
|
||||
/**
|
||||
Returns buffer of the specified type containing the string data.
|
||||
|
||||
This method is only useful in template code, otherwise you should
|
||||
directly call mb_str() or wc_str() if you need to retrieve a narrow or
|
||||
wide string from this wxString. The template parameter @a t should be
|
||||
either @c char or @c wchar_t.
|
||||
|
||||
Notice that retrieving a char buffer in UTF-8 build will return the
|
||||
internal string representation in UTF-8 while in wchar_t build the char
|
||||
buffer will contain the conversion of the string to the encoding of the
|
||||
current locale (and so can fail).
|
||||
|
||||
@param len If non-@NULL, filled with the length of the returned buffer.
|
||||
@return
|
||||
buffer containing the string contents in the specified type,
|
||||
notice that it may be @NULL if the conversion failed (e.g. Unicode
|
||||
string couldn't be converted to the current encoding when @a T is
|
||||
@c char).
|
||||
*/
|
||||
template <typename T>
|
||||
wxCharTypeBuffer<T> tchar_str(size_t *len = NULL) const;
|
||||
|
||||
//@{
|
||||
/**
|
||||
Returns string representation suitable for passing to OS' functions
|
||||
|
@@ -53,7 +53,7 @@ private:
|
||||
CPPUNIT_TEST( ToULongLong );
|
||||
#endif // wxLongLong_t
|
||||
CPPUNIT_TEST( ToDouble );
|
||||
CPPUNIT_TEST( WriteBuf );
|
||||
CPPUNIT_TEST( StringBuf );
|
||||
CPPUNIT_TEST( UTF8Buf );
|
||||
CPPUNIT_TEST( CStrDataTernaryOperator );
|
||||
CPPUNIT_TEST( CStrDataOperators );
|
||||
@@ -82,7 +82,7 @@ private:
|
||||
void ToULongLong();
|
||||
#endif // wxLongLong_t
|
||||
void ToDouble();
|
||||
void WriteBuf();
|
||||
void StringBuf();
|
||||
void UTF8Buf();
|
||||
void CStrDataTernaryOperator();
|
||||
void DoCStrDataTernaryOperator(bool cond);
|
||||
@@ -661,31 +661,50 @@ void StringTestCase::ToDouble()
|
||||
}
|
||||
}
|
||||
|
||||
void StringTestCase::WriteBuf()
|
||||
void StringTestCase::StringBuf()
|
||||
{
|
||||
// check that buffer can be used to write into the string
|
||||
wxString s;
|
||||
wxStrcpy(wxStringBuffer(s, 10), _T("foo"));
|
||||
|
||||
CPPUNIT_ASSERT(s[0u] == _T('f') );
|
||||
WX_ASSERT_SIZET_EQUAL(3, s.length());
|
||||
CPPUNIT_ASSERT(_T('f') == s[0u]);
|
||||
CPPUNIT_ASSERT(_T('o') == s[1]);
|
||||
CPPUNIT_ASSERT(_T('o') == s[2]);
|
||||
WX_ASSERT_SIZET_EQUAL(3, s.length());
|
||||
|
||||
{
|
||||
// also check that the buffer initially contains the original string
|
||||
// contents
|
||||
wxStringBuffer buf(s, 10);
|
||||
CPPUNIT_ASSERT_EQUAL( _T('f'), buf[0] );
|
||||
CPPUNIT_ASSERT_EQUAL( _T('o'), buf[1] );
|
||||
CPPUNIT_ASSERT_EQUAL( _T('o'), buf[2] );
|
||||
CPPUNIT_ASSERT_EQUAL( _T('\0'), buf[3] );
|
||||
}
|
||||
|
||||
{
|
||||
wxStringBufferLength buf(s, 10);
|
||||
CPPUNIT_ASSERT_EQUAL( _T('f'), buf[0] );
|
||||
CPPUNIT_ASSERT_EQUAL( _T('o'), buf[1] );
|
||||
CPPUNIT_ASSERT_EQUAL( _T('o'), buf[2] );
|
||||
CPPUNIT_ASSERT_EQUAL( _T('\0'), buf[3] );
|
||||
|
||||
// and check that it can be used to write only the specified number of
|
||||
// characters to the string
|
||||
wxStrcpy(buf, _T("barrbaz"));
|
||||
buf.SetLength(4);
|
||||
}
|
||||
|
||||
WX_ASSERT_SIZET_EQUAL(4, s.length());
|
||||
CPPUNIT_ASSERT(_T('b') == s[0u]);
|
||||
CPPUNIT_ASSERT(_T('a') == s[1]);
|
||||
CPPUNIT_ASSERT(_T('r') == s[2]);
|
||||
CPPUNIT_ASSERT(_T('r') == s[3]);
|
||||
WX_ASSERT_SIZET_EQUAL(4, s.length());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( 0, wxStrcmp(_T("barr"), s) );
|
||||
// check that creating buffer of length smaller than string works, i.e. at
|
||||
// least doesn't crash (it would if we naively copied the entire original
|
||||
// string contents in the buffer)
|
||||
*wxStringBuffer(s, 1) = '!';
|
||||
}
|
||||
|
||||
void StringTestCase::UTF8Buf()
|
||||
|
Reference in New Issue
Block a user