const size_t dstLen = ToWChar(NULL, 0, inBuff, inLen);
if ( dstLen != wxCONV_FAILED )
{
- wxWCharBuffer wbuf(dstLen - 1);
+ // notice that we allocate space for dstLen+1 wide characters here
+ // because we want the buffer to always be NUL-terminated, even if the
+ // input isn't (as otherwise the caller has no way to know its length)
+ wxWCharBuffer wbuf(dstLen);
+ wbuf.data()[dstLen - 1] = L'\0';
if ( ToWChar(wbuf.data(), dstLen, inBuff, inLen) != wxCONV_FAILED )
{
if ( outLen )
size_t dstLen = FromWChar(NULL, 0, inBuff, inLen);
if ( dstLen != wxCONV_FAILED )
{
- // special case of empty input: can't allocate 0 size buffer below as
- // wxCharBuffer insists on NUL-terminating it
- wxCharBuffer buf(dstLen ? dstLen - 1 : 1);
+ const size_t nulLen = GetMBNulLen();
+
+ // as above, ensure that the buffer is always NUL-terminated, even if
+ // the input is not
+ wxCharBuffer buf(dstLen + nulLen - 1);
+ memset(buf.data() + dstLen, 0, nulLen);
if ( FromWChar(buf.data(), dstLen, inBuff, inLen) != wxCONV_FAILED )
{
if ( outLen )
{
*outLen = dstLen;
- const size_t nulLen = GetMBNulLen();
if ( dstLen >= nulLen &&
!NotAllNULs(buf.data() + dstLen - nulLen, nulLen) )
{
return wxCONV_FAILED;
}
-size_t wxMBConvUTF8::MB2WC(wchar_t *buf, const char *psz, size_t n) const
+size_t wxMBConvUTF8::ToWChar(wchar_t *buf, size_t n,
+ const char *psz, size_t srcLen) const
{
if ( m_options == MAP_INVALID_UTF8_NOT )
- return wxMBConvStrictUTF8::MB2WC(buf, psz, n);
+ return wxMBConvStrictUTF8::ToWChar(buf, n, psz, srcLen);
size_t len = 0;
- while (*psz && ((!buf) || (len < n)))
+ while ((srcLen == wxNO_LEN ? *psz : srcLen--) && ((!buf) || (len < n)))
{
const char *opsz = psz;
bool invalid = false;
}
}
- if (buf && (len < n))
+ if (srcLen == wxNO_LEN && buf && (len < n))
*buf = 0;
- return len;
+ return len + 1;
}
static inline bool isoctal(wchar_t wch)
return L'0' <= wch && wch <= L'7';
}
-size_t wxMBConvUTF8::WC2MB(char *buf, const wchar_t *psz, size_t n) const
+size_t wxMBConvUTF8::FromWChar(char *buf, size_t n,
+ const wchar_t *psz, size_t srcLen) const
{
if ( m_options == MAP_INVALID_UTF8_NOT )
- return wxMBConvStrictUTF8::WC2MB(buf, psz, n);
+ return wxMBConvStrictUTF8::FromWChar(buf, n, psz, srcLen);
size_t len = 0;
- while (*psz && ((!buf) || (len < n)))
+ while ((srcLen == wxNO_LEN ? *psz : srcLen--) && ((!buf) || (len < n)))
{
wxUint32 cc;
}
}
- if (buf && (len < n))
+ if (srcLen == wxNO_LEN && buf && (len < n))
*buf = 0;
- return len;
+ return len + 1;
}
// ============================================================================
return wxCONV_FAILED;
}
- // if we were really converting, check if we succeeded
- if ( buf )
+ // we did something, check if we really succeeded
+ if ( flags )
{
- if ( flags )
+ // check if the conversion failed, i.e. if any replacements
+ // were done
+ if ( usedDef )
+ return wxCONV_FAILED;
+ }
+ else // we must resort to double tripping...
+ {
+ // first we need to ensure that we really have the MB data: this is
+ // not the case if we're called with NULL buffer, in which case we
+ // need to do the conversion yet again
+ wxCharBuffer bufDef;
+ if ( !buf )
{
- // check if the conversion failed, i.e. if any replacements
- // were done
- if ( usedDef )
+ bufDef = wxCharBuffer(len);
+ buf = bufDef.data();
+ if ( !::WideCharToMultiByte(m_CodePage, flags, pwz, -1,
+ buf, len, NULL, NULL) )
return wxCONV_FAILED;
}
- else // we must resort to double tripping...
+
+ if ( !n )
+ n = wcslen(pwz);
+ wxWCharBuffer wcBuf(n);
+ if ( MB2WC(wcBuf.data(), buf, n + 1) == wxCONV_FAILED ||
+ wcscmp(wcBuf, pwz) != 0 )
{
- wxWCharBuffer wcBuf(n);
- if ( MB2WC(wcBuf.data(), buf, n) == wxCONV_FAILED ||
- wcscmp(wcBuf, pwz) != 0 )
- {
- // we didn't obtain the same thing we started from, hence
- // the conversion was lossy and we consider that it failed
- return wxCONV_FAILED;
- }
+ // we didn't obtain the same thing we started from, hence
+ // the conversion was lossy and we consider that it failed
+ return wxCONV_FAILED;
}
}
WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConvLibc, wxConvLibc, wxEMPTY_PARAMETER_VALUE);
#endif
-WX_DEFINE_GLOBAL_CONV(wxMBConvStrictUTF8, wxConvUTF8, wxEMPTY_PARAMETER_VALUE);
-WX_DEFINE_GLOBAL_CONV(wxMBConvUTF7, wxConvUTF7, wxEMPTY_PARAMETER_VALUE);
+// NB: we can't use wxEMPTY_PARAMETER_VALUE as final argument here because it's
+// passed to WX_DEFINE_GLOBAL_CONV2 after a macro expansion and so still
+// provokes an error message about "not enough macro parameters"; and we
+// can't use "()" here as the name##Obj declaration would be parsed as a
+// function declaration then, so use a semicolon and live with an extra
+// empty statement (and hope that no compilers warns about this)
+WX_DEFINE_GLOBAL_CONV(wxMBConvStrictUTF8, wxConvUTF8, ;);
+WX_DEFINE_GLOBAL_CONV(wxMBConvUTF7, wxConvUTF7, ;);
WX_DEFINE_GLOBAL_CONV(wxCSConv, wxConvLocal, (wxFONTENCODING_SYSTEM));
WX_DEFINE_GLOBAL_CONV(wxCSConv, wxConvISO8859_1, (wxFONTENCODING_ISO8859_1));