octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Patch for fgetl (i.e., do_gets) not meant for immediate check-in


From: Daniel J Sebald
Subject: Re: Patch for fgetl (i.e., do_gets) not meant for immediate check-in
Date: Thu, 08 Jan 2009 02:58:03 -0600
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020

PPS:  I'm going to send a slight variation on this patch.

In this version of the patch is a buffer which expands so that the lines can be 
gotten with just a single call to getline().  After the end of the file, the 
buffer is shrunk back down in case someone accidentally typed a file name for 
which the file has no newline characters and is quite long.  I like the 
concept, but the code gets a little bulky.

Dan
--- octave/src/oct-stream.cc    2009-01-05 01:53:38.000000000 -0600
+++ octave-mod/src/oct-stream.cc        2009-01-08 02:34:21.000000000 -0600
@@ -961,7 +961,6 @@
 octave_base_stream::do_gets (octave_idx_type max_len, bool& err,
                             bool strip_newline, const std::string& who)
 {
-  std::string retval;
 
   err = false;
 
@@ -969,62 +968,123 @@
 
   if (isp)
     {
-      std::istream& is = *isp;
+      static std::ostringstream *buf;
 
-      std::ostringstream buf;
+      // Construct only once.  There is a lot of initialization and
+      // memory allocation that goes on to construct a string class
+      // and its base class.
+      if (! buf)
+        {
+         if (! (buf = new std::ostringstream))
+           {
+             err = true;
+             error(who, "allocate error");
+             std::string retval;
+             return retval;
+           }
+       }
+      else
+       buf->str("");
+
+#define MINTMPBUFLEN 32
+#define MAXTMPBUFLEN 2048
 
-      int c = 0;
-      int char_count = 0;
+      static char *ctmpbuf;
+      static int ctmpbuf_len = 0;
 
-      if (max_len != 0)
+      if (! ctmpbuf)
        {
-         while (is && (c = is.get ()) != EOF)
+         ctmpbuf_len = MINTMPBUFLEN;
+         if (! (ctmpbuf = new char[ctmpbuf_len]))
            {
-             char_count++;
+             err = true;
+             error(who, "allocate error");
+             std::string retval;
+             return retval;
+           }
+       }
 
-             if (c == '\n')
-               {
-                 if (! strip_newline)
-                   buf << static_cast<char> (c);
+      octave_idx_type read_len = max_len < 0 ? -max_len : max_len;
 
-                 break;
-               }
+      while (isp->good () && ctmpbuf && read_len > 0)
+       {
+         if (max_len > 0)
+           {
+             if (read_len < ctmpbuf_len)
+               isp->getline (ctmpbuf, read_len + 1);
              else
-               buf << static_cast<char> (c);
+               isp->getline (ctmpbuf, ctmpbuf_len);
+             read_len -= ctmpbuf_len - 1;
+           }
+         else
+           isp->getline (ctmpbuf, ctmpbuf_len);
+                   
+         *buf << ctmpbuf;
 
-             if (max_len > 0 && char_count == max_len)
-               break;
+         if (isp->eof () || ! isp->fail ())
+           {
+              if (! strip_newline)
+               *buf << static_cast<char> ('\n');
+             break;
+            }
+         else
+           {
+             if (ctmpbuf_len < MAXTMPBUFLEN)
+               {
+                 // Double the size of the buffer.
+                 ctmpbuf_len *= 2;
+                 delete ctmpbuf;
+                 if (! (ctmpbuf = new char[ctmpbuf_len]))
+                   {
+                     err = true;
+                     error(who, "allocate error");
+                     std::string retval;
+                     return retval;
+                   }
+               }
+             isp->clear (isp->rdstate () & ~std::istream::failbit);
            }
        }
 
-      if (! is.eof () && char_count > 0)
+      if (! isp->good())
        {
-         // GAGME.  Matlab seems to check for EOF even if the last
-         // character in a file is a newline character.  This is NOT
-         // what the corresponding C-library functions do.
-         int disgusting_compatibility_hack = is.get ();
-         if (! is.eof ())
-           is.putback (disgusting_compatibility_hack);
+         if (isp->eof () && (ctmpbuf_len != MINTMPBUFLEN))
+           {
+             // Shrink the buffer back down now that end of file reached.
+             ctmpbuf_len = MINTMPBUFLEN;
+             delete ctmpbuf;
+             ctmpbuf = new char[ctmpbuf_len];
+             if (! (ctmpbuf = new char[ctmpbuf_len]))
+               {
+                 err = true;
+                 error(who, "allocate error");
+                 std::string retval;
+                 return retval;
+               }
+           }
+
+         if (isp->eof () && ! buf->tellp ())
+           {
+             err = true;
+             error (who, "at end of file");
+           }
+         else if (isp->bad ())
+           {
+             err = true;
+             error (who, "read error");
+           }
        }
 
-      if (is.good () || (is.eof () && char_count > 0))
-       retval = buf.str ();
-      else
-       {
-         err = true;
+#undef MINTMPBUFLEN
+#undef MAXTMPBUFLEN
 
-         if (is.eof () && char_count == 0)
-           error (who, "at end of file");
-         else
-           error (who, "read error");
-       }
-    }
-  else
-    {
-      err = true;
-      invalid_operation (who, "reading");
+      return buf->str ();
     }
 
+  err = true;
+  invalid_operation (who, "reading");
+
+  std::string retval;
   return retval;
 }
 
@@ -3881,13 +3941,12 @@
   bool retval = true;
 
   if (! instance)
-    instance = new octave_stream_list ();
-
-  if (! instance)
     {
-      ::error ("unable to create stream list object!");
-
-      retval = false;
+      if (! (instance = new octave_stream_list ()))
+       {
+         ::error ("unable to create stream list object!");
+         retval = false;
+       }
     }
 
   return retval;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]