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; }