[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;