X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c9f7896861f734ce044ee8601ba2d8a6959c9d9e..0bbe61b8c18a1795189f0cf73cc61c14a0fb846d:/src/common/sstream.cpp?ds=inline diff --git a/src/common/sstream.cpp b/src/common/sstream.cpp index a16ea1b24a..aabe01e977 100644 --- a/src/common/sstream.cpp +++ b/src/common/sstream.cpp @@ -38,27 +38,20 @@ // TODO: Do we want to include the null char in the stream? If so then // just add +1 to m_len in the ctor -wxStringInputStream::wxStringInputStream(const wxString& s) +wxStringInputStream::wxStringInputStream(const wxString& s) #if wxUSE_UNICODE - : m_str(s), m_buf(wxMBConvUTF8().cWX2MB(s).release()), m_len(strlen(m_buf)) + // FIXME-UTF8: use wxCharBufferWithLength if we have it + : m_str(s), m_buf(s.utf8_str()), m_len(strlen(m_buf)) #else - : m_str(s), m_buf((char*)(const char*)s.c_str()), m_len(s.length()) + : m_str(s), m_buf(s.mb_str()), m_len(s.length()) #endif { #if wxUSE_UNICODE - wxASSERT_MSG(m_buf != NULL, _T("Could not convert string to UTF8!")); + wxASSERT_MSG(m_buf.data() != NULL, _T("Could not convert string to UTF8!")); #endif m_pos = 0; } -wxStringInputStream::~wxStringInputStream() -{ -#if wxUSE_UNICODE - // Note: wx[W]CharBuffer uses malloc()/free() - free(m_buf); -#endif -} - // ---------------------------------------------------------------------------- // getlength // ---------------------------------------------------------------------------- @@ -126,7 +119,7 @@ size_t wxStringInputStream::OnSysRead(void *buffer, size_t size) size = sizeMax; } - memcpy(buffer, m_buf + m_pos, size); + memcpy(buffer, m_buf.data() + m_pos, size); m_pos += size; return size; @@ -153,9 +146,53 @@ size_t wxStringOutputStream::OnSysWrite(const void *buffer, size_t size) { const char *p = wx_static_cast(const char *, buffer); - // append the input buffer (may not be null terminated - thus - // the literal length - m_str->Append(wxString(p, m_conv, size)); +#if wxUSE_UNICODE_WCHAR + // the part of the string we have here may be incomplete, i.e. it can stop + // in the middle of an UTF-8 character and so converting it would fail; if + // this is the case, accumulate the part which we failed to convert until + // we get the rest (and also take into account the part which we might have + // left unconverted before) + const char *src; + size_t srcLen; + if ( m_unconv.GetDataLen() ) + { + // append the new data to the data remaining since the last time + m_unconv.AppendData(p, size); + src = m_unconv; + srcLen = m_unconv.GetDataLen(); + } + else // no unconverted data left, avoid extra copy + { + src = p; + srcLen = size; + } + + size_t wlen; + wxWCharBuffer wbuf(m_conv.cMB2WC(src, srcLen, &wlen)); + if ( wbuf ) + { + // conversion succeeded, clear the unconverted buffer + m_unconv = wxMemoryBuffer(0); + + m_str->append(wbuf, wlen); + } + else // conversion failed + { + // remember unconverted data if there had been none before (otherwise + // we've already got it in the buffer) + if ( src == p ) + m_unconv.AppendData(src, srcLen); + + // pretend that we wrote the data anyhow, otherwise the caller would + // believe there was an error and this might not be the case, but do + // not update m_pos as m_str hasn't changed + return size; + } +#else // !wxUSE_UNICODE_WCHAR + // no recoding necessary, the data is supposed to already be in UTF-8 (if + // supported) or ASCII otherwise + m_str->append(p, size); +#endif // wxUSE_UNICODE_WCHAR/!wxUSE_UNICODE_WCHAR // update position m_pos += size;