OR-Tools  8.1
container_logging.h
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 // Utilities for container logging.
15 // TODO(user): Broaden the scope and rename to "stream_util.h"
16 //
17 // Maintainers: This file is part of portable google3 (go/pg3).
18 //
19 // The typical use looks like this:
20 //
21 // LOG(INFO) << gtl::LogContainer(container);
22 //
23 // By default, LogContainer() uses the LogShortUpTo100 policy: comma-space
24 // separation, no newlines, and with limit of 100 items.
25 //
26 // Policies can be specified:
27 //
28 // LOG(INFO) << gtl::LogContainer(container, gtl::LogMultiline());
29 //
30 // The above example will print the container using newlines between
31 // elements, enclosed in [] braces.
32 //
33 // See below for further details on policies.
34 
35 #ifndef OR_TOOLS_BASE_CONTAINER_LOGGING_H_
36 #define OR_TOOLS_BASE_CONTAINER_LOGGING_H_
37 
38 #include <limits>
39 #include <ostream>
40 #include <sstream>
41 #include <string>
42 #include <type_traits>
43 
45 
46 namespace gtl {
47 
48 // Several policy classes below determine how LogRangeToStream will
49 // format a range of items. A Policy class should have these methods:
50 //
51 // Called to print an individual container element.
52 // void Log(ostream &out, const ElementT &element) const;
53 //
54 // Called before printing the set of elements:
55 // void LogOpening(ostream &out) const;
56 //
57 // Called after printing the set of elements:
58 // void LogClosing(ostream &out) const;
59 //
60 // Called before printing the first element:
61 // void LogFirstSeparator(ostream &out) const;
62 //
63 // Called before printing the remaining elements:
64 // void LogSeparator(ostream &out) const;
65 //
66 // Returns the maximum number of elements to print:
67 // int64 MaxElements() const;
68 //
69 // Called to print an indication that MaximumElements() was reached:
70 // void LogEllipsis(ostream &out) const;
71 
72 namespace internal {
73 
74 struct LogBase {
75  template <typename ElementT>
76  void Log(std::ostream& out, const ElementT& element) const { // NOLINT
77  out << element;
78  }
79  void LogEllipsis(std::ostream& out) const { // NOLINT
80  out << "...";
81  }
82 };
83 
84 struct LogShortBase : public LogBase {
85  void LogOpening(std::ostream& out) const { out << "["; } // NOLINT
86  void LogClosing(std::ostream& out) const { out << "]"; } // NOLINT
87  void LogFirstSeparator(std::ostream& out) const { out << ""; } // NOLINT
88  void LogSeparator(std::ostream& out) const { out << ", "; } // NOLINT
89 };
90 
91 struct LogMultilineBase : public LogBase {
92  void LogOpening(std::ostream& out) const { out << "["; } // NOLINT
93  void LogClosing(std::ostream& out) const { out << "\n]"; } // NOLINT
94  void LogFirstSeparator(std::ostream& out) const { out << "\n"; } // NOLINT
95  void LogSeparator(std::ostream& out) const { out << "\n"; } // NOLINT
96 };
97 
98 struct LogLegacyBase : public LogBase {
99  void LogOpening(std::ostream& out) const { out << ""; } // NOLINT
100  void LogClosing(std::ostream& out) const { out << ""; } // NOLINT
101  void LogFirstSeparator(std::ostream& out) const { out << ""; } // NOLINT
102  void LogSeparator(std::ostream& out) const { out << " "; } // NOLINT
103 };
104 
105 } // namespace internal
106 
107 // LogShort uses [] braces and separates items with comma-spaces. For
108 // example "[1, 2, 3]".
111 };
112 
113 // LogShortUpToN(max_elements) formats the same as LogShort but prints no more
114 // than the max_elements elements.
116  public:
117  explicit LogShortUpToN(int64 max_elements) : max_elements_(max_elements) {}
118  int64 MaxElements() const { return max_elements_; }
119 
120  private:
121  int64 max_elements_;
122 };
123 
124 // LogShortUpTo100 formats the same as LogShort but prints no more
125 // than 100 elements.
128 };
129 
130 // LogMultiline uses [] braces and separates items with
131 // newlines. For example "[
132 // 1
133 // 2
134 // 3
135 // ]".
138 };
139 
140 // LogMultilineUpToN(max_elements) formats the same as LogMultiline but
141 // prints no more than max_elements elements.
143  public:
144  explicit LogMultilineUpToN(int64 max_elements)
145  : max_elements_(max_elements) {}
146  int64 MaxElements() const { return max_elements_; }
147 
148  private:
149  int64 max_elements_;
150 };
151 
152 // LogMultilineUpTo100 formats the same as LogMultiline but
153 // prints no more than 100 elements.
156 };
157 
158 // The legacy behavior of LogSequence() does not use braces and
159 // separates items with spaces. For example "1 2 3".
161  int64 MaxElements() const { return 100; }
162 };
165 };
166 
167 // The default policy for new code.
169 
170 // LogRangeToStream should be used to define operator<< for
171 // STL and STL-like containers. For example, see stl_logging.h.
172 template <typename IteratorT, typename PolicyT>
173 inline void LogRangeToStream(std::ostream& out, // NOLINT
174  IteratorT begin, IteratorT end,
175  const PolicyT& policy) {
176  policy.LogOpening(out);
177  for (int64 i = 0; begin != end && i < policy.MaxElements(); ++i, ++begin) {
178  if (i == 0) {
179  policy.LogFirstSeparator(out);
180  } else {
181  policy.LogSeparator(out);
182  }
183  policy.Log(out, *begin);
184  }
185  if (begin != end) {
186  policy.LogSeparator(out);
187  policy.LogEllipsis(out);
188  }
189  policy.LogClosing(out);
190 }
191 
192 namespace detail {
193 
194 // RangeLogger is a helper class for gtl::LogRange and
195 // gtl::LogContainer; do not use it directly. This object
196 // captures iterators into the argument of the LogRange and
197 // LogContainer functions, so its lifetime should be confined to a
198 // single logging statement. Objects of this type should not be
199 // assigned to local variables.
200 template <typename IteratorT, typename PolicyT>
201 class RangeLogger {
202  public:
203  RangeLogger(const IteratorT& begin, const IteratorT& end,
204  const PolicyT& policy)
205  : begin_(begin), end_(end), policy_(policy) {}
206 
207  friend std::ostream& operator<<(std::ostream& out, const RangeLogger& range) {
208  gtl::LogRangeToStream<IteratorT, PolicyT>(out, range.begin_, range.end_,
209  range.policy_);
210  return out;
211  }
212 
213  // operator<< above is generally recommended. However, some situations may
214  // require a string, so a convenience str() method is provided as well.
215  std::string str() const {
216  std::stringstream ss;
217  ss << *this;
218  return ss.str();
219  }
220 
221  private:
222  IteratorT begin_;
223  IteratorT end_;
224  PolicyT policy_;
225 };
226 
227 template <typename E>
228 class EnumLogger {
229  public:
230  explicit EnumLogger(E e) : e_(e) {}
231 
232  friend std::ostream& operator<<(std::ostream& out, const EnumLogger& v) {
233  using I = typename std::underlying_type<E>::type;
234  return out << static_cast<I>(v.e_);
235  }
236 
237  private:
238  E e_;
239 };
240 
241 } // namespace detail
242 
243 // Log a range using "policy". For example:
244 //
245 // LOG(INFO) << gtl::LogRange(start_pos, end_pos, gtl::LogMultiline());
246 //
247 // The above example will print the range using newlines between
248 // elements, enclosed in [] braces.
249 template <typename IteratorT, typename PolicyT>
251  const IteratorT& end,
252  const PolicyT& policy) {
253  return gtl::detail::RangeLogger<IteratorT, PolicyT>(begin, end, policy);
254 }
255 
256 // Log a range. For example:
257 //
258 // LOG(INFO) << gtl::LogRange(start_pos, end_pos);
259 //
260 // By default, Range() uses the LogShortUpTo100 policy: comma-space
261 // separation, no newlines, and with limit of 100 items.
262 template <typename IteratorT>
264  const IteratorT& end) {
265  return gtl::LogRange(begin, end, LogDefault());
266 }
267 
268 // Log a container using "policy". For example:
269 //
270 // LOG(INFO) << gtl::LogContainer(container, gtl::LogMultiline());
271 //
272 // The above example will print the container using newlines between
273 // elements, enclosed in [] braces.
274 template <typename ContainerT, typename PolicyT>
275 auto LogContainer(const ContainerT& container, const PolicyT& policy)
276  -> decltype(gtl::LogRange(container.begin(), container.end(), policy)) {
277  return gtl::LogRange(container.begin(), container.end(), policy);
278 }
279 
280 // Log a container. For example:
281 //
282 // LOG(INFO) << gtl::LogContainer(container);
283 //
284 // By default, Container() uses the LogShortUpTo100 policy: comma-space
285 // separation, no newlines, and with limit of 100 items.
286 template <typename ContainerT>
287 auto LogContainer(const ContainerT& container)
288  -> decltype(gtl::LogContainer(container, LogDefault())) {
289  return gtl::LogContainer(container, LogDefault());
290 }
291 
292 // Log a (possibly scoped) enum. For example:
293 //
294 // enum class Color { kRed, kGreen, kBlue };
295 // LOG(INFO) << gtl::LogEnum(kRed);
296 template <typename E>
298  static_assert(std::is_enum<E>::value, "must be an enum");
299  return detail::EnumLogger<E>(e);
300 }
301 
302 } // namespace gtl
303 
304 #endif // OR_TOOLS_BASE_CONTAINER_LOGGING_H_
gtl::LogLegacy::MaxElements
int64 MaxElements() const
Definition: container_logging.h:164
gtl::LogDefault
LogShortUpTo100 LogDefault
Definition: container_logging.h:168
integral_types.h
gtl::LogShortUpTo100
Definition: container_logging.h:126
gtl::LogShort::MaxElements
int64 MaxElements() const
Definition: container_logging.h:110
max
int64 max
Definition: alldiff_cst.cc:139
gtl::internal::LogMultilineBase
Definition: container_logging.h:91
gtl::internal::LogLegacyBase::LogFirstSeparator
void LogFirstSeparator(std::ostream &out) const
Definition: container_logging.h:101
gtl::internal::LogShortBase::LogFirstSeparator
void LogFirstSeparator(std::ostream &out) const
Definition: container_logging.h:87
gtl::LogMultilineUpToN::MaxElements
int64 MaxElements() const
Definition: container_logging.h:146
gtl::internal::LogMultilineBase::LogClosing
void LogClosing(std::ostream &out) const
Definition: container_logging.h:93
value
int64 value
Definition: demon_profiler.cc:43
gtl::detail::EnumLogger
Definition: container_logging.h:228
gtl::LogContainer
auto LogContainer(const ContainerT &container, const PolicyT &policy) -> decltype(gtl::LogRange(container.begin(), container.end(), policy))
Definition: container_logging.h:275
gtl::LogEnum
detail::EnumLogger< E > LogEnum(E e)
Definition: container_logging.h:297
gtl::LogRange
detail::RangeLogger< IteratorT, PolicyT > LogRange(const IteratorT &begin, const IteratorT &end, const PolicyT &policy)
Definition: container_logging.h:250
gtl::LogLegacyUpTo100
Definition: container_logging.h:160
gtl::detail::EnumLogger::operator<<
friend std::ostream & operator<<(std::ostream &out, const EnumLogger &v)
Definition: container_logging.h:232
gtl::internal::LogShortBase::LogOpening
void LogOpening(std::ostream &out) const
Definition: container_logging.h:85
gtl::internal::LogLegacyBase::LogSeparator
void LogSeparator(std::ostream &out) const
Definition: container_logging.h:102
gtl::detail::RangeLogger::str
std::string str() const
Definition: container_logging.h:215
int64
int64_t int64
Definition: integral_types.h:34
gtl::internal::LogLegacyBase::LogClosing
void LogClosing(std::ostream &out) const
Definition: container_logging.h:100
gtl::LogShort
Definition: container_logging.h:109
gtl::LogShortUpToN::LogShortUpToN
LogShortUpToN(int64 max_elements)
Definition: container_logging.h:117
gtl::internal::LogMultilineBase::LogOpening
void LogOpening(std::ostream &out) const
Definition: container_logging.h:92
gtl::internal::LogBase::Log
void Log(std::ostream &out, const ElementT &element) const
Definition: container_logging.h:76
gtl::internal::LogLegacyBase::LogOpening
void LogOpening(std::ostream &out) const
Definition: container_logging.h:99
gtl::internal::LogMultilineBase::LogFirstSeparator
void LogFirstSeparator(std::ostream &out) const
Definition: container_logging.h:94
gtl
Definition: container_logging.h:46
gtl::internal::LogMultilineBase::LogSeparator
void LogSeparator(std::ostream &out) const
Definition: container_logging.h:95
gtl::LogMultilineUpToN::LogMultilineUpToN
LogMultilineUpToN(int64 max_elements)
Definition: container_logging.h:144
gtl::LogMultilineUpTo100::LogMultilineUpTo100
LogMultilineUpTo100()
Definition: container_logging.h:155
gtl::internal::LogShortBase
Definition: container_logging.h:84
gtl::LogLegacy
Definition: container_logging.h:163
gtl::LogMultiline
Definition: container_logging.h:136
gtl::LogMultilineUpTo100
Definition: container_logging.h:154
gtl::LogMultilineUpToN
Definition: container_logging.h:142
gtl::internal::LogLegacyBase
Definition: container_logging.h:98
gtl::internal::LogShortBase::LogClosing
void LogClosing(std::ostream &out) const
Definition: container_logging.h:86
gtl::detail::RangeLogger::operator<<
friend std::ostream & operator<<(std::ostream &out, const RangeLogger &range)
Definition: container_logging.h:207
gtl::internal::LogShortBase::LogSeparator
void LogSeparator(std::ostream &out) const
Definition: container_logging.h:88
gtl::LogMultiline::MaxElements
int64 MaxElements() const
Definition: container_logging.h:137
gtl::LogLegacyUpTo100::MaxElements
int64 MaxElements() const
Definition: container_logging.h:161
gtl::detail::EnumLogger::EnumLogger
EnumLogger(E e)
Definition: container_logging.h:230
gtl::LogShortUpToN
Definition: container_logging.h:115
gtl::detail::RangeLogger
Definition: container_logging.h:201
gtl::LogRangeToStream
void LogRangeToStream(std::ostream &out, IteratorT begin, IteratorT end, const PolicyT &policy)
Definition: container_logging.h:173
internal
Definition: bop_parameters.pb.h:39
gtl::detail::RangeLogger::RangeLogger
RangeLogger(const IteratorT &begin, const IteratorT &end, const PolicyT &policy)
Definition: container_logging.h:203
gtl::internal::LogBase
Definition: container_logging.h:74
gtl::LogShortUpToN::MaxElements
int64 MaxElements() const
Definition: container_logging.h:118
gtl::internal::LogBase::LogEllipsis
void LogEllipsis(std::ostream &out) const
Definition: container_logging.h:79
gtl::LogShortUpTo100::LogShortUpTo100
LogShortUpTo100()
Definition: container_logging.h:127