diff libinterp/corefcn/oct-stream.cc @ 24346:f77da8da0f3f

Fix textscan missing fields and number reads for cell-specified delimiters (bug #52550). * oct-stream.cc (textscan::read_double): Remove what looks like repetitive code hunk concerning reading INF and NAN. (textscan::read_until): Treat eol1 and eol2 as delimiters. When no valid data is found between delimiters, put the delimiter symbol back into the stream since the ensuing skip_delimiter() call will be removing it. (textscan::scan_string): Add eol1 and eol2 characters to "ends" string array. (textscan::read_format_once): Distinguish between the cell-specified and string-specified delimiter scenario. For cell-specified delimiters, use the tellg-seekg restoration of the stream position similar to what is present inside lookahead(). * file-io.cc (Ftextscan): Add BIST tests for bug #52550.
author Daniel J Sebald <daniel.sebald@ieee.org>
date Fri, 01 Dec 2017 17:28:37 -0600
parents ddaee520d342
children bb8ae4e9e09d
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc	Thu Nov 30 22:57:15 2017 +0100
+++ b/libinterp/corefcn/oct-stream.cc	Fri Dec 01 17:28:37 2017 -0600
@@ -2914,22 +2914,6 @@
           }
       }
 
-    // Check for +/- inf and NaN
-    if (! valid && width_left >= 3)
-      {
-        int i = lookahead (is, inf_nan, 3, false);   // false -> case insensitive
-        if (i == 0)
-          {
-            retval = numeric_limits<double>::Inf ();
-            valid = true;
-          }
-        else if (i == 1)
-          {
-            retval = numeric_limits<double>::NaN ();
-            valid = true;
-          }
-      }
-
     if (! valid)
       is.setstate (std::ios::failbit);
     else
@@ -3126,6 +3110,9 @@
 
         if (last != std::istream::traits_type::eof ())
           {
+            if (last == eol1 || last == eol2)
+                break;
+
             retval = retval + static_cast<char> (last);
             for (int i = 0; i < delimiters.numel (); i++)
               {
@@ -3138,6 +3125,8 @@
                   {
                     done = true;
                     retval = retval.substr (0, start);
+                    if (start == 0)
+                      is.putback (last);
                     break;
                   }
               }
@@ -3181,12 +3170,15 @@
       }
     else  // Cell array of multi-character delimiters
       {
-        std::string ends (delim_list.numel (), '\0');
-        for (int i = 0; i < delim_list.numel (); i++)
+        std::string ends (delim_list.numel () + 2, '\0');
+        int i;
+        for (i = 0; i < delim_list.numel (); i++)
           {
             std::string tmp = delim_list(i).string_value ();
             ends[i] = tmp.back ();
           }
+        ends[i++] = eol1;
+        ends[i++] = eol2;
         val = textscan::read_until (is, delim_list, ends);
       }
   }
@@ -3488,8 +3480,22 @@
           {
             is.clear (is.rdstate () & ~std::ios::failbit);
 
-            if (! is.eof () && ! is_delim (is.peek ()))
-              this_conversion_failed = true;
+            if (! is.eof ())
+              {
+                if (delim_list.isempty ())
+                  {
+                    if (! is_delim (is.peek ()))
+                      this_conversion_failed = true;
+                  }
+                else  // Cell array of multi-character delimiters
+                  {
+                    char *pos = is.tellg ();
+                    if (-1 == lookahead (is, delim_list, delim_len))
+                      this_conversion_failed = true;
+                    is.clear ();
+                    is.seekg (pos);     // reset to position before look-ahead
+                  }
+              }
           }
 
         if (! elem->discard)
@@ -3861,7 +3867,7 @@
     char *look = is.read (&tmp[0], tmp.size (), pos);
 
     is.clear ();
-    is.seekg (pos);              // reset to position before look-ahead
+    is.seekg (pos);              // reset to position before read
                                  // FIXME: pos may be corrupted by is.read
 
     int i;