ostream.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright 2015-2017 Hans Dembinski
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // String representations here evaluate correctly in Python.
  8. #ifndef BOOST_HISTOGRAM_AXIS_OSTREAM_HPP
  9. #define BOOST_HISTOGRAM_AXIS_OSTREAM_HPP
  10. #include <boost/assert.hpp>
  11. #include <boost/core/typeinfo.hpp>
  12. #include <boost/histogram/axis/regular.hpp>
  13. #include <boost/histogram/detail/cat.hpp>
  14. #include <boost/histogram/detail/meta.hpp>
  15. #include <boost/histogram/fwd.hpp>
  16. #include <boost/throw_exception.hpp>
  17. #include <iomanip>
  18. #include <iosfwd>
  19. #include <stdexcept>
  20. #include <type_traits>
  21. #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
  22. namespace boost {
  23. namespace histogram {
  24. namespace detail {
  25. inline const char* axis_suffix(const axis::transform::id&) { return ""; }
  26. inline const char* axis_suffix(const axis::transform::log&) { return "_log"; }
  27. inline const char* axis_suffix(const axis::transform::sqrt&) { return "_sqrt"; }
  28. inline const char* axis_suffix(const axis::transform::pow&) { return "_pow"; }
  29. template <class OStream, class T>
  30. void stream_metadata(OStream& os, const T& t) {
  31. detail::static_if<detail::is_streamable<T>>(
  32. [&os](const auto& t) {
  33. std::ostringstream oss;
  34. oss << t;
  35. if (!oss.str().empty()) { os << ", metadata=" << std::quoted(oss.str()); }
  36. },
  37. [&os](const auto&) {
  38. os << ", metadata=" << boost::core::demangled_name(BOOST_CORE_TYPEID(T));
  39. },
  40. t);
  41. }
  42. template <class OStream>
  43. void stream_options(OStream& os, const unsigned bits) {
  44. os << ", options=";
  45. bool first = true;
  46. #define BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(x) \
  47. if (bits & axis::option::x) { \
  48. if (first) \
  49. first = false; \
  50. else { \
  51. os << " | "; \
  52. } \
  53. os << #x; \
  54. }
  55. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(underflow);
  56. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(overflow);
  57. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(circular);
  58. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(growth);
  59. #undef BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM
  60. if (first) os << "none";
  61. }
  62. template <class OStream, class T>
  63. void stream_transform(OStream&, const T&) {}
  64. template <class OStream>
  65. void stream_transform(OStream& os, const axis::transform::pow& t) {
  66. os << ", power=" << t.power;
  67. }
  68. template <class OStream, class T>
  69. void stream_value(OStream& os, const T& t) {
  70. os << t;
  71. }
  72. template <class OStream, class... Ts>
  73. void stream_value(OStream& os, const std::basic_string<Ts...>& t) {
  74. os << std::quoted(t);
  75. }
  76. } // namespace detail
  77. namespace axis {
  78. template <class T>
  79. class polymorphic_bin;
  80. template <class... Ts>
  81. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const null_type&) {
  82. return os; // do nothing
  83. }
  84. template <class... Ts, class U>
  85. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  86. const interval_view<U>& i) {
  87. os << "[" << i.lower() << ", " << i.upper() << ")";
  88. return os;
  89. }
  90. template <class... Ts, class U>
  91. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  92. const polymorphic_bin<U>& i) {
  93. if (i.is_discrete())
  94. os << static_cast<double>(i);
  95. else
  96. os << "[" << i.lower() << ", " << i.upper() << ")";
  97. return os;
  98. }
  99. template <class... Ts, class... Us>
  100. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  101. const regular<Us...>& a) {
  102. os << "regular" << detail::axis_suffix(a.transform()) << "(" << a.size() << ", "
  103. << a.value(0) << ", " << a.value(a.size());
  104. detail::stream_metadata(os, a.metadata());
  105. detail::stream_options(os, a.options());
  106. detail::stream_transform(os, a.transform());
  107. os << ")";
  108. return os;
  109. }
  110. template <class... Ts, class... Us>
  111. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  112. const integer<Us...>& a) {
  113. os << "integer(" << a.value(0) << ", " << a.value(a.size());
  114. detail::stream_metadata(os, a.metadata());
  115. detail::stream_options(os, a.options());
  116. os << ")";
  117. return os;
  118. }
  119. template <class... Ts, class... Us>
  120. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  121. const variable<Us...>& a) {
  122. os << "variable(" << a.value(0);
  123. for (index_type i = 1, n = a.size(); i <= n; ++i) { os << ", " << a.value(i); }
  124. detail::stream_metadata(os, a.metadata());
  125. detail::stream_options(os, a.options());
  126. os << ")";
  127. return os;
  128. }
  129. template <class... Ts, class... Us>
  130. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  131. const category<Us...>& a) {
  132. os << "category(";
  133. for (index_type i = 0, n = a.size(); i < n; ++i) {
  134. detail::stream_value(os, a.value(i));
  135. os << (i == (a.size() - 1) ? "" : ", ");
  136. }
  137. detail::stream_metadata(os, a.metadata());
  138. detail::stream_options(os, a.options());
  139. os << ")";
  140. return os;
  141. }
  142. template <class... Ts, class... Us>
  143. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  144. const variant<Us...>& v) {
  145. visit(
  146. [&os](const auto& x) {
  147. using A = detail::remove_cvref_t<decltype(x)>;
  148. detail::static_if<detail::is_streamable<A>>(
  149. [&os](const auto& x) { os << x; },
  150. [](const auto&) {
  151. BOOST_THROW_EXCEPTION(std::runtime_error(
  152. detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(A)),
  153. " is not streamable")));
  154. },
  155. x);
  156. },
  157. v);
  158. return os;
  159. }
  160. } // namespace axis
  161. } // namespace histogram
  162. } // namespace boost
  163. #endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
  164. #endif