/* Boost Software License - Version 1.0 - August 17th, 2003 * * Permission is hereby granted, free of charge, to any person or organization * obtaining a copy of the software and accompanying documentation covered by * this license (the "Software") to use, reproduce, display, distribute, * execute, and transmit the Software, and to prepare derivative works of the * Software, and to permit third-parties to whom the Software is furnished to * do so, all subject to the following: * * The copyright notices in the Software and this entire statement, including * the above license grant, this restriction and the following disclaimer, * must be included in all copies of the Software, in whole or in part, and * all derivative works of the Software, unless such copies or derivative * works are solely in the form of machine-executable object code generated by * a source language processor. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef HEADER_GENERIC_INSERTER_HPP_INCLUDED #define HEADER_GENERIC_INSERTER_HPP_INCLUDED #include #include // bad_alloc template std::basic_ostream& generic_inserter(void (*print)(std::basic_ostream& os, argument_type const& arg), std::basic_ostream& os, argument_type const& arg) { using namespace ::std; ios_base::iostate err = ios_base::goodbit; try { typename basic_ostream::sentry sentry(os); if (sentry) { print(os, arg); err = os.rdstate(); os.width(0); // Reset width in case the user didn't do it. } } catch (bad_alloc const&) { err |= ios_base::badbit; // bad_alloc is considered fatal ios_base::iostate const exception_mask = os.exceptions(); // Two cases: 1.) badbit is not set; 2.) badbit is set if (((exception_mask & ios_base::failbit) != 0) && // failbit shall throw ((exception_mask & ios_base::badbit) == 0)) // badbit shall not throw { // Do not throw unless failbit is set. // If it is set throw ios_base::failure because we don't know what caused the failbit to be set. os.setstate(err); } else if (exception_mask & ios_base::badbit) { try { // This will set the badbit and throw ios_base::failure. os.setstate(err); } catch (ios_base::failure const&) { // Do nothing since we want bad_alloc to be rethrown. } throw; } // else: no exception must get out! } catch (...) { err |= ios_base::failbit; // Any other exception is considered "only" as a failure. ios_base::iostate const exception_mask = os.exceptions(); // badbit is considered more important if (((exception_mask & ios_base::badbit) != 0) && // badbit shall throw ((err & ios_base::badbit) != 0)) // badbit is set { // Throw ios_base::failure because we don't know what caused the badbit to be set. os.setstate(err); } else if ((exception_mask & ios_base::failbit) != 0) { try { // This will set the failbit and throw the exception ios_base::failure. os.setstate(err); } catch (ios_base::failure const&) { // Do nothing since we want the original exception to be rethrown. } throw; } // else: no exception must get out! } // Needed in the case that no exception has been thrown but the stream state has changed. if (err) os.setstate(err); return os; } #endif // HEADER_GENERIC_INSERTER_HPP_INCLUDED