X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dee1a63ff52bfe4da396187f8438aa1a29796737..4e916e61ea24c165fb55e78172f1093bf7481b48:/src/common/stream.cpp diff --git a/src/common/stream.cpp b/src/common/stream.cpp index 07984617d2..657e6675d4 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -22,20 +22,20 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop + #pragma hdrstop #endif +#if wxUSE_STREAMS + +#include "wx/stream.h" + #ifndef WX_PRECOMP - #include "wx/defs.h" + #include "wx/log.h" #endif -#if wxUSE_STREAMS - #include -#include "wx/stream.h" #include "wx/datstrm.h" #include "wx/textfile.h" -#include "wx/log.h" // ---------------------------------------------------------------------------- // constants @@ -63,7 +63,6 @@ void wxStreamBuffer::InitBuffer() m_buffer_start = m_buffer_end = m_buffer_pos = NULL; - m_buffer_size = 0; // if we are going to allocate the buffer, we should free it later as well m_destroybuf = true; @@ -76,24 +75,24 @@ void wxStreamBuffer::Init() m_fixed = true; } -wxStreamBuffer::wxStreamBuffer(BufMode mode) +void wxStreamBuffer::InitWithStream(wxStreamBase& stream, BufMode mode) { Init(); - m_stream = NULL; + m_stream = &stream; m_mode = mode; - m_flushable = false; + m_flushable = true; } -wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode) +wxStreamBuffer::wxStreamBuffer(BufMode mode) { Init(); - m_stream = &stream; + m_stream = NULL; m_mode = mode; - m_flushable = true; + m_flushable = false; } wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer) @@ -106,7 +105,6 @@ wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer) m_buffer_start = buffer.m_buffer_start; m_buffer_end = buffer.m_buffer_end; m_buffer_pos = buffer.m_buffer_pos; - m_buffer_size = buffer.m_buffer_size; m_fixed = buffer.m_fixed; m_flushable = buffer.m_flushable; m_stream = buffer.m_stream; @@ -117,7 +115,10 @@ wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer) void wxStreamBuffer::FreeBuffer() { if ( m_destroybuf ) + { free(m_buffer_start); + m_buffer_start = NULL; + } } wxStreamBuffer::~wxStreamBuffer() @@ -153,8 +154,6 @@ void wxStreamBuffer::SetBufferIO(void *start, m_buffer_start = (char *)start; m_buffer_end = m_buffer_start + len; - m_buffer_size = len; - // if we own it, we free it m_destroybuf = takeOwnership; @@ -163,15 +162,15 @@ void wxStreamBuffer::SetBufferIO(void *start, void wxStreamBuffer::SetBufferIO(size_t bufsize) { - // start by freeing the old buffer - FreeBuffer(); - if ( bufsize ) { + // this will free the old buffer and allocate the new one SetBufferIO(malloc(bufsize), bufsize, true /* take ownership */); } else // no buffer size => no buffer { + // still free the old one + FreeBuffer(); InitBuffer(); } } @@ -189,6 +188,27 @@ void wxStreamBuffer::ResetBuffer() : m_buffer_start; } +void wxStreamBuffer::Truncate() +{ + size_t new_size = m_buffer_pos - m_buffer_start; + if ( m_buffer_pos == m_buffer_end ) + return; + + if ( !new_size ) + { + FreeBuffer(); + InitBuffer(); + return; + } + + char *new_start = (char *)realloc(m_buffer_start, new_size); + wxCHECK_RET( new_size, _T("shrinking buffer shouldn't fail") ); + + m_buffer_start = new_start; + m_buffer_end = m_buffer_start + new_size; + m_buffer_pos = m_buffer_end; +} + // fill the buffer with as much data as possible (only for read buffers) bool wxStreamBuffer::FillBuffer() { @@ -198,7 +218,7 @@ bool wxStreamBuffer::FillBuffer() if ( !inStream ) return false; - size_t count = inStream->OnSysRead(m_buffer_start, m_buffer_size); + size_t count = inStream->OnSysRead(GetBufferStart(), GetBufferSize()); if ( !count ) return false; @@ -268,24 +288,26 @@ void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size) else // !m_fixed { // realloc the buffer to have enough space for the data - size_t delta = m_buffer_pos - m_buffer_start; - - char *startOld = m_buffer_start; - m_buffer_size += size; - m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size); - if ( !m_buffer_start ) + if ( m_buffer_pos + size > m_buffer_end ) { - // don't leak memory if realloc() failed - m_buffer_start = startOld; - m_buffer_size -= size; + size_t delta = m_buffer_pos - m_buffer_start; + size_t new_size = delta + size; - // what else can we do? - return; - } + char *startOld = m_buffer_start; + m_buffer_start = (char *)realloc(m_buffer_start, new_size); + if ( !m_buffer_start ) + { + // don't leak memory if realloc() failed + m_buffer_start = startOld; - // adjust the pointers invalidated by realloc() - m_buffer_pos = m_buffer_start + delta; - m_buffer_end = m_buffer_start + m_buffer_size; + // what else can we do? + return; + } + + // adjust the pointers invalidated by realloc() + m_buffer_pos = m_buffer_start + delta; + m_buffer_end = m_buffer_start + new_size; + } // else: the buffer is big enough } } @@ -368,6 +390,11 @@ char wxStreamBuffer::GetChar() size_t wxStreamBuffer::Read(void *buffer, size_t size) { + wxASSERT_MSG( buffer, _T("Warning: Null pointer is about to be used") ); + + /* Clear buffer first */ + memset(buffer, 0x00, size); + // lasterror is reset before all new IO calls if ( m_stream ) m_stream->Reset(); @@ -444,6 +471,8 @@ 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") ); + if (m_stream) { // lasterror is reset before all new IO calls @@ -647,6 +676,8 @@ wxFileOffset wxStreamBuffer::Tell() const // wxStreamBase // ---------------------------------------------------------------------------- +IMPLEMENT_ABSTRACT_CLASS(wxStreamBase, wxObject) + wxStreamBase::wxStreamBase() { m_lasterror = wxSTREAM_NO_ERROR; @@ -660,11 +691,11 @@ wxStreamBase::~wxStreamBase() size_t wxStreamBase::GetSize() const { wxFileOffset length = GetLength(); - if ( length == wxInvalidOffset ) + if ( length == (wxFileOffset)wxInvalidOffset ) return 0; const size_t len = wx_truncate_cast(size_t, length); - wxASSERT_MSG( len == length, _T("large files not supported") ); + wxASSERT_MSG( len == length + size_t(0), _T("large files not supported") ); return len; } @@ -683,6 +714,8 @@ wxFileOffset wxStreamBase::OnSysTell() const // wxInputStream // ---------------------------------------------------------------------------- +IMPLEMENT_ABSTRACT_CLASS(wxInputStream, wxStreamBase) + wxInputStream::wxInputStream() { m_wback = NULL; @@ -738,6 +771,11 @@ 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") ); + + /* Clear buffer first */ + memset(buf, 0x00, size); + if (!m_wback) return 0; @@ -769,6 +807,8 @@ 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()") ); + if ( m_lasterror != wxSTREAM_NO_ERROR && m_lasterror != wxSTREAM_EOF ) { // can't operate on this stream until the error is cleared @@ -792,15 +832,17 @@ bool wxInputStream::Ungetch(char c) return Ungetch(&c, sizeof(c)) != 0; } -char wxInputStream::GetC() +int wxInputStream::GetC() { - char c; + unsigned char c; Read(&c, sizeof(c)); - return c; + return LastRead() ? c : wxEOF; } wxInputStream& wxInputStream::Read(void *buf, size_t size) { + wxASSERT_MSG( buf, _T("Warning: Null pointer is about to be read") ); + char *p = (char *)buf; m_lastcount = 0; @@ -850,6 +892,7 @@ char wxInputStream::Peek() wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) { + size_t lastcount = 0; char buf[BUF_TEMP_SIZE]; for ( ;; ) @@ -860,8 +903,12 @@ wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) if ( stream_out.Write(buf, bytes_read).LastWrite() != bytes_read ) break; + + lastcount += bytes_read; } + m_lastcount = lastcount; + return *this; } @@ -914,6 +961,8 @@ wxFileOffset wxInputStream::TellI() const // wxOutputStream // ---------------------------------------------------------------------------- +IMPLEMENT_ABSTRACT_CLASS(wxOutputStream, wxStreamBase) + wxOutputStream::wxOutputStream() { } @@ -964,6 +1013,8 @@ void wxOutputStream::Sync() // wxCountingOutputStream // ---------------------------------------------------------------------------- +IMPLEMENT_DYNAMIC_CLASS(wxCountingOutputStream, wxOutputStream) + wxCountingOutputStream::wxCountingOutputStream () { m_currentPos = 0; @@ -1026,59 +1077,162 @@ wxFileOffset wxCountingOutputStream::OnSysTell() const // wxFilterInputStream // ---------------------------------------------------------------------------- +IMPLEMENT_ABSTRACT_CLASS(wxFilterInputStream, wxInputStream) + wxFilterInputStream::wxFilterInputStream() + : m_parent_i_stream(NULL), + m_owns(false) { - m_parent_i_stream = NULL; } wxFilterInputStream::wxFilterInputStream(wxInputStream& stream) + : m_parent_i_stream(&stream), + m_owns(false) +{ +} + +wxFilterInputStream::wxFilterInputStream(wxInputStream *stream) + : m_parent_i_stream(stream), + m_owns(true) { - m_parent_i_stream = &stream; } wxFilterInputStream::~wxFilterInputStream() { + if (m_owns) + delete m_parent_i_stream; } // ---------------------------------------------------------------------------- // wxFilterOutputStream // ---------------------------------------------------------------------------- +IMPLEMENT_ABSTRACT_CLASS(wxFilterOutputStream, wxOutputStream) + wxFilterOutputStream::wxFilterOutputStream() + : m_parent_o_stream(NULL), + m_owns(false) { - m_parent_o_stream = NULL; } wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream) + : m_parent_o_stream(&stream), + m_owns(false) +{ +} + +wxFilterOutputStream::wxFilterOutputStream(wxOutputStream *stream) + : m_parent_o_stream(stream), + m_owns(true) +{ +} + +bool wxFilterOutputStream::Close() { - m_parent_o_stream = &stream; + if (m_parent_o_stream && m_owns) + return m_parent_o_stream->Close(); + else + return true; } wxFilterOutputStream::~wxFilterOutputStream() { + if (m_owns) + delete m_parent_o_stream; } // ---------------------------------------------------------------------------- -// wxBufferedInputStream +// wxFilterClassFactoryBase // ---------------------------------------------------------------------------- -wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s, - wxStreamBuffer *buffer) - : wxFilterInputStream(s) +IMPLEMENT_ABSTRACT_CLASS(wxFilterClassFactoryBase, wxObject) + +wxString wxFilterClassFactoryBase::PopExtension(const wxString& location) const { - if ( buffer ) + return location.substr(0, FindExtension(location)); +} + +wxString::size_type wxFilterClassFactoryBase::FindExtension( + const wxString& location) const +{ + for (const wxChar *const *p = GetProtocols(wxSTREAM_FILEEXT); *p; p++) { - // use the buffer provided by the user - m_i_streambuf = buffer; + if ( location.EndsWith(*p) ) + return location.length() - wxStrlen(*p); } - else // create a default buffer + + return wxString::npos; +} + +bool wxFilterClassFactoryBase::CanHandle(const wxString& protocol, + wxStreamProtocolType type) const +{ + if (type == wxSTREAM_FILEEXT) + return FindExtension(protocol) != wxString::npos; + else + for (const wxChar *const *p = GetProtocols(type); *p; p++) + if (protocol == *p) + return true; + + return false; +} + +// ---------------------------------------------------------------------------- +// wxFilterClassFactory +// ---------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxFilterClassFactory, wxFilterClassFactoryBase) + +wxFilterClassFactory *wxFilterClassFactory::sm_first = NULL; + +void wxFilterClassFactory::Remove() +{ + if (m_next != this) { - m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read); + wxFilterClassFactory **pp = &sm_first; + + while (*pp != this) + pp = &(*pp)->m_next; + + *pp = m_next; - m_i_streambuf->SetBufferIO(1024); + m_next = this; } } +// ---------------------------------------------------------------------------- +// wxBufferedInputStream +// ---------------------------------------------------------------------------- + +namespace +{ + +// helper function used for initializing the buffer used by +// wxBufferedInput/OutputStream: it simply returns the provided buffer if it's +// not NULL or creates a buffer of the given size otherwise +template +wxStreamBuffer * +CreateBufferIfNeeded(T& stream, wxStreamBuffer *buffer, size_t bufsize = 1024) +{ + return buffer ? buffer : new wxStreamBuffer(stream, bufsize); +} + +} // anonymous namespace + +wxBufferedInputStream::wxBufferedInputStream(wxInputStream& stream, + wxStreamBuffer *buffer) + : wxFilterInputStream(stream) +{ + m_i_streambuf = CreateBufferIfNeeded(*this, buffer); +} + +wxBufferedInputStream::wxBufferedInputStream(wxInputStream& stream, + size_t bufsize) + : wxFilterInputStream(stream) +{ + m_i_streambuf = CreateBufferIfNeeded(*this, NULL, bufsize); +} + wxBufferedInputStream::~wxBufferedInputStream() { m_parent_i_stream->SeekI(-(wxFileOffset)m_i_streambuf->GetBytesLeft(), @@ -1106,12 +1260,15 @@ wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size) size -= m_lastcount; buf = (char *)buf + m_lastcount; - // the call to wxStreamBuffer::Read() below will reset our m_lastcount, - // so save it + // the call to wxStreamBuffer::Read() below may reset our m_lastcount + // (but it also may not do it if the buffer is associated to another + // existing stream and wasn't created by us), so save it size_t countOld = m_lastcount; - m_i_streambuf->Read(buf, size); + // the new count of the bytes read is the count of bytes read this time + m_lastcount = m_i_streambuf->Read(buf, size); + // plus those we had read before m_lastcount += countOld; } @@ -1175,20 +1332,18 @@ void wxBufferedInputStream::SetInputStreamBuffer(wxStreamBuffer *buffer) // wxBufferedOutputStream // ---------------------------------------------------------------------------- -wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s, +wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& stream, wxStreamBuffer *buffer) - : wxFilterOutputStream(s) + : wxFilterOutputStream(stream) { - if ( buffer ) - { - m_o_streambuf = buffer; - } - else // create a default one - { - m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write); + m_o_streambuf = CreateBufferIfNeeded(*this, buffer); +} - m_o_streambuf->SetBufferIO(1024); - } +wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& stream, + size_t bufsize) + : wxFilterOutputStream(stream) +{ + m_o_streambuf = CreateBufferIfNeeded(*this, NULL, bufsize); } wxBufferedOutputStream::~wxBufferedOutputStream()