diff --git a/src/common/datstrm.cpp b/src/common/datstrm.cpp index fa1eaa7d89..a4cecc093b 100644 --- a/src/common/datstrm.cpp +++ b/src/common/datstrm.cpp @@ -25,13 +25,7 @@ #endif #include "wx/datstrm.h" - -/* -#if !USE_SHARED_LIBRARY -IMPLEMENT_CLASS(wxDataInputStream, wxFilterInputStream) -IMPLEMENT_CLASS(wxDataOutputStream, wxFilterOutputStream) -#endif -*/ +#include "wx/bufstrm.h" wxDataInputStream::wxDataInputStream(wxInputStream& s) : wxFilterInputStream(s) @@ -89,10 +83,30 @@ double wxDataInputStream::ReadDouble() wxString wxDataInputStream::ReadLine() { - char i_strg[255]; + char c, last_endl = 0; + bool end_line = FALSE; + wxString line; - // TODO: Implement ReadLine - return i_strg; + while (!end_line) { + c = GetC(); + switch (c) { + case '\n': + end_line = TRUE; + break; + case '\r': + last_endl = '\r'; + break; + default: + if (last_endl == '\r') { + end_line = TRUE; + InputStreamBuffer()->WriteBack(c); + break; + } + line += c; + break; + } + } + return line; } wxString wxDataInputStream::ReadString() diff --git a/src/common/fstream.cpp b/src/common/fstream.cpp index d1bfb0637b..4014d31031 100644 --- a/src/common/fstream.cpp +++ b/src/common/fstream.cpp @@ -32,25 +32,29 @@ wxFileInputStream::wxFileInputStream(const wxString& fileName) : wxFile(fileName, read) { - m_lastread = 0; + m_i_streambuf->SetBufferIO(1024); } wxFileInputStream::~wxFileInputStream() { } -wxInputStream& wxFileInputStream::Read(void *buffer, size_t size) +char wxFileInputStream::Peek() { - m_lastread = wxFile::Read(buffer, size); - return *this; + return 0; } -off_t wxFileInputStream::SeekI(off_t pos, wxSeekMode mode) +size_t wxFileInputStream::DoRead(void *buffer, size_t size) +{ + return wxFile::Read(buffer, size); +} + +off_t wxFileInputStream::DoSeekInput(off_t pos, wxSeekMode mode) { return wxFile::Seek(pos, mode); } -off_t wxFileInputStream::TellI() const +off_t wxFileInputStream::DoTellInput() const { return wxFile::Tell(); } @@ -62,32 +66,34 @@ off_t wxFileInputStream::TellI() const wxFileOutputStream::wxFileOutputStream(const wxString& fileName) : wxFile(fileName, write) { - m_lastwrite = 0; + m_o_streambuf->SetBufferIO(1024); } wxFileOutputStream::~wxFileOutputStream() { + Sync(); } -wxOutputStream& wxFileOutputStream::Write(const void *buffer, size_t size) +size_t wxFileOutputStream::DoWrite(const void *buffer, size_t size) { - m_lastwrite = wxFile::Write(buffer, size); + size_t ret = wxFile::Write(buffer, size); m_bad = wxFile::Error(); - return *this; + return ret; } -off_t wxFileOutputStream::TellO() const +off_t wxFileOutputStream::DoTellOutput() const { return wxFile::Tell(); } -off_t wxFileOutputStream::SeekO(off_t pos, wxSeekMode mode) +off_t wxFileOutputStream::DoSeekOutput(off_t pos, wxSeekMode mode) { return wxFile::Seek(pos, mode); } void wxFileOutputStream::Sync() { + wxOutputStream::Sync(); wxFile::Flush(); } diff --git a/src/common/mstream.cpp b/src/common/mstream.cpp index d75c423885..9e1ee174f2 100644 --- a/src/common/mstream.cpp +++ b/src/common/mstream.cpp @@ -67,29 +67,30 @@ wxMemoryInputStream::wxMemoryInputStream(const char *data, size_t len) m_lastread = 0; m_eof = FALSE; m_iolimit = 1; + + m_i_streambuf->SetBufferIO(0); } wxMemoryInputStream::~wxMemoryInputStream() { } -wxInputStream& wxMemoryInputStream::Read(void *buffer, size_t size) +size_t wxMemoryInputStream::DoRead(void *buffer, size_t size) { if (m_iolimit == 2) { m_eof = TRUE; - return *this; + return 0; } if (m_position_i+size > m_length) size = m_length-m_position_i; memcpy((void *)((unsigned long)buffer+m_position_i), m_buffer, size); m_position_i += size; - m_lastread = size; - return *this; + return size; } -off_t wxMemoryInputStream::SeekI(off_t pos, wxSeekMode mode) +off_t wxMemoryInputStream::DoSeekInput(off_t pos, wxSeekMode mode) { if (m_iolimit == 2) return 0; @@ -129,33 +130,35 @@ wxMemoryOutputStream::wxMemoryOutputStream(char *data, size_t len) m_lastwrite = 0; m_bad = FALSE; m_iolimit = 2; + + m_o_streambuf->SetBufferIO(0); } wxMemoryOutputStream::~wxMemoryOutputStream() { + Sync(); } -wxOutputStream& wxMemoryOutputStream::Write(const void *buffer, size_t size) +size_t wxMemoryOutputStream::DoWrite(const void *buffer, size_t size) { if (m_iolimit == 1) { m_bad = TRUE; - return *this; + return 0; } if (m_position_o+size > m_length) if (!ChangeBufferSize(m_position_o+size)) { m_bad = TRUE; - return *this; + return 0; } memcpy(m_buffer+m_position_o, buffer, size); m_position_o += size; - m_lastwrite = size; - return *this; + return size; } -off_t wxMemoryOutputStream::SeekO(off_t pos, wxSeekMode mode) +off_t wxMemoryOutputStream::DoSeekOutput(off_t pos, wxSeekMode mode) { if (m_iolimit == 1) return 0; diff --git a/src/common/objstrm.cpp b/src/common/objstrm.cpp new file mode 100644 index 0000000000..1d2b01d01a --- /dev/null +++ b/src/common/objstrm.cpp @@ -0,0 +1,224 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: objstrm.cpp +// Purpose: wxObjectStream classes +// Author: Guilhem Lavaux +// Modified by: +// Created: 16/07/98 +// RCS-ID: $Id$ +// Copyright: (c) 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// +#ifdef __GNUG__ +#pragma implementation "objstrm.h" +#endif + +#include "wx/object.h" +#include "wx/objstrm.h" +#include "wx/datstrm.h" + +#define WXOBJ_BEGIN "OBEGIN" +#define WXOBJ_BEG_LEN 6 + +// ---------------------------------------------------------------------------- +// wxObjectOutputStream +// ---------------------------------------------------------------------------- + +wxObjectOutputStream::wxObjectOutputStream(wxOutputStream& s) + : wxFilterOutputStream(s) +{ + m_saving = FALSE; +} + +wxString wxObjectOutputStream::GetObjectName(wxObject *obj) +{ + wxString name; + + name.Printf("%x", (unsigned long)obj); + return name; +} + +void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo& info) +{ + wxDataOutputStream data_s(*this); + + Write(WXOBJ_BEGIN, WXOBJ_BEG_LEN); + data_s.WriteString(info.object->GetClassInfo()->GetClassName()); + data_s.WriteString(GetObjectName(info.object)); + // I assume an object will not have millions of children + data_s.Write8(info.children.Number()); +} + +void wxObjectOutputStream::AddChildren(wxObject *obj) +{ + wxObjectStreamInfo *info; + + if (!FirstStage()) + return; + + info = new wxObjectStreamInfo; + info->n_children = 0; + info->object = obj; + info->parent = m_current_info->object; // Not useful here. + m_current_info->n_children++; + m_current_info->children.Append(info); +} + +void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo *info) +{ + wxNode *node; + + m_current_info = info; + // First stage: get children of obj + info->object->StoreObject(*this); + + // Prepare and write the sub-entry about the child obj. + WriteObjectDef(*info); + + node = info->children.First(); + + while (node) { + ProcessObjectDef((wxObjectStreamInfo *)node->Data()); + node = node->Next(); + } +} + +void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo *info) +{ + wxNode *node = info->children.First(); + + m_current_info = info; + + info->object->StoreObject(*this); + + while (node) { + ProcessObjectData((wxObjectStreamInfo *)node->Data()); + node = node->Next(); + } +} + +bool wxObjectOutputStream::SaveObject(wxObject& obj) +{ + wxObjectStreamInfo info; + + if (m_saving) + return FALSE; + + m_saving = TRUE; + + // First stage + m_stage = 0; + info.object = &obj; + info.n_children = 0; + ProcessObjectDef(&info); + + m_stage = 1; + ProcessObjectData(&info); + + info.children.Clear(); + + m_saving = FALSE; + + return TRUE; +} + +// ---------------------------------------------------------------------------- +// wxObjectInputStream +// ---------------------------------------------------------------------------- + +wxObjectInputStream::wxObjectInputStream(wxInputStream& s) + : wxFilterInputStream(s) +{ +} + +wxObject *wxObjectInputStream::SolveName(const wxString& name) const +{ + wxNode *node = m_solver.First(); + wxObjectStreamInfo *info; + + while (node) { + info = (wxObjectStreamInfo *)node->Data(); + if (info->object_name == name) + return info->object; + + node = node->Next(); + } + return NULL; +} + +wxObject *wxObjectInputStream::GetChild(int no) const +{ + return m_current_info->children.Nth(no); +} + +bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo *info) +{ + wxDataInputStream data_s(*this); + char sig[WXOBJ_BEG_LEN+1]; + + Read(sig, WXOBJ_BEG_LEN); + sig[WXOBJ_BEG_LEN] = 0; + if (wxString(sig) != WXOBJ_BEGIN) + return FALSE; + info->object = wxCreateDynamicObject((char *)data_s.ReadString()); + info->object_name = data_s.ReadString(); + info->n_children = data_s.Read8(); + info->children = wxList(); + + return TRUE; +} + +wxObjectStreamInfo *wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo *parent) +{ + wxObjectStreamInfo *info, *c_info; + int c; + + info = new wxObjectStreamInfo; + info->parent = parent; + info->children.DeleteContents(TRUE); + + m_solver.Append(info); + + if (!ReadObjectDef(info)) + return NULL; + + for (c=0;cn_children;c++) { + c_info = ProcessObjectDef(info); + if (!c_info) + return NULL; + info->children.Append(c_info); + } + + return info; +} + +void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo *info) +{ + wxNode *node = info->children.First(); + wxObjectStreamInfo *c_info; + + m_current_info = info; + + info->object->LoadObject(*this); + while (node) { + c_info = (wxObjectStreamInfo *)node->Data(); + c_info->object->LoadObject(*this); + node = node->Next(); + } +} + +wxObject *wxObjectInputStream::LoadObject() +{ + wxObjectStreamInfo *info; + wxObject *object; + + info = ProcessObjectDef(NULL); + if (!info) + return NULL; + ProcessObjectData(info); + + object = info->object; + + delete info; // It's magic ! The whole tree is destroyed. + + return object; +} diff --git a/src/common/stream.cpp b/src/common/stream.cpp index b3a43423a7..0186a9548c 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -15,22 +15,219 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" +#include #include +#include #ifdef __BORLANDC__ #pragma hdrstop #endif +// ---------------------------------------------------------------------------- +// wxStreamBuffer +// ---------------------------------------------------------------------------- + +wxStreamBuffer::wxStreamBuffer(wxInputStream& i_stream) + : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL), + m_buffer_size(0), m_istream(&i_stream), m_ostream(NULL) +{ +} + +wxStreamBuffer::wxStreamBuffer(wxOutputStream& o_stream) + : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL), + m_buffer_size(0), m_istream(NULL), m_ostream(&o_stream) +{ +} + +wxStreamBuffer::~wxStreamBuffer() +{ +} + +void wxStreamBuffer::WriteBack(char c) +{ + if (m_ostream) + return; + + // Assume that if we write "back" we have read a few bytes: so we have some + // space. + + m_buffer_pos--; + *m_buffer_pos = c; +} + +void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end) +{ + m_buffer_pos = m_buffer_start = buffer_start; + m_buffer_end = buffer_end; + + m_buffer_size = m_buffer_end-m_buffer_start; +} + +void wxStreamBuffer::SetBufferIO(size_t bufsize) +{ + if (m_buffer_start) + delete[] m_buffer_start; + + if (!bufsize) { + m_buffer_start = NULL; + m_buffer_end = NULL; + m_buffer_pos = NULL; + m_buffer_size = 0; + } + + m_buffer_start = new char[bufsize]; + m_buffer_end = m_buffer_start + bufsize; + if (m_istream) + m_buffer_pos = m_buffer_end; + else + m_buffer_pos = m_buffer_start; + m_buffer_size = bufsize; +} + +void wxStreamBuffer::ResetBuffer() +{ + if (m_istream) + m_buffer_pos = m_buffer_end; + else + m_buffer_pos = m_buffer_start; +} + +void wxStreamBuffer::Read(void *buffer, size_t size) +{ + wxASSERT(m_istream != NULL); + + // ------------------ + // Buffering disabled + // ------------------ + + if (!m_buffer_size) { + m_istream->m_lastread = m_istream->DoRead(buffer, size); + return; + } + + // ----------------- + // Buffering enabled + // ----------------- + size_t buf_left, orig_size = size; + size_t read_ret; + + while (size > 0) { + buf_left = m_buffer_end - m_buffer_pos; + + // First case: the requested buffer is larger than the stream buffer, + // we split + if (size > buf_left) { + memcpy(buffer, m_buffer_pos, 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 + if (read_ret == 0) { + m_istream->m_lastread = orig_size-size; + 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; + } + } else { + + // Second case: we just copy from the stream buffer. + memcpy(buffer, m_buffer_pos, size); + m_buffer_pos += size; + break; + } + } + m_istream->m_lastread = orig_size; +} + +void wxStreamBuffer::Write(const void *buffer, size_t size) +{ + wxASSERT(m_ostream != NULL); + + // ------------------ + // Buffering disabled + // ------------------ + + if (!m_buffer_size) { + m_ostream->m_lastwrite = m_ostream->DoWrite(buffer, size); + return; + } + + // ------------------ + // 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); + 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; + } + 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; + break; + } + } + m_ostream->m_lastwrite = orig_size; +} + // ---------------------------------------------------------------------------- // wxInputStream // ---------------------------------------------------------------------------- wxInputStream::wxInputStream() { + m_i_destroybuf = TRUE; + m_i_streambuf = new wxStreamBuffer(*this); +} + +wxInputStream::wxInputStream(wxStreamBuffer *buffer) +{ + m_i_destroybuf = FALSE; + m_i_streambuf = buffer; } wxInputStream::~wxInputStream() { + if (m_i_destroybuf) + delete m_i_streambuf; +} + +char wxInputStream::GetC() +{ + char c; + m_i_streambuf->Read(&c, 1); + return c; +} + +wxInputStream& wxInputStream::Read(void *buffer, size_t size) +{ + m_i_streambuf->Read(buffer, size); + // wxStreamBuffer sets all variables for us + return *this; } #define BUF_TEMP_SIZE 10000 @@ -48,14 +245,6 @@ wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) return *this; } -int wxInputStream::Scanf(const wxString& format, ...) -{ - va_list params; - - va_start(params, format); - va_end(params); -} - wxInputStream& wxInputStream::operator>>(wxString& line) { wxDataInputStream s(*this); @@ -67,65 +256,320 @@ wxInputStream& wxInputStream::operator>>(wxString& line) wxInputStream& wxInputStream::operator>>(char& c) { c = GetC(); + return *this; } wxInputStream& wxInputStream::operator>>(short& i) { - Scanf("%i", &i); + long l; + + *this >> l; + i = (short)l; return *this; } wxInputStream& wxInputStream::operator>>(long& i) { - Scanf("%l", &i); + /* I only implemented a simple integer parser */ + int c, sign; + + while (isspace( c = GetC() ) ) + /* Do nothing */ ; + + i = 0; + if (! (c == '-' || isdigit(c)) ) { + InputStreamBuffer()->WriteBack(c); + return *this; + } + + if (c == '-') { + sign = -1; + c = GetC(); + } else + sign = 1; + + while (isdigit(c)) { + i = i*10 + c; + c = GetC(); + } + + i *= sign; + return *this; } wxInputStream& wxInputStream::operator>>(float& f) { - Scanf("%f", &f); + /* I only implemented a simple float parser */ + int c, sign; + + while (isspace( c = GetC() ) ) + /* Do nothing */ ; + + f = 0.0; + if (! (c == '-' || isdigit(c)) ) { + InputStreamBuffer()->WriteBack(c); + return *this; + } + + if (c == '-') { + sign = -1; + c = GetC(); + } else + sign = 1; + + while (isdigit(c)) { + f = f*10 + c; + c = GetC(); + } + + if (c == '.') { + float f_multiplicator = 0.1; + c = GetC(); + + while (isdigit(c)) { + f += c*f_multiplicator; + f_multiplicator /= 10; + c = GetC(); + } + } + + f *= sign; + return *this; } +off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode) +{ + off_t ret_off; + + switch (mode) { + case wxFromStart: + if ( (unsigned)abs (DoTellInput()-pos) > m_i_streambuf->GetLastAccess() ) { + ret_off = DoSeekInput(pos, wxFromStart); + m_i_streambuf->ResetBuffer(); + return ret_off; + } else { + m_i_streambuf->SetIntPosition(DoTellInput() - pos); + return pos; + } + case wxFromCurrent: + if ( ((unsigned)pos > m_i_streambuf->GetLastAccess()) || (pos < 0) ) { + ret_off = DoSeekInput(pos, wxFromCurrent); + m_i_streambuf->ResetBuffer(); + return ret_off; + } else { + m_i_streambuf->SetIntPosition(pos); + return pos; + } + 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; +} + +off_t wxInputStream::TellI() const +{ + return DoTellInput() - m_i_streambuf->GetLastAccess() + + m_i_streambuf->GetIntPosition(); +} + // ---------------------------------------------------------------------------- // wxOutputStream // ---------------------------------------------------------------------------- wxOutputStream::wxOutputStream() { + m_o_destroybuf = TRUE; + m_o_streambuf = new wxStreamBuffer(*this); +} + +wxOutputStream::wxOutputStream(wxStreamBuffer *buffer) +{ + m_o_destroybuf = FALSE; + m_o_streambuf = buffer; } wxOutputStream::~wxOutputStream() { + if (m_o_destroybuf) + delete m_o_streambuf; +} + +wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size) +{ + m_o_streambuf->Write(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 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; +} + +off_t wxOutputStream::TellO() const +{ + return DoTellOutput() - m_o_streambuf->GetLastAccess() + + m_o_streambuf->GetIntPosition(); +} + +void wxOutputStream::Sync() +{ + DoWrite(m_o_streambuf->GetBufferStart(), m_o_streambuf->GetIntPosition()); + + m_o_streambuf->ResetBuffer(); +} + +wxOutputStream& wxOutputStream::operator<<(const char *string) +{ + return Write(string, strlen(string)); +} + +wxOutputStream& wxOutputStream::operator<<(wxString& string) +{ + return Write(string, string.Len()); +} + +wxOutputStream& wxOutputStream::operator<<(char c) +{ + return Write(&c, 1); +} + +wxOutputStream& wxOutputStream::operator<<(short i) +{ + wxString strint; + + strint.Printf("%i", i); + return Write(strint, strint.Len()); +} + +wxOutputStream& wxOutputStream::operator<<(int i) +{ + wxString strint; + + strint.Printf("%i", i); + return Write(strint, strint.Len()); +} + +wxOutputStream& wxOutputStream::operator<<(long i) +{ + wxString strlong; + + strlong.Printf("%i", i); + return Write((const char *)strlong, strlong.Len()); +} + +wxOutputStream& wxOutputStream::operator<<(double f) +{ + wxString strfloat; + + strfloat.Printf("%f", f); + return Write(strfloat, strfloat.Len()); } // ---------------------------------------------------------------------------- // wxFilterInputStream // ---------------------------------------------------------------------------- wxFilterInputStream::wxFilterInputStream(wxInputStream& stream) - : wxInputStream() + : wxInputStream(NULL) { m_parent_i_stream = &stream; + m_i_streambuf = stream.InputStreamBuffer(); } wxFilterInputStream::~wxFilterInputStream() { } +size_t wxFilterInputStream::DoRead(void *buffer, size_t size) +{ + return m_parent_i_stream->Read(buffer, size).LastRead(); +} + +off_t wxFilterInputStream::DoSeekInput(off_t pos, wxSeekMode mode) +{ + return m_parent_i_stream->SeekI(pos, mode); +} + +off_t wxFilterInputStream::DoTellInput() const +{ + return m_parent_i_stream->TellI(); +} + + // ---------------------------------------------------------------------------- // wxFilterOutputStream // ---------------------------------------------------------------------------- wxFilterOutputStream::wxFilterOutputStream(wxOutputStream& stream) - : wxOutputStream() + : wxOutputStream(NULL) { m_parent_o_stream = &stream; + m_o_streambuf = stream.OutputStreamBuffer(); } wxFilterOutputStream::~wxFilterOutputStream() { } + +size_t wxFilterOutputStream::DoWrite(const void *buffer, size_t size) +{ + return m_parent_o_stream->Write(buffer, size).LastWrite(); +} + +off_t wxFilterOutputStream::DoSeekOutput(off_t pos, wxSeekMode mode) +{ + return m_parent_o_stream->SeekO(pos, mode); +} + +off_t wxFilterOutputStream::DoTellOutput() const +{ + return m_parent_o_stream->TellO(); +} + +// ---------------------------------------------------------------------------- +// Some IOManip function +// ---------------------------------------------------------------------------- + +wxOutputStream& wxEndL(wxOutputStream& stream) +{ +#ifdef __MSW__ + return stream.Write("\r\n", 2); +#else + return stream.Write("\n", 1); +#endif +} diff --git a/src/common/zstream.cpp b/src/common/zstream.cpp index 2db13338a3..ea64071eb7 100644 --- a/src/common/zstream.cpp +++ b/src/common/zstream.cpp @@ -17,11 +17,14 @@ #include #include #include +#include "zlib.h" #ifdef __BORLANDC__ #pragma hdrstop #endif +#define ZSTREAM_BUFFER_SIZE 1024 + ////////////////////// // wxZlibInputStream ////////////////////// @@ -31,6 +34,10 @@ wxZlibInputStream::wxZlibInputStream(wxInputStream& stream) { int err; + // I need a private stream buffer. + m_i_streambuf = new wxStreamBuffer(*this); + m_i_destroybuf = TRUE; + m_inflate.zalloc = (alloc_func)0; m_inflate.zfree = (free_func)0; m_inflate.opaque = (voidpf)0; @@ -41,7 +48,11 @@ wxZlibInputStream::wxZlibInputStream(wxInputStream& stream) return; } + m_z_buffer = new unsigned char[ZSTREAM_BUFFER_SIZE]; + m_z_size = ZSTREAM_BUFFER_SIZE; + m_inflate.avail_in = 0; + m_inflate.next_in = NULL; } wxZlibInputStream::~wxZlibInputStream() @@ -49,50 +60,35 @@ wxZlibInputStream::~wxZlibInputStream() inflateEnd(&m_inflate); } -wxInputStream& wxZlibInputStream::Read(void *buffer, size_t size) +size_t wxZlibInputStream::DoRead(void *buffer, size_t size) { int err; m_inflate.next_out = (unsigned char *)buffer; m_inflate.avail_out = size; - m_eof = FALSE; while (m_inflate.avail_out > 0) { if (m_inflate.avail_in == 0) { - wxFilterInputStream::Read(m_z_buffer, m_z_size); + + m_parent_i_stream->Read(m_z_buffer, m_z_size); m_inflate.next_in = m_z_buffer; - m_inflate.avail_in = wxFilterInputStream::LastRead(); - if (wxFilterInputStream::Eof()) { - m_lastread = size - m_inflate.avail_out; - return *this; - } + m_inflate.avail_in = m_parent_i_stream->LastRead(); + + if (m_parent_i_stream->Eof()) + return (size - m_inflate.avail_in); } err = inflate(&m_inflate, Z_FINISH); - if (err == Z_STREAM_END) { - m_lastread = size - m_inflate.avail_out; - m_eof = TRUE; - return *this; - } + if (err == Z_STREAM_END) + return (size - m_inflate.avail_in); } - m_lastread = size; - return *this; -} - -off_t wxZlibInputStream::SeekI(off_t WXUNUSED(pos), wxSeekMode WXUNUSED(mode)) -{ - return 0; -} - -off_t wxZlibInputStream::TellI() const -{ - return 0; + return size-m_inflate.avail_in; } bool wxZlibInputStream::Eof() const { if (!m_eof) - return wxFilterInputStream::Eof(); + return m_parent_i_stream->Eof(); return m_eof; } @@ -105,6 +101,9 @@ wxZlibOutputStream::wxZlibOutputStream(wxOutputStream& stream) { int err; + m_o_streambuf = new wxStreamBuffer(*this); + m_o_destroybuf = TRUE; + m_deflate.zalloc = (alloc_func)0; m_deflate.zfree = (free_func)0; m_deflate.opaque = (voidpf)0; @@ -114,6 +113,10 @@ wxZlibOutputStream::wxZlibOutputStream(wxOutputStream& stream) deflateEnd(&m_deflate); return; } + + m_z_buffer = new unsigned char[ZSTREAM_BUFFER_SIZE]; + m_z_size = ZSTREAM_BUFFER_SIZE; + m_deflate.avail_in = 0; m_deflate.next_out = m_z_buffer; m_deflate.avail_out = m_z_size; @@ -123,72 +126,67 @@ wxZlibOutputStream::~wxZlibOutputStream() { int err; - while (1) { - err = deflate(&m_deflate, Z_FINISH); - if (err == Z_STREAM_END) - break; - if (err < 0) { - wxDebugMsg("wxZlibOutputStream: error during final deflate"); - break; - } - if (m_deflate.avail_out == 0) { - wxFilterOutputStream::Write(m_z_buffer, m_z_size); - if (wxFilterOutputStream::Bad()) { - wxDebugMsg("wxZlibOutputStream: error during final write"); - break; - } - m_deflate.next_out = m_z_buffer; - m_deflate.avail_out = m_z_size; - } + Sync(); + + err = deflate(&m_deflate, Z_FINISH); + if (err != Z_STREAM_END) { + wxDebugMsg("wxZlibOutputStream: an error occured while we was closing " + "the stream.\n"); + return; } - wxFilterOutputStream::Write(m_z_buffer, m_z_size-m_deflate.avail_out); deflateEnd(&m_deflate); + + delete[] m_z_buffer; } -wxOutputStream& wxZlibOutputStream::Write(const void *buffer, size_t size) +void wxZlibOutputStream::Sync() +{ + int err; + + m_parent_o_stream->Write(m_z_buffer, m_z_size-m_deflate.avail_out); + m_deflate.next_out = m_z_buffer; + m_deflate.avail_out = m_z_size; + + err = deflate(&m_deflate, Z_FULL_FLUSH); + if (err != Z_OK) { + m_bad = TRUE; + return; + } + + m_parent_o_stream->Write(m_z_buffer, m_z_size-m_deflate.avail_out); + m_deflate.next_out = m_z_buffer; + m_deflate.avail_out = m_z_size; +} + +size_t wxZlibOutputStream::DoWrite(const void *buffer, size_t size) { int err; m_deflate.next_in = (unsigned char *)buffer; m_deflate.avail_in = size; - m_bad = FALSE; while (m_deflate.avail_in > 0) { + if (m_deflate.avail_out == 0) { - wxFilterOutputStream::Write(m_z_buffer, m_z_size); - if (wxFilterOutputStream::Bad()) { - m_lastwrite = size - m_deflate.avail_in; - return *this; - } - + m_parent_o_stream->Write(m_z_buffer, m_z_size); + if (m_parent_o_stream->Bad()) + return (size - m_deflate.avail_in); + m_deflate.next_out = m_z_buffer; m_deflate.avail_out = m_z_size; } + err = deflate(&m_deflate, Z_NO_FLUSH); - if (err < 0) { - m_bad = TRUE; - m_lastwrite = size - m_deflate.avail_in; - return *this; - } + if (err != Z_OK) + return (size - m_deflate.avail_in); } - m_lastwrite = size; - return *this; -} - -off_t wxZlibOutputStream::SeekO(off_t WXUNUSED(pos), wxSeekMode WXUNUSED(mode)) -{ - return 0; -} - -off_t wxZlibOutputStream::TellO() const -{ - return 0; + return size; } bool wxZlibOutputStream::Bad() const { if (!m_bad) - return wxFilterOutputStream::Bad(); + return m_parent_o_stream->Bad(); return m_bad; }