You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

114 regels
4.3 KiB

  1. /* Boost Software License - Version 1.0 - August 17th, 2003
  2. *
  3. * Permission is hereby granted, free of charge, to any person or organization
  4. * obtaining a copy of the software and accompanying documentation covered by
  5. * this license (the "Software") to use, reproduce, display, distribute,
  6. * execute, and transmit the Software, and to prepare derivative works of the
  7. * Software, and to permit third-parties to whom the Software is furnished to
  8. * do so, all subject to the following:
  9. *
  10. * The copyright notices in the Software and this entire statement, including
  11. * the above license grant, this restriction and the following disclaimer,
  12. * must be included in all copies of the Software, in whole or in part, and
  13. * all derivative works of the Software, unless such copies or derivative
  14. * works are solely in the form of machine-executable object code generated by
  15. * a source language processor.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  20. * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  21. * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  22. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE. */
  24. #ifndef HEADER_GENERIC_INSERTER_HPP_INCLUDED
  25. #define HEADER_GENERIC_INSERTER_HPP_INCLUDED
  26. #include <ostream>
  27. #include <new> // bad_alloc
  28. template <typename char_type, typename traits_type, typename argument_type>
  29. std::basic_ostream<char_type, traits_type>& generic_inserter(void (*print)(std::basic_ostream<char_type, traits_type>& os, argument_type const& arg), std::basic_ostream<char_type, traits_type>& os, argument_type const& arg)
  30. {
  31. using namespace ::std;
  32. ios_base::iostate err = ios_base::goodbit;
  33. try
  34. {
  35. typename basic_ostream<char_type, traits_type>::sentry sentry(os);
  36. if (sentry)
  37. {
  38. print(os, arg);
  39. err = os.rdstate();
  40. os.width(0); // Reset width in case the user didn't do it.
  41. }
  42. }
  43. catch (bad_alloc const&)
  44. {
  45. err |= ios_base::badbit; // bad_alloc is considered fatal
  46. ios_base::iostate const exception_mask = os.exceptions();
  47. // Two cases: 1.) badbit is not set; 2.) badbit is set
  48. if (((exception_mask & ios_base::failbit) != 0) && // failbit shall throw
  49. ((exception_mask & ios_base::badbit) == 0)) // badbit shall not throw
  50. {
  51. // Do not throw unless failbit is set.
  52. // If it is set throw ios_base::failure because we don't know what caused the failbit to be set.
  53. os.setstate(err);
  54. }
  55. else if (exception_mask & ios_base::badbit)
  56. {
  57. try
  58. {
  59. // This will set the badbit and throw ios_base::failure.
  60. os.setstate(err);
  61. }
  62. catch (ios_base::failure const&)
  63. {
  64. // Do nothing since we want bad_alloc to be rethrown.
  65. }
  66. throw;
  67. }
  68. // else: no exception must get out!
  69. }
  70. catch (...)
  71. {
  72. err |= ios_base::failbit; // Any other exception is considered "only" as a failure.
  73. ios_base::iostate const exception_mask = os.exceptions();
  74. // badbit is considered more important
  75. if (((exception_mask & ios_base::badbit) != 0) && // badbit shall throw
  76. ((err & ios_base::badbit) != 0)) // badbit is set
  77. {
  78. // Throw ios_base::failure because we don't know what caused the badbit to be set.
  79. os.setstate(err);
  80. }
  81. else if ((exception_mask & ios_base::failbit) != 0)
  82. {
  83. try
  84. {
  85. // This will set the failbit and throw the exception ios_base::failure.
  86. os.setstate(err);
  87. }
  88. catch (ios_base::failure const&)
  89. {
  90. // Do nothing since we want the original exception to be rethrown.
  91. }
  92. throw;
  93. }
  94. // else: no exception must get out!
  95. }
  96. // Needed in the case that no exception has been thrown but the stream state has changed.
  97. if (err)
  98. os.setstate(err);
  99. return os;
  100. }
  101. #endif // HEADER_GENERIC_INSERTER_HPP_INCLUDED