X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8faef7ccbc4b4e192da06de7e1a2a7f1dff7ec91..76015a6bb79156d8af1b5e8b4b8e46b4e192d18f:/src/common/stream.cpp diff --git a/src/common/stream.cpp b/src/common/stream.cpp index 357499b047..1b1c6baf04 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -36,6 +36,7 @@ #include #include "wx/datstrm.h" #include "wx/textfile.h" +#include "wx/scopeguard.h" // ---------------------------------------------------------------------------- // constants @@ -100,7 +101,7 @@ wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer) // doing this has big chances to lead to a crash when the source buffer is // destroyed (otherwise assume the caller knows what he does) wxASSERT_MSG( !buffer.m_destroybuf, - _T("it's a bad idea to copy this buffer") ); + wxT("it's a bad idea to copy this buffer") ); m_buffer_start = buffer.m_buffer_start; m_buffer_end = buffer.m_buffer_end; @@ -202,7 +203,7 @@ void wxStreamBuffer::Truncate() } char *new_start = (char *)realloc(m_buffer_start, new_size); - wxCHECK_RET( new_size, _T("shrinking buffer shouldn't fail") ); + wxCHECK_RET( new_size, wxT("shrinking buffer shouldn't fail") ); m_buffer_start = new_start; m_buffer_end = m_buffer_start + new_size; @@ -231,7 +232,7 @@ bool wxStreamBuffer::FillBuffer() // write the buffer contents to the stream (only for write buffers) bool wxStreamBuffer::FlushBuffer() { - wxCHECK_MSG( m_flushable, false, _T("can't flush this buffer") ); + wxCHECK_MSG( m_flushable, false, wxT("can't flush this buffer") ); // FIXME: what is this check for? (VZ) if ( m_buffer_pos == m_buffer_start ) @@ -239,7 +240,7 @@ bool wxStreamBuffer::FlushBuffer() wxOutputStream *outStream = GetOutputStream(); - wxCHECK_MSG( outStream, false, _T("should have a stream in wxStreamBuffer") ); + wxCHECK_MSG( outStream, false, wxT("should have a stream in wxStreamBuffer") ); size_t current = m_buffer_pos - m_buffer_start; size_t count = outStream->OnSysWrite(m_buffer_start, current); @@ -319,7 +320,7 @@ void wxStreamBuffer::PutChar(char c) { wxOutputStream *outStream = GetOutputStream(); - wxCHECK_RET( outStream, _T("should have a stream in wxStreamBuffer") ); + wxCHECK_RET( outStream, wxT("should have a stream in wxStreamBuffer") ); // if we don't have buffer at all, just forward this call to the stream, if ( !HasBuffer() ) @@ -345,7 +346,7 @@ void wxStreamBuffer::PutChar(char c) char wxStreamBuffer::Peek() { wxCHECK_MSG( m_stream && HasBuffer(), 0, - _T("should have the stream and the buffer in wxStreamBuffer") ); + wxT("should have the stream and the buffer in wxStreamBuffer") ); if ( !GetDataLeft() ) { @@ -364,7 +365,7 @@ char wxStreamBuffer::GetChar() { wxInputStream *inStream = GetInputStream(); - wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") ); + wxCHECK_MSG( inStream, 0, wxT("should have a stream in wxStreamBuffer") ); char c; if ( !HasBuffer() ) @@ -390,7 +391,7 @@ char wxStreamBuffer::GetChar() size_t wxStreamBuffer::Read(void *buffer, size_t size) { - wxASSERT_MSG( buffer, _T("Warning: Null pointer is about to be used") ); + wxASSERT_MSG( buffer, wxT("Warning: Null pointer is about to be used") ); /* Clear buffer first */ memset(buffer, 0x00, size); @@ -404,7 +405,7 @@ size_t wxStreamBuffer::Read(void *buffer, size_t size) { wxInputStream *inStream = GetInputStream(); - wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") ); + wxCHECK_MSG( inStream, 0, wxT("should have a stream in wxStreamBuffer") ); readBytes = inStream->OnSysRead(buffer, size); } @@ -449,7 +450,7 @@ size_t wxStreamBuffer::Read(void *buffer, size_t size) // this should really be called "Copy()" size_t wxStreamBuffer::Read(wxStreamBuffer *dbuf) { - wxCHECK_MSG( m_mode != write, 0, _T("can't read from this buffer") ); + wxCHECK_MSG( m_mode != write, 0, wxT("can't read from this buffer") ); char buf[BUF_TEMP_SIZE]; size_t nRead, @@ -471,7 +472,7 @@ size_t wxStreamBuffer::Read(wxStreamBuffer *dbuf) size_t wxStreamBuffer::Write(const void *buffer, size_t size) { - wxASSERT_MSG( buffer, _T("Warning: Null pointer is about to be send") ); + wxASSERT_MSG( buffer, wxT("Warning: Null pointer is about to be send") ); if (m_stream) { @@ -485,7 +486,7 @@ size_t wxStreamBuffer::Write(const void *buffer, size_t size) { wxOutputStream *outStream = GetOutputStream(); - wxCHECK_MSG( outStream, 0, _T("should have a stream in wxStreamBuffer") ); + wxCHECK_MSG( outStream, 0, wxT("should have a stream in wxStreamBuffer") ); // no buffer, just forward the call to the stream ret = outStream->OnSysWrite(buffer, size); @@ -543,8 +544,8 @@ size_t wxStreamBuffer::Write(const void *buffer, size_t size) size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf) { - wxCHECK_MSG( m_mode != read, 0, _T("can't write to this buffer") ); - wxCHECK_MSG( sbuf->m_mode != write, 0, _T("can't read from that buffer") ); + wxCHECK_MSG( m_mode != read, 0, wxT("can't write to this buffer") ); + wxCHECK_MSG( sbuf->m_mode != write, 0, wxT("can't read from that buffer") ); char buf[BUF_TEMP_SIZE]; size_t nWrite, @@ -599,7 +600,7 @@ wxFileOffset wxStreamBuffer::Seek(wxFileOffset pos, wxSeekMode mode) break; default: - wxFAIL_MSG( _T("invalid seek mode") ); + wxFAIL_MSG( wxT("invalid seek mode") ); return wxInvalidOffset; } @@ -635,7 +636,7 @@ wxFileOffset wxStreamBuffer::Seek(wxFileOffset pos, wxSeekMode mode) size_t int_diff = wx_truncate_cast(size_t, diff); wxCHECK_MSG( (wxFileOffset)int_diff == diff, wxInvalidOffset, wxT("huge file not supported") ); SetIntPosition(int_diff); - return pos; + return diff; } case wxFromEnd: @@ -695,7 +696,7 @@ size_t wxStreamBase::GetSize() const return 0; const size_t len = wx_truncate_cast(size_t, length); - wxASSERT_MSG( len == length + size_t(0), _T("large files not supported") ); + wxASSERT_MSG( len == length + size_t(0), wxT("large files not supported") ); return len; } @@ -771,7 +772,7 @@ char *wxInputStream::AllocSpaceWBack(size_t needed_size) size_t wxInputStream::GetWBack(void *buf, size_t size) { - wxASSERT_MSG( buf, _T("Warning: Null pointer is about to be used") ); + wxASSERT_MSG( buf, wxT("Warning: Null pointer is about to be used") ); /* Clear buffer first */ memset(buf, 0x00, size); @@ -807,7 +808,7 @@ size_t wxInputStream::GetWBack(void *buf, size_t size) size_t wxInputStream::Ungetch(const void *buf, size_t bufsize) { - wxASSERT_MSG( buf, _T("Warning: Null pointer is about to be used in Ungetch()") ); + wxASSERT_MSG( buf, wxT("Warning: Null pointer is about to be used in Ungetch()") ); if ( m_lasterror != wxSTREAM_NO_ERROR && m_lasterror != wxSTREAM_EOF ) { @@ -841,7 +842,7 @@ int wxInputStream::GetC() wxInputStream& wxInputStream::Read(void *buf, size_t size) { - wxASSERT_MSG( buf, _T("Warning: Null pointer is about to be read") ); + wxASSERT_MSG( buf, wxT("Warning: Null pointer is about to be read") ); char *p = (char *)buf; m_lastcount = 0; @@ -912,6 +913,47 @@ wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) return *this; } +bool wxInputStream::ReadAll(void *buffer_, size_t size) +{ + char* buffer = static_cast(buffer_); + + size_t totalCount = 0; + + for ( ;; ) + { + const size_t lastCount = Read(buffer, size).LastRead(); + + // There is no point in continuing looping if we can't read anything at + // all. + if ( !lastCount ) + break; + + totalCount += lastCount; + + // ... Or if an error occurred on the stream. + if ( !IsOk() ) + break; + + // Return successfully if we read exactly the requested number of + // bytes (normally the ">" case should never occur and so we could use + // "==" test, but be safe and avoid overflowing size even in case of + // bugs in LastRead()). + if ( lastCount >= size ) + { + size = 0; + break; + } + + // Advance the buffer before trying to read the rest of data. + size -= lastCount; + buffer += lastCount; + } + + m_lastcount = totalCount; + + return size == 0; +} + wxFileOffset wxInputStream::SeekI(wxFileOffset pos, wxSeekMode mode) { // RR: This code is duplicated in wxBufferedInputStream. This is @@ -943,18 +985,18 @@ wxFileOffset wxInputStream::SeekI(wxFileOffset pos, wxSeekMode mode) bytes_read = Read(buf, WXSIZEOF(buf)).LastRead(); if ( m_lasterror != wxSTREAM_NO_ERROR ) return wxInvalidOffset; - + wxASSERT(bytes_read == WXSIZEOF(buf)); } - + // read the last 'pos' bytes bytes_read = Read(buf, (size_t)pos).LastRead(); if ( m_lasterror != wxSTREAM_NO_ERROR ) return wxInvalidOffset; - + wxASSERT(bytes_read == (size_t)pos); - - // we should now have seeked to the right position... + + // we should now have sought to the right position... return TellI(); } @@ -1029,6 +1071,38 @@ wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in) return *this; } +bool wxOutputStream::WriteAll(const void *buffer_, size_t size) +{ + // This exactly mirrors ReadAll(), see there for more comments. + const char* buffer = static_cast(buffer_); + + size_t totalCount = 0; + + for ( ;; ) + { + const size_t lastCount = Write(buffer, size).LastWrite(); + if ( !lastCount ) + break; + + totalCount += lastCount; + + if ( !IsOk() ) + break; + + if ( lastCount >= size ) + { + size = 0; + break; + } + + size -= lastCount; + buffer += lastCount; + } + + m_lastcount = totalCount; + return size == 0; +} + wxFileOffset wxOutputStream::TellO() const { return OnSysTell(); @@ -1052,22 +1126,23 @@ IMPLEMENT_DYNAMIC_CLASS(wxCountingOutputStream, wxOutputStream) wxCountingOutputStream::wxCountingOutputStream () { - m_currentPos = 0; + m_currentPos = + m_lastPos = 0; } wxFileOffset wxCountingOutputStream::GetLength() const { - return m_lastcount; + return m_lastPos; } size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer), size_t size) { m_currentPos += size; - if (m_currentPos > m_lastcount) - m_lastcount = m_currentPos; + if ( m_currentPos > m_lastPos ) + m_lastPos = m_currentPos; - return m_currentPos; + return size; } wxFileOffset wxCountingOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode) @@ -1081,24 +1156,24 @@ wxFileOffset wxCountingOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode break; case wxFromEnd: - new_pos = m_lastcount + new_pos; - wxCHECK_MSG( (wxFileOffset)new_pos == (wxFileOffset)(m_lastcount + pos), wxInvalidOffset, wxT("huge position not supported") ); + new_pos += m_lastPos; + wxCHECK_MSG( (wxFileOffset)new_pos == (wxFileOffset)(m_lastPos + pos), wxInvalidOffset, wxT("huge position not supported") ); break; case wxFromCurrent: - new_pos = m_currentPos + new_pos; + new_pos += m_currentPos; wxCHECK_MSG( (wxFileOffset)new_pos == (wxFileOffset)(m_currentPos + pos), wxInvalidOffset, wxT("huge position not supported") ); break; default: - wxFAIL_MSG( _T("invalid seek mode") ); + wxFAIL_MSG( wxT("invalid seek mode") ); return wxInvalidOffset; } m_currentPos = new_pos; - if (m_currentPos > m_lastcount) - m_lastcount = m_currentPos; + if ( m_currentPos > m_lastPos ) + m_lastPos = m_currentPos; return m_currentPos; } @@ -1357,7 +1432,7 @@ wxFileOffset wxBufferedInputStream::OnSysTell() const void wxBufferedInputStream::SetInputStreamBuffer(wxStreamBuffer *buffer) { - wxCHECK_RET( buffer, _T("wxBufferedInputStream needs buffer") ); + wxCHECK_RET( buffer, wxT("wxBufferedInputStream needs buffer") ); delete m_i_streambuf; m_i_streambuf = buffer; @@ -1440,12 +1515,99 @@ wxFileOffset wxBufferedOutputStream::GetLength() const void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer *buffer) { - wxCHECK_RET( buffer, _T("wxBufferedOutputStream needs buffer") ); + wxCHECK_RET( buffer, wxT("wxBufferedOutputStream needs buffer") ); delete m_o_streambuf; m_o_streambuf = buffer; } +// --------------------------------------------------------------------------- +// wxWrapperInputStream implementation +// --------------------------------------------------------------------------- + +wxWrapperInputStream::wxWrapperInputStream() +{ + m_lasterror = wxSTREAM_READ_ERROR; +} + +wxWrapperInputStream::wxWrapperInputStream(wxInputStream& stream) + : wxFilterInputStream(stream) +{ + SynchronizeLastError(); +} + +wxWrapperInputStream::wxWrapperInputStream(wxInputStream *stream) + : wxFilterInputStream(stream) +{ + if ( m_parent_i_stream ) + SynchronizeLastError(); + else + m_lasterror = wxSTREAM_READ_ERROR; +} + +void wxWrapperInputStream::InitParentStream(wxInputStream& stream) +{ + wxCHECK_RET( !m_parent_i_stream, "Can't init parent stream twice" ); + + m_parent_i_stream = &stream; + + SynchronizeLastError(); +} + +void wxWrapperInputStream::InitParentStream(wxInputStream* stream) +{ + wxCHECK_RET( !m_parent_i_stream, "Can't init parent stream twice" ); + + m_parent_i_stream = stream; + + if ( m_parent_i_stream ) + { + m_owns = true; + + SynchronizeLastError(); + } +} + +wxFileOffset wxWrapperInputStream::GetLength() const +{ + wxCHECK_MSG(m_parent_i_stream, wxInvalidOffset, "Stream not valid"); + + wxON_BLOCK_EXIT_THIS0(wxWrapperInputStream::SynchronizeLastError); + return m_parent_i_stream->GetLength(); +} + +bool wxWrapperInputStream::IsSeekable() const +{ + wxCHECK_MSG(m_parent_i_stream, false, "Stream not valid"); + return m_parent_i_stream->IsSeekable(); +} + +size_t wxWrapperInputStream::OnSysRead(void *buffer, size_t size) +{ + wxCHECK_MSG(m_parent_i_stream, false, "Stream not valid"); + + wxON_BLOCK_EXIT_THIS0(wxWrapperInputStream::SynchronizeLastError); + + m_parent_i_stream->Read(buffer, size); + return m_parent_i_stream->LastRead(); +} + +wxFileOffset wxWrapperInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode) +{ + wxCHECK_MSG(IsSeekable(), false, "Stream not seekable"); + + wxON_BLOCK_EXIT_THIS0(wxWrapperInputStream::SynchronizeLastError); + return m_parent_i_stream->SeekI (pos, mode); +} + +wxFileOffset wxWrapperInputStream::OnSysTell() const +{ + wxCHECK_MSG(m_parent_i_stream, false, "Stream not valid"); + + wxON_BLOCK_EXIT_THIS0(wxWrapperInputStream::SynchronizeLastError); + return m_parent_i_stream->TellI(); +} + // ---------------------------------------------------------------------------- // Some IOManip function // ----------------------------------------------------------------------------