print.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #ifndef BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED
  2. #define BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED
  3. // Copyright 2018-2024 Emil Dotchevski and Reverge Studios, Inc.
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/leaf/config.hpp>
  7. #include <boost/leaf/detail/demangle.hpp>
  8. #include <type_traits>
  9. #include <exception>
  10. #include <iosfwd>
  11. #include <cstring>
  12. namespace boost { namespace leaf {
  13. template <class E>
  14. struct show_in_diagnostics: std::true_type
  15. {
  16. };
  17. namespace detail
  18. {
  19. template <class T, class E = void>
  20. struct is_printable: std::false_type
  21. {
  22. };
  23. template <class T>
  24. struct is_printable<T, decltype(std::declval<std::ostream&>()<<std::declval<T const &>(), void())>: show_in_diagnostics<T>
  25. {
  26. };
  27. ////////////////////////////////////////
  28. template <class T, class E = void>
  29. struct has_printable_member_value: std::false_type
  30. {
  31. };
  32. template <class T>
  33. struct has_printable_member_value<T, decltype(std::declval<std::ostream&>()<<std::declval<T const &>().value, void())>: show_in_diagnostics<T>
  34. {
  35. };
  36. ////////////////////////////////////////
  37. template <class T, class CharT, class Traits>
  38. void print_name(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter)
  39. {
  40. static_assert(show_in_diagnostics<T>::value, "show_in_diagnostics violation");
  41. BOOST_LEAF_ASSERT(delimiter);
  42. char const * p = prefix;
  43. prefix = nullptr;
  44. os << (p ? p : delimiter) << parse<T>();
  45. }
  46. template <class T, class PrintableInfo, class CharT, class Traits>
  47. bool print_impl(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, char const * mid, PrintableInfo const & x)
  48. {
  49. print_name<T>(os, prefix, delimiter);
  50. if( mid )
  51. os << mid << x;
  52. return true;
  53. }
  54. template <class T, class PrintableInfo, class CharT, class Traits>
  55. bool print_impl(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, char const * mid, PrintableInfo const * x)
  56. {
  57. print_name<T>(os, prefix, delimiter);
  58. if( mid )
  59. {
  60. os << mid;
  61. if( x )
  62. os << x;
  63. else
  64. os << "<nullptr>";
  65. }
  66. return true;
  67. }
  68. ////////////////////////////////////////
  69. template <
  70. class Wrapper,
  71. bool ShowInDiagnostics = show_in_diagnostics<Wrapper>::value,
  72. bool WrapperPrintable = is_printable<Wrapper>::value,
  73. bool ValuePrintable = has_printable_member_value<Wrapper>::value,
  74. bool IsException = std::is_base_of<std::exception,Wrapper>::value,
  75. bool IsEnum = std::is_enum<Wrapper>::value>
  76. struct diagnostic;
  77. template <class Wrapper, bool WrapperPrintable, bool ValuePrintable, bool IsException, bool IsEnum>
  78. struct diagnostic<Wrapper, false, WrapperPrintable, ValuePrintable, IsException, IsEnum>
  79. {
  80. template <class CharT, class Traits>
  81. static bool print(std::basic_ostream<CharT, Traits> &, char const * &, char const *, Wrapper const & x) noexcept
  82. {
  83. return false;
  84. }
  85. };
  86. template <class Wrapper, bool ValuePrintable, bool IsEnum>
  87. struct diagnostic<Wrapper, true, true, ValuePrintable, false, IsEnum>
  88. {
  89. template <class CharT, class Traits>
  90. static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Wrapper const & x)
  91. {
  92. return print_impl<Wrapper>(os, prefix, delimiter, ": ", x);
  93. }
  94. };
  95. template <class Wrapper>
  96. struct diagnostic<Wrapper, true, false, true, false, false>
  97. {
  98. template <class CharT, class Traits>
  99. static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Wrapper const & x)
  100. {
  101. return print_impl<Wrapper>(os, prefix, delimiter, ": ", x.value);
  102. }
  103. };
  104. template <class Exception, bool WrapperPrintable, bool ValuePrintable>
  105. struct diagnostic<Exception, true, WrapperPrintable, ValuePrintable, true, false>
  106. {
  107. template <class CharT, class Traits>
  108. static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Exception const & ex)
  109. {
  110. if( print_impl<Exception>(os, prefix, delimiter, ": \"", static_cast<std::exception const &>(ex).what()) )
  111. {
  112. os << '"';
  113. return true;
  114. }
  115. return false;
  116. }
  117. };
  118. template <class Wrapper>
  119. struct diagnostic<Wrapper, true, false, false, false, false>
  120. {
  121. template <class CharT, class Traits>
  122. static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Wrapper const &)
  123. {
  124. return print_impl<Wrapper>(os, prefix, delimiter, nullptr, 0);
  125. }
  126. };
  127. template <class Enum>
  128. struct diagnostic<Enum, true, false, false, false, true>
  129. {
  130. template <class CharT, class Traits>
  131. static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Enum const & enum_)
  132. {
  133. return print_impl<Enum>(os, prefix, delimiter, ": ", static_cast<typename std::underlying_type<Enum>::type>(enum_));
  134. }
  135. };
  136. }
  137. } }
  138. #endif // BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED