]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/textfile.cpp
use wx/dynlib.h and not wx/dynload.h (patch 1448691)
[wxWidgets.git] / src / common / textfile.cpp
index 28593b36f56ccaf63747891ffea36435c7e12106..f9cd34077d22b650c94051aa1933a030f51822b1 100644 (file)
 // headers
 // ============================================================================
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "textfile.h"
-#endif
-
 #include  "wx/wxprec.h"
 
 #ifdef    __BORLANDC__
@@ -92,91 +88,119 @@ bool wxTextFile::OnClose()
 bool wxTextFile::OnRead(wxMBConv& conv)
 {
     // file should be opened and we must be in it's beginning
-    wxASSERT( m_file.IsOpened() && m_file.Tell() == 0 );
-
-    char *strBuf, *strPtr, *strEnd;
-    char ch, chLast = '\0';
-    char buf[1024];
-    int n, nRead;
+    wxASSERT( m_file.IsOpened() &&
+                (m_file.GetKind() != wxFILE_KIND_DISK || m_file.Tell() == 0) );
+
+    static const size_t BUF_SIZE = 1024;
+#if wxUSE_UNICODE
+    static const size_t NUL_SIZE = 4;
+#else
+    static const size_t NUL_SIZE = 1;
+#endif
 
-    strPtr = strBuf = new char[1024];
-    strEnd = strBuf + 1024;
+    char buf[BUF_SIZE + NUL_SIZE];
+    wxChar chLast = '\0';
+    wxString str;
 
-    do 
+    for ( ;; )
     {
-        nRead = m_file.Read(buf, WXSIZEOF(buf));
-        if ( nRead == wxInvalidOffset ) 
+        // leave space for trailing NUL
+        ssize_t nRead = m_file.Read(buf, BUF_SIZE);
+
+        if ( nRead == wxInvalidOffset )
         {
             // read error (error message already given in wxFile::Read)
-            delete[] strBuf;
-            return FALSE;
+            return false;
+        }
+
+        if ( nRead == 0 )
+            break;
+
+        // save the number characters which we already processed during the
+        // last loop iteration
+        const size_t lenOld = str.length();
+
+#if wxUSE_UNICODE
+        // we have to properly NUL-terminate the string for any encoding it may
+        // use -- 4 NULs should be enough for everyone (this is why we add 4
+        // extra bytes to the buffer)
+        buf[nRead] =
+        buf[nRead + 1] =
+        buf[nRead + 2] =
+        buf[nRead + 3] = '\0';
+
+        // append to the remains of the last block, don't overwrite
+        wxString strbuf(buf, conv);
+        if ( strbuf.empty() )
+        {
+            // conversion failed
+            return false;
         }
 
-        for (n = 0; n < nRead; n++)
+        str += strbuf;
+#else // ANSI
+        wxUnusedVar(conv);
+        buf[nRead] = '\0';
+        str += buf;
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+
+
+        // the beginning of the current line, changes inside the loop
+        wxString::const_iterator lineStart = str.begin();
+        const wxString::const_iterator end = str.end();
+        for ( wxString::const_iterator p = lineStart + lenOld; p != end; p++ )
         {
-            ch = buf[n];
-            switch ( ch ) 
+            const wxChar ch = *p;
+            switch ( ch )
             {
                 case '\n':
-                    // Dos/Unix line termination
-                    *strPtr = '\0';
-                    AddLine(wxString(strBuf, conv), 
-                            chLast == '\r' ? wxTextFileType_Dos
-                                           : wxTextFileType_Unix);
-                    strPtr = strBuf;
-                    chLast = '\n';
+                    // could be a DOS or Unix EOL
+                    if ( chLast == '\r' )
+                    {
+                        AddLine(wxString(lineStart, p - 1), wxTextFileType_Dos);
+                    }
+                    else // bare '\n', Unix style
+                    {
+                        AddLine(wxString(lineStart, p), wxTextFileType_Unix);
+                    }
+
+                    lineStart = p + 1;
                     break;
 
                 case '\r':
-                    if ( chLast == '\r' ) 
+                    if ( chLast == '\r' )
                     {
                         // Mac empty line
                         AddLine(wxEmptyString, wxTextFileType_Mac);
+                        lineStart = p + 1;
                     }
-                    else
-                        chLast = '\r';
+                    //else: we don't what this is yet -- could be a Mac EOL or
+                    //      start of DOS EOL so wait for next char
                     break;
 
                 default:
                     if ( chLast == '\r' )
                     {
                         // Mac line termination
-                        *strPtr = '\0';
-                        AddLine(wxString(strBuf, conv), wxTextFileType_Mac);
-                        chLast = ch;
-                        strPtr = strBuf;
-                        *(strPtr++) = ch;
-                    }
-                    else 
-                    {
-                        // add to the current line
-                        *(strPtr++) = ch;
-                        if ( strPtr == strEnd )
-                        {
-                            // we must allocate more memory
-                            size_t size = strEnd - strBuf;
-                            char *newBuf = new char[size + 1024];
-                            memcpy(newBuf, strBuf, size);
-                            delete[] strBuf;
-                            strBuf = newBuf;
-                            strEnd = strBuf + size + 1024;
-                            strPtr = strBuf + size;
-                        }
+                        AddLine(wxString(lineStart, p - 1), wxTextFileType_Mac);
+                        lineStart = p;
                     }
             }
+
+            chLast = ch;
         }
-    } while ( nRead == WXSIZEOF(buf) );
+
+        // remove the part we already processed
+        str.erase(0, lineStart - str.begin());
+    }
 
     // anything in the last line?
-    if ( strPtr != strBuf ) 
+    if ( !str.empty() )
     {
-        *strPtr = '\0';
-        AddLine(wxString(strBuf, conv), 
-                wxTextFileType_None); // no line terminator
+        AddLine(str, wxTextFileType_None); // no line terminator
     }
 
-    delete[] strBuf;
-    return TRUE;
+    return true;
 }
 
 
@@ -194,7 +218,7 @@ bool wxTextFile::OnWrite(wxTextFileType typeNew, wxMBConv& conv)
 
     if ( !fileTmp.IsOpened() ) {
         wxLogError(_("can't write buffer '%s' to disk."), m_strBufferName.c_str());
-        return FALSE;
+        return false;
     }
 
     size_t nCount = GetLineCount();