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