+ if (m_owns)
+ delete m_parent_o_stream;
+}
+
+// ----------------------------------------------------------------------------
+// wxFilterClassFactoryBase
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxFilterClassFactoryBase, wxObject)
+
+wxString wxFilterClassFactoryBase::PopExtension(const wxString& location) const
+{
+ return location.substr(0, FindExtension(location));
+}
+
+wxString::size_type wxFilterClassFactoryBase::FindExtension(
+ const wxChar *location) const
+{
+ size_t len = wxStrlen(location);
+
+ for (const wxChar *const *p = GetProtocols(wxSTREAM_FILEEXT); *p; p++)
+ {
+ size_t l = wxStrlen(*p);
+
+ if (l <= len && wxStrcmp(*p, location + len - l) == 0)
+ return len - l;
+ }
+
+ return wxString::npos;
+}
+
+bool wxFilterClassFactoryBase::CanHandle(const wxChar *protocol,
+ wxStreamProtocolType type) const
+{
+ if (type == wxSTREAM_FILEEXT)
+ return FindExtension(protocol) != wxString::npos;
+ else
+ for (const wxChar *const *p = GetProtocols(type); *p; p++)
+ if (wxStrcmp(*p, protocol) == 0)
+ return true;
+
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+// wxFilterClassFactory
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxFilterClassFactory, wxFilterClassFactoryBase)
+
+wxFilterClassFactory *wxFilterClassFactory::sm_first = NULL;
+
+void wxFilterClassFactory::Remove()
+{
+ if (m_next != this)
+ {
+ wxFilterClassFactory **pp = &sm_first;
+
+ while (*pp != this)
+ pp = &(*pp)->m_next;
+
+ *pp = m_next;
+
+ m_next = this;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// wxBufferedInputStream
+// ----------------------------------------------------------------------------
+
+wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s,
+ wxStreamBuffer *buffer)
+ : wxFilterInputStream(s)
+{
+ 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);
+ }
+}
+
+wxBufferedInputStream::~wxBufferedInputStream()
+{
+ m_parent_i_stream->SeekI(-(wxFileOffset)m_i_streambuf->GetBytesLeft(),
+ wxFromCurrent);
+
+ delete m_i_streambuf;
+}
+
+char wxBufferedInputStream::Peek()
+{
+ return m_i_streambuf->Peek();
+}
+
+wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size)
+{
+ // reset the error flag
+ Reset();
+
+ // first read from the already cached data
+ m_lastcount = GetWBack(buf, size);
+
+ // do we have to read anything more?
+ if ( m_lastcount < size )
+ {
+ size -= m_lastcount;
+ buf = (char *)buf + m_lastcount;
+
+ // 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;
+}
+
+wxFileOffset wxBufferedInputStream::SeekI(wxFileOffset pos, wxSeekMode mode)
+{
+ // RR: Look at wxInputStream for comments.
+
+ if (m_lasterror==wxSTREAM_EOF)
+ Reset();
+
+ if (m_wback)
+ {
+ wxLogDebug( wxT("Seeking in stream which has data written back to it.") );
+
+ free(m_wback);
+ m_wback = NULL;
+ m_wbacksize = 0;
+ m_wbackcur = 0;
+ }
+
+ return m_i_streambuf->Seek(pos, mode);
+}
+
+wxFileOffset wxBufferedInputStream::TellI() const
+{
+ wxFileOffset pos = m_i_streambuf->Tell();
+
+ if (pos != wxInvalidOffset)
+ pos -= (m_wbacksize - m_wbackcur);
+
+ return pos;
+}
+
+size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
+{
+ return m_parent_i_stream->Read(buffer, bufsize).LastRead();
+}
+
+wxFileOffset wxBufferedInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
+{
+ return m_parent_i_stream->SeekI(seek, mode);
+}
+
+wxFileOffset 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,
+ wxStreamBuffer *buffer)
+ : wxFilterOutputStream(s)
+{
+ 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()
+{
+ Sync();
+ delete m_o_streambuf;
+}
+
+bool wxBufferedOutputStream::Close()
+{
+ Sync();
+ return IsOk();
+}
+
+
+wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
+{
+ m_lastcount = 0;
+ m_o_streambuf->Write(buffer, size);
+ return *this;
+}
+
+wxFileOffset wxBufferedOutputStream::SeekO(wxFileOffset pos, wxSeekMode mode)
+{
+ Sync();
+ return m_o_streambuf->Seek(pos, mode);
+}
+
+wxFileOffset wxBufferedOutputStream::TellO() const
+{
+ return m_o_streambuf->Tell();
+}
+
+void wxBufferedOutputStream::Sync()
+{
+ m_o_streambuf->FlushBuffer();
+ m_parent_o_stream->Sync();
+}
+
+size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
+{
+ return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
+}
+
+wxFileOffset wxBufferedOutputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
+{
+ return m_parent_o_stream->SeekO(seek, mode);
+}
+
+wxFileOffset wxBufferedOutputStream::OnSysTell() const
+{
+ return m_parent_o_stream->TellO();
+}
+
+wxFileOffset wxBufferedOutputStream::GetLength() const
+{
+ return m_parent_o_stream->GetLength() + m_o_streambuf->GetIntPosition();
+}
+
+void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer *buffer)
+{
+ wxCHECK_RET( buffer, _T("wxBufferedOutputStream needs buffer") );
+
+ delete m_o_streambuf;
+ m_o_streambuf = buffer;