fix linking problems due to MSVC implicitly considering template classes specializations used as base classes DLL-exported even though it doesn't actually export them when building the DLL (with or without explicit declspec(dllexport)); also replace wxCharTypeBuffer::NullData with a static function to allow not DLL-exporting this class
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -27,7 +27,7 @@ class WXDLLIMPEXP_FWD_BASE wxCStrData;
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class WXDLLIMPEXP_BASE wxCharTypeBuffer
|
class wxCharTypeBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef T CharType;
|
typedef T CharType;
|
||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
if ( str )
|
if ( str )
|
||||||
m_data = new Data(wxStrdup(str));
|
m_data = new Data(wxStrdup(str));
|
||||||
else
|
else
|
||||||
m_data = &NullData;
|
m_data = GetNullData();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxCharTypeBuffer(size_t len)
|
wxCharTypeBuffer(size_t len)
|
||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
// that ref-counting is used, it's not really needed.
|
// that ref-counting is used, it's not really needed.
|
||||||
CharType *release() const
|
CharType *release() const
|
||||||
{
|
{
|
||||||
if ( m_data == &NullData )
|
if ( m_data == GetNullData() )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wxASSERT_MSG( m_data->m_owned, _T("can't release non-owned buffer") );
|
wxASSERT_MSG( m_data->m_owned, _T("can't release non-owned buffer") );
|
||||||
@@ -121,7 +121,7 @@ public:
|
|||||||
if ( !str )
|
if ( !str )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( m_data == &NullData )
|
if ( m_data == GetNullData() )
|
||||||
{
|
{
|
||||||
m_data = new Data(str);
|
m_data = new Data(str);
|
||||||
}
|
}
|
||||||
@@ -167,30 +167,27 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// placeholder for NULL string, to simplify this code
|
// placeholder for NULL string, to simplify this code
|
||||||
// NB: this is defined in string.cpp, not (non-existent) buffer.cpp
|
static Data *GetNullData()
|
||||||
#ifdef __MINGW32__
|
{
|
||||||
// MinGW requires explicit WXDLLIMPEXP_DATA_BASE to avoid compilation
|
static Data s_nullData(NULL);
|
||||||
// errors
|
|
||||||
static WXDLLIMPEXP_DATA_BASE(Data) NullData;
|
return &s_nullData;
|
||||||
#else
|
}
|
||||||
// but Visual C++ doesn't like it
|
|
||||||
static Data NullData;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void IncRef()
|
void IncRef()
|
||||||
{
|
{
|
||||||
if ( m_data == &NullData ) // exception, not ref-counted
|
if ( m_data == GetNullData() ) // exception, not ref-counted
|
||||||
return;
|
return;
|
||||||
m_data->m_ref++;
|
m_data->m_ref++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecRef()
|
void DecRef()
|
||||||
{
|
{
|
||||||
if ( m_data == &NullData ) // exception, not ref-counted
|
if ( m_data == GetNullData() ) // exception, not ref-counted
|
||||||
return;
|
return;
|
||||||
if ( --m_data->m_ref == 0 )
|
if ( --m_data->m_ref == 0 )
|
||||||
delete m_data;
|
delete m_data;
|
||||||
m_data = &NullData;
|
m_data = GetNullData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -199,7 +196,7 @@ private:
|
|||||||
|
|
||||||
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
|
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
|
||||||
|
|
||||||
class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
|
class wxCharBuffer : public wxCharTypeBuffer<char>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
|
typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
|
||||||
@@ -216,7 +213,7 @@ public:
|
|||||||
#if wxUSE_WCHAR_T
|
#if wxUSE_WCHAR_T
|
||||||
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
|
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
|
||||||
|
|
||||||
class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
|
class wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
|
typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
|
||||||
@@ -342,7 +339,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class WXDLLIMPEXP_BASE wxMemoryBuffer
|
class wxMemoryBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// ctor and dtor
|
// ctor and dtor
|
||||||
|
@@ -3605,7 +3605,7 @@ private:
|
|||||||
#endif // !wxUSE_STL_BASED_WXSTRING
|
#endif // !wxUSE_STL_BASED_WXSTRING
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class WXDLLIMPEXP_BASE wxStringTypeBufferBase
|
class wxStringTypeBufferBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef T CharType;
|
typedef T CharType;
|
||||||
@@ -3645,8 +3645,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class WXDLLIMPEXP_BASE wxStringTypeBufferLengthBase
|
class wxStringTypeBufferLengthBase : public wxStringTypeBufferBase<T>
|
||||||
: public wxStringTypeBufferBase<T>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024)
|
wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024)
|
||||||
@@ -3750,25 +3749,57 @@ typedef wxStringInternalBufferLength wxUTF8StringBufferLength;
|
|||||||
|
|
||||||
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferBase<char> )
|
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferBase<char> )
|
||||||
|
|
||||||
class WXDLLIMPEXP_BASE wxUTF8StringBuffer : public wxStringTypeBufferBase<char>
|
// Note about inlined dtors in the classes below: this is done not for
|
||||||
|
// performance reasons but just to avoid linking errors in the MSVC DLL build
|
||||||
|
// under Windows: if a class has non-inline methods it must be declared as
|
||||||
|
// being DLL-exported but, due to an extremely interesting feature of MSVC 7
|
||||||
|
// and later, any template class which is used as a base of a DLL-exported
|
||||||
|
// class is implicitly made DLL-exported too, as explained at the bottom of
|
||||||
|
// http://msdn.microsoft.com/en-us/library/twa2aw10.aspx (just to confirm: yes,
|
||||||
|
// _inheriting_ from a class can change whether it is being exported from DLL)
|
||||||
|
//
|
||||||
|
// But this results in link errors because the base template class is not DLL-
|
||||||
|
// exported, whether it is declared with WXDLLIMPEXP_BASE or not, because it
|
||||||
|
// does have only inline functions. So the simplest fix is to just make all the
|
||||||
|
// functions of these classes inline too.
|
||||||
|
|
||||||
|
class wxUTF8StringBuffer : public wxStringTypeBufferBase<char>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxUTF8StringBuffer(wxString& str, size_t lenWanted = 1024)
|
wxUTF8StringBuffer(wxString& str, size_t lenWanted = 1024)
|
||||||
: wxStringTypeBufferBase<char>(str, lenWanted) {}
|
: wxStringTypeBufferBase<char>(str, lenWanted) {}
|
||||||
~wxUTF8StringBuffer();
|
~wxUTF8StringBuffer()
|
||||||
|
{
|
||||||
|
wxMBConvStrictUTF8 conv;
|
||||||
|
size_t wlen = conv.ToWChar(NULL, 0, m_buf);
|
||||||
|
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
|
||||||
|
|
||||||
|
wxStringInternalBuffer wbuf(m_str, wlen);
|
||||||
|
conv.ToWChar(wbuf, wlen, m_buf);
|
||||||
|
}
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(wxUTF8StringBuffer)
|
DECLARE_NO_COPY_CLASS(wxUTF8StringBuffer)
|
||||||
};
|
};
|
||||||
|
|
||||||
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferLengthBase<char> )
|
WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferLengthBase<char> )
|
||||||
|
|
||||||
class WXDLLIMPEXP_BASE wxUTF8StringBufferLength
|
class wxUTF8StringBufferLength : public wxStringTypeBufferLengthBase<char>
|
||||||
: public wxStringTypeBufferLengthBase<char>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxUTF8StringBufferLength(wxString& str, size_t lenWanted = 1024)
|
wxUTF8StringBufferLength(wxString& str, size_t lenWanted = 1024)
|
||||||
: wxStringTypeBufferLengthBase<char>(str, lenWanted) {}
|
: wxStringTypeBufferLengthBase<char>(str, lenWanted) {}
|
||||||
~wxUTF8StringBufferLength();
|
~wxUTF8StringBufferLength()
|
||||||
|
{
|
||||||
|
wxCHECK_RET(m_lenSet, "length not set");
|
||||||
|
|
||||||
|
wxMBConvStrictUTF8 conv;
|
||||||
|
size_t wlen = conv.ToWChar(NULL, 0, m_buf, m_len);
|
||||||
|
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
|
||||||
|
|
||||||
|
wxStringInternalBufferLength wbuf(m_str, wlen);
|
||||||
|
conv.ToWChar(wbuf, wlen, m_buf, m_len);
|
||||||
|
wbuf.SetLength(wlen);
|
||||||
|
}
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(wxUTF8StringBufferLength)
|
DECLARE_NO_COPY_CLASS(wxUTF8StringBufferLength)
|
||||||
};
|
};
|
||||||
|
@@ -2096,48 +2096,3 @@ int wxString::Freq(wxUniChar ch) const
|
|||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// wxUTF8StringBuffer
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if wxUSE_UNICODE_WCHAR
|
|
||||||
wxUTF8StringBuffer::~wxUTF8StringBuffer()
|
|
||||||
{
|
|
||||||
wxMBConvStrictUTF8 conv;
|
|
||||||
size_t wlen = conv.ToWChar(NULL, 0, m_buf);
|
|
||||||
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
|
|
||||||
|
|
||||||
wxStringInternalBuffer wbuf(m_str, wlen);
|
|
||||||
conv.ToWChar(wbuf, wlen, m_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxUTF8StringBufferLength::~wxUTF8StringBufferLength()
|
|
||||||
{
|
|
||||||
wxCHECK_RET(m_lenSet, "length not set");
|
|
||||||
|
|
||||||
wxMBConvStrictUTF8 conv;
|
|
||||||
size_t wlen = conv.ToWChar(NULL, 0, m_buf, m_len);
|
|
||||||
wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
|
|
||||||
|
|
||||||
wxStringInternalBufferLength wbuf(m_str, wlen);
|
|
||||||
conv.ToWChar(wbuf, wlen, m_buf, m_len);
|
|
||||||
wbuf.SetLength(wlen);
|
|
||||||
}
|
|
||||||
#endif // wxUSE_UNICODE_WCHAR
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// wxCharBufferType<T>
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef __VMS_BROKEN_TEMPLATES
|
|
||||||
template<>
|
|
||||||
#endif
|
|
||||||
wxCharTypeBuffer<char>::Data
|
|
||||||
wxCharTypeBuffer<char>::NullData(NULL);
|
|
||||||
|
|
||||||
#ifndef __VMS_BROKEN_TEMPLATES
|
|
||||||
template<>
|
|
||||||
#endif
|
|
||||||
wxCharTypeBuffer<wchar_t>::Data
|
|
||||||
wxCharTypeBuffer<wchar_t>::NullData(NULL);
|
|
||||||
|
@@ -542,16 +542,3 @@ wxU16CharBuffer wxUString::utf16_str() const
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if SIZEOF_WCHAR_T != 2
|
|
||||||
template<>
|
|
||||||
wxCharTypeBuffer<wxChar16>::Data
|
|
||||||
wxCharTypeBuffer<wxChar16>::NullData(NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SIZEOF_WCHAR_T != 4
|
|
||||||
template<>
|
|
||||||
wxCharTypeBuffer<wxChar32>::Data
|
|
||||||
wxCharTypeBuffer<wxChar32>::NullData(NULL);
|
|
||||||
#endif
|
|
||||||
|
Reference in New Issue
Block a user