]> git.saurik.com Git - wxWidgets.git/commitdiff
make wxTextFile work with unseekable files again (patch 1632613, bug 1629581)
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 18 Jan 2007 20:29:12 +0000 (20:29 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 18 Jan 2007 20:29:12 +0000 (20:29 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44249 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
src/common/textfile.cpp

index 272b265ac6a76edcca6d930ac772c27e99790fef..26f7d97cdc52ac65dd5c02b71f3bbaae8d842b8f 100644 (file)
@@ -95,6 +95,7 @@ All:
 
 - Added wxSizerFlags::Shaped() and FixedMinSize() methods
 - Added wxDateTime::GetDateOnly()
+- Made wxTextFile work with unseekable files again (David Hart)
 
 wxMSW
 
index 1d033f87db1f4f4a99c49d203601b93f396ab50d..2b7af13e1dc068c6dcd6e5cd1e176b0f842ac8c4 100644 (file)
@@ -88,8 +88,8 @@ bool wxTextFile::OnClose()
 
 bool wxTextFile::OnRead(const wxMBConv& conv)
 {
-    // file should be opened and we must be in it's beginning
-    wxASSERT( m_file.IsOpened() && m_file.Tell() == 0 );
+    // file should be opened
+    wxASSERT_MSG( m_file.IsOpened(), _T("can't read closed file") );
 
     // read the entire file in memory: this is not the most efficient thing to
     // do but there is no good way to avoid it in Unicode build because if we
@@ -98,14 +98,35 @@ bool wxTextFile::OnRead(const wxMBConv& conv)
     // read and so the conversion would fail) and, as the file contents is kept
     // in memory by wxTextFile anyhow, it shouldn't be a big problem to read
     // the file entirely
-    const size_t bufSize = (size_t)(m_file.Length() + 4 /* for trailing NULs */ );
-    size_t bufPos = 0;
-    wxCharBuffer buf(bufSize - 1 /* it adds 1 internally */);
-
+    size_t bufSize,
+           bufPos = 0;
     char block[1024];
-    for ( bool eof = false; !eof; )
+    wxCharBuffer buf;
+
+    // first determine if the file is seekable or not and so whether we can
+    // determine its length in advance
+    wxFileOffset fileLength;
+    {
+        wxLogNull logNull;
+        fileLength = m_file.Length();
+    }
+
+    // some non-seekable files under /proc under Linux pretend that they're
+    // seekable but always return 0; others do return an error
+    const bool seekable = fileLength != wxInvalidOffset && fileLength != 0;
+    if ( seekable )
+    {
+        // we know the required length, so set the buffer size in advance
+        bufSize = fileLength;
+        if ( !buf.extend(bufSize - 1 /* it adds 1 internally */) )
+            return false;
+
+        // if the file is seekable, also check that we're at its beginning
+        wxASSERT_MSG( m_file.Tell() == 0, _T("should be at start of file") );
+    }
+
+    for ( ;; )
     {
-        // try to read up to the size of the entire block
         ssize_t nRead = m_file.Read(block, WXSIZEOF(block));
 
         if ( nRead == wxInvalidOffset )
@@ -115,20 +136,41 @@ bool wxTextFile::OnRead(const wxMBConv& conv)
         }
 
         if ( nRead == 0 )
+        {
+            // if no bytes have been read, presumably this is a valid-but-empty file
+            if ( bufPos == 0 )
+                return true;
+
+            // otherwise we've finished reading the file
             break;
+        }
 
-        // this shouldn't happen but don't overwrite the buffer if it does
-        wxCHECK_MSG( bufPos + nRead <= bufSize, false,
-                     _T("read more than file length?") );
+        if ( seekable )
+        {
+            // this shouldn't happen but don't overwrite the buffer if it does
+            wxCHECK_MSG( bufPos + nRead <= bufSize, false,
+                         _T("read more than file length?") );
+        }
+        else // !seekable
+        {
+            // for non-seekable files we have to allocate more memory on the go
+            if ( !buf.extend(bufPos + nRead - 1 /* it adds 1 internally */) )
+                return false;
+        }
 
         // append to the buffer
         memcpy(buf.data() + bufPos, block, nRead);
         bufPos += nRead;
     }
 
+    if ( !seekable )
+    {
+        bufSize = bufPos;
+    }
+
     const wxString str(buf, conv, bufPos);
 
-    // this doesn't risk to happen in ANSI build
+    // there's no risk of this happening in ANSI build
 #if wxUSE_UNICODE
     if ( bufSize > 4 && str.empty() )
     {