X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5a4c7f718a0a4f36b1af71335c39a08439a1689b..76015a6bb79156d8af1b5e8b4b8e46b4e192d18f:/src/common/sstream.cpp diff --git a/src/common/sstream.cpp b/src/common/sstream.cpp index de3496327e..14c7dca8a2 100644 --- a/src/common/sstream.cpp +++ b/src/common/sstream.cpp @@ -1,8 +1,8 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: common/sstream.cpp +// Name: src/common/sstream.cpp // Purpose: string-based streams implementation // Author: Vadim Zeitlin -// Modified by: +// Modified by: Ryan Norton (UTF8 UNICODE) // Created: 2004-09-19 // RCS-ID: $Id$ // Copyright: (c) 2004 Vadim Zeitlin @@ -33,13 +33,40 @@ // ============================================================================ // ---------------------------------------------------------------------------- -// seek/tell +// construction/destruction // ---------------------------------------------------------------------------- -off_t wxStringInputStream::OnSysSeek(off_t ofs, wxSeekMode mode) +// 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) +#if wxUSE_UNICODE + // 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(s.mb_str()), m_len(s.length()) +#endif { - const size_t ofsMax = m_str.length()*sizeof(wxChar); +#if wxUSE_UNICODE + wxASSERT_MSG(m_buf.data() != NULL, wxT("Could not convert string to UTF8!")); +#endif + m_pos = 0; +} +// ---------------------------------------------------------------------------- +// getlength +// ---------------------------------------------------------------------------- + +wxFileOffset wxStringInputStream::GetLength() const +{ + return m_len; +} + +// ---------------------------------------------------------------------------- +// seek/tell +// ---------------------------------------------------------------------------- + +wxFileOffset wxStringInputStream::OnSysSeek(wxFileOffset ofs, wxSeekMode mode) +{ switch ( mode ) { case wxFromStart: @@ -47,7 +74,7 @@ off_t wxStringInputStream::OnSysSeek(off_t ofs, wxSeekMode mode) break; case wxFromEnd: - ofs += ofsMax; + ofs += m_len; break; case wxFromCurrent: @@ -55,21 +82,22 @@ off_t wxStringInputStream::OnSysSeek(off_t ofs, wxSeekMode mode) break; default: - wxFAIL_MSG( _T("invalid seek mode") ); + wxFAIL_MSG( wxT("invalid seek mode") ); return wxInvalidOffset; } - if ( ofs < 0 || wx_static_cast(size_t, ofs) >= ofsMax ) + if ( ofs < 0 || ofs > static_cast(m_len) ) return wxInvalidOffset; - m_pos = wx_static_cast(size_t, ofs); + // FIXME: this can't be right + m_pos = wx_truncate_cast(size_t, ofs); return ofs; } -off_t wxStringInputStream::OnSysTell() const +wxFileOffset wxStringInputStream::OnSysTell() const { - return wx_static_cast(off_t, m_pos); + return static_cast(m_pos); } // ---------------------------------------------------------------------------- @@ -78,7 +106,7 @@ off_t wxStringInputStream::OnSysTell() const size_t wxStringInputStream::OnSysRead(void *buffer, size_t size) { - const size_t sizeMax = m_str.length()*sizeof(wxChar) - m_pos; + const size_t sizeMax = m_len - m_pos; if ( size >= sizeMax ) { @@ -91,7 +119,7 @@ size_t wxStringInputStream::OnSysRead(void *buffer, size_t size) size = sizeMax; } - memcpy(buffer, m_str.data() + m_pos, size); + memcpy(buffer, m_buf.data() + m_pos, size); m_pos += size; return size; @@ -101,21 +129,75 @@ size_t wxStringInputStream::OnSysRead(void *buffer, size_t size) // wxStringOutputStream implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// seek/tell +// ---------------------------------------------------------------------------- + +wxFileOffset wxStringOutputStream::OnSysTell() const +{ + return static_cast(m_pos); +} + // ---------------------------------------------------------------------------- // actual IO // ---------------------------------------------------------------------------- size_t wxStringOutputStream::OnSysWrite(const void *buffer, size_t size) { - // in Unicode mode we might not be able to write the last byte - size_t len = size / sizeof(wxChar); + const char *p = static_cast(buffer); + +#if wxUSE_UNICODE + // 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); - const wxChar *p = wx_static_cast(const wxChar *, buffer); + 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 + // no recoding necessary + m_str->append(p, size); +#endif // wxUSE_UNICODE/!wxUSE_UNICODE - m_str->Append(wxString(p, p + len + 1)); + // update position + m_pos += size; // return number of bytes actually written - return len*sizeof(wxChar); + return size; } #endif // wxUSE_STREAMS