Anton Pevtsov wrote:
Martin, the changes look goog, but I have a question about __rw_insert:

When macro _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE is defined the width(0)
will be called only if __pad > 0. But pad can be <= 0 when len >= width.

I see what you mean. This must pass:

  #include <cassert>
  #include <sstream>

  int main ()
  {
      std::ostringstream strm;
      strm.width (-1);
      strm << ' ';
      assert (0 == strm.width ());
  }


I propose to add '.' after "if (len < width)" to the comment:

Sounds good.


[...]
Also it may be useful to remove lines:
[...]
and append these lines:
[...]
What do you think about this?

Good catch, thanks! The changes you suggest are in the attached
patch.

Btw., it was pointed out to me that the width test was still subtly
wrong WRT the currently mandated behavior for single character
inserters: they are specified to reset width before inserting any
characters. I fixed this bug in the test but I haven't yet fixed it
in the library. Since the single char inserters are implemented using
the same function as the array forms and since the array forms are
supposed to call width(0) after they're done inserting the fix would
require either adding a new overload of __rw_insert for the single-char
inserters or adding an argument to the array overload of __rw_insert()
as you suggested yesterday. I haven't decided which we should go with
or even if it's worth the trouble. I'm beginning to think that we might
just go with the proposed behavior and forget about strict conformance
here since the latter is inconsistent and would be a hassle to
implement.

Martin
==== //stdlib/dev/include/rw/_ioinsert.cc#12 - 
/build/sebor/dev/stdlib/include/rw/_ioinsert.cc ====
@@ -7,16 +7,22 @@
  *
  ***************************************************************************
  *
- * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
- * Software division. Licensed under the Apache License, Version 2.0 (the
- * "License");  you may  not use this file except  in compliance with the
- * License.    You    may   obtain   a   copy   of    the   License    at
- * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
- * applicable law  or agreed to  in writing,  software  distributed under
- * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
- * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
- * for the specific language governing permissions  and limitations under
- * the License.
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 1994-2006 Rogue Wave Software.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  * 
  **************************************************************************/
 
@@ -40,13 +46,23 @@
         typedef _STD::ostreambuf_iterator<_CharT, _Traits> _Iter;
         typedef _STD::num_put<_CharT, _Iter>               _NumPut;
 
-        if (__opfx && _STD_USE_FACET (_NumPut, __strm.getloc ())
-            .put (_Iter (__strm), __strm, __strm.fill (), __val).failed ()) {
+        if (__opfx) {
+
+            if(_STD_USE_FACET (_NumPut, __strm.getloc ())
+               .put (_Iter (__strm), __strm, __strm.fill (), __val).failed ()) 
{
 
-            // this may throw but the exception will just be caught
-            // and rethrown below; this optimizes for the common case
-            // (i.e., success) but pessimizes the case of failure
-            __strm.setstate (_STD::ios_base::badbit);
+                // this may throw but the exception will just be caught
+                // and rethrown below; this optimizes for the common case
+                // (i.e., success) but pessimizes the case of failure
+                __strm.setstate (_STD::ios_base::badbit);
+            }
+#ifndef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+            else
+                __strm.width (0);   // reset width only on success
+#else   // if defined (_RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE)
+            __strm.width (0);   // reset width unconditionally
+            
+#endif   // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
         }
     }
     _CATCH (...) {
@@ -118,8 +134,11 @@
       
     _STD::ios_base::iostate __err = _STD::ios_base::goodbit;
 
-    // will write out max(len, width) characters, padding
-    // appropriately (with fill character) if len < width
+    // writes out max(len, width) characters, padding appropriately
+    // with the fill character if (len < width);
+    // calls width(0) if and only if the write has been successful
+    // (i.e., will leave it unchanged if sputn fails or throws an
+    // exception)
 
     _TRY {
   
@@ -148,17 +167,35 @@
                     || _STD::ios_base::left == __padbits
                     && __pad != __strm._C_pad (__pad))
                     __err = _STD::ios_base::badbit;
+#ifndef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+                else
+                    __strm.width (0);   // reset width only on success
+#else   // if defined (_RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE)
+                __strm.width (0);   // reset width unconditionally
+#endif   // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
             }
-            else if (__len != __rw_sputn (__strm, __s, __len, _Same ()))
+            else if (__len == __rw_sputn (__strm, __s, __len, _Same ())) {
+                __strm.width (0);   // reset width only on success
+            }
+            else {
                 __err = _STD::ios_base::badbit;
+
+#ifndef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+                __strm.width (0);   // reset width only on success
+#endif   // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+            }
         }
     }
     _CATCH (...) {
+        // set badbit and rethrow the caught exception if badbit
+        // is also set in exceptions()
         __strm.setstate (_STD::ios_base::badbit | _RW::__rw_rethrow);
     }
 
-    if (__err)
-        __strm.setstate (__err);  
+    if (__err) {
+        // set badbit which may throw ios_base::failure
+        __strm.setstate (__err);
+    }
 
     return __strm;
 }

Reply via email to