changeset 17818:f1b59ef34eda

attempt to avoid setting persistent state on i/o streams (bug #40396) * utils.h, utils.cc (octave_preserve_stream_state): New class. * debug.cc, pr-output.cc, variables.cc, ov-base-sparse.cc: Use it to save and restore stream flags, precision, field width, and fill character.
author John W. Eaton <jwe@octave.org>
date Thu, 31 Oct 2013 17:26:04 -0400
parents 9c8988786053
children af924e6572cb
files libinterp/corefcn/debug.cc libinterp/corefcn/pr-output.cc libinterp/corefcn/utils.cc libinterp/corefcn/utils.h libinterp/corefcn/variables.cc libinterp/octave-value/ov-base-sparse.cc
diffstat 6 files changed, 85 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/debug.cc	Thu Oct 31 21:44:58 2013 +0100
+++ b/libinterp/corefcn/debug.cc	Thu Oct 31 17:26:04 2013 -0400
@@ -55,6 +55,7 @@
 #include "pt-stmt.h"
 #include "toplev.h"
 #include "unwind-prot.h"
+#include "utils.h"
 #include "variables.h"
 
 #include "debug.h"
@@ -1166,6 +1167,8 @@
 
           if (nframes_to_display > 0)
             {
+              octave_preserve_stream_state stream_state (os);
+
               os << "stopped in:\n\n";
 
               Cell names = stk.contents ("name");
--- a/libinterp/corefcn/pr-output.cc	Thu Oct 31 21:44:58 2013 +0100
+++ b/libinterp/corefcn/pr-output.cc	Thu Oct 31 17:26:04 2013 -0400
@@ -283,15 +283,16 @@
 std::ostream&
 operator << (std::ostream& os, const pr_engineering_float& pef)
 {
+  octave_preserve_stream_state stream_state (os);
+
   if (pef.f.fw >= 0)
     os << std::setw (pef.f.fw - pef.f.ex);
 
   if (pef.f.prec >= 0)
     os << std::setprecision (pef.f.prec);
 
-  std::ios::fmtflags oflags =
-    os.flags (static_cast<std::ios::fmtflags>
-              (pef.f.fmt | pef.f.up | pef.f.sp));
+  os.flags (static_cast<std::ios::fmtflags>
+            (pef.f.fmt | pef.f.up | pef.f.sp));
 
   os << pef.mantissa ();
 
@@ -304,10 +305,7 @@
   else
     os << std::setw (0) << "e+";
 
-  os << std::setw (pef.f.ex - 2) << std::setfill ('0') << ex
-     << std::setfill (' ');
-
-  os.flags (oflags);
+  os << std::setw (pef.f.ex - 2) << std::setfill ('0') << ex;
 
   return os;
 }
@@ -328,20 +326,19 @@
 std::ostream&
 operator << (std::ostream& os, const pr_formatted_float& pff)
 {
+  octave_preserve_stream_state stream_state (os);
+
   if (pff.f.fw >= 0)
     os << std::setw (pff.f.fw);
 
   if (pff.f.prec >= 0)
     os << std::setprecision (pff.f.prec);
 
-  std::ios::fmtflags oflags =
-    os.flags (static_cast<std::ios::fmtflags>
-              (pff.f.fmt | pff.f.up | pff.f.sp));
+  os.flags (static_cast<std::ios::fmtflags>
+            (pff.f.fmt | pff.f.up | pff.f.sp));
 
   os << pff.val;
 
-  os.flags (oflags);
-
   return os;
 }
 
@@ -454,23 +451,22 @@
 std::ostream&
 operator << (std::ostream& os, const pr_rational_float& prf)
 {
+  octave_preserve_stream_state stream_state (os);
+
   int fw = (rat_string_len > 0 ? rat_string_len : prf.f.fw);
   std::string s = rational_approx (prf.val, fw);
 
   if (fw >= 0)
     os << std::setw (fw);
 
-  std::ios::fmtflags oflags =
-    os.flags (static_cast<std::ios::fmtflags>
-              (prf.f.fmt | prf.f.up | prf.f.sp));
+  os.flags (static_cast<std::ios::fmtflags>
+            (prf.f.fmt | prf.f.up | prf.f.sp));
 
   if (fw > 0 && s.length () > static_cast<unsigned int>(fw))
     os << "*";
   else
     os << s;
 
-  os.flags (oflags);
-
   return os;
 }
 
@@ -1453,6 +1449,8 @@
 
       if (hex_format)
         {
+          octave_preserve_stream_state stream_state (os);
+
           equiv tmp;
           tmp.d = d;
 
@@ -1465,10 +1463,8 @@
           oct_mach_info::float_format flt_fmt =
             oct_mach_info::native_float_format ();
 
-          char ofill = os.fill ('0');
-
-          std::ios::fmtflags oflags
-            = os.flags (std::ios::right | std::ios::hex);
+          os.fill ('0');
+          os.flags (std::ios::right | std::ios::hex);
 
           if (hex_format > 1
               || flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian)
@@ -1481,9 +1477,6 @@
               for (int i = sizeof (double) - 1; i >= 0; i--)
                 os << std::setw (2) << static_cast<int> (tmp.i[i]);
             }
-
-          os.fill (ofill);
-          os.setf (oflags);
         }
       else if (bit_format)
         {
@@ -1514,6 +1507,8 @@
         }
       else if (octave_is_NA (d))
         {
+          octave_preserve_stream_state stream_state (os);
+
           if (fw > 0)
             os << std::setw (fw) << "NA";
           else
@@ -1523,6 +1518,8 @@
         os << pr_rational_float (*fmt, d);
       else if (xisinf (d))
         {
+          octave_preserve_stream_state stream_state (os);
+
           const char *s;
           if (d < 0.0)
             s = "-Inf";
@@ -1536,6 +1533,8 @@
         }
       else if (xisnan (d))
         {
+          octave_preserve_stream_state stream_state (os);
+
           if (fw > 0)
             os << std::setw (fw) << "NaN";
           else
@@ -1642,11 +1641,12 @@
 {
   if (Vfixed_point_format && ! print_g && scale != 1.0)
     {
+      octave_preserve_stream_state stream_state (os);
+
       os << "  "
          << std::setw (8) << std::setprecision (1)
          << std::setiosflags (std::ios::scientific|std::ios::left)
          << scale
-         << std::resetiosflags (std::ios::scientific|std::ios::left)
          << " *\n";
 
       if (! Vcompact_format)
@@ -1660,6 +1660,8 @@
 {
   if (total_width > max_width && Vsplit_long_rows)
     {
+      octave_preserve_stream_state stream_state (os);
+
       if (col != 0)
         {
           if (Vcompact_format)
@@ -1818,6 +1820,8 @@
         }
       else
         {
+          octave_preserve_stream_state stream_state (os);
+
           pr_scale_header (os, scale);
 
           for (octave_idx_type col = 0; col < nc; col += inc)
@@ -1947,6 +1951,8 @@
         }
       else
         {
+          octave_preserve_stream_state stream_state (os);
+
           os << "Diagonal Matrix\n";
           if (! Vcompact_format)
             os << "\n";
@@ -2232,6 +2238,8 @@
         }
       else
         {
+          octave_preserve_stream_state stream_state (os);
+
           pr_scale_header (os, scale);
 
           for (octave_idx_type col = 0; col < nc; col += inc)
@@ -2363,6 +2371,8 @@
         }
       else
         {
+          octave_preserve_stream_state stream_state (os);
+
           os << "Diagonal Matrix\n";
           if (! Vcompact_format)
             os << "\n";
@@ -2511,6 +2521,8 @@
         }
       else
         {
+          octave_preserve_stream_state stream_state (os);
+
           os << "Permutation Matrix\n";
           if (! Vcompact_format)
             os << "\n";
@@ -2677,6 +2689,8 @@
         }
       else
         {
+          octave_preserve_stream_state stream_state (os);
+
           int column_width = fw + 2;
           octave_idx_type total_width = num_elem * column_width;
           octave_idx_type max_width = command_editor::terminal_cols ();
@@ -2972,10 +2986,9 @@
 
   if (hex_format)
     {
-      char ofill = os.fill ('0');
-
-      std::ios::fmtflags oflags
-        = os.flags (std::ios::right | std::ios::hex);
+      octave_preserve_stream_state stream_state (os);
+
+      os.flags (std::ios::right | std::ios::hex);
 
       if (hex_format > 1 || oct_mach_info::words_big_endian ())
         {
@@ -2987,9 +3000,6 @@
           for (int i = sz - 1; i >= 0; i--)
             os << std::setw (2) << static_cast<int> (tmpi[i]);
         }
-
-      os.fill (ofill);
-      os.setf (oflags);
     }
   else if (bit_format)
     {
@@ -3014,6 +3024,8 @@
     }
   else
     {
+      octave_preserve_stream_state stream_state (os);
+
       os << std::setw (fw)
          << typename octave_print_conv<T>::print_conv_type (d);
 
@@ -3308,6 +3320,8 @@
             }
           else
             {
+              octave_preserve_stream_state stream_state (os);
+
               octave_idx_type n_rows = page.rows ();
               octave_idx_type n_cols = page.cols ();
 
--- a/libinterp/corefcn/utils.cc	Thu Oct 31 21:44:58 2013 +0100
+++ b/libinterp/corefcn/utils.cc	Thu Oct 31 17:26:04 2013 -0400
@@ -1434,3 +1434,11 @@
 
   return retval;
 }
+
+octave_preserve_stream_state::~octave_preserve_stream_state (void)
+{
+  stream.flags (oflags);
+  stream.precision (oprecision);
+  stream.width (owidth);
+  stream.fill (ofill);
+}
--- a/libinterp/corefcn/utils.h	Thu Oct 31 21:44:58 2013 +0100
+++ b/libinterp/corefcn/utils.h	Thu Oct 31 17:26:04 2013 -0400
@@ -127,4 +127,25 @@
 do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
                    const char *fun_name, const octave_value_list& args);
 
+class
+octave_preserve_stream_state
+{
+public:
+
+  octave_preserve_stream_state (std::ios& s)
+    : stream (s), oflags (s.flags ()), oprecision (s.precision ()),
+      owidth (s.width ()), ofill (s.fill ())
+  { }
+
+  ~octave_preserve_stream_state (void);
+
+private:
+
+  std::ios& stream;
+  std::ios::fmtflags oflags;
+  std::streamsize oprecision;
+  int owidth;
+  char ofill;
+};
+
 #endif
--- a/libinterp/corefcn/variables.cc	Thu Oct 31 21:44:58 2013 +0100
+++ b/libinterp/corefcn/variables.cc	Thu Oct 31 17:26:04 2013 -0400
@@ -940,6 +940,8 @@
   std::list<whos_parameter>::iterator i = params.begin ();
   std::ostringstream param_buf;
 
+  octave_preserve_stream_state stream_state (os);
+
   while (i != params.end ())
     {
       whos_parameter param = *i;
@@ -1071,6 +1073,8 @@
 
       std::list<whos_parameter>::const_iterator i = params.begin ();
 
+      octave_preserve_stream_state stream_state (os);
+
       while (i != params.end ())
         {
           whos_parameter param = *i;
--- a/libinterp/octave-value/ov-base-sparse.cc	Thu Oct 31 21:44:58 2013 +0100
+++ b/libinterp/octave-value/ov-base-sparse.cc	Thu Oct 31 17:26:04 2013 -0400
@@ -42,6 +42,7 @@
 #include "boolSparse.h"
 #include "ov-base-sparse.h"
 #include "pager.h"
+#include "utils.h"
 
 template <class T>
 octave_value
@@ -306,6 +307,8 @@
 octave_base_sparse<T>::print_raw (std::ostream& os,
                                   bool pr_as_read_syntax) const
 {
+  octave_preserve_stream_state stream_state (os);
+
   octave_idx_type nr = matrix.rows ();
   octave_idx_type nc = matrix.cols ();
   octave_idx_type nz = nnz ();