# HG changeset patch # User John W. Eaton # Date 1340744252 14400 # Node ID 52cb71787cd1510941081c1b7c4eaf273ed85f87 # Parent d40349493d874022ed9187e729c6b25e7aa53b89 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, octave_read_value, octave_read_value, octave_read_value): Call new template functions to do the work. (read_inf_nan_na): Use templates to avoid duplicate code. diff -r d40349493d87 -r 52cb71787cd1 liboctave/lo-utils.cc --- 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 +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::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::quiet_NaN (); else - d = octave_NA; + val = octave_numeric_limits::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 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 (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 (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 +std::complex +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 cx = 0.0; char ch = ' '; @@ -323,16 +324,16 @@ if (ch == '(') { - re = octave_read_value (is); + re = octave_read_value (is); ch = is.get (); if (ch == ',') { - im = octave_read_value (is); + im = octave_read_value (is); ch = is.get (); if (ch == ')') - cx = Complex (re, im); + cx = std::complex (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 (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 (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 (is); - ch = is.get (); + return octave_read_fp_value (is); +} - if (ch == ',') - { - im = octave_read_value (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 (is); - } - - return cx; - +template <> OCTAVE_API FloatComplex octave_read_value (std::istream& is) +{ + return octave_read_cx_fp_value (is); } void