X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/49e399d8c0f2683a885bfec77e43cfde3b2249f4..59c962bf54667cab735353b2ec3b7a2438464f22:/src/common/stream.cpp diff --git a/src/common/stream.cpp b/src/common/stream.cpp index 872d03c52c..c6ffc3895b 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -17,8 +17,9 @@ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- + #ifdef __GNUG__ -#pragma implementation "stream.h" + #pragma implementation "stream.h" #endif // For compilers that support precompilation, includes "wx.h". @@ -37,7 +38,7 @@ #include #include "wx/stream.h" #include "wx/datstrm.h" -#include "wx/objstrm.h" +#include "wx/textfile.h" // ---------------------------------------------------------------------------- // constants @@ -67,8 +68,8 @@ void wxStreamBuffer::InitBuffer() m_buffer_pos = NULL; m_buffer_size = 0; - // there is nothing to destroy anyhow - m_destroybuf = FALSE; + // if we are going to allocate the buffer, we should free it later as well + m_destroybuf = TRUE; } void wxStreamBuffer::Init() @@ -80,6 +81,8 @@ void wxStreamBuffer::Init() wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode) { + Init(); + m_stream = &stream; m_mode = mode; @@ -89,7 +92,16 @@ wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode) wxStreamBuffer::wxStreamBuffer(BufMode mode) { - m_stream = new wxStreamBase; + Init(); + + wxASSERT_MSG(mode != read_write, wxT("you have to use the other ctor for read_write mode") ); + if ( mode == read ) + m_stream = new wxInputStream; + else if ( mode == write) + m_stream = new wxOutputStream; + else + m_stream = NULL; + m_mode = mode; m_flushable = FALSE; @@ -129,20 +141,38 @@ wxStreamBuffer::~wxStreamBuffer() delete m_stream; } +wxInputStream *wxStreamBuffer::GetInputStream() const +{ + return m_mode == write ? NULL : (wxInputStream *)m_stream; +} + +wxOutputStream *wxStreamBuffer::GetOutputStream() const +{ + return m_mode == read ? NULL : (wxOutputStream *)m_stream; +} + void wxStreamBuffer::SetBufferIO(void *buffer_start, void *buffer_end, bool takeOwnership) +{ + SetBufferIO(buffer_start, (char *)buffer_end - (char *)buffer_start, + takeOwnership); +} + +void wxStreamBuffer::SetBufferIO(void *start, + size_t len, + bool takeOwnership) { // start by freeing the old buffer FreeBuffer(); - m_buffer_start = (char *)buffer_start; - m_buffer_end = (char *)buffer_end; + m_buffer_start = (char *)start; + m_buffer_end = m_buffer_start + len; - m_buffer_size = m_buffer_end - m_buffer_start; + m_buffer_size = len; // if we own it, we free it - m_destroybuf = !takeOwnership; + m_destroybuf = takeOwnership; ResetBuffer(); } @@ -154,8 +184,7 @@ void wxStreamBuffer::SetBufferIO(size_t bufsize) if ( bufsize ) { - char *buf = (char *)malloc(bufsize); - SetBufferIO(buf, buf + bufsize, TRUE /* take ownership */); + SetBufferIO(malloc(bufsize), bufsize, TRUE /* take ownership */); } else // no buffer size => no buffer { @@ -178,9 +207,11 @@ void wxStreamBuffer::ResetBuffer() // fill the buffer with as much data as possible (only for read buffers) bool wxStreamBuffer::FillBuffer() { - wxCHECK_MSG( m_stream, FALSE, _T("should have a stream in wxStreamBuffer") ); + wxInputStream *inStream = GetInputStream(); + + wxCHECK_MSG( inStream, FALSE, _T("should have a stream in wxStreamBuffer") ); - size_t count = m_stream->OnSysRead(m_buffer_start, m_buffer_size); + size_t count = inStream->OnSysRead(m_buffer_start, m_buffer_size); if ( !count ) return FALSE; @@ -199,10 +230,12 @@ bool wxStreamBuffer::FlushBuffer() if ( m_buffer_pos == m_buffer_start ) return FALSE; - wxCHECK_MSG( m_stream, FALSE, _T("should have a stream in wxStreamBuffer") ); + wxOutputStream *outStream = GetOutputStream(); + + wxCHECK_MSG( outStream, FALSE, _T("should have a stream in wxStreamBuffer") ); size_t current = m_buffer_pos - m_buffer_start; - size_t count = m_stream->OnSysWrite(m_buffer_start, current); + size_t count = outStream->OnSysWrite(m_buffer_start, current); if ( count != current ) return FALSE; @@ -274,12 +307,14 @@ void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size) void wxStreamBuffer::PutChar(char c) { - wxCHECK_RET( m_stream, _T("should have a stream in wxStreamBuffer") ); + wxOutputStream *outStream = GetOutputStream(); + + wxCHECK_RET( outStream, _T("should have a stream in wxStreamBuffer") ); // if we don't have buffer at all, just forward this call to the stream, if ( !HasBuffer() ) { - m_stream->OnSysWrite(&c, 1); + outStream->OnSysWrite(&c, 1); } else { @@ -317,12 +352,14 @@ char wxStreamBuffer::Peek() char wxStreamBuffer::GetChar() { - wxCHECK_MSG( m_stream, 0, _T("should have a stream in wxStreamBuffer") ); + wxInputStream *inStream = GetInputStream(); + + wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") ); char c; if ( !HasBuffer() ) { - m_stream->OnSysRead(&c, 1); + inStream->OnSysRead(&c, 1); } else { @@ -343,16 +380,16 @@ char wxStreamBuffer::GetChar() size_t wxStreamBuffer::Read(void *buffer, size_t size) { - wxCHECK_MSG( m_stream, 0, _T("should have a stream in wxStreamBuffer") ); + wxInputStream *inStream = GetInputStream(); - wxCHECK_MSG( m_mode != write, 0, _T("can't read from this buffer") ); + wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") ); // lasterror is reset before all new IO calls m_stream->m_lasterror = wxStream_NOERROR; if ( !HasBuffer() ) { - m_stream->m_lastcount = m_stream->OnSysRead(buffer, size); + m_stream->m_lastcount = inStream->OnSysRead(buffer, size); } else // we have a buffer, use it { @@ -414,8 +451,9 @@ size_t wxStreamBuffer::Read(wxStreamBuffer *dbuf) size_t wxStreamBuffer::Write(const void *buffer, size_t size) { - wxCHECK_MSG( m_stream, 0, _T("should have a stream in wxStreamBuffer") ); - wxCHECK_MSG( m_mode != read, 0, _T("can't write to this buffer") ); + wxOutputStream *outStream = GetOutputStream(); + + wxCHECK_MSG( outStream, 0, _T("should have a stream in wxStreamBuffer") ); // lasterror is reset before all new IO calls m_stream->m_lasterror = wxStream_NOERROR; @@ -423,7 +461,7 @@ size_t wxStreamBuffer::Write(const void *buffer, size_t size) if ( !HasBuffer() && m_fixed ) { // no buffer, just forward the call to the stream - m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size); + m_stream->m_lastcount = outStream->OnSysWrite(buffer, size); } else // we [may] have a buffer, use it { @@ -600,16 +638,6 @@ wxStreamBase::~wxStreamBase() { } -size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer), size_t WXUNUSED(size)) -{ - return 0; -} - -size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer), size_t WXUNUSED(bufsize)) -{ - return 0; -} - off_t wxStreamBase::OnSysSeek(off_t WXUNUSED(seek), wxSeekMode WXUNUSED(mode)) { return wxInvalidOffset; @@ -636,13 +664,24 @@ wxInputStream::~wxInputStream() free(m_wback); } +size_t wxInputStream::OnSysRead(void * WXUNUSED(buffer), + size_t WXUNUSED(bufsize)) +{ + return 0; +} + bool wxInputStream::Eof() const { wxInputStream *self = wxConstCast(this, wxInputStream); char c; self->Read(&c, 1); - if ( GetLastError() == wxSTREAM_EOF ) + + // some streams can know that they're at EOF before actually trying to + // read beyond the end of stream (e.g. files) while others have no way of + // knowing it, so to provide the same behaviour in all cases we only + // return TRUE from here if the character really couldn't be read + if ( !self->LastRead() && GetLastError() == wxSTREAM_EOF ) { return TRUE; } @@ -680,25 +719,32 @@ char *wxInputStream::AllocSpaceWBack(size_t needed_size) size_t wxInputStream::GetWBack(void *buf, size_t bsize) { - size_t toget = m_wbacksize-m_wbackcur; - if (!m_wback) return 0; - if (bsize < toget) - toget = bsize; + // how many bytes do we have in the buffer? + size_t toget = m_wbacksize - m_wbackcur; - memcpy(buf, (m_wback+m_wbackcur), toget); + if ( bsize < toget ) + { + // we won't read everything + toget = bsize; + } + + // copy the data from the cache + memcpy(buf, m_wback + m_wbackcur, toget); m_wbackcur += toget; - if (m_wbackcur == m_wbacksize) + if ( m_wbackcur == m_wbacksize ) { + // TODO: should we really free it here all the time? maybe keep it? free(m_wback); m_wback = NULL; m_wbacksize = 0; m_wbackcur = 0; } + // return the number of bytes copied return toget; } @@ -810,19 +856,6 @@ off_t wxInputStream::TellI() const return pos; } -// -------------------- -// Overloaded operators -// -------------------- - -#if wxUSE_SERIAL -wxInputStream& wxInputStream::operator>>(wxObject *& obj) -{ - wxObjectInputStream obj_s(*this); - obj = obj_s.LoadObject(); - return *this; -} -#endif // wxUSE_SERIAL - // ---------------------------------------------------------------------------- // wxOutputStream @@ -836,6 +869,12 @@ wxOutputStream::~wxOutputStream() { } +size_t wxOutputStream::OnSysWrite(const void * WXUNUSED(buffer), + size_t WXUNUSED(bufsize)) +{ + return 0; +} + void wxOutputStream::PutC(char c) { Write(&c, 1); @@ -867,14 +906,6 @@ void wxOutputStream::Sync() { } -#if wxUSE_SERIAL -wxOutputStream& wxOutputStream::operator<<(wxObject& obj) -{ - wxObjectOutputStream obj_s(*this); - obj_s.SaveObject(obj); - return *this; -} -#endif // wxUSE_SERIAL // ---------------------------------------------------------------------------- // wxCountingOutputStream @@ -938,6 +969,7 @@ off_t wxCountingOutputStream::OnSysTell() const wxFilterInputStream::wxFilterInputStream() { + m_parent_i_stream = NULL; } wxFilterInputStream::wxFilterInputStream(wxInputStream& stream) @@ -955,6 +987,7 @@ wxFilterInputStream::~wxFilterInputStream() wxFilterOutputStream::wxFilterOutputStream() { + m_parent_o_stream = NULL; } wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream) @@ -970,17 +1003,27 @@ wxFilterOutputStream::~wxFilterOutputStream() // wxBufferedInputStream // ---------------------------------------------------------------------------- -wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s) +wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s, + wxStreamBuffer *buffer) : wxFilterInputStream(s) { - m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read); + if ( buffer ) + { + // use the buffer provided by the user + m_i_streambuf = buffer; + } + else // create a default buffer + { + m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read); - m_i_streambuf->SetBufferIO(1024); + m_i_streambuf->SetBufferIO(1024); + } } wxBufferedInputStream::~wxBufferedInputStream() { - m_parent_i_stream->SeekI(-m_i_streambuf->GetBytesLeft(), wxFromCurrent); + m_parent_i_stream->SeekI(-(off_t)m_i_streambuf->GetBytesLeft(), + wxFromCurrent); delete m_i_streambuf; } @@ -992,19 +1035,26 @@ char wxBufferedInputStream::Peek() wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size) { - size_t retsize; + // reset the error flag + m_lasterror = wxStream_NOERROR; - retsize = GetWBack(buf, size); - m_lastcount = retsize; - if (retsize == size) + // first read from the already cached data + m_lastcount = GetWBack(buf, size); + + // do we have to read anything more? + if ( m_lastcount < size ) { - m_lasterror = wxStream_NOERROR; - return *this; - } - size -= retsize; - buf = (char *)buf + retsize; + size -= m_lastcount; + buf = (char *)buf + m_lastcount; - m_i_streambuf->Read(buf, size); + // the call to wxStreamBuffer::Read() below will reset our m_lastcount, + // so save it + size_t countOld = m_lastcount; + + m_i_streambuf->Read(buf, size); + + m_lastcount += countOld; + } return *this; } @@ -1034,15 +1084,32 @@ off_t wxBufferedInputStream::OnSysTell() const return m_parent_i_stream->TellI(); } +void wxBufferedInputStream::SetInputStreamBuffer(wxStreamBuffer *buffer) +{ + wxCHECK_RET( buffer, _T("wxBufferedInputStream needs buffer") ); + + delete m_i_streambuf; + m_i_streambuf = buffer; +} + // ---------------------------------------------------------------------------- // wxBufferedOutputStream // ---------------------------------------------------------------------------- -wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s) +wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s, + wxStreamBuffer *buffer) : wxFilterOutputStream(s) { - m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write); - m_o_streambuf->SetBufferIO(1024); + if ( buffer ) + { + m_o_streambuf = buffer; + } + else // create a default one + { + m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write); + + m_o_streambuf->SetBufferIO(1024); + } } wxBufferedOutputStream::~wxBufferedOutputStream() @@ -1095,21 +1162,23 @@ size_t wxBufferedOutputStream::GetSize() const return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition(); } +void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer *buffer) +{ + wxCHECK_RET( buffer, _T("wxBufferedOutputStream needs buffer") ); + + delete m_o_streambuf; + m_o_streambuf = buffer; +} + // ---------------------------------------------------------------------------- // Some IOManip function // ---------------------------------------------------------------------------- wxOutputStream& wxEndL(wxOutputStream& stream) { -#ifdef __MSW__ - return stream.Write("\r\n", 2); -#else -#ifdef __WXMAC__ - return stream.Write("\r", 1); -#else - return stream.Write("\n", 1); -#endif -#endif + static const wxChar *eol = wxTextFile::GetEOL(); + + return stream.Write(eol, wxStrlen(eol)); } #endif