X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fcc6dddd1f1da49f94767ff148eaa3f1d3ca9367..748a3af8e74ce74fe143650af0b2da2534c70d45:/src/common/stream.cpp diff --git a/src/common/stream.cpp b/src/common/stream.cpp index 1b0e66c82e..310f1ee7e0 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -15,632 +15,933 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#include -#include -#include -#include #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/defs.h" #endif +#if wxUSE_STREAMS + +#include +#include "wx/stream.h" +#include "wx/datstrm.h" +#include "wx/objstrm.h" + +#define BUF_TEMP_SIZE 10000 + // ---------------------------------------------------------------------------- // wxStreamBuffer // ---------------------------------------------------------------------------- -wxStreamBuffer::wxStreamBuffer(wxInputStream& i_stream) +#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_istream(&i_stream), m_ostream(NULL) + m_buffer_size(0), m_fixed(TRUE), m_flushable(TRUE), m_stream(&stream), + m_mode(mode), m_destroybuf(FALSE), m_destroystream(FALSE) { } -wxStreamBuffer::wxStreamBuffer(wxOutputStream& o_stream) +wxStreamBuffer::wxStreamBuffer(BufMode mode) : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL), - m_buffer_size(0), m_istream(NULL), m_ostream(&o_stream) + m_buffer_size(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() +wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer) { - wxDELETEA(m_buffer_start); + 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; } -void wxStreamBuffer::WriteBack(char c) +wxStreamBuffer::~wxStreamBuffer() { - if (m_ostream) - return; - - // Assume that if we write "back" we have read a few bytes: so we have some - // space. - if (m_buffer_pos == m_buffer_start) - return; - - m_buffer_pos--; - *m_buffer_pos = c; + if (m_destroybuf) + wxDELETEA(m_buffer_start); + if (m_destroystream) + delete m_stream; } void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end) { - size_t ret; - + 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; - - if (m_istream) { - ret = m_istream->DoRead(m_buffer_start, m_buffer_size); - m_buffer_end = m_buffer_start + ret; - } - m_buffer_pos = m_buffer_start; + m_destroybuf = FALSE; + ResetBuffer(); } 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; - m_buffer_end = NULL; - m_buffer_pos = NULL; + m_buffer_start = (char*)NULL; + m_buffer_end = (char*)NULL; + m_buffer_pos = (char*)NULL; m_buffer_size = 0; return; } b_start = new char[bufsize]; - SetBufferIO(b_start, b_start + bufsize); + m_destroybuf = TRUE; } void wxStreamBuffer::ResetBuffer() { - if (m_istream) + m_stream->m_lasterror = wxStream_NOERROR; + m_stream->m_lastcount = 0; + if (m_mode == read && m_flushable) m_buffer_pos = m_buffer_end; else m_buffer_pos = m_buffer_start; } -void wxStreamBuffer::Read(void *buffer, size_t size) +bool wxStreamBuffer::FillBuffer() { - wxASSERT(m_istream != NULL); + size_t count; - // ------------------ - // Buffering disabled - // ------------------ + count = m_stream->OnSysRead(m_buffer_start, m_buffer_size); + m_buffer_end = m_buffer_start+count; + m_buffer_pos = m_buffer_start; + + if (count == 0) + return FALSE; + return TRUE; +} + +bool wxStreamBuffer::FlushBuffer() +{ + size_t count, current; + + if (m_buffer_pos == m_buffer_start || !m_flushable) + return FALSE; + + current = m_buffer_pos-m_buffer_start; + count = m_stream->OnSysWrite(m_buffer_start, current); + if (count != current) + return FALSE; + m_buffer_pos = m_buffer_start; + + return TRUE; +} + +void wxStreamBuffer::GetFromBuffer(void *buffer, size_t size) +{ + size_t s_toget = m_buffer_end-m_buffer_pos; + + if (size < s_toget) + s_toget = size; + + memcpy(buffer, m_buffer_pos, s_toget); + m_buffer_pos += s_toget; +} + +void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size) +{ + size_t s_toput = m_buffer_end-m_buffer_pos; + + if (s_toput < size && !m_fixed) { + if (!m_buffer_start) + SetBufferIO(size); + else { + size_t delta = m_buffer_pos-m_buffer_start; + + m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size+size); + m_buffer_pos = m_buffer_start + delta; + // I round a bit + m_buffer_size += size; + m_buffer_end = m_buffer_start+m_buffer_size; + } + s_toput = size; + } + if (s_toput > size) + s_toput = size; + memcpy(m_buffer_pos, buffer, s_toput); + m_buffer_pos += s_toput; +} + +void wxStreamBuffer::PutChar(char c) +{ + wxASSERT(m_stream != NULL); if (!m_buffer_size) { - m_istream->m_lastread = m_istream->DoRead(buffer, size); + m_stream->OnSysWrite(&c, 1); + return; + } + + if (GetDataLeft() == 0 && !FlushBuffer()) { + CHECK_ERROR(wxStream_WRITE_ERR); return; } + PutToBuffer(&c, 1); + m_stream->m_lastcount = 1; +} + +char wxStreamBuffer::Peek() +{ + char c; + + wxASSERT(m_stream != NULL && m_buffer_size != 0); + + if (!GetDataLeft()) { + CHECK_ERROR(wxStream_READ_ERR); + return 0; + } + + GetFromBuffer(&c, 1); + m_buffer_pos--; + + return c; +} + +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); + + if (m_mode == write) + return 0; + + // ------------------ + // Buffering disabled + // ------------------ + + m_stream->m_lasterror = wxStream_NOERROR; + if (!m_buffer_size) + return (m_stream->m_lastcount += m_stream->OnSysRead(buffer, size)); + // ----------------- // Buffering enabled // ----------------- size_t buf_left, orig_size = size; - size_t read_ret; while (size > 0) { - buf_left = m_buffer_end - m_buffer_pos; + buf_left = GetDataLeft(); // First case: the requested buffer is larger than the stream buffer, - // we split + // we split it. if (size > buf_left) { - memcpy(buffer, m_buffer_pos, buf_left); - size -= buf_left; + GetFromBuffer(buffer, buf_left); + size -= buf_left; buffer = (char *)buffer + buf_left; // ANSI C++ violation. - read_ret = m_istream->DoRead(m_buffer_start, m_buffer_size); - - // Read failed: EOF - if (read_ret == 0) { - m_istream->m_lastread = orig_size-size; - m_istream->m_eof = TRUE; - m_buffer_pos = m_buffer_end = m_buffer_start; - return; - } else { - m_buffer_end = m_buffer_start+read_ret; - m_buffer_pos = m_buffer_start; + if (!FillBuffer()) { + CHECK_ERROR(wxStream_EOF); + return (m_stream->m_lastcount = orig_size-size); } } else { // Second case: we just copy from the stream buffer. - memcpy(buffer, m_buffer_pos, size); - m_buffer_pos += size; + GetFromBuffer(buffer, size); break; } } - m_istream->m_lastread = 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; + + if (m_mode == write) + return 0; + + while (bytes_read != 0) { + 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_ostream != NULL); + wxASSERT(m_stream != NULL); + + if (m_mode == read) + return 0; // ------------------ // Buffering disabled // ------------------ - if (!m_buffer_size) { - m_ostream->m_lastwrite = m_ostream->DoWrite(buffer, size); - return; - } + m_stream->m_lasterror = wxStream_NOERROR; + if (!m_buffer_size && m_fixed) + return (m_stream->m_lastcount = m_stream->OnSysWrite(buffer, size)); // ------------------ // Buffering enabled // ------------------ size_t buf_left, orig_size = size; - size_t write_ret; while (size > 0) { buf_left = m_buffer_end - m_buffer_pos; // First case: the buffer to write is larger than the stream buffer, // we split it - if (size > buf_left) { - memcpy(m_buffer_pos, buffer, buf_left); + // NB: If stream buffer isn't fixed (as for wxMemoryOutputStream), + // we always go to the second case. + if (size > buf_left && m_fixed) { + PutToBuffer(buffer, buf_left); size -= buf_left; buffer = (char *)buffer + buf_left; // ANSI C++ violation. - write_ret = m_ostream->DoWrite(m_buffer_start, m_buffer_size); - if (write_ret != m_buffer_size) { - m_ostream->m_bad = TRUE; - m_ostream->m_lastwrite = orig_size-size; - m_buffer_pos = m_buffer_end = m_buffer_start; - return; + if (!FlushBuffer()) { + CHECK_ERROR(wxStream_WRITE_ERR); + return (m_stream->m_lastcount = orig_size-size); } + m_buffer_pos = m_buffer_start; } else { // Second case: just copy it in the stream buffer. - - memcpy(m_buffer_pos, buffer, size); - m_buffer_pos += size; + PutToBuffer(buffer, size); break; } } - m_ostream->m_lastwrite = orig_size; + return (m_stream->m_lastcount = orig_size); } -// ---------------------------------------------------------------------------- -// wxInputStream -// ---------------------------------------------------------------------------- - -wxInputStream::wxInputStream() +size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf) { - m_i_destroybuf = TRUE; - m_i_streambuf = new wxStreamBuffer(*this); - m_eof = FALSE; - m_lastread = 0; + char buf[BUF_TEMP_SIZE]; + size_t s = 0, bytes_count = BUF_TEMP_SIZE, b_count2; + wxInputStream *in_stream; + + if (m_mode == read) + return 0; + + in_stream = (wxInputStream *)sbuf->Stream(); + + while (bytes_count == BUF_TEMP_SIZE) { + b_count2 = sbuf->Read(buf, bytes_count); + bytes_count = Write(buf, b_count2); + if (b_count2 > bytes_count) + in_stream->Ungetch(buf+bytes_count, b_count2-bytes_count); + s += bytes_count; + } + return s; } -wxInputStream::wxInputStream(wxStreamBuffer *buffer) +off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode) { - m_i_destroybuf = FALSE; - m_i_streambuf = buffer; - m_eof = FALSE; - m_lastread = 0; + off_t ret_off, diff, last_access; + + last_access = GetLastAccess(); + + if (!m_flushable) { + switch (mode) { + case wxFromStart: diff = pos; break; + case wxFromCurrent: diff = pos + GetIntPosition(); break; + case wxFromEnd: diff = pos + last_access; break; + default: return wxInvalidOffset; + } + 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 ... + ret_off = m_stream->OnSysSeek(pos, wxFromStart); + ResetBuffer(); + return ret_off; + } + case wxFromCurrent: { + diff = pos + GetIntPosition(); + + if ( (diff > last_access) || (diff < 0) ) { + // We must take into account the fact that we have read something + // previously. + ret_off = m_stream->OnSysSeek(diff-last_access, wxFromCurrent); + ResetBuffer(); + return ret_off; + } else { + SetIntPosition(diff); + return pos; + } + } + case wxFromEnd: + // Hard to compute: always seek to the requested position. + ret_off = m_stream->OnSysSeek(pos, wxFromEnd); + ResetBuffer(); + return ret_off; + } + return wxInvalidOffset; } -wxInputStream::~wxInputStream() +off_t wxStreamBuffer::Tell() const { - if (m_i_destroybuf) - delete m_i_streambuf; + off_t pos = m_stream->OnSysTell(); + if (pos == wxInvalidOffset) + return wxInvalidOffset; + + pos += GetIntPosition(); + + if (m_mode == read && m_flushable) + pos -= GetLastAccess(); + + return pos; } -char wxInputStream::GetC() +size_t wxStreamBuffer::GetDataLeft() { - char c; - m_i_streambuf->Read(&c, 1); - return c; + /* Why is this done? RR. */ + if (m_buffer_end == m_buffer_pos && m_flushable) + FillBuffer(); + + return m_buffer_end-m_buffer_pos; } -wxInputStream& wxInputStream::Read(void *buffer, size_t size) +// ---------------------------------------------------------------------------- +// wxStreamBase +// ---------------------------------------------------------------------------- + +wxStreamBase::wxStreamBase() { - m_i_streambuf->Read(buffer, size); - // wxStreamBuffer sets all variables for us - return *this; + m_lasterror = wxStream_NOERROR; + m_lastcount = 0; } -#define BUF_TEMP_SIZE 10000 +wxStreamBase::~wxStreamBase() +{ +} -wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) +size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer), size_t WXUNUSED(size)) { - char buf[BUF_TEMP_SIZE]; - size_t bytes_read = BUF_TEMP_SIZE; + return 0; +} - while (bytes_read == BUF_TEMP_SIZE && !stream_out.Bad()) { - bytes_read = Read(buf, bytes_read).LastRead(); +size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer), size_t WXUNUSED(bufsize)) +{ + return 0; +} - stream_out.Write(buf, bytes_read); - } - return *this; +off_t wxStreamBase::OnSysSeek(off_t WXUNUSED(seek), wxSeekMode WXUNUSED(mode)) +{ + return wxInvalidOffset; } -wxInputStream& wxInputStream::operator>>(wxString& line) +off_t wxStreamBase::OnSysTell() const { - wxDataInputStream s(*this); + return wxInvalidOffset; +} - line = s.ReadLine(); - return *this; +// ---------------------------------------------------------------------------- +// wxInputStream +// ---------------------------------------------------------------------------- + +wxInputStream::wxInputStream() + : wxStreamBase(), + m_wback(NULL), m_wbacksize(0), m_wbackcur(0) +{ } -wxInputStream& wxInputStream::operator>>(char& c) +wxInputStream::~wxInputStream() { - c = GetC(); - return *this; + if (m_wback) + free(m_wback); } -wxInputStream& wxInputStream::operator>>(short& i) +bool wxInputStream::Eof() const { - long l; + wxInputStream *self = (wxInputStream *)this; // const_cast + + char c; + self->Read(&c, 1); + if ( GetLastError() == wxSTREAM_EOF ) + { + return TRUE; + } + + self->Ungetch(c); - *this >> l; - i = (short)l; - return *this; + return FALSE; } -wxInputStream& wxInputStream::operator>>(int& i) +char *wxInputStream::AllocSpaceWBack(size_t needed_size) { - long l; + /* get number of bytes left from previous wback buffer */ + size_t toget = m_wbacksize - m_wbackcur; + + /* allocate a buffer large enough to hold prev + new data */ + char *temp_b = (char *) malloc(needed_size + toget); + + if (!temp_b) + return NULL; + + /* copy previous data (and free old buffer) if needed */ + if (m_wback) + { + memmove(temp_b + needed_size, m_wback + m_wbackcur, toget); + free(m_wback); + } + + /* done */ + m_wback = temp_b; + m_wbackcur = 0; + m_wbacksize = needed_size + toget; - *this >> l; - i = (short)l; - return *this; + return (char *) m_wback; } -wxInputStream& wxInputStream::operator>>(long& i) +size_t wxInputStream::GetWBack(char *buf, size_t bsize) { - /* I only implemented a simple integer parser */ - int c, sign; + size_t s_toget = m_wbacksize-m_wbackcur; - while (isspace( c = GetC() ) ) - /* Do nothing */ ; + if (!m_wback) + return 0; - i = 0; - if (! (c == '-' || isdigit(c)) ) { - InputStreamBuffer()->WriteBack(c); - return *this; - } + if (bsize < s_toget) + s_toget = bsize; - if (c == '-') { - sign = -1; - c = GetC(); - } else - sign = 1; + memcpy(buf, (m_wback+m_wbackcur), s_toget); - while (isdigit(c)) { - i = i*10 + c; - c = GetC(); - } - - i *= sign; + m_wbackcur += s_toget; + if (m_wbackcur == m_wbacksize) + { + free(m_wback); + m_wback = (char *)NULL; + m_wbacksize = 0; + m_wbackcur = 0; + } - return *this; + return s_toget; } -wxInputStream& wxInputStream::operator>>(float& f) +size_t wxInputStream::Ungetch(const void *buf, size_t bufsize) { - /* I only implemented a simple float parser */ - int c, sign; + char *ptrback = AllocSpaceWBack(bufsize); + if (!ptrback) + return 0; - while (isspace( c = GetC() ) ) - /* Do nothing */ ; + memcpy(ptrback, buf, bufsize); + return bufsize; +} - f = 0.0; - if (! (c == '-' || isdigit(c)) ) { - InputStreamBuffer()->WriteBack(c); - return *this; - } +bool wxInputStream::Ungetch(char c) +{ + char * ptrback = AllocSpaceWBack(1); + if (!ptrback) + return FALSE; - if (c == '-') { - sign = -1; - c = GetC(); - } else - sign = 1; + *ptrback = c; + return TRUE; +} - while (isdigit(c)) { - f = f*10 + c; - c = GetC(); - } +char wxInputStream::GetC() +{ + char c; + Read(&c, 1); + return c; +} - if (c == '.') { - float f_multiplicator = 0.1; - c = GetC(); +wxInputStream& wxInputStream::Read(void *buffer, size_t size) +{ + char *buf = (char *)buffer; - while (isdigit(c)) { - f += c*f_multiplicator; - f_multiplicator /= 10; - c = GetC(); + size_t retsize = GetWBack(buf, size); + if (retsize == size) + { + m_lastcount = size; + m_lasterror = wxStream_NOERROR; + return *this; } - } - - f *= sign; + size -= retsize; + buf += retsize; - return *this; + m_lastcount = OnSysRead(buf, size) + retsize; + return *this; } -#if USE_SERIAL -wxInputStream& wxInputStream::operator>>(wxObject *& obj) +char wxInputStream::Peek() { - wxObjectInputStream obj_s(*this); - obj = obj_s.LoadObject(); - return *this; + char c; + Read(&c, 1); + if (m_lasterror == wxStream_NOERROR) + { + Ungetch(c); + return c; + } + + return 0; } -#endif -off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode) +wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) { - off_t ret_off, diff, last_access; - - last_access = m_i_streambuf->GetLastAccess(); + char buf[BUF_TEMP_SIZE]; + size_t bytes_read = BUF_TEMP_SIZE; - switch (mode) { - case wxFromStart: - diff = DoTellInput() - pos; - if ( diff < 0 || diff > last_access ) { - ret_off = DoSeekInput(pos, wxFromStart); - m_i_streambuf->ResetBuffer(); - return ret_off; - } else { - m_i_streambuf->SetIntPosition(last_access - diff); - return pos; + while (bytes_read == BUF_TEMP_SIZE) + { + bytes_read = Read(buf, bytes_read).LastRead(); + bytes_read = stream_out.Write(buf, bytes_read).LastWrite(); } - case wxFromCurrent: - diff = pos + m_i_streambuf->GetIntPosition(); + return *this; +} - if ( (diff > last_access) || (diff < 0) ) { - ret_off = DoSeekInput(pos, wxFromCurrent); - m_i_streambuf->ResetBuffer(); - return ret_off; - } else { - m_i_streambuf->SetIntPosition(diff); - return pos; +off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode) +{ + /* Should be check and improve, just to remove a slight bug ! + I don't know whether it should be put as well in wxFileInputStream::OnSysSeek ? */ + if (m_lasterror==wxSTREAM_EOF) + m_lasterror=wxSTREAM_NOERROR; + + /* A call to SeekI() will automatically invalidate any previous call + to Ungetch(), otherwise it would be possible to SeekI() to one + one position, unread some bytes there, SeekI() to another position + and the data would be corrupted. + + GRG: Could add code here to try to navigate within the wback + buffer if possible, but is it really needed? It would only work + when seeking in wxFromCurrent mode, else it would invalidate + anyway... + */ + if (m_wback) + { + free(m_wback); + m_wback = (char*) NULL; + m_wbacksize = 0; + m_wbackcur = 0; } - case wxFromEnd: - // Hard to compute: always seek to the requested position. - ret_off = DoSeekInput(pos, wxFromEnd); - m_i_streambuf->ResetBuffer(); - return ret_off; - } - return wxInvalidOffset; + + return OnSysSeek(pos, mode); } off_t wxInputStream::TellI() const { - return DoTellInput() - m_i_streambuf->GetLastAccess() + - m_i_streambuf->GetIntPosition(); + /* GRG: Changed to make it compatible with the wback buffer */ + off_t pos = OnSysTell(); + + if (pos != wxInvalidOffset) + pos -= (m_wbacksize - m_wbackcur); + + return pos; } +// -------------------- +// Overloaded operators +// -------------------- + +#if wxUSE_SERIAL +wxInputStream& wxInputStream::operator>>(wxObject *& obj) +{ + wxObjectInputStream obj_s(*this); + obj = obj_s.LoadObject(); + return *this; +} +#endif + + // ---------------------------------------------------------------------------- // wxOutputStream // ---------------------------------------------------------------------------- wxOutputStream::wxOutputStream() + : wxStreamBase() { - m_o_destroybuf = TRUE; - m_o_streambuf = new wxStreamBuffer(*this); - m_bad = FALSE; - m_lastwrite = 0; } -wxOutputStream::wxOutputStream(wxStreamBuffer *buffer) +wxOutputStream::~wxOutputStream() { - m_o_destroybuf = FALSE; - m_o_streambuf = buffer; - m_bad = FALSE; - m_lastwrite = 0; } -wxOutputStream::~wxOutputStream() +void wxOutputStream::PutC(char c) { - if (m_o_destroybuf) - delete m_o_streambuf; + Write((void *) &c, 1); } wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size) { - m_o_streambuf->Write(buffer, size); - return *this; + m_lastcount = OnSysWrite(buffer, size); + return *this; } wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in) { - stream_in.Read(*this); - return *this; + stream_in.Read(*this); + return *this; } -off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode) +off_t wxOutputStream::TellO() const { - off_t ret_off; - - switch (mode) { - case wxFromStart: - if ( (unsigned)abs (DoTellOutput()-pos) > m_o_streambuf->GetLastAccess() ) { - ret_off = DoSeekOutput(pos, wxFromStart); - m_o_streambuf->ResetBuffer(); - return ret_off; - } else { - m_o_streambuf->SetIntPosition( DoTellOutput() - pos); - return pos; - } - case wxFromCurrent: - if ( ((unsigned)pos > m_o_streambuf->GetLastAccess()) || (pos < 0) ) { - ret_off = DoSeekOutput(pos, wxFromCurrent); - m_o_streambuf->ResetBuffer(); - return ret_off; - } else { - m_o_streambuf->SetIntPosition(pos); - return pos; - } - case wxFromEnd: - // Hard to compute: always seek to the requested position. - ret_off = DoSeekOutput(pos, wxFromEnd); - m_o_streambuf->ResetBuffer(); - return ret_off; - } - return wxInvalidOffset; + return OnSysTell(); } -off_t wxOutputStream::TellO() const +off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode) { - return DoTellOutput() - m_o_streambuf->GetLastAccess() - + m_o_streambuf->GetIntPosition(); + return OnSysSeek(pos, mode); } void wxOutputStream::Sync() { - DoWrite(m_o_streambuf->GetBufferStart(), m_o_streambuf->GetIntPosition()); +} - m_o_streambuf->ResetBuffer(); +#if wxUSE_SERIAL +wxOutputStream& wxOutputStream::operator<<(wxObject& obj) +{ + wxObjectOutputStream obj_s(*this); + obj_s.SaveObject(obj); + return *this; } +#endif -wxOutputStream& wxOutputStream::operator<<(const char *string) +// ---------------------------------------------------------------------------- +// wxCountingOutputStream +// ---------------------------------------------------------------------------- + +wxCountingOutputStream::wxCountingOutputStream () + : wxOutputStream() { - return Write(string, strlen(string)); + m_currentPos = 0; } -wxOutputStream& wxOutputStream::operator<<(wxString& string) +size_t wxCountingOutputStream::GetSize() const { - return Write(string, string.Len()); + return m_lastcount; } -wxOutputStream& wxOutputStream::operator<<(char c) +size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer), size_t size) { - return Write(&c, 1); + m_currentPos += size; + if (m_currentPos > m_lastcount) m_lastcount = m_currentPos; + return m_currentPos; } -wxOutputStream& wxOutputStream::operator<<(short i) +off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode) { - wxString strint; + if (mode == wxFromStart) + m_currentPos = pos; + if (mode == wxFromEnd) + m_currentPos = m_lastcount + pos; + else + m_currentPos += pos; + + if (m_currentPos > m_lastcount) m_lastcount = m_currentPos; - strint.Printf("%i", i); - return Write(strint, strint.Len()); + return m_currentPos; } -wxOutputStream& wxOutputStream::operator<<(int i) +off_t wxCountingOutputStream::OnSysTell() const { - wxString strint; + return m_currentPos; +} + +// ---------------------------------------------------------------------------- +// wxFilterInputStream +// ---------------------------------------------------------------------------- - strint.Printf("%i", i); - return Write(strint, strint.Len()); +wxFilterInputStream::wxFilterInputStream() + : wxInputStream() +{ } -wxOutputStream& wxOutputStream::operator<<(long i) +wxFilterInputStream::wxFilterInputStream(wxInputStream& stream) + : wxInputStream() { - wxString strlong; + m_parent_i_stream = &stream; +} - strlong.Printf("%i", i); - return Write((const char *)strlong, strlong.Len()); +wxFilterInputStream::~wxFilterInputStream() +{ } -wxOutputStream& wxOutputStream::operator<<(double f) +// ---------------------------------------------------------------------------- +// wxFilterOutputStream +// ---------------------------------------------------------------------------- +wxFilterOutputStream::wxFilterOutputStream() + : wxOutputStream() { - wxString strfloat; +} - strfloat.Printf("%f", f); - return Write(strfloat, strfloat.Len()); +wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream) + : wxOutputStream() +{ + m_parent_o_stream = &stream; } -#if USE_SERIAL -wxOutputStream& wxOutputStream::operator<<(wxObject& obj) +wxFilterOutputStream::~wxFilterOutputStream() { - wxObjectOutputStream obj_s(*this); - obj_s.SaveObject(obj); - return *this; } -#endif // ---------------------------------------------------------------------------- -// wxStream +// wxBufferedInputStream // ---------------------------------------------------------------------------- +wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s) + : wxFilterInputStream(s) +{ + m_i_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::read); + m_i_streambuf->SetBufferIO(1024); +} -wxStream::wxStream() - : wxInputStream(), wxOutputStream() +wxBufferedInputStream::~wxBufferedInputStream() { + off_t unused_bytes=m_i_streambuf->GetBufferPos()-m_i_streambuf->GetBufferEnd(); + m_parent_i_stream->SeekI(unused_bytes,wxFromCurrent); + + delete m_i_streambuf; } -// ---------------------------------------------------------------------------- -// wxFilterInputStream -// ---------------------------------------------------------------------------- -wxFilterInputStream::wxFilterInputStream() - : wxInputStream(NULL) +char wxBufferedInputStream::Peek() { + return m_i_streambuf->Peek(); } -wxFilterInputStream::wxFilterInputStream(wxInputStream& stream) - : wxInputStream(NULL) +wxInputStream& wxBufferedInputStream::Read(void *buffer, size_t size) +{ + size_t retsize; + char *buf = (char *)buffer; + + retsize = GetWBack(buf, size); + m_lastcount = retsize; + if (retsize == size) + { + m_lasterror = wxStream_NOERROR; + return *this; + } + size -= retsize; + buf += retsize; + + m_i_streambuf->Read(buf, size); + + return *this; +} + +off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode) { - m_parent_i_stream = &stream; - m_i_streambuf = stream.InputStreamBuffer(); + return m_i_streambuf->Seek(pos, mode); } -wxFilterInputStream::~wxFilterInputStream() +off_t wxBufferedInputStream::TellI() const { + return m_i_streambuf->Tell(); } -size_t wxFilterInputStream::DoRead(void *buffer, size_t size) +size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize) { - return m_parent_i_stream->Read(buffer, size).LastRead(); + return m_parent_i_stream->Read(buffer, bufsize).LastRead(); } -off_t wxFilterInputStream::DoSeekInput(off_t pos, wxSeekMode mode) +off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode) { - return m_parent_i_stream->SeekI(pos, mode); + return m_parent_i_stream->SeekI(seek, mode); } -off_t wxFilterInputStream::DoTellInput() const +off_t wxBufferedInputStream::OnSysTell() const { - return m_parent_i_stream->TellI(); + return m_parent_i_stream->TellI(); } + // ---------------------------------------------------------------------------- -// wxFilterOutputStream +// wxBufferedOutputStream // ---------------------------------------------------------------------------- -wxFilterOutputStream::wxFilterOutputStream() - : wxOutputStream(NULL) + +wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s) + : wxFilterOutputStream(s) { + m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write); + m_o_streambuf->SetBufferIO(1024); } -wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream) - : wxOutputStream(NULL) +wxBufferedOutputStream::~wxBufferedOutputStream() { - m_parent_o_stream = &stream; - m_o_streambuf = stream.OutputStreamBuffer(); + Sync(); + delete m_o_streambuf; } -wxFilterOutputStream::~wxFilterOutputStream() +wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size) { + m_lastcount = 0; + m_o_streambuf->Write(buffer, size); + return *this; } -size_t wxFilterOutputStream::DoWrite(const void *buffer, size_t size) +off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode) { - return m_parent_o_stream->Write(buffer, size).LastWrite(); + Sync(); + return m_o_streambuf->Seek(pos, mode); } -off_t wxFilterOutputStream::DoSeekOutput(off_t pos, wxSeekMode mode) +off_t wxBufferedOutputStream::TellO() const { - return m_parent_o_stream->SeekO(pos, mode); + return m_o_streambuf->Tell(); } -off_t wxFilterOutputStream::DoTellOutput() const +void wxBufferedOutputStream::Sync() { - return m_parent_o_stream->TellO(); + m_o_streambuf->FlushBuffer(); + m_parent_o_stream->Sync(); } -// ---------------------------------------------------------------------------- -// wxFilterStream -// ---------------------------------------------------------------------------- +size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize) +{ + return m_parent_o_stream->Write(buffer, bufsize).LastWrite(); +} + +off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode) +{ + return m_parent_o_stream->SeekO(seek, mode); +} -wxFilterStream::wxFilterStream() +off_t wxBufferedOutputStream::OnSysTell() const { + return m_parent_o_stream->TellO(); } -wxFilterStream::wxFilterStream(wxStream& stream) - : wxFilterInputStream(stream), wxFilterOutputStream(stream) +size_t wxBufferedOutputStream::GetSize() const { + return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition(); } // ---------------------------------------------------------------------------- @@ -651,7 +952,14 @@ 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 } + +#endif + // wxUSE_STREAMS