provide both const char* and const wchar_t* implicit conversion of wxCStrData regardless of the build type

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45262 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2007-04-05 21:28:14 +00:00
parent 633566f6ef
commit 11aac4baa6
15 changed files with 190 additions and 63 deletions

View File

@@ -126,9 +126,7 @@ public:
wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
#if !wxUSE_UNICODE
wxCharBuffer(const wxCStrData& cstr);
#endif
};
#if wxUSE_WCHAR_T
@@ -140,9 +138,7 @@ public:
wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
#if wxUSE_UNICODE
wxWCharBuffer(const wxCStrData& cstr);
#endif
};
#endif // wxUSE_WCHAR_T

View File

@@ -73,7 +73,7 @@ public:
// def ctor
wxFile() { m_fd = fd_invalid; m_error = false; }
// open specified file (may fail, use IsOpened())
wxFile(const wxChar *szFileName, OpenMode mode = read);
wxFile(const wxString& fileName, OpenMode mode = read);
// attach to (already opened) file
wxFile(int lfd) { m_fd = lfd; m_error = false; }

View File

@@ -87,13 +87,9 @@ public:
static int GetResolution();
WX_DEFINE_VARARG_FUNC_VOID(PsPrintf, DoPsPrintfFormat)
void PsPrint( const char* psdata );
void PsPrint( const wxString& psdata );
void PsPrint( int ch );
#if wxUSE_UNICODE
void PsPrint( const wxChar* psdata ) { PsPrint( wxConvUTF8.cWX2MB( psdata ) ); }
#endif
private:
void DoPsPrintfFormat(const wxChar *fmt, ... );

View File

@@ -269,6 +269,9 @@ public:
{ DoPut( value, lhash, object ); }
void Put(const wxChar *value, wxObject *object)
{ DoPut( value, MakeKey( value ), object ); }
// FIXME-UTF8: have only wxString forms here
void Put(const wxString& value, wxObject *object)
{ DoPut( value, MakeKey( value ), object ); }
void Put(long lhash, const wxChar *value, wxObject *object)
{ DoPut( value, lhash, object ); }
@@ -279,6 +282,9 @@ public:
{ return (wxObject*)DoGet( value, lhash ); }
wxObject *Get(const wxChar *value) const
{ return (wxObject*)DoGet( value, MakeKey( value ) ); }
// FIXME-UTF8: have only wxString forms here
wxObject *Get(const wxString& value) const
{ return (wxObject*)DoGet( value, MakeKey( value ) ); }
wxObject *Get(long lhash, const wxChar *value) const
{ return (wxObject*)DoGet( value, lhash ); }
@@ -289,6 +295,9 @@ public:
{ return (wxObject*)DoDelete( key, lhash ); }
wxObject *Delete(const wxChar *key)
{ return (wxObject*)DoDelete( key, MakeKey( key ) ); }
// FIXME-UTF8: have only wxString forms here
wxObject *Delete(const wxString& key)
{ return (wxObject*)DoDelete( key, MakeKey( key ) ); }
wxObject *Delete(long lhash, const wxChar *key)
{ return (wxObject*)DoDelete( key, lhash ); }

View File

@@ -184,21 +184,18 @@ public:
~wxCStrData();
// FIXME: we'll need convertors for both char* and wchar_t* and NONE
// for wxChar*, but that's after completing the transition to
// "smart" wxUniChar class. For now, just have conversion to
// char* in ANSI build and wchar_t in Unicode build.
#if wxUSE_UNICODE
const wchar_t* AsWChar() const;
operator const wchar_t*() const { return AsWChar(); }
#else
operator bool() const;
const char* AsChar() const;
const unsigned char* AsUnsignedChar() const
{ return (const unsigned char *) AsChar(); }
operator const void*() const { return AsChar(); }
operator const char*() const { return AsChar(); }
operator const unsigned char*() const { return AsUnsignedChar(); }
#endif
operator const void*() const { return AsChar(); }
wxString AsString() const;
@@ -448,6 +445,7 @@ private:
static void PosLenToImpl(size_t pos, size_t len,
size_t *implPos, size_t *implLen)
{ *implPos = pos; *implLen = len; }
static size_t LenToImpl(size_t len) { return len; }
static size_t PosFromImpl(size_t pos) { return pos; }
#else // wxUSE_UNICODE_UTF8
@@ -557,12 +555,14 @@ public:
// as we provide both ctors with this signature for both char and unsigned
// char string, we need to provide one for wxCStrData to resolve ambiguity
wxString(const wxCStrData& cstr, size_t nLength)
{ assign(cstr.AsString(), nLength); }
: m_impl(cstr.AsString().Mid(0, nLength).m_impl) {}
// and because wxString is convertible to wxCStrData and const wxChar *
// we also need to provide this one
wxString(const wxString& str, size_t nLength)
{ assign(str, nLength); }
: m_impl(str.Mid(0, nLength).m_impl) {}
~wxString();
public:
// standard types
@@ -910,7 +910,8 @@ public:
// implicit conversion to C string
operator wxCStrData() const { return c_str(); }
operator const wxChar*() const { return c_str(); }
operator const char*() const { return c_str(); }
operator const wchar_t*() const { return c_str(); }
// identical to c_str(), for MFC compatibility
const wxCStrData GetData() const { return c_str(); }
@@ -1171,16 +1172,29 @@ public:
{ return CmpNoCase(wxString(pwz)); }
// test for the string equality, either considering case or not
// (if compareWithCase then the case matters)
bool IsSameAs(const char *psz, bool compareWithCase = true) const
{ return (compareWithCase ? Cmp(psz) : CmpNoCase(psz)) == 0; }
bool IsSameAs(const wchar_t *pwz, bool compareWithCase = true) const
{ return (compareWithCase ? Cmp(pwz) : CmpNoCase(pwz)) == 0; }
bool IsSameAs(const wxString& str, bool compareWithCase = true) const
{ return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0; }
bool IsSameAs(const char *str, bool compareWithCase = true) const
{ return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0; }
bool IsSameAs(const wchar_t *str, bool compareWithCase = true) const
{ return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0; }
// comparison with a single character: returns true if equal
bool IsSameAs(wxUniChar c, bool compareWithCase = true) const
{
return (length() == 1) && (compareWithCase ? GetChar(0u) == c
: wxToupper(GetChar(0u)) == wxToupper(c));
}
// FIXME-UTF8: remove these overloads
bool IsSameAs(wxUniCharRef c, bool compareWithCase = true) const
{ return IsSameAs(wxUniChar(c), compareWithCase); }
bool IsSameAs(char c, bool compareWithCase = true) const
{ return IsSameAs(wxUniChar(c), compareWithCase); }
bool IsSameAs(unsigned char c, bool compareWithCase = true) const
{ return IsSameAs(wxUniChar(c), compareWithCase); }
bool IsSameAs(wchar_t c, bool compareWithCase = true) const
{ return IsSameAs(wxUniChar(c), compareWithCase); }
bool IsSameAs(int c, bool compareWithCase = true) const
{ return IsSameAs(wxUniChar(c), compareWithCase); }
// simple sub-string extraction
// return substring starting at nFirst of length nCount (or till the end
@@ -1449,6 +1463,11 @@ public:
// same as `this_string = str'
wxString& assign(const wxString& str)
{ m_impl = str.m_impl; return *this; }
wxString& assign(const wxString& str, size_t len)
{
m_impl.assign(str.m_impl, 0, str.LenToImpl(len));
return *this;
}
// same as ` = str[pos..pos + n]
wxString& assign(const wxString& str, size_t pos, size_t n)
{
@@ -1485,6 +1504,16 @@ public:
m_impl.assign(n, (wxStringCharType)ch);
return *this;
}
wxString& assign(size_t n, wxUniCharRef ch)
{ return assign(n, wxUniChar(ch)); }
wxString& assign(size_t n, char ch)
{ return assign(n, wxUniChar(ch)); }
wxString& assign(size_t n, unsigned char ch)
{ return assign(n, wxUniChar(ch)); }
wxString& assign(size_t n, wchar_t ch)
{ return assign(n, wxUniChar(ch)); }
// assign from first to last
wxString& assign(const_iterator first, const_iterator last)
{ m_impl.assign(first, last); return *this; }
@@ -1649,6 +1678,15 @@ public:
m_impl.replace(from, len, str.data, str.len);
return *this;
}
wxString& replace(size_t nStart, size_t nLen,
const wxString& s, size_t nCount)
{
size_t from, len;
PosLenToImpl(nStart, nLen, &from, &len);
m_impl.replace(from, len, s.m_impl.c_str(), s.LenToImpl(nCount));
return *this;
}
wxString& replace(iterator first, iterator last, const char* s)
{ m_impl.replace(first, last, ImplStr(s)); return *this; }
wxString& replace(iterator first, iterator last, const wchar_t* s)
@@ -2195,12 +2233,8 @@ wxDEFINE_ALL_COMPARISONS(const char *, const wxString&, wxCMP_CHAR_STRING)
#define wxCMP_CHAR_CSTRDATA(p, s, op) p op s.AsChar()
#define wxCMP_WCHAR_CSTRDATA(p, s, op) p op s.AsWChar()
// FIXME: these ifdefs must be removed when wxCStrData has both conversions
#if wxUSE_UNICODE
wxDEFINE_ALL_COMPARISONS(const wchar_t *, const wxCStrData&, wxCMP_WCHAR_CSTRDATA)
#else
wxDEFINE_ALL_COMPARISONS(const char *, const wxCStrData&, wxCMP_CHAR_CSTRDATA)
#endif
wxDEFINE_ALL_COMPARISONS(const wchar_t *, const wxCStrData&, wxCMP_WCHAR_CSTRDATA)
wxDEFINE_ALL_COMPARISONS(const char *, const wxCStrData&, wxCMP_CHAR_CSTRDATA)
#undef wxCMP_CHAR_CSTRDATA
#undef wxCMP_WCHAR_CSTRDATA
@@ -2237,15 +2271,26 @@ inline wxCStrData::~wxCStrData()
delete m_str;
}
#if wxUSE_UNICODE
inline const wchar_t* wxCStrData::AsWChar() const
#else
inline const char* wxCStrData::AsChar() const
#endif
inline wxCStrData::operator bool() const
{
return !m_str->empty();
};
// simple cases for AsChar() and AsWChar(), the complicated ones are
// in string.cpp
#if wxUSE_UNICODE_WCHAR
inline const wchar_t* wxCStrData::AsWChar() const
{
// FIXME-UTF8: incorrect position, incorrect charset
return m_str->wx_str() + m_offset;
}
#endif // wxUSE_UNICODE_WCHAR
#if !wxUSE_UNICODE
inline const char* wxCStrData::AsChar() const
{
return m_str->wx_str() + m_offset;
}
#endif // !wxUSE_UNICODE
inline wxString wxCStrData::AsString() const
{
@@ -2272,10 +2317,15 @@ inline wxUniChar wxCStrData::operator[](size_t n) const
// implementation of wx[W]CharBuffer inline methods using wxCStrData
// ----------------------------------------------------------------------------
// FIXME-UTF8: move this to buffer.h; provide versions for both variants
inline wxWxCharBuffer::wxWxCharBuffer(const wxCStrData& cstr)
: wxCharTypeBufferBase((const wxChar *)cstr)
// FIXME-UTF8: move this to buffer.h
inline wxCharBuffer::wxCharBuffer(const wxCStrData& cstr)
: wxCharTypeBufferBase(cstr.AsChar())
{
}
#endif // _WX_WXSTRING_H__
inline wxWCharBuffer::wxWCharBuffer(const wxCStrData& cstr)
: wxCharTypeBufferBase(cstr.AsWChar())
{
}
#endif // _WX_WXSTRING_H_

View File

@@ -184,12 +184,12 @@ bool wxFile::Access(const wxChar *name, OpenMode mode)
// ----------------------------------------------------------------------------
// ctors
wxFile::wxFile(const wxChar *szFileName, OpenMode mode)
wxFile::wxFile(const wxString& fileName, OpenMode mode)
{
m_fd = fd_invalid;
m_error = false;
Open(szFileName, mode);
Open(fileName, mode);
}
// create the file, fail if it already exists and bOverwrite

View File

@@ -1534,7 +1534,8 @@ bool wxLocale::Init(const wxString& name,
// the argument to setlocale()
szLocale = shortName;
wxCHECK_MSG( szLocale, false, _T("no locale to set in wxLocale::Init()") );
wxCHECK_MSG( !szLocale.empty(), false,
_T("no locale to set in wxLocale::Init()") );
}
#ifdef __WXWINCE__

View File

@@ -45,6 +45,7 @@
#include <clib.h>
#endif
#include <wx/hashmap.h>
// string handling functions used by wxString:
#if wxUSE_UNICODE_UTF8
@@ -104,6 +105,74 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxWCharBuffer& str)
#endif // wxUSE_STD_IOSTREAM
// ----------------------------------------------------------------------------
// wxCStrData converted strings caching
// ----------------------------------------------------------------------------
// For backward compatibility reasons, it must be possible to assign the value
// returned by wxString::c_str() to a char* or wchar_t* variable and work with
// it. Returning wxCharBuffer from (const char*)c_str() wouldn't do the trick,
// because the memory would be freed immediately, but it has to be valid as long
// as the string is not modified, so that code like this still works:
//
// const wxChar *s = str.c_str();
// while ( s ) { ... }
// FIXME-UTF8: not thread safe!
// FIXME-UTF8: we currently clear the cached conversion only when the string is
// destroyed, but we should do it when the string is modified, to
// keep memory usage down
// FIXME-UTF8: we do the conversion every time As[W]Char() is called, but if we
// invalidated the cache on every change, we could keep the previous
// conversion
// FIXME-UTF8: add tracing of usage of these two methods - new code is supposed
// to use mb_str() or wc_str() instead of (const [w]char*)c_str()
template<typename T>
static inline void DeleteStringFromConversionCache(T& hash, const wxString *s)
{
typename T::iterator i = hash.find(s);
if ( i != hash.end() )
{
free(i->second);
hash.erase(i);
}
}
#if wxUSE_UNICODE
WX_DECLARE_HASH_MAP(wxString*, char*, wxPointerHash, wxPointerEqual,
wxStringCharConversionCache);
static wxStringCharConversionCache gs_stringsCharCache;
const char* wxCStrData::AsChar() const
{
// remove previously cache value, if any (see FIXMEs above):
DeleteStringFromConversionCache(gs_stringsCharCache, m_str);
// convert the string and keep it:
const char *s = gs_stringsCharCache[m_str] = m_str->mb_str().release();
return s + m_offset;
}
#endif // wxUSE_UNICODE
#if !wxUSE_UNICODE_WCHAR
WX_DECLARE_HASH_MAP(wxString*, wchar_t*, wxPointerHash, wxPointerEqual,
wxStringWCharConversionCache);
static wxStringWCharConversionCache gs_stringsWCharCache;
const wchar_t* wxCStrData::AsWChar() const
{
// remove previously cache value, if any (see FIXMEs above):
DeleteStringFromConversionCache(gs_stringsWCharCache, m_str);
// convert the string and keep it:
const wchar_t *s = gs_stringsWCharCache[m_str] = m_str->wc_str().release();
return s + m_offset;
}
#endif // !wxUSE_UNICODE_WCHAR
// ===========================================================================
// wxString class core
// ===========================================================================
@@ -112,6 +181,17 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxWCharBuffer& str)
// construction and conversion
// ---------------------------------------------------------------------------
wxString::~wxString()
{
#if wxUSE_UNICODE
// FIXME-UTF8: do this only if locale is not UTF8 if wxUSE_UNICODE_UTF8
DeleteStringFromConversionCache(gs_stringsCharCache, this);
#endif
#if !wxUSE_UNICODE_WCHAR
DeleteStringFromConversionCache(gs_stringsWCharCache, this);
#endif
}
#if wxUSE_UNICODE
/* static */
wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
@@ -1510,4 +1590,3 @@ wxString wxString::Upper() const
// convert to lower case, return the copy of the string
wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }

View File

@@ -2206,11 +2206,13 @@ void wxPostScriptDC::DoPsPrintfFormat(const wxChar *fmt, ... )
va_list argptr;
va_start(argptr, fmt);
PsPrint( wxString::FormatV( fmt, argptr ).c_str() );
PsPrint( wxString::FormatV( fmt, argptr ) );
}
void wxPostScriptDC::PsPrint( const char* psdata )
void wxPostScriptDC::PsPrint( const wxString& str )
{
wxWX2MBbuf psdata(str.mb_str(wxConvUTF8));
wxPostScriptPrintNativeData *data =
(wxPostScriptPrintNativeData *) m_printData.GetNativeData();

View File

@@ -705,9 +705,9 @@ bool wxGenericPrintSetupDialog::TransferDataToWindow()
wxPostScriptPrintNativeData *data =
(wxPostScriptPrintNativeData *) m_printData.GetNativeData();
if (m_printerCommandText && data->GetPrinterCommand())
if (m_printerCommandText && !data->GetPrinterCommand().empty())
m_printerCommandText->SetValue(data->GetPrinterCommand());
if (m_printerOptionsText && data->GetPrinterOptions())
if (m_printerOptionsText && !data->GetPrinterOptions().empty())
m_printerOptionsText->SetValue(data->GetPrinterOptions());
if (m_colourCheckBox)
m_colourCheckBox->SetValue(m_printData.GetColour());

View File

@@ -130,7 +130,9 @@ void wxCrashReportImpl::Output(const wxChar *format, ...)
DWORD cbWritten;
wxString s = wxString::FormatV(format, argptr);
::WriteFile(m_hFile, s, s.length() * sizeof(wxChar), &cbWritten, 0);
wxCharBuffer buf(s.mb_str(wxConvUTF8));
::WriteFile(m_hFile, buf.data(), strlen(buf.data()), &cbWritten, 0);
va_end(argptr);
}

View File

@@ -1125,7 +1125,7 @@ static inline bool WriteAsciiString(wxOutputStream& ostr, const wxString& s)
wxCharBuffer name(s.mb_str());
ostr.Write(name, strlen(name));
#else
ostr.Write(s, s.length());
ostr.Write(s.mb_str(), s.length());
#endif
return ostr.IsOk();

View File

@@ -74,7 +74,7 @@ wxObject *wxCheckListBoxXmlHandler::DoCreateResource()
// checking boolean is a bit ugly here (see GetBool() )
wxString v = n->GetPropVal(wxT("checked"), wxEmptyString);
v.MakeLower();
if (v && v == wxT("1"))
if (v == wxT("1"))
control->Check( i, true );
i++;

View File

@@ -265,7 +265,7 @@ void TextStreamTestCase::TestInput(const wxMBConv& conv,
CPPUNIT_ASSERT_EQUAL( WXSIZEOF(txtWchar), temp.length() );
CPPUNIT_ASSERT_EQUAL( 0, memcmp(txtWchar, temp.c_str(), sizeof(txtWchar)) );
CPPUNIT_ASSERT_EQUAL( 0, memcmp(txtWchar, temp.wc_str(), sizeof(txtWchar)) );
}
#endif // wxUSE_UNICODE

View File

@@ -679,21 +679,17 @@ void StringTestCase::DoCStrDataTernaryOperator(bool cond)
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
const wchar_t *wcStr = L"foo";
CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : wcStr)) );
CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : L"bar")) );
CPPUNIT_ASSERT( CheckStr(s, (cond ? wcStr : s.c_str())) );
CPPUNIT_ASSERT( CheckStr(s, (cond ? L"bar" : s.c_str())) );
#else
const char *mbStr = "foo";
CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : mbStr)) );
CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : "foo")) );
CPPUNIT_ASSERT( CheckStr(s, (cond ? mbStr : s.c_str())) );
CPPUNIT_ASSERT( CheckStr(s, (cond ? "foo" : s.c_str())) );
#endif
wxString empty("");
CPPUNIT_ASSERT( CheckStr(empty, (cond ? empty.c_str() : wxEmptyString)) );
@@ -713,15 +709,11 @@ 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()