changeset 14811:52cb71787cd1

use templates to avoid code duplication in octave_read_value functions * lo-utils.cc (octave_read_fp_value, octave_read_cx_fp_value): New template functions. (octave_read_value<double>, octave_read_value<float>, octave_read_value<Complex>, octave_read_value<FloatComplex>): Call new template functions to do the work. (read_inf_nan_na): Use templates to avoid duplicate code.
author John W. Eaton <jwe@octave.org>
date Tue, 26 Jun 2012 16:57:32 -0400
parents d40349493d87
children 95b93a728603
files liboctave/lo-utils.cc
diffstat 1 files changed, 34 insertions(+), 170 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/lo-utils.cc	Tue Jun 26 16:53:48 2012 -0400
+++ b/liboctave/lo-utils.cc	Tue Jun 26 16:57:32 2012 -0400
@@ -198,10 +198,11 @@
 // Note that the caller is responsible for repositioning the stream on
 // failure.
 
-static inline double
+template <typename T>
+T
 read_inf_nan_na (std::istream& is, char c0)
 {
-  double d = 0.0;
+  T val = 0.0;
 
   switch (c0)
     {
@@ -212,7 +213,7 @@
           {
             char c2 = is.get ();
             if (c2 == 'f' || c2 == 'F')
-              d = octave_Inf;
+              val = std::numeric_limits<T>::infinity ();
             else
               is.setstate (std::ios::failbit);
           }
@@ -228,9 +229,9 @@
           {
             char c2 = is.get ();
             if (c2 == 'n' || c2 == 'N')
-              d = octave_NaN;
+              val = std::numeric_limits<T>::quiet_NaN ();
             else
-              d = octave_NA;
+              val = octave_numeric_limits<T>::NA ();
           }
         else
           is.setstate (std::ios::failbit);
@@ -241,16 +242,16 @@
       abort ();
     }
 
-  return d;
+  return val;
 }
 
 // Read a double value.  Discard any sign on NaN and NA.
 
-template <>
+template <typename T>
 double
-octave_read_value (std::istream& is)
+octave_read_fp_value (std::istream& is)
 {
-  double d = 0.0;
+  T val = 0.0;
 
   // FIXME -- resetting stream position is likely to fail unless we are
   // reading from a file.
@@ -274,26 +275,26 @@
         char c2 = 0;
         c2 = is.get ();
         if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
-          d = read_inf_nan_na (is, c2);
+          val = read_inf_nan_na<T> (is, c2);
         else
           {
             is.putback (c2);
-            is >> d;
+            is >> val;
           }
 
         if (neg && ! is.fail ())
-          d = -d;
+          val = -val;
       }
       break;
 
     case 'i': case 'I':
     case 'n': case 'N':
-      d = read_inf_nan_na (is, c1);
+      val = read_inf_nan_na<T> (is, c1);
       break;
 
     default:
       is.putback (c1);
-      is >> d;
+      is >> val;
       break;
     }
 
@@ -305,16 +306,16 @@
       is.setstate (status);
     }
 
-  return d;
+  return val;
 }
 
-template <>
-Complex
-octave_read_value (std::istream& is)
+template <typename T>
+std::complex<T>
+octave_read_cx_fp_value (std::istream& is)
 {
-  double re = 0.0, im = 0.0;
+  T re = 0.0, im = 0.0;
 
-  Complex cx = 0.0;
+  std::complex<T> cx = 0.0;
 
   char ch = ' ';
 
@@ -323,16 +324,16 @@
 
   if (ch == '(')
     {
-      re = octave_read_value<double> (is);
+      re = octave_read_value<T> (is);
       ch = is.get ();
 
       if (ch == ',')
         {
-          im = octave_read_value<double> (is);
+          im = octave_read_value<T> (is);
           ch = is.get ();
 
           if (ch == ')')
-            cx = Complex (re, im);
+            cx = std::complex<T> (re, im);
           else
             is.setstate (std::ios::failbit);
         }
@@ -348,163 +349,26 @@
     }
 
   return cx;
-
 }
 
-// Note that the caller is responsible for repositioning the stream on
-// failure.
-
-static inline float
-read_float_inf_nan_na (std::istream& is, char c0, char sign = '+')
+template <> OCTAVE_API double octave_read_value (std::istream& is)
 {
-  float d = 0.0;
-
-  switch (c0)
-    {
-    case 'i': case 'I':
-      {
-        char c1 = is.get ();
-        if (c1 == 'n' || c1 == 'N')
-          {
-            char c2 = is.get ();
-            if (c2 == 'f' || c2 == 'F')
-              d = octave_Float_Inf;
-            else
-              is.setstate (std::ios::failbit);
-          }
-        else
-          is.setstate (std::ios::failbit);
-      }
-      break;
-
-    case 'n': case 'N':
-      {
-        char c1 = is.get ();
-        if (c1 == 'a' || c1 == 'A')
-          {
-            char c2 = is.get ();
-            if (c2 == 'n' || c2 == 'N')
-              d = octave_Float_NaN;
-            else
-              d = octave_Float_NA;
-          }
-        else
-          is.setstate (std::ios::failbit);
-      }
-      break;
-
-    default:
-      abort ();
-    }
-
-  return d;
+  return octave_read_fp_value<double> (is);
 }
 
-// Read a float value.  Discard any sign on NaN and NA.
-
-template <>
-float
-octave_read_value (std::istream& is)
+template <> OCTAVE_API Complex octave_read_value (std::istream& is)
 {
-  float d = 0.0;
-
-  // FIXME -- resetting stream position is likely to fail unless we are
-  // reading from a file.
-  std::ios::streampos pos = is.tellg ();
-
-  char c1 = ' ';
-
-  while (isspace (c1))
-    c1 = is.get ();
-
-  bool neg = false;
-
-  switch (c1)
-    {
-    case '-':
-      neg = true;
-      // fall through...
-
-    case '+':
-      {
-        char c2 = 0;
-        c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
-          d = read_float_inf_nan_na (is, c2);
-        else
-          {
-            is.putback (c2);
-            is >> d;
-          }
-
-        if (neg && ! is.fail ())
-          d = -d;
-      }
-      break;
-
-    case 'i': case 'I':
-    case 'n': case 'N':
-      d = read_float_inf_nan_na (is, c1);
-      break;
-
-    default:
-      is.putback (c1);
-      is >> d;
-      break;
-    }
-
-  std::ios::iostate status = is.rdstate ();
-  if (status & std::ios::failbit)
-    {
-      is.clear ();
-      is.seekg (pos);
-      is.setstate (status);
-    }
-
-  return d;
+  return octave_read_cx_fp_value<double> (is);
 }
 
-template <>
-FloatComplex
-octave_read_value (std::istream& is)
+template <> OCTAVE_API float octave_read_value (std::istream& is)
 {
-  float re = 0.0, im = 0.0;
-
-  FloatComplex cx = 0.0;
-
-  char ch = ' ';
-
-  while (isspace (ch))
-    ch = is.get ();
-
-  if (ch == '(')
-    {
-      re = octave_read_value<float> (is);
-      ch = is.get ();
+  return octave_read_fp_value<float> (is);
+}
 
-      if (ch == ',')
-        {
-          im = octave_read_value<float> (is);
-          ch = is.get ();
-
-          if (ch == ')')
-            cx = FloatComplex (re, im);
-          else
-            is.setstate (std::ios::failbit);
-        }
-      else if (ch == ')')
-        cx = re;
-      else
-        is.setstate (std::ios::failbit);
-    }
-  else
-    {
-      is.putback (ch);
-      cx = octave_read_value<float> (is);
-    }
-
-  return cx;
-
+template <> OCTAVE_API FloatComplex octave_read_value (std::istream& is)
+{
+  return octave_read_cx_fp_value<float> (is);
 }
 
 void