ostream.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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/histogram/axis/regular.hpp>
  11. #include <boost/histogram/detail/counting_streambuf.hpp>
  12. #include <boost/histogram/detail/priority.hpp>
  13. #include <boost/histogram/detail/type_name.hpp>
  14. #include <boost/histogram/fwd.hpp>
  15. #include <boost/throw_exception.hpp>
  16. #include <cassert>
  17. #include <iomanip>
  18. #include <iosfwd>
  19. #include <sstream>
  20. #include <stdexcept>
  21. #include <type_traits>
  22. /**
  23. \file boost/histogram/axis/ostream.hpp
  24. Simple streaming operators for the builtin axis types.
  25. The text representation is not guaranteed to be stable between versions of
  26. Boost.Histogram. This header is only included by
  27. [boost/histogram/ostream.hpp](histogram/reference.html#header.boost.histogram.ostream_hpp).
  28. To use your own, include your own implementation instead of this header and do not
  29. include
  30. [boost/histogram/ostream.hpp](histogram/reference.html#header.boost.histogram.ostream_hpp).
  31. */
  32. #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
  33. namespace boost {
  34. namespace histogram {
  35. namespace detail {
  36. template <class OStream, class T>
  37. auto ostream_any_impl(OStream& os, const T& t, priority<1>) -> decltype(os << t) {
  38. return os << t;
  39. }
  40. template <class OStream, class T>
  41. OStream& ostream_any_impl(OStream& os, const T&, priority<0>) {
  42. return os << type_name<T>();
  43. }
  44. template <class OStream, class T>
  45. OStream& ostream_any(OStream& os, const T& t) {
  46. return ostream_any_impl(os, t, priority<1>{});
  47. }
  48. template <class OStream, class... Ts>
  49. OStream& ostream_any_quoted(OStream& os, const std::basic_string<Ts...>& s) {
  50. return os << std::quoted(s);
  51. }
  52. template <class OStream, class T>
  53. OStream& ostream_any_quoted(OStream& os, const T& t) {
  54. return ostream_any(os, t);
  55. }
  56. template <class... Ts, class T>
  57. std::basic_ostream<Ts...>& ostream_metadata(std::basic_ostream<Ts...>& os, const T& t,
  58. const char* prefix = ", ") {
  59. std::streamsize count = 0;
  60. {
  61. auto g = make_count_guard(os, count);
  62. ostream_any(os, t);
  63. }
  64. if (!count) return os;
  65. os << prefix << "metadata=";
  66. return ostream_any_quoted(os, t);
  67. }
  68. template <class OStream>
  69. void ostream_options(OStream& os, const unsigned bits) {
  70. bool first = true;
  71. os << ", options=";
  72. #define BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(x) \
  73. if (bits & axis::option::x) { \
  74. if (first) \
  75. first = false; \
  76. else { \
  77. os << " | "; \
  78. } \
  79. os << #x; \
  80. }
  81. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(underflow);
  82. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(overflow);
  83. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(circular);
  84. BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(growth);
  85. #undef BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM
  86. if (first) os << "none";
  87. }
  88. } // namespace detail
  89. namespace axis {
  90. template <class T>
  91. class polymorphic_bin;
  92. template <class... Ts>
  93. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const null_type&) {
  94. return os; // do nothing
  95. }
  96. template <class... Ts, class U>
  97. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  98. const interval_view<U>& i) {
  99. return os << "[" << i.lower() << ", " << i.upper() << ")";
  100. }
  101. template <class... Ts, class U>
  102. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  103. const polymorphic_bin<U>& i) {
  104. if (i.is_discrete()) return os << static_cast<double>(i);
  105. return os << "[" << i.lower() << ", " << i.upper() << ")";
  106. }
  107. namespace transform {
  108. template <class... Ts>
  109. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const id&) {
  110. return os;
  111. }
  112. template <class... Ts>
  113. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const log&) {
  114. return os << "transform::log{}";
  115. }
  116. template <class... Ts>
  117. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const sqrt&) {
  118. return os << "transform::sqrt{}";
  119. }
  120. template <class... Ts>
  121. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const pow& p) {
  122. return os << "transform::pow{" << p.power << "}";
  123. }
  124. } // namespace transform
  125. template <class... Ts, class... Us>
  126. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  127. const regular<Us...>& a) {
  128. os << "regular(";
  129. const auto pos = os.tellp();
  130. os << a.transform();
  131. if (os.tellp() > pos) os << ", ";
  132. os << a.size() << ", " << a.value(0) << ", " << a.value(a.size());
  133. detail::ostream_metadata(os, a.metadata());
  134. detail::ostream_options(os, a.options());
  135. return os << ")";
  136. }
  137. template <class... Ts, class... Us>
  138. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  139. const integer<Us...>& a) {
  140. os << "integer(" << a.value(0) << ", " << a.value(a.size());
  141. detail::ostream_metadata(os, a.metadata());
  142. detail::ostream_options(os, a.options());
  143. return os << ")";
  144. }
  145. template <class... Ts, class... Us>
  146. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  147. const variable<Us...>& a) {
  148. os << "variable(" << a.value(0);
  149. for (index_type i = 1, n = a.size(); i <= n; ++i) { os << ", " << a.value(i); }
  150. detail::ostream_metadata(os, a.metadata());
  151. detail::ostream_options(os, a.options());
  152. return os << ")";
  153. }
  154. template <class... Ts, class... Us>
  155. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  156. const category<Us...>& a) {
  157. os << "category(";
  158. for (index_type i = 0, n = a.size(); i < n; ++i) {
  159. detail::ostream_any_quoted(os, a.value(i));
  160. os << (i == (a.size() - 1) ? "" : ", ");
  161. }
  162. detail::ostream_metadata(os, a.metadata());
  163. detail::ostream_options(os, a.options());
  164. return os << ")";
  165. }
  166. template <class... Ts, class M>
  167. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  168. const boolean<M>& a) {
  169. os << "boolean(";
  170. detail::ostream_metadata(os, a.metadata(), "");
  171. return os << ")";
  172. }
  173. template <class... Ts, class... Us>
  174. std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
  175. const variant<Us...>& v) {
  176. visit([&os](const auto& x) { detail::ostream_any(os, x); }, v);
  177. return os;
  178. }
  179. } // namespace axis
  180. } // namespace histogram
  181. } // namespace boost
  182. #endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
  183. #endif