changeset 12995:7872afb42fab

fix scanf problem with reading I (bug #33722) * lo-utils.cc (read_inf_nan_na, read_float_inf_nan_na): Return characters to input stream and set stream state on failed reads. (read_float_inf_nan_na): Use Float versions of Inf, NaN, and NA * test_io.m: New tests.
author John W. Eaton <jwe@octave.org>
date Wed, 24 Aug 2011 12:13:11 -0400
parents 0413227e407b
children 7aafa7a2edad
files liboctave/lo-utils.cc test/test_io.m
diffstat 2 files changed, 78 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/lo-utils.cc
+++ b/liboctave/lo-utils.cc
@@ -196,44 +196,57 @@
 }
 
 static inline double
-read_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   double d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
               d = sign == '-' ? -octave_Inf : octave_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
               d = octave_NaN;
             else
               {
-                is.putback (c);
+                is.putback (c2);
                 d = octave_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
@@ -346,44 +359,57 @@
 }
 
 static inline float
-read_float_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_float_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   float d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
-              d = sign == '-' ? -octave_Inf : octave_Inf;
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
+              d = sign == '-' ? -octave_Float_Inf : octave_Float_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
-              d = octave_NaN;
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
+              d = octave_Float_NaN;
             else
               {
-                is.putback (c);
-                d = octave_NA;
+                is.putback (c2);
+                d = octave_Float_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
--- a/test/test_io.m
+++ b/test/test_io.m
@@ -245,6 +245,27 @@
 %!assert (sscanf ('123456', '%10c'), '123456')
 %!assert (sscanf ('123456', '%10s'), '123456')
 
+%!test
+%! [val, count, msg, pos] = sscanf ("3I2", "%f")
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3In2", "%f")
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3Inf2", "%f")
+%! assert (val, [3; Inf, 2);
+%! assert (count, 3);
+%! assert (msg, "");
+%! assert (pos, 6);
+
 %% test/octave.test/io/sscanf-1.m
 %!test
 %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C");