Mercurial > hg > octave-nkf
changeset 14806:980e2d5c83f7 stable
avoid calling putback more than once between reads
* liboctave/lo-utils.cc (octave_read_value<double>,
(octave_read_value<float>): Save stream position with tellg. On
failure, restore stream position with seekg. Avoid calling putback
multiple times between stream reads.
(octave_read_inf_nan_na, octave_read_float_inf_nan_na): Don't call
putback. Make it the caller's responsibility to reset stream
positioning on failed reads.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 26 Jun 2012 16:18:35 -0400 |
parents | f0552937a8eb |
children | 616981c9907c f06a16021024 |
files | liboctave/lo-utils.cc |
diffstat | 1 files changed, 59 insertions(+), 73 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/lo-utils.cc +++ b/liboctave/lo-utils.cc @@ -195,8 +195,11 @@ return retval; } +// Note that the caller is responsible for repositioning the stream on +// failure. + static inline double -read_inf_nan_na (std::istream& is, char c0, char sign = '+') +read_inf_nan_na (std::istream& is, char c0) { double d = 0.0; @@ -209,21 +212,12 @@ { char c2 = is.get (); if (c2 == 'f' || c2 == 'F') - d = sign == '-' ? -octave_Inf : octave_Inf; + d = octave_Inf; else - { - is.putback (c2); - is.putback (c1); - is.putback (c0); - is.setstate (std::ios::failbit); - } + is.setstate (std::ios::failbit); } else - { - is.putback (c1); - is.putback (c0); - is.setstate (std::ios::failbit); - } + is.setstate (std::ios::failbit); } break; @@ -236,17 +230,10 @@ if (c2 == 'n' || c2 == 'N') d = octave_NaN; else - { - is.putback (c2); - d = octave_NA; - } + d = octave_NA; } else - { - is.putback (c1); - is.putback (c0); - is.setstate (std::ios::failbit); - } + is.setstate (std::ios::failbit); } break; @@ -265,40 +252,37 @@ { double 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 '-': - { - char c2 = 0; - c2 = is.get (); - if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') - d = read_inf_nan_na (is, c2, c1); - else - { - is.putback (c2); - is.putback (c1); - is >> d; - } - } - break; + neg = true; + // fall through... case '+': { char c2 = 0; c2 = is.get (); if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') - d = read_inf_nan_na (is, c2, c1); + d = read_inf_nan_na (is, c2); else { is.putback (c2); - is.putback (c1); is >> d; } + + if (neg && ! is.fail ()) + d = -d; } break; @@ -310,6 +294,15 @@ 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; @@ -358,6 +351,9 @@ } +// 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 = '+') { @@ -372,21 +368,12 @@ { char c2 = is.get (); if (c2 == 'f' || c2 == 'F') - d = sign == '-' ? -octave_Float_Inf : octave_Float_Inf; + d = octave_Float_Inf; else - { - is.putback (c2); - is.putback (c1); - is.putback (c0); - is.setstate (std::ios::failbit); - } + is.setstate (std::ios::failbit); } else - { - is.putback (c1); - is.putback (c0); - is.setstate (std::ios::failbit); - } + is.setstate (std::ios::failbit); } break; @@ -399,17 +386,10 @@ if (c2 == 'n' || c2 == 'N') d = octave_Float_NaN; else - { - is.putback (c2); - d = octave_Float_NA; - } + d = octave_Float_NA; } else - { - is.putback (c1); - is.putback (c0); - is.setstate (std::ios::failbit); - } + is.setstate (std::ios::failbit); } break; @@ -428,40 +408,37 @@ { 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 '-': - { - char c2 = 0; - c2 = is.get (); - if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') - d = read_float_inf_nan_na (is, c2, c1); - else - { - is.putback (c2); - is.putback (c1); - is >> d; - } - } - break; + 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, c1); + d = read_float_inf_nan_na (is, c2); else { is.putback (c2); - is.putback (c1); is >> d; } + + if (neg && ! is.fail ()) + d = -d; } break; @@ -473,6 +450,15 @@ 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;