m_buffer_start =
m_buffer_end =
m_buffer_pos = NULL;
- m_buffer_size = 0;
// if we are going to allocate the buffer, we should free it later as well
m_destroybuf = true;
m_fixed = true;
}
-wxStreamBuffer::wxStreamBuffer(BufMode mode)
+void wxStreamBuffer::InitWithStream(wxStreamBase& stream, BufMode mode)
{
Init();
- m_stream = NULL;
+ m_stream = &stream;
m_mode = mode;
- m_flushable = false;
+ m_flushable = true;
}
-wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
+wxStreamBuffer::wxStreamBuffer(BufMode mode)
{
Init();
- m_stream = &stream;
+ m_stream = NULL;
m_mode = mode;
- m_flushable = true;
+ m_flushable = false;
}
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_buffer_start = (char *)start;
m_buffer_end = m_buffer_start + len;
- m_buffer_size = len;
-
// if we own it, we free it
m_destroybuf = takeOwnership;
: m_buffer_start;
}
+void wxStreamBuffer::Truncate()
+{
+ size_t new_size = m_buffer_pos - m_buffer_start;
+ if ( m_buffer_pos == m_buffer_end )
+ return;
+
+ if ( !new_size )
+ {
+ FreeBuffer();
+ InitBuffer();
+ return;
+ }
+
+ char *new_start = (char *)realloc(m_buffer_start, new_size);
+ wxCHECK_RET( new_size, _T("shrinking buffer shouldn't fail") );
+
+ m_buffer_start = new_start;
+ m_buffer_end = m_buffer_start + new_size;
+ m_buffer_pos = m_buffer_end;
+}
+
// fill the buffer with as much data as possible (only for read buffers)
bool wxStreamBuffer::FillBuffer()
{
if ( !inStream )
return false;
- size_t count = inStream->OnSysRead(m_buffer_start, m_buffer_size);
+ size_t count = inStream->OnSysRead(GetBufferStart(), GetBufferSize());
if ( !count )
return false;
else // !m_fixed
{
// realloc the buffer to have enough space for the data
- size_t delta = m_buffer_pos - m_buffer_start;
-
- char *startOld = m_buffer_start;
- m_buffer_size += size;
- m_buffer_start = (char *)realloc(m_buffer_start, m_buffer_size);
- if ( !m_buffer_start )
+ if ( m_buffer_pos + size > m_buffer_end )
{
- // don't leak memory if realloc() failed
- m_buffer_start = startOld;
- m_buffer_size -= size;
+ size_t delta = m_buffer_pos - m_buffer_start;
+ size_t new_size = delta + size;
- // what else can we do?
- return;
- }
+ char *startOld = m_buffer_start;
+ m_buffer_start = (char *)realloc(m_buffer_start, new_size);
+ if ( !m_buffer_start )
+ {
+ // don't leak memory if realloc() failed
+ m_buffer_start = startOld;
- // adjust the pointers invalidated by realloc()
- m_buffer_pos = m_buffer_start + delta;
- m_buffer_end = m_buffer_start + m_buffer_size;
+ // what else can we do?
+ return;
+ }
+
+ // adjust the pointers invalidated by realloc()
+ m_buffer_pos = m_buffer_start + delta;
+ m_buffer_end = m_buffer_start + new_size;
+ } // else: the buffer is big enough
}
}
// wxStreamBase
// ----------------------------------------------------------------------------
+IMPLEMENT_ABSTRACT_CLASS(wxStreamBase, wxObject)
+
wxStreamBase::wxStreamBase()
{
m_lasterror = wxSTREAM_NO_ERROR;
// wxInputStream
// ----------------------------------------------------------------------------
+IMPLEMENT_ABSTRACT_CLASS(wxInputStream, wxStreamBase)
+
wxInputStream::wxInputStream()
{
m_wback = NULL;
return Ungetch(&c, sizeof(c)) != 0;
}
-char wxInputStream::GetC()
+int wxInputStream::GetC()
{
- char c;
+ unsigned char c;
Read(&c, sizeof(c));
- return c;
+ return LastRead() ? c : wxEOF;
}
wxInputStream& wxInputStream::Read(void *buf, size_t size)
wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
{
+ size_t lastcount = 0;
char buf[BUF_TEMP_SIZE];
for ( ;; )
if ( stream_out.Write(buf, bytes_read).LastWrite() != bytes_read )
break;
+
+ lastcount += bytes_read;
}
+ m_lastcount = lastcount;
+
return *this;
}
// wxOutputStream
// ----------------------------------------------------------------------------
+IMPLEMENT_ABSTRACT_CLASS(wxOutputStream, wxStreamBase)
+
wxOutputStream::wxOutputStream()
{
}
// wxCountingOutputStream
// ----------------------------------------------------------------------------
+IMPLEMENT_DYNAMIC_CLASS(wxCountingOutputStream, wxOutputStream)
+
wxCountingOutputStream::wxCountingOutputStream ()
{
m_currentPos = 0;
// wxFilterInputStream
// ----------------------------------------------------------------------------
+IMPLEMENT_ABSTRACT_CLASS(wxFilterInputStream, wxInputStream)
+
wxFilterInputStream::wxFilterInputStream()
: m_parent_i_stream(NULL),
m_owns(false)
// wxFilterOutputStream
// ----------------------------------------------------------------------------
+IMPLEMENT_ABSTRACT_CLASS(wxFilterOutputStream, wxOutputStream)
+
wxFilterOutputStream::wxFilterOutputStream()
: m_parent_o_stream(NULL),
m_owns(false)
}
// ----------------------------------------------------------------------------
-// wxFilterClassFactory
+// wxFilterClassFactoryBase
// ----------------------------------------------------------------------------
-IMPLEMENT_ABSTRACT_CLASS(wxFilterClassFactory, wxObject)
+IMPLEMENT_ABSTRACT_CLASS(wxFilterClassFactoryBase, wxObject)
-wxFilterClassFactory *wxFilterClassFactory::sm_first = NULL;
+wxString wxFilterClassFactoryBase::PopExtension(const wxString& location) const
+{
+ return location.substr(0, FindExtension(location));
+}
-bool wxFilterClassFactory::CanHandle(const wxChar *protocol,
- wxStreamProtocolType type) const
+wxString::size_type wxFilterClassFactoryBase::FindExtension(
+ const wxString& location) const
{
- if (type == wxSTREAM_FILEEXTENSION)
+ for (const wxChar *const *p = GetProtocols(wxSTREAM_FILEEXT); *p; p++)
{
- size_t len = wxStrlen(protocol);
+ if ( location.EndsWith(*p) )
+ return location.length() - wxStrlen(*p);
+ }
- for (const wxChar * const *p = GetProtocols(type); p && *p; p++)
- {
- size_t l = wxStrlen(*p);
+ return wxString::npos;
+}
- if (l <= len && wxStrcmp(*p, protocol + len - l) == 0)
- return true;
- }
- }
+bool wxFilterClassFactoryBase::CanHandle(const wxString& protocol,
+ wxStreamProtocolType type) const
+{
+ if (type == wxSTREAM_FILEEXT)
+ return FindExtension(protocol) != wxString::npos;
else
- {
- for (const wxChar * const *p = GetProtocols(type); p && *p; p++)
- if (wxStrcmp(*p, protocol) == 0)
+ for (const wxChar *const *p = GetProtocols(type); *p; p++)
+ if (protocol == *p)
return true;
- }
return false;
}
+// ----------------------------------------------------------------------------
+// wxFilterClassFactory
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxFilterClassFactory, wxFilterClassFactoryBase)
+
+wxFilterClassFactory *wxFilterClassFactory::sm_first = NULL;
+
void wxFilterClassFactory::Remove()
{
if (m_next != this)
// wxBufferedInputStream
// ----------------------------------------------------------------------------
-wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s,
+namespace
+{
+
+// helper function used for initializing the buffer used by
+// wxBufferedInput/OutputStream: it simply returns the provided buffer if it's
+// not NULL or creates a buffer of the given size otherwise
+template <typename T>
+wxStreamBuffer *
+CreateBufferIfNeeded(T& stream, wxStreamBuffer *buffer, size_t bufsize = 1024)
+{
+ return buffer ? buffer : new wxStreamBuffer(stream, bufsize);
+}
+
+} // anonymous namespace
+
+wxBufferedInputStream::wxBufferedInputStream(wxInputStream& stream,
wxStreamBuffer *buffer)
- : wxFilterInputStream(s)
+ : wxFilterInputStream(stream)
{
- 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 = CreateBufferIfNeeded(*this, buffer);
+}
- m_i_streambuf->SetBufferIO(1024);
- }
+wxBufferedInputStream::wxBufferedInputStream(wxInputStream& stream,
+ size_t bufsize)
+ : wxFilterInputStream(stream)
+{
+ m_i_streambuf = CreateBufferIfNeeded(*this, NULL, bufsize);
}
wxBufferedInputStream::~wxBufferedInputStream()
size -= m_lastcount;
buf = (char *)buf + m_lastcount;
- // the call to wxStreamBuffer::Read() below will reset our m_lastcount,
- // so save it
+ // the call to wxStreamBuffer::Read() below may reset our m_lastcount
+ // (but it also may not do it if the buffer is associated to another
+ // existing stream and wasn't created by us), so save it
size_t countOld = m_lastcount;
- m_i_streambuf->Read(buf, size);
+ // the new count of the bytes read is the count of bytes read this time
+ m_lastcount = m_i_streambuf->Read(buf, size);
+ // plus those we had read before
m_lastcount += countOld;
}
// wxBufferedOutputStream
// ----------------------------------------------------------------------------
-wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& s,
+wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& stream,
wxStreamBuffer *buffer)
- : wxFilterOutputStream(s)
+ : wxFilterOutputStream(stream)
{
- if ( buffer )
- {
- m_o_streambuf = buffer;
- }
- else // create a default one
- {
- m_o_streambuf = new wxStreamBuffer(*this, wxStreamBuffer::write);
+ m_o_streambuf = CreateBufferIfNeeded(*this, buffer);
+}
- m_o_streambuf->SetBufferIO(1024);
- }
+wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream& stream,
+ size_t bufsize)
+ : wxFilterOutputStream(stream)
+{
+ m_o_streambuf = CreateBufferIfNeeded(*this, NULL, bufsize);
}
wxBufferedOutputStream::~wxBufferedOutputStream()