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
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
// 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; }
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, ... );
{ 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 ); }
{ 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 ); }
{ 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 ); }
~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;
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
// 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
// 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(); }
{ 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
// 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)
{
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; }
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)
#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
delete m_str;
}
-#if wxUSE_UNICODE
+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
-#else
+{
+ return m_str->wx_str() + m_offset;
+}
+#endif // wxUSE_UNICODE_WCHAR
+
+#if !wxUSE_UNICODE
inline const char* wxCStrData::AsChar() const
-#endif
{
- // FIXME-UTF8: incorrect position, incorrect charset
return m_str->wx_str() + m_offset;
}
+#endif // !wxUSE_UNICODE
inline wxString wxCStrData::AsString() 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())
+{
+}
+
+inline wxWCharBuffer::wxWCharBuffer(const wxCStrData& cstr)
+ : wxCharTypeBufferBase(cstr.AsWChar())
{
}
-#endif // _WX_WXSTRING_H__
+#endif // _WX_WXSTRING_H_
// ----------------------------------------------------------------------------
// 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
// 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__
#include <clib.h>
#endif
+#include <wx/hashmap.h>
// string handling functions used by wxString:
#if wxUSE_UNICODE_UTF8
#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
// ===========================================================================
// 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,
// convert to lower case, return the copy of the string
wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }
-
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();
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());
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);
}
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();
// 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++;
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
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)) );
{
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()