X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/75ed1d15d0d866cac78f7c0da176db8dd5288bc8..89c684ef8280e2d91096da2d96ba36e24a1fb917:/src/common/stream.cpp diff --git a/src/common/stream.cpp b/src/common/stream.cpp index ecedf6b106..728d50b5cf 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -24,31 +24,70 @@ #pragma hdrstop #endif +#define BUF_TEMP_SIZE 10000 + // ---------------------------------------------------------------------------- // wxStreamBuffer // ---------------------------------------------------------------------------- +#define CHECK_ERROR(err) \ + if (m_stream->m_lasterror == wxStream_NOERROR) \ + m_stream->m_lasterror = err + wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode) : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL), - m_buffer_size(0), m_stream(&stream), m_mode(mode) + m_buffer_size(0), m_wback(NULL), m_wbacksize(0), m_wbackcur(0), + m_fixed(TRUE), m_flushable(TRUE), m_stream(&stream), + m_mode(mode), m_destroybuf(FALSE), m_destroystream(FALSE) +{ +} + +wxStreamBuffer::wxStreamBuffer(BufMode mode) + : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL), + m_buffer_size(0), m_wback(NULL), m_wbacksize(0), m_wbackcur(0), + m_fixed(TRUE), m_flushable(FALSE), m_stream(NULL), + m_mode(mode), m_destroybuf(FALSE), m_destroystream(TRUE) +{ + m_stream = new wxStreamBase(); +} + +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; + m_mode = buffer.m_mode; + m_destroybuf = FALSE; + m_destroystream = FALSE; + m_wback = NULL; + m_wbacksize = 0; + m_wbackcur = 0; } wxStreamBuffer::~wxStreamBuffer() { - wxDELETEA(m_buffer_start); + if (m_wback) + free(m_wback); + if (m_destroybuf) + wxDELETEA(m_buffer_start); + if (m_destroystream) + delete m_stream; } -bool wxStreamBuffer::WriteBack(const char *buf, size_t bufsize) +size_t wxStreamBuffer::WriteBack(const char *buf, size_t bufsize) { char *ptrback; ptrback = AllocSpaceWBack(bufsize); if (!ptrback) - return FALSE; + return 0; memcpy(ptrback, buf, bufsize); - return TRUE; + return bufsize; } bool wxStreamBuffer::WriteBack(char c) @@ -65,10 +104,13 @@ bool wxStreamBuffer::WriteBack(char c) void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end) { + if (m_destroybuf) + wxDELETEA(m_buffer_start); m_buffer_start = buffer_start; m_buffer_end = buffer_end; m_buffer_size = m_buffer_end-m_buffer_start; + m_destroybuf = FALSE; ResetBuffer(); } @@ -76,7 +118,8 @@ void wxStreamBuffer::SetBufferIO(size_t bufsize) { char *b_start; - wxDELETE(m_buffer_start); + if (m_destroybuf) + wxDELETEA(m_buffer_start); if (!bufsize) { m_buffer_start = NULL; @@ -87,12 +130,13 @@ void wxStreamBuffer::SetBufferIO(size_t bufsize) } b_start = new char[bufsize]; - SetBufferIO(b_start, b_start + bufsize); + m_destroybuf = TRUE; } void wxStreamBuffer::ResetBuffer() { + m_stream->m_lasterror = wxStream_NOERROR; if (m_mode == read) m_buffer_pos = m_buffer_end; else @@ -112,7 +156,9 @@ char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size) if (!temp_b) return NULL; - return (char *)((size_t)m_wback+(m_wbacksize-needed_size)); + m_wback = temp_b; + + return (char *)(m_wback+(m_wbacksize-needed_size)); } size_t wxStreamBuffer::GetWBack(char *buf, size_t bsize) @@ -152,7 +198,7 @@ bool wxStreamBuffer::FlushBuffer() { size_t count, current; - if (m_buffer_pos == m_buffer_start) + if (m_buffer_pos == m_buffer_start || !m_flushable) return FALSE; current = m_buffer_pos-m_buffer_start; @@ -182,6 +228,7 @@ void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size) if (s_toput < size && !m_fixed) { m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size+size); // I round a bit + m_buffer_size += size; m_buffer_end = m_buffer_start+m_buffer_size; s_toput = size; } @@ -191,7 +238,46 @@ void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size) m_buffer_pos += s_toput; } -void wxStreamBuffer::Read(void *buffer, size_t size) +void wxStreamBuffer::PutChar(char c) +{ + wxASSERT(m_stream != NULL); + + if (!m_buffer_size) { + m_stream->OnSysWrite(&c, 1); + return; + } + + if (!GetDataLeft() && !FlushBuffer()) { + CHECK_ERROR(wxStream_READ_ERR); + return; + } + + PutToBuffer(&c, 1); + m_stream->m_lastcount = 1; +} + +char wxStreamBuffer::GetChar() +{ + char c; + + wxASSERT(m_stream != NULL); + + if (!m_buffer_size) { + m_stream->OnSysRead(&c, 1); + return c; + } + + if (!GetDataLeft()) { + CHECK_ERROR(wxStream_READ_ERR); + return 0; + } + + GetFromBuffer(&c, 1); + m_stream->m_lastcount = 1; + return c; +} + +size_t wxStreamBuffer::Read(void *buffer, size_t size) { wxASSERT(m_stream != NULL); @@ -199,17 +285,16 @@ void wxStreamBuffer::Read(void *buffer, size_t size) // Buffering disabled // ------------------ + m_stream->m_lasterror = wxStream_NOERROR; m_stream->m_lastcount = GetWBack((char *)buffer, size); size -= m_stream->m_lastcount; if (size == 0) - return; + return m_stream->m_lastcount; buffer = (void *)((char *)buffer+m_stream->m_lastcount); - if (!m_buffer_size) { - m_stream->m_lastcount += m_stream->OnSysRead(buffer, size); - return; - } + if (!m_buffer_size) + return (m_stream->m_lastcount += m_stream->OnSysRead(buffer, size)); // ----------------- // Buffering enabled @@ -220,15 +305,15 @@ void wxStreamBuffer::Read(void *buffer, size_t size) buf_left = GetDataLeft(); // First case: the requested buffer is larger than the stream buffer, - // we split + // we split it. if (size > buf_left) { GetFromBuffer(buffer, buf_left); size -= buf_left; buffer = (char *)buffer + buf_left; // ANSI C++ violation. if (!FillBuffer()) { - m_stream->m_lastcount = orig_size-size; - return; + CHECK_ERROR(wxStream_READ_ERR); + return (m_stream->m_lastcount = orig_size-size); } } else { @@ -237,10 +322,23 @@ void wxStreamBuffer::Read(void *buffer, size_t size) break; } } - m_stream->m_lastcount += orig_size; + return (m_stream->m_lastcount += orig_size); +} + +size_t wxStreamBuffer::Read(wxStreamBuffer *s_buf) +{ + char buf[BUF_TEMP_SIZE]; + size_t s = 0, bytes_read = BUF_TEMP_SIZE; + + while (bytes_read == BUF_TEMP_SIZE) { + bytes_read = Read(buf, bytes_read); + bytes_read = s_buf->Write(buf, bytes_read); + s += bytes_read; + } + return s; } -void wxStreamBuffer::Write(const void *buffer, size_t size) +size_t wxStreamBuffer::Write(const void *buffer, size_t size) { wxASSERT(m_stream != NULL); @@ -248,10 +346,9 @@ void wxStreamBuffer::Write(const void *buffer, size_t size) // Buffering disabled // ------------------ - if (!m_buffer_size) { - m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size); - return; - } + m_stream->m_lasterror = wxStream_NOERROR; + if (!m_buffer_size) + return (m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size)); // ------------------ // Buffering enabled @@ -270,9 +367,10 @@ void wxStreamBuffer::Write(const void *buffer, size_t size) buffer = (char *)buffer + buf_left; // ANSI C++ violation. if (!FlushBuffer()) { - m_stream->m_lastcount = orig_size-size; - return; + CHECK_ERROR(wxStream_WRITE_ERR); + return (m_stream->m_lastcount = orig_size-size); } + m_buffer_pos = m_buffer_start; } else { @@ -282,7 +380,22 @@ void wxStreamBuffer::Write(const void *buffer, size_t size) break; } } - m_stream->m_lastcount = orig_size; + return (m_stream->m_lastcount = orig_size); +} + +size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf) +{ + char buf[BUF_TEMP_SIZE]; + size_t s = 0, bytes_count = BUF_TEMP_SIZE, b_count2; + + while (bytes_count == BUF_TEMP_SIZE) { + b_count2 = sbuf->Read(buf, bytes_count); + bytes_count = Write(buf, b_count2); + if (b_count2 > bytes_count) + sbuf->WriteBack(buf+bytes_count, b_count2-bytes_count); + s += bytes_count; + } + return s; } off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode) @@ -291,6 +404,14 @@ off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode) last_access = GetLastAccess(); + if (!m_flushable) { + diff = pos + GetIntPosition(); + if (diff < 0 || diff > last_access) + return wxInvalidOffset; + SetIntPosition(diff); + return diff; + } + switch (mode) { case wxFromStart: { // We'll try to compute an internal position later ... @@ -323,15 +444,19 @@ off_t wxStreamBuffer::Tell() const { off_t pos; - pos = m_stream->OnSysTell(); - if (pos == wxInvalidOffset) - return wxInvalidOffset; - - return pos - GetLastAccess() + GetIntPosition(); + if (m_flushable) { + pos = m_stream->OnSysTell(); + if (pos == wxInvalidOffset) + return wxInvalidOffset; + return pos - GetLastAccess() + GetIntPosition(); + } else + return GetIntPosition(); } -size_t wxStreamBuffer::GetDataLeft() const +size_t wxStreamBuffer::GetDataLeft() { + if (m_buffer_end == m_buffer_pos && m_flushable) + FillBuffer(); return m_buffer_end-m_buffer_pos; } @@ -349,22 +474,22 @@ wxStreamBase::~wxStreamBase() { } -size_t wxStreamBase::OnSysRead(void *buffer, size_t size) +size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer), size_t WXUNUSED(size)) { return 0; } -size_t wxStreamBase::OnSysWrite(const void *buffer, size_t bufsize) +size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer), size_t WXUNUSED(bufsize)) { return 0; } -off_t wxStreamBase::OnSysSeek(off_t seek, wxSeekMode mode) +off_t wxStreamBase::OnSysSeek(off_t WXUNUSED(seek), wxSeekMode WXUNUSED(mode)) { return wxInvalidOffset; } -off_t wxStreamBase::OnSysTell() +off_t wxStreamBase::OnSysTell() const { return wxInvalidOffset; } @@ -409,23 +534,20 @@ wxInputStream& wxInputStream::Read(void *buffer, size_t size) char wxInputStream::Peek() { - if (!m_i_streambuf->GetDataLeft()) - m_i_streambuf->FillBuffer(); + m_i_streambuf->GetDataLeft(); return *(m_i_streambuf->GetBufferPos()); } -#define BUF_TEMP_SIZE 10000 wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) { char buf[BUF_TEMP_SIZE]; size_t bytes_read = BUF_TEMP_SIZE; - while (bytes_read == BUF_TEMP_SIZE && stream_out.LastError() != wxStream_NOERROR) { + while (bytes_read == BUF_TEMP_SIZE) { bytes_read = Read(buf, bytes_read).LastRead(); - - stream_out.Write(buf, bytes_read); + bytes_read = stream_out.Write(buf, bytes_read).LastWrite(); } return *this; }