]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/stream.cpp
Updated list of subprojects.
[wxWidgets.git] / src / common / stream.cpp
index 3cf1db7f2749d40f527e22325b374170bcef9949..18bcc6f518478364b5e9b22848d3fd3aa71fcfdc 100644 (file)
@@ -7,7 +7,7 @@
 // Created:     11/07/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Guilhem Lavaux
 // Created:     11/07/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Guilhem Lavaux
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 // headers
 // ----------------------------------------------------------------------------
 
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
-    #pragma implementation "stream.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-  #pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #endif
 
+#if wxUSE_STREAMS
+
+#include "wx/stream.h"
+
 #ifndef WX_PRECOMP
 #ifndef WX_PRECOMP
-  #include "wx/defs.h"
+    #include "wx/log.h"
 #endif
 
 #endif
 
-#if wxUSE_STREAMS
-
 #include <ctype.h>
 #include <ctype.h>
-#include "wx/stream.h"
 #include "wx/datstrm.h"
 #include "wx/textfile.h"
 
 #include "wx/datstrm.h"
 #include "wx/textfile.h"
 
@@ -45,7 +42,7 @@
 // ----------------------------------------------------------------------------
 
 // the temporary buffer size used when copying from stream to stream
 // ----------------------------------------------------------------------------
 
 // the temporary buffer size used when copying from stream to stream
-#define BUF_TEMP_SIZE 10000
+#define BUF_TEMP_SIZE 4096
 
 // ============================================================================
 // implementation
 
 // ============================================================================
 // implementation
@@ -57,7 +54,7 @@
 
 void wxStreamBuffer::SetError(wxStreamError err)
 {
 
 void wxStreamBuffer::SetError(wxStreamError err)
 {
-   if ( m_stream->m_lasterror == wxStream_NOERROR )
+   if ( m_stream && m_stream->m_lasterror == wxSTREAM_NO_ERROR )
        m_stream->m_lasterror = err;
 }
 
        m_stream->m_lasterror = err;
 }
 
@@ -68,51 +65,42 @@ void wxStreamBuffer::InitBuffer()
     m_buffer_pos = NULL;
     m_buffer_size = 0;
 
     m_buffer_pos = NULL;
     m_buffer_size = 0;
 
-    // there is nothing to destroy anyhow
-    m_destroybuf = FALSE;
+    // if we are going to allocate the buffer, we should free it later as well
+    m_destroybuf = true;
 }
 
 void wxStreamBuffer::Init()
 {
     InitBuffer();
 
 }
 
 void wxStreamBuffer::Init()
 {
     InitBuffer();
 
-    m_fixed = TRUE;
+    m_fixed = true;
 }
 
 }
 
-wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
+wxStreamBuffer::wxStreamBuffer(BufMode mode)
 {
     Init();
 
 {
     Init();
 
-    m_stream = &stream;
+    m_stream = NULL;
     m_mode = mode;
 
     m_mode = mode;
 
-    m_flushable = TRUE;
-    m_destroystream = FALSE;
+    m_flushable = false;
 }
 
 }
 
-wxStreamBuffer::wxStreamBuffer(BufMode mode)
+wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
 {
     Init();
 
 {
     Init();
 
-    wxASSERT_MSG(mode != read_write, wxT("you have to use the other ctor for read_write mode") );
-    if ( mode == read )
-        m_stream = new wxInputStream;
-    else if ( mode == write)
-        m_stream = new wxOutputStream;
-    else
-        m_stream = NULL;
-
+    m_stream = &stream;
     m_mode = mode;
 
     m_mode = mode;
 
-    m_flushable = FALSE;
-    m_destroystream = TRUE;
+    m_flushable = true;
 }
 
 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer)
 {
 }
 
 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer)
 {
-    // doing this has big chances to lead to a crashwhen the source buffer is
+    // doing this has big chances to lead to a crash when the source buffer is
     // destroyed (otherwise assume the caller knows what he does)
     // destroyed (otherwise assume the caller knows what he does)
-    wxASSERT_MSG( !buffer.m_destroybuf && !buffer.m_destroystream,
+    wxASSERT_MSG( !buffer.m_destroybuf,
                   _T("it's a bad idea to copy this buffer") );
 
     m_buffer_start = buffer.m_buffer_start;
                   _T("it's a bad idea to copy this buffer") );
 
     m_buffer_start = buffer.m_buffer_start;
@@ -123,22 +111,21 @@ wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer& buffer)
     m_flushable = buffer.m_flushable;
     m_stream = buffer.m_stream;
     m_mode = buffer.m_mode;
     m_flushable = buffer.m_flushable;
     m_stream = buffer.m_stream;
     m_mode = buffer.m_mode;
-    m_destroybuf = FALSE;
-    m_destroystream = FALSE;
+    m_destroybuf = false;
 }
 
 void wxStreamBuffer::FreeBuffer()
 {
     if ( m_destroybuf )
 }
 
 void wxStreamBuffer::FreeBuffer()
 {
     if ( m_destroybuf )
+    {
         free(m_buffer_start);
         free(m_buffer_start);
+        m_buffer_start = NULL;
+    }
 }
 
 wxStreamBuffer::~wxStreamBuffer()
 {
     FreeBuffer();
 }
 
 wxStreamBuffer::~wxStreamBuffer()
 {
     FreeBuffer();
-
-    if ( m_destroystream )
-        delete m_stream;
 }
 
 wxInputStream *wxStreamBuffer::GetInputStream() const
 }
 
 wxInputStream *wxStreamBuffer::GetInputStream() const
@@ -179,29 +166,30 @@ void wxStreamBuffer::SetBufferIO(void *start,
 
 void wxStreamBuffer::SetBufferIO(size_t bufsize)
 {
 
 void wxStreamBuffer::SetBufferIO(size_t bufsize)
 {
-    // start by freeing the old buffer
-    FreeBuffer();
-
     if ( bufsize )
     {
     if ( bufsize )
     {
-        SetBufferIO(malloc(bufsize), bufsize, TRUE /* take ownership */);
+        // this will free the old buffer and allocate the new one
+        SetBufferIO(malloc(bufsize), bufsize, true /* take ownership */);
     }
     else // no buffer size => no buffer
     {
     }
     else // no buffer size => no buffer
     {
+        // still free the old one
+        FreeBuffer();
         InitBuffer();
     }
 }
 
 void wxStreamBuffer::ResetBuffer()
 {
         InitBuffer();
     }
 }
 
 void wxStreamBuffer::ResetBuffer()
 {
-    wxCHECK_RET( m_stream, _T("should have a stream in wxStreamBuffer") );
+    if ( m_stream )
+    {
+        m_stream->Reset();
+        m_stream->m_lastcount = 0;
+    }
 
 
-    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;
+    m_buffer_pos = m_mode == read && m_flushable
+                        ? m_buffer_end
+                        : m_buffer_start;
 }
 
 // fill the buffer with as much data as possible (only for read buffers)
 }
 
 // fill the buffer with as much data as possible (only for read buffers)
@@ -209,39 +197,41 @@ bool wxStreamBuffer::FillBuffer()
 {
     wxInputStream *inStream = GetInputStream();
 
 {
     wxInputStream *inStream = GetInputStream();
 
-    wxCHECK_MSG( inStream, FALSE, _T("should have a stream in wxStreamBuffer") );
+    // It's legal to have no stream, so we don't complain about it just return false
+    if ( !inStream )
+        return false;
 
     size_t count = inStream->OnSysRead(m_buffer_start, m_buffer_size);
     if ( !count )
 
     size_t count = inStream->OnSysRead(m_buffer_start, m_buffer_size);
     if ( !count )
-        return FALSE;
+        return false;
 
     m_buffer_end = m_buffer_start + count;
     m_buffer_pos = m_buffer_start;
 
 
     m_buffer_end = m_buffer_start + count;
     m_buffer_pos = m_buffer_start;
 
-    return TRUE;
+    return true;
 }
 
 // write the buffer contents to the stream (only for write buffers)
 bool wxStreamBuffer::FlushBuffer()
 {
 }
 
 // write the buffer contents to the stream (only for write buffers)
 bool wxStreamBuffer::FlushBuffer()
 {
-    wxCHECK_MSG( m_flushable, FALSE, _T("can't flush this buffer") );
+    wxCHECK_MSG( m_flushable, false, _T("can't flush this buffer") );
 
     // FIXME: what is this check for? (VZ)
     if ( m_buffer_pos == m_buffer_start )
 
     // FIXME: what is this check for? (VZ)
     if ( m_buffer_pos == m_buffer_start )
-        return FALSE;
+        return false;
 
     wxOutputStream *outStream = GetOutputStream();
 
 
     wxOutputStream *outStream = GetOutputStream();
 
-    wxCHECK_MSG( outStream, FALSE, _T("should have a stream in wxStreamBuffer") );
+    wxCHECK_MSG( outStream, false, _T("should have a stream in wxStreamBuffer") );
 
     size_t current = m_buffer_pos - m_buffer_start;
     size_t count = outStream->OnSysWrite(m_buffer_start, current);
     if ( count != current )
 
     size_t current = m_buffer_pos - m_buffer_start;
     size_t count = outStream->OnSysWrite(m_buffer_start, current);
     if ( count != current )
-        return FALSE;
+        return false;
 
     m_buffer_pos = m_buffer_start;
 
 
     m_buffer_pos = m_buffer_start;
 
-    return TRUE;
+    return true;
 }
 
 size_t wxStreamBuffer::GetDataLeft()
 }
 
 size_t wxStreamBuffer::GetDataLeft()
@@ -270,6 +260,7 @@ void wxStreamBuffer::GetFromBuffer(void *buffer, size_t size)
 void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size)
 {
     size_t left = GetBytesLeft();
 void wxStreamBuffer::PutToBuffer(const void *buffer, size_t size)
 {
     size_t left = GetBytesLeft();
+
     if ( size > left )
     {
         if ( m_fixed )
     if ( size > left )
     {
         if ( m_fixed )
@@ -314,7 +305,7 @@ void wxStreamBuffer::PutChar(char c)
     // if we don't have buffer at all, just forward this call to the stream,
     if ( !HasBuffer() )
     {
     // if we don't have buffer at all, just forward this call to the stream,
     if ( !HasBuffer() )
     {
-        outStream->OnSysWrite(&c, 1);
+        outStream->OnSysWrite(&c, sizeof(c));
     }
     else
     {
     }
     else
     {
@@ -322,11 +313,11 @@ void wxStreamBuffer::PutChar(char c)
         if ( !GetDataLeft() && !FlushBuffer() )
         {
             // we don't
         if ( !GetDataLeft() && !FlushBuffer() )
         {
             // we don't
-            SetError(wxStream_WRITE_ERR);
+            SetError(wxSTREAM_WRITE_ERROR);
         }
         else
         {
         }
         else
         {
-            PutToBuffer(&c, 1);
+            PutToBuffer(&c, sizeof(c));
             m_stream->m_lastcount = 1;
         }
     }
             m_stream->m_lastcount = 1;
         }
     }
@@ -339,12 +330,12 @@ char wxStreamBuffer::Peek()
 
     if ( !GetDataLeft() )
     {
 
     if ( !GetDataLeft() )
     {
-        SetError(wxStream_READ_ERR);
+        SetError(wxSTREAM_READ_ERROR);
         return 0;
     }
 
     char c;
         return 0;
     }
 
     char c;
-    GetFromBuffer(&c, 1);
+    GetFromBuffer(&c, sizeof(c));
     m_buffer_pos--;
 
     return c;
     m_buffer_pos--;
 
     return c;
@@ -359,18 +350,18 @@ char wxStreamBuffer::GetChar()
     char c;
     if ( !HasBuffer() )
     {
     char c;
     if ( !HasBuffer() )
     {
-        inStream->OnSysRead(&c, 1);
+        inStream->OnSysRead(&c, sizeof(c));
     }
     else
     {
         if ( !GetDataLeft() )
         {
     }
     else
     {
         if ( !GetDataLeft() )
         {
-            SetError(wxStream_READ_ERR);
+            SetError(wxSTREAM_READ_ERROR);
             c = 0;
         }
         else
         {
             c = 0;
         }
         else
         {
-            GetFromBuffer(&c, 1);
+            GetFromBuffer(&c, sizeof(c));
             m_stream->m_lastcount = 1;
         }
     }
             m_stream->m_lastcount = 1;
         }
     }
@@ -380,16 +371,23 @@ char wxStreamBuffer::GetChar()
 
 size_t wxStreamBuffer::Read(void *buffer, size_t size)
 {
 
 size_t wxStreamBuffer::Read(void *buffer, size_t size)
 {
-    wxInputStream *inStream = GetInputStream();
+    wxASSERT_MSG( buffer, _T("Warning: Null pointer is about to be used") );
 
 
-    wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") );
+    /* Clear buffer first */
+    memset(buffer, 0x00, size);
 
     // lasterror is reset before all new IO calls
 
     // lasterror is reset before all new IO calls
-    m_stream->m_lasterror = wxStream_NOERROR;
+    if ( m_stream )
+        m_stream->Reset();
 
 
+    size_t readBytes;
     if ( !HasBuffer() )
     {
     if ( !HasBuffer() )
     {
-        m_stream->m_lastcount = inStream->OnSysRead(buffer, size);
+        wxInputStream *inStream = GetInputStream();
+
+        wxCHECK_MSG( inStream, 0, _T("should have a stream in wxStreamBuffer") );
+
+        readBytes = inStream->OnSysRead(buffer, size);
     }
     else // we have a buffer, use it
     {
     }
     else // we have a buffer, use it
     {
@@ -409,7 +407,7 @@ size_t wxStreamBuffer::Read(void *buffer, size_t size)
 
                 if ( !FillBuffer() )
                 {
 
                 if ( !FillBuffer() )
                 {
-                    SetError(wxStream_EOF);
+                    SetError(wxSTREAM_EOF);
                     break;
                 }
             }
                     break;
                 }
             }
@@ -420,10 +418,13 @@ size_t wxStreamBuffer::Read(void *buffer, size_t size)
             }
         }
 
             }
         }
 
-        m_stream->m_lastcount = orig_size - size;
+        readBytes = orig_size - size;
     }
 
     }
 
-    return m_stream->m_lastcount;
+    if ( m_stream )
+        m_stream->m_lastcount = readBytes;
+
+    return readBytes;
 }
 
 // this should really be called "Copy()"
 }
 
 // this should really be called "Copy()"
@@ -437,7 +438,7 @@ size_t wxStreamBuffer::Read(wxStreamBuffer *dbuf)
 
     do
     {
 
     do
     {
-        nRead = Read(dbuf, WXSIZEOF(buf));
+        nRead = Read(buf, WXSIZEOF(buf));
         if ( nRead )
         {
             nRead = dbuf->Write(buf, nRead);
         if ( nRead )
         {
             nRead = dbuf->Write(buf, nRead);
@@ -451,17 +452,24 @@ size_t wxStreamBuffer::Read(wxStreamBuffer *dbuf)
 
 size_t wxStreamBuffer::Write(const void *buffer, size_t size)
 {
 
 size_t wxStreamBuffer::Write(const void *buffer, size_t size)
 {
-    wxOutputStream *outStream = GetOutputStream();
+    wxASSERT_MSG( buffer, _T("Warning: Null pointer is about to be send") );
 
 
-    wxCHECK_MSG( outStream, 0, _T("should have a stream in wxStreamBuffer") );
+    if (m_stream)
+    {
+        // lasterror is reset before all new IO calls
+        m_stream->Reset();
+    }
 
 
-    // lasterror is reset before all new IO calls
-    m_stream->m_lasterror = wxStream_NOERROR;
+    size_t ret;
 
     if ( !HasBuffer() && m_fixed )
     {
 
     if ( !HasBuffer() && m_fixed )
     {
+        wxOutputStream *outStream = GetOutputStream();
+
+        wxCHECK_MSG( outStream, 0, _T("should have a stream in wxStreamBuffer") );
+
         // no buffer, just forward the call to the stream
         // no buffer, just forward the call to the stream
-        m_stream->m_lastcount = outStream->OnSysWrite(buffer, size);
+        ret = outStream->OnSysWrite(buffer, size);
     }
     else // we [may] have a buffer, use it
     {
     }
     else // we [may] have a buffer, use it
     {
@@ -479,6 +487,7 @@ size_t wxStreamBuffer::Write(const void *buffer, size_t size)
             //
             // FIXME: fine, but if it fails we should (re)try writing it by
             //        chunks as this will (hopefully) always work (VZ)
             //
             // FIXME: fine, but if it fails we should (re)try writing it by
             //        chunks as this will (hopefully) always work (VZ)
+
             if ( size > left && m_fixed )
             {
                 PutToBuffer(buffer, left);
             if ( size > left && m_fixed )
             {
                 PutToBuffer(buffer, left);
@@ -487,7 +496,7 @@ size_t wxStreamBuffer::Write(const void *buffer, size_t size)
 
                 if ( !FlushBuffer() )
                 {
 
                 if ( !FlushBuffer() )
                 {
-                    SetError(wxStream_WRITE_ERR);
+                    SetError(wxSTREAM_WRITE_ERROR);
 
                     break;
                 }
 
                     break;
                 }
@@ -501,10 +510,16 @@ size_t wxStreamBuffer::Write(const void *buffer, size_t size)
             }
         }
 
             }
         }
 
-        m_stream->m_lastcount = orig_size - size;
+        ret = orig_size - size;
+    }
+
+    if (m_stream)
+    {
+        // i am not entirely sure what we do this for
+        m_stream->m_lastcount = ret;
     }
 
     }
 
-    return m_stream->m_lastcount;
+    return ret;
 }
 
 size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf)
 }
 
 size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf)
@@ -542,11 +557,11 @@ size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf)
     return total;
 }
 
     return total;
 }
 
-off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
+wxFileOffset wxStreamBuffer::Seek(wxFileOffset pos, wxSeekMode mode)
 {
 {
-    off_t ret_off, diff;
+    wxFileOffset ret_off, diff;
 
 
-    off_t last_access = GetLastAccess();
+    wxFileOffset last_access = GetLastAccess();
 
     if ( !m_flushable )
     {
 
     if ( !m_flushable )
     {
@@ -571,7 +586,9 @@ off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
         }
         if (diff < 0 || diff > last_access)
             return wxInvalidOffset;
         }
         if (diff < 0 || diff > last_access)
             return wxInvalidOffset;
-        SetIntPosition(diff);
+        size_t int_diff = wx_truncate_cast(size_t, diff);
+        wxCHECK_MSG( (wxFileOffset)int_diff == diff, wxInvalidOffset, wxT("huge file not supported") );
+        SetIntPosition(int_diff);
         return diff;
     }
 
         return diff;
     }
 
@@ -596,7 +613,9 @@ off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
             }
             else
             {
             }
             else
             {
-                SetIntPosition(diff);
+                size_t int_diff = wx_truncate_cast(size_t, diff);
+                wxCHECK_MSG( (wxFileOffset)int_diff == diff, wxInvalidOffset, wxT("huge file not supported") );
+                SetIntPosition(int_diff);
                 return pos;
             }
 
                 return pos;
             }
 
@@ -610,11 +629,21 @@ off_t wxStreamBuffer::Seek(off_t pos, wxSeekMode mode)
     return wxInvalidOffset;
 }
 
     return wxInvalidOffset;
 }
 
-off_t wxStreamBuffer::Tell() const
+wxFileOffset wxStreamBuffer::Tell() const
 {
 {
-    off_t pos = m_stream->OnSysTell();
-    if ( pos == wxInvalidOffset )
-        return wxInvalidOffset;
+    wxFileOffset pos;
+
+    // ask the stream for position if we have a real one
+    if ( m_stream )
+    {
+        pos = m_stream->OnSysTell();
+        if ( pos == wxInvalidOffset )
+            return wxInvalidOffset;
+    }
+    else // no associated stream
+    {
+        pos = 0;
+    }
 
     pos += GetIntPosition();
 
 
     pos += GetIntPosition();
 
@@ -630,7 +659,7 @@ off_t wxStreamBuffer::Tell() const
 
 wxStreamBase::wxStreamBase()
 {
 
 wxStreamBase::wxStreamBase()
 {
-    m_lasterror = wxStream_NOERROR;
+    m_lasterror = wxSTREAM_NO_ERROR;
     m_lastcount = 0;
 }
 
     m_lastcount = 0;
 }
 
@@ -638,12 +667,24 @@ wxStreamBase::~wxStreamBase()
 {
 }
 
 {
 }
 
-off_t wxStreamBase::OnSysSeek(off_t WXUNUSED(seek), wxSeekMode WXUNUSED(mode))
+size_t wxStreamBase::GetSize() const
+{
+    wxFileOffset length = GetLength();
+    if ( length == (wxFileOffset)wxInvalidOffset )
+        return 0;
+
+    const size_t len = wx_truncate_cast(size_t, length);
+    wxASSERT_MSG( len == length + size_t(0), _T("large files not supported") );
+
+    return len;
+}
+
+wxFileOffset wxStreamBase::OnSysSeek(wxFileOffset WXUNUSED(seek), wxSeekMode WXUNUSED(mode))
 {
     return wxInvalidOffset;
 }
 
 {
     return wxInvalidOffset;
 }
 
-off_t wxStreamBase::OnSysTell() const
+wxFileOffset wxStreamBase::OnSysTell() const
 {
     return wxInvalidOffset;
 }
 {
     return wxInvalidOffset;
 }
@@ -664,31 +705,19 @@ wxInputStream::~wxInputStream()
     free(m_wback);
 }
 
     free(m_wback);
 }
 
-size_t wxInputStream::OnSysRead(void * WXUNUSED(buffer),
-                                size_t WXUNUSED(bufsize))
+bool wxInputStream::CanRead() const
 {
 {
-    return 0;
+    // we don't know if there is anything to read or not and by default we
+    // prefer to be optimistic and try to read data unless we know for sure
+    // there is no more of it
+    return m_lasterror != wxSTREAM_EOF;
 }
 
 bool wxInputStream::Eof() const
 {
 }
 
 bool wxInputStream::Eof() const
 {
-    wxInputStream *self = wxConstCast(this, wxInputStream);
-
-    char c;
-    self->Read(&c, 1);
-
-    // some streams can know that they're at EOF before actually trying to
-    // read beyond the end of stream (e.g. files) while others have no way of
-    // knowing it, so to provide the same behaviour in all cases we only
-    // return TRUE from here if the character really couldn't be read
-    if ( !self->LastRead() && GetLastError() == wxSTREAM_EOF )
-    {
-        return TRUE;
-    }
-
-    self->Ungetch(c);
-
-    return FALSE;
+    // the only way the base class can know we're at EOF is when we'd already
+    // tried to read beyond it in which case last error is set accordingly
+    return GetLastError() == wxSTREAM_EOF;
 }
 
 char *wxInputStream::AllocSpaceWBack(size_t needed_size)
 }
 
 char *wxInputStream::AllocSpaceWBack(size_t needed_size)
@@ -702,14 +731,14 @@ char *wxInputStream::AllocSpaceWBack(size_t needed_size)
     if (!temp_b)
         return NULL;
 
     if (!temp_b)
         return NULL;
 
-    /* copy previous data (and free old buffer) if needed */
+    // 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);
     }
 
     if (m_wback)
     {
         memmove(temp_b + needed_size, m_wback + m_wbackcur, toget);
         free(m_wback);
     }
 
-    /* done */
+    // done
     m_wback = temp_b;
     m_wbackcur = 0;
     m_wbacksize = needed_size + toget;
     m_wback = temp_b;
     m_wbackcur = 0;
     m_wbacksize = needed_size + toget;
@@ -717,21 +746,26 @@ char *wxInputStream::AllocSpaceWBack(size_t needed_size)
     return m_wback;
 }
 
     return m_wback;
 }
 
-size_t wxInputStream::GetWBack(void *buf, size_t bsize)
+size_t wxInputStream::GetWBack(void *buf, size_t size)
 {
 {
+    wxASSERT_MSG( buf, _T("Warning: Null pointer is about to be used") );
+
+    /* Clear buffer first */
+    memset(buf, 0x00, size);
+
     if (!m_wback)
         return 0;
 
     // how many bytes do we have in the buffer?
     size_t toget = m_wbacksize - m_wbackcur;
 
     if (!m_wback)
         return 0;
 
     // how many bytes do we have in the buffer?
     size_t toget = m_wbacksize - m_wbackcur;
 
-    if ( bsize < toget )
+    if ( size < toget )
     {
         // we won't read everything
     {
         // we won't read everything
-        toget = bsize;
+        toget = size;
     }
 
     }
 
-    // copy the data from the cache 
+    // copy the data from the cache
     memcpy(buf, m_wback + m_wbackcur, toget);
 
     m_wbackcur += toget;
     memcpy(buf, m_wback + m_wbackcur, toget);
 
     m_wbackcur += toget;
@@ -750,52 +784,81 @@ size_t wxInputStream::GetWBack(void *buf, size_t bsize)
 
 size_t wxInputStream::Ungetch(const void *buf, size_t bufsize)
 {
 
 size_t wxInputStream::Ungetch(const void *buf, size_t bufsize)
 {
+    wxASSERT_MSG( buf, _T("Warning: Null pointer is about to be used in Ungetch()") );
+
+    if ( m_lasterror != wxSTREAM_NO_ERROR && m_lasterror != wxSTREAM_EOF )
+    {
+        // can't operate on this stream until the error is cleared
+        return 0;
+    }
+
     char *ptrback = AllocSpaceWBack(bufsize);
     if (!ptrback)
         return 0;
 
     char *ptrback = AllocSpaceWBack(bufsize);
     if (!ptrback)
         return 0;
 
+    // Eof() shouldn't return true any longer
+    if ( m_lasterror == wxSTREAM_EOF )
+        m_lasterror = wxSTREAM_NO_ERROR;
+
     memcpy(ptrback, buf, bufsize);
     return bufsize;
 }
 
 bool wxInputStream::Ungetch(char c)
 {
     memcpy(ptrback, buf, bufsize);
     return bufsize;
 }
 
 bool wxInputStream::Ungetch(char c)
 {
-    void *ptrback = AllocSpaceWBack(1);
-    if (!ptrback)
-        return FALSE;
-
-    *(char *)ptrback = c;
-    return TRUE;
+    return Ungetch(&c, sizeof(c)) != 0;
 }
 
 char wxInputStream::GetC()
 {
     char c;
 }
 
 char wxInputStream::GetC()
 {
     char c;
-    Read(&c, 1);
+    Read(&c, sizeof(c));
     return c;
 }
 
 wxInputStream& wxInputStream::Read(void *buf, size_t size)
 {
     return c;
 }
 
 wxInputStream& wxInputStream::Read(void *buf, size_t size)
 {
-    size_t retsize = GetWBack(buf, size);
-    if (retsize == size)
+    wxASSERT_MSG( buf, _T("Warning: Null pointer is about to be read") );
+
+    char *p = (char *)buf;
+    m_lastcount = 0;
+
+    size_t read = GetWBack(buf, size);
+    for ( ;; )
     {
     {
-        m_lastcount = size;
-        m_lasterror = wxStream_NOERROR;
-        return *this;
+        size -= read;
+        m_lastcount += read;
+        p += read;
+
+        if ( !size )
+        {
+            // we read the requested amount of data
+            break;
+        }
+
+        if ( p != buf && !CanRead() )
+        {
+            // we have already read something and we would block in OnSysRead()
+            // now: don't do it but return immediately
+            break;
+        }
+
+        read = OnSysRead(p, size);
+        if ( !read )
+        {
+            // no more data available
+            break;
+        }
     }
     }
-    size -= retsize;
-    buf = (char *)buf + retsize;
 
 
-    m_lastcount = OnSysRead(buf, size) + retsize;
     return *this;
 }
 
 char wxInputStream::Peek()
 {
     char c;
     return *this;
 }
 
 char wxInputStream::Peek()
 {
     char c;
-    Read(&c, 1);
-    if (m_lasterror == wxStream_NOERROR)
+    Read(&c, sizeof(c));
+    if (m_lasterror == wxSTREAM_NO_ERROR)
     {
         Ungetch(c);
         return c;
     {
         Ungetch(c);
         return c;
@@ -807,35 +870,45 @@ char wxInputStream::Peek()
 wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
 {
     char buf[BUF_TEMP_SIZE];
 wxInputStream& wxInputStream::Read(wxOutputStream& stream_out)
 {
     char buf[BUF_TEMP_SIZE];
-    size_t bytes_read = BUF_TEMP_SIZE;
 
 
-    while (bytes_read == BUF_TEMP_SIZE)
+    for ( ;; )
     {
     {
-        bytes_read = Read(buf, bytes_read).LastRead();
-        bytes_read = stream_out.Write(buf, bytes_read).LastWrite();
+        size_t bytes_read = Read(buf, WXSIZEOF(buf)).LastRead();
+        if ( !bytes_read )
+            break;
+
+        if ( stream_out.Write(buf, bytes_read).LastWrite() != bytes_read )
+            break;
     }
     }
+
     return *this;
 }
 
     return *this;
 }
 
-off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode)
+wxFileOffset wxInputStream::SeekI(wxFileOffset 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 ? */
+    // RR: This code is duplicated in wxBufferedInputStream. This is
+    // not really a good design, but buffered stream are different
+    // from all other in that they handle two stream-related objects,
+    // the stream buffer and parent stream.
+
+    // I don't know whether it should be put as well in wxFileInputStream::OnSysSeek
     if (m_lasterror==wxSTREAM_EOF)
     if (m_lasterror==wxSTREAM_EOF)
-        m_lasterror=wxSTREAM_NOERROR;
+        m_lasterror=wxSTREAM_NO_ERROR;
 
 
-    /* A call to SeekI() will automatically invalidate any previous call
-       to Ungetch(), otherwise it would be possible to SeekI() to one
+    /* RR: A call to SeekI() will automatically invalidate any previous
+       call to Ungetch(), otherwise it would be possible to SeekI() to
        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
        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...
-     */
+       anyway... */
+
     if (m_wback)
     {
     if (m_wback)
     {
+        wxLogDebug( wxT("Seeking in stream which has data written back to it.") );
+
         free(m_wback);
         m_wback = NULL;
         m_wbacksize = 0;
         free(m_wback);
         m_wback = NULL;
         m_wbacksize = 0;
@@ -845,10 +918,9 @@ off_t wxInputStream::SeekI(off_t pos, wxSeekMode mode)
     return OnSysSeek(pos, mode);
 }
 
     return OnSysSeek(pos, mode);
 }
 
-off_t wxInputStream::TellI() const
+wxFileOffset wxInputStream::TellI() const
 {
 {
-    /* GRG: Changed to make it compatible with the wback buffer */
-    off_t pos = OnSysTell();
+    wxFileOffset pos = OnSysTell();
 
     if (pos != wxInvalidOffset)
         pos -= (m_wbacksize - m_wbackcur);
 
     if (pos != wxInvalidOffset)
         pos -= (m_wbacksize - m_wbackcur);
@@ -877,7 +949,7 @@ size_t wxOutputStream::OnSysWrite(const void * WXUNUSED(buffer),
 
 void wxOutputStream::PutC(char c)
 {
 
 void wxOutputStream::PutC(char c)
 {
-    Write(&c, 1);
+    Write(&c, sizeof(c));
 }
 
 wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
 }
 
 wxOutputStream& wxOutputStream::Write(const void *buffer, size_t size)
@@ -892,12 +964,12 @@ wxOutputStream& wxOutputStream::Write(wxInputStream& stream_in)
     return *this;
 }
 
     return *this;
 }
 
-off_t wxOutputStream::TellO() const
+wxFileOffset wxOutputStream::TellO() const
 {
     return OnSysTell();
 }
 
 {
     return OnSysTell();
 }
 
-off_t wxOutputStream::SeekO(off_t pos, wxSeekMode mode)
+wxFileOffset wxOutputStream::SeekO(wxFileOffset pos, wxSeekMode mode)
 {
     return OnSysSeek(pos, mode);
 }
 {
     return OnSysSeek(pos, mode);
 }
@@ -916,7 +988,7 @@ wxCountingOutputStream::wxCountingOutputStream ()
      m_currentPos = 0;
 }
 
      m_currentPos = 0;
 }
 
-size_t wxCountingOutputStream::GetSize() const
+wxFileOffset wxCountingOutputStream::GetLength() const
 {
     return m_lastcount;
 }
 {
     return m_lastcount;
 }
@@ -931,20 +1003,24 @@ size_t wxCountingOutputStream::OnSysWrite(const void *WXUNUSED(buffer),
     return m_currentPos;
 }
 
     return m_currentPos;
 }
 
-off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode)
+wxFileOffset wxCountingOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
 {
 {
+    ssize_t new_pos = wx_truncate_cast(ssize_t, pos);
+
     switch ( mode )
     {
         case wxFromStart:
     switch ( mode )
     {
         case wxFromStart:
-            m_currentPos = pos;
+            wxCHECK_MSG( (wxFileOffset)new_pos == pos, wxInvalidOffset, wxT("huge position not supported") );
             break;
 
         case wxFromEnd:
             break;
 
         case wxFromEnd:
-            m_currentPos = m_lastcount + pos;
+            new_pos = m_lastcount + new_pos;
+            wxCHECK_MSG( (wxFileOffset)new_pos == (wxFileOffset)(m_lastcount + pos), wxInvalidOffset, wxT("huge position not supported") );
             break;
 
         case wxFromCurrent:
             break;
 
         case wxFromCurrent:
-            m_currentPos += pos;
+            new_pos = m_currentPos + new_pos;
+            wxCHECK_MSG( (wxFileOffset)new_pos == (wxFileOffset)(m_currentPos + pos), wxInvalidOffset, wxT("huge position not supported") );
             break;
 
         default:
             break;
 
         default:
@@ -952,13 +1028,15 @@ off_t wxCountingOutputStream::OnSysSeek(off_t pos, wxSeekMode mode)
             return wxInvalidOffset;
     }
 
             return wxInvalidOffset;
     }
 
+    m_currentPos = new_pos;
+
     if (m_currentPos > m_lastcount)
         m_lastcount = m_currentPos;
 
     return m_currentPos;
 }
 
     if (m_currentPos > m_lastcount)
         m_lastcount = m_currentPos;
 
     return m_currentPos;
 }
 
-off_t wxCountingOutputStream::OnSysTell() const
+wxFileOffset wxCountingOutputStream::OnSysTell() const
 {
     return m_currentPos;
 }
 {
     return m_currentPos;
 }
@@ -1022,7 +1100,7 @@ wxBufferedInputStream::wxBufferedInputStream(wxInputStream& s,
 
 wxBufferedInputStream::~wxBufferedInputStream()
 {
 
 wxBufferedInputStream::~wxBufferedInputStream()
 {
-    m_parent_i_stream->SeekI(-(off_t)m_i_streambuf->GetBytesLeft(),
+    m_parent_i_stream->SeekI(-(wxFileOffset)m_i_streambuf->GetBytesLeft(),
                              wxFromCurrent);
 
     delete m_i_streambuf;
                              wxFromCurrent);
 
     delete m_i_streambuf;
@@ -1036,7 +1114,7 @@ char wxBufferedInputStream::Peek()
 wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size)
 {
     // reset the error flag
 wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size)
 {
     // reset the error flag
-    m_lasterror = wxStream_NOERROR;
+    Reset();
 
     // first read from the already cached data
     m_lastcount = GetWBack(buf, size);
 
     // first read from the already cached data
     m_lastcount = GetWBack(buf, size);
@@ -1059,14 +1137,34 @@ wxInputStream& wxBufferedInputStream::Read(void *buf, size_t size)
     return *this;
 }
 
     return *this;
 }
 
-off_t wxBufferedInputStream::SeekI(off_t pos, wxSeekMode mode)
+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);
 }
 
     return m_i_streambuf->Seek(pos, mode);
 }
 
-off_t wxBufferedInputStream::TellI() const
+wxFileOffset wxBufferedInputStream::TellI() const
 {
 {
-    return m_i_streambuf->Tell();
+    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)
 }
 
 size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
@@ -1074,12 +1172,12 @@ size_t wxBufferedInputStream::OnSysRead(void *buffer, size_t bufsize)
     return m_parent_i_stream->Read(buffer, bufsize).LastRead();
 }
 
     return m_parent_i_stream->Read(buffer, bufsize).LastRead();
 }
 
-off_t wxBufferedInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
+wxFileOffset wxBufferedInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
 {
     return m_parent_i_stream->SeekI(seek, mode);
 }
 
 {
     return m_parent_i_stream->SeekI(seek, mode);
 }
 
-off_t wxBufferedInputStream::OnSysTell() const
+wxFileOffset wxBufferedInputStream::OnSysTell() const
 {
     return m_parent_i_stream->TellI();
 }
 {
     return m_parent_i_stream->TellI();
 }
@@ -1118,6 +1216,13 @@ wxBufferedOutputStream::~wxBufferedOutputStream()
     delete m_o_streambuf;
 }
 
     delete m_o_streambuf;
 }
 
+bool wxBufferedOutputStream::Close()
+{
+    Sync();
+    return IsOk();
+}
+
+
 wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
 {
     m_lastcount = 0;
 wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
 {
     m_lastcount = 0;
@@ -1125,13 +1230,13 @@ wxOutputStream& wxBufferedOutputStream::Write(const void *buffer, size_t size)
     return *this;
 }
 
     return *this;
 }
 
-off_t wxBufferedOutputStream::SeekO(off_t pos, wxSeekMode mode)
+wxFileOffset wxBufferedOutputStream::SeekO(wxFileOffset pos, wxSeekMode mode)
 {
     Sync();
     return m_o_streambuf->Seek(pos, mode);
 }
 
 {
     Sync();
     return m_o_streambuf->Seek(pos, mode);
 }
 
-off_t wxBufferedOutputStream::TellO() const
+wxFileOffset wxBufferedOutputStream::TellO() const
 {
     return m_o_streambuf->Tell();
 }
 {
     return m_o_streambuf->Tell();
 }
@@ -1147,19 +1252,19 @@ size_t wxBufferedOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
     return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
 }
 
     return m_parent_o_stream->Write(buffer, bufsize).LastWrite();
 }
 
-off_t wxBufferedOutputStream::OnSysSeek(off_t seek, wxSeekMode mode)
+wxFileOffset wxBufferedOutputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
 {
     return m_parent_o_stream->SeekO(seek, mode);
 }
 
 {
     return m_parent_o_stream->SeekO(seek, mode);
 }
 
-off_t wxBufferedOutputStream::OnSysTell() const
+wxFileOffset wxBufferedOutputStream::OnSysTell() const
 {
     return m_parent_o_stream->TellO();
 }
 
 {
     return m_parent_o_stream->TellO();
 }
 
-size_t wxBufferedOutputStream::GetSize() const
+wxFileOffset wxBufferedOutputStream::GetLength() const
 {
 {
-   return m_parent_o_stream->GetSize() + m_o_streambuf->GetIntPosition();
+   return m_parent_o_stream->GetLength() + m_o_streambuf->GetIntPosition();
 }
 
 void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer *buffer)
 }
 
 void wxBufferedOutputStream::SetOutputStreamBuffer(wxStreamBuffer *buffer)
@@ -1181,5 +1286,4 @@ wxOutputStream& wxEndL(wxOutputStream& stream)
     return stream.Write(eol, wxStrlen(eol));
 }
 
     return stream.Write(eol, wxStrlen(eol));
 }
 
-#endif
-  // wxUSE_STREAMS
+#endif // wxUSE_STREAMS