Anton Pevtsov wrote:
[...]
The possible fix of the STDCXX-206 and STDCXX-205 is here
http://people.apache.org/~antonp/stdcxx06262006/lib/
It required changes in several places:
[...]
What do you think about this?

I'm still thinking about what the best way to deal with it is
and discussing it with others. I made similar changes last week
and implemented the proposed resolution I mentioned previously.
I tested them with an updated version of the width test (the
original contained a number of bugs that I fixed last Friday):
http://people.apache.org/~sebor/width_test.cpp

The changes are attached for your review. The new behavior is
guarded by the _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE macro. Defining
the macro disables the new behavior and enables the behavior required
by the current standard (except for the boolalpha part which is just
a silly mistake in the standard).

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,34 @@
                     || _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 ())) {
+
+#ifndef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+                __strm.width (0);   // reset width only on success
+#endif   // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+
             }
-            else if (__len != __rw_sputn (__strm, __s, __len, _Same ()))
+            else
                 __err = _STD::ios_base::badbit;
         }
     }
     _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;
 }
==== //stdlib/dev/include/loc/_num_put.cc#35 - 
/build/sebor/dev/stdlib/include/loc/_num_put.cc ====
@@ -6,16 +6,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 2001-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.
  * 
  **************************************************************************/
 
@@ -31,6 +37,18 @@
 _RWSTD_EXPORT extern const unsigned char
 __rw_digit_map[];
 
+
+template <class _OutputIter>
+inline bool
+__rw_iter_failed (const _OutputIter&) { return false; }
+
+template <class _CharT, class _Traits>
+inline bool
+__rw_iter_failed (const _STD::ostreambuf_iterator<_CharT, _Traits> &__it)
+{
+    return __it.failed ();
+}
+
 }   // namespace __rw
 
 
@@ -94,6 +112,14 @@
     // number of fill chars to pad with
     streamsize __pad = __flags.width () - streamsize (__res);
 
+#ifdef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+
+    // unconditionally reset width before inserting anything
+    // in case the insertion causes an exception to be thrown
+    __flags.width (0);
+
+#endif   // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+
     // adjustfield bits (left, internal, or the default right)
     const int __adj = __f & _RWSTD_IOS_ADJUSTFIELD;
 
@@ -164,8 +190,14 @@
     for (; __pad > 0; ++__it, --__pad)
         *__it = __fill;
 
-    // 22.2.2.2.2, p1
-    __flags.width (0);
+#ifndef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
+
+    // reset width only if the insertion has been successful
+    // (i.e., no exception and the iterator has not failed)
+    if (!_RW::__rw_iter_failed (__it))
+        __flags.width (0);
+
+#endif   // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
 
     return __it;
 }
==== //stdlib/dev/include/ostream#77 - /build/sebor/dev/stdlib/include/ostream 
====
@@ -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.
  * 
  **************************************************************************/
 
@@ -336,8 +342,7 @@
 inline basic_ostream<_CharT, _Traits>&
 operator<< (basic_ostream<_CharT, _Traits> &__strm, _CharT __c)
 {
-    _RW::__rw_insert (__strm, &__c, 1, __strm.width ()).width (0);
-    return __strm;
+    return _RW::__rw_insert (__strm, &__c, 1, __strm.width ());
 }
 
 
@@ -347,8 +352,7 @@
 inline basic_ostream<_CharT, _Traits>&
 operator<< (basic_ostream<_CharT, _Traits> &__strm, char __c)
 {
-    _RW::__rw_insert (__strm, &__c, 1, __strm.width ()).width (0);
-    return __strm;
+    return _RW::__rw_insert (__strm, &__c, 1, __strm.width ());
 }
 
 
@@ -358,8 +362,7 @@
 inline basic_ostream<char, _Traits>&
 operator<< (basic_ostream<char, _Traits> &__strm, char __c)
 {
-    _RW::__rw_insert (__strm, &__c, 1, __strm.width ()).width (0);
-    return __strm;
+    return _RW::__rw_insert (__strm, &__c, 1, __strm.width ());
 }
 
 #  else   // if defined (_RWSTD_NO_FUNC_PARTIAL_SPEC)
@@ -367,8 +370,7 @@
 inline basic_ostream<char, char_traits<char> >&
 operator<< (basic_ostream<char, char_traits<char> > &__strm, char __c)
 {
-    _RW::__rw_insert (__strm, &__c, 1, __strm.width ()).width (0);
-    return __strm;
+    return _RW::__rw_insert (__strm, &__c, 1, __strm.width ());
 }
 
 #  endif   // _RWSTD_NO_FUNC_PARTIAL_SPEC
@@ -380,8 +382,7 @@
 inline basic_ostream<_CharT, _Traits>&
 operator<< (basic_ostream<_CharT, _Traits> &__strm, const _CharT *__s)
 {
-    _RW::__rw_insert (__strm, __s, _Traits::length (__s),
-                      __strm.width ()).width (0);
+    _RW::__rw_insert (__strm, __s, _Traits::length (__s), __strm.width ());
     return __strm;
 }
 
@@ -393,7 +394,7 @@
 operator<< (basic_ostream<_CharT, _Traits> &__strm, const char *__s)
 {
     _RW::__rw_insert (__strm, __s, char_traits<char>::length (__s),
-                      __strm.width ()).width (0);
+                      __strm.width ());
     return __strm;
 }
 
@@ -405,7 +406,7 @@
 operator<< (basic_ostream<char, _Traits> &__strm, const char *__s)
 {
     _RW::__rw_insert (__strm, __s, char_traits<char>::length (__s),
-                      __strm.width ()).width (0);
+                      __strm.width ());
     return __strm;
 }
 
@@ -415,7 +416,7 @@
 operator<< (basic_ostream<char, char_traits<char> >& __strm, const char *__s)
 {
     _RW::__rw_insert (__strm, __s, streamsize (char_traits<char>::length 
(__s)),
-                      __strm.width ()).width (0);
+                      __strm.width ());
     return __strm;
 }
 
@@ -489,7 +490,7 @@
             const basic_string<_CharT, _Traits, _Allocator> &__str)
 {
     _RW::__rw_insert (__strm, __str.data (), __str.length (),
-                      __strm.width ()).width (0);
+                      __strm.width ());
     return __strm;
 }
 

Reply via email to