Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
container_logging.h
Go to the documentation of this file.
1// Copyright 2010-2024 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//
18// The typical use looks like this:
19//
20// LOG(INFO) << gtl::LogContainer(container);
21//
22// By default, LogContainer() uses the LogShortUpTo100 policy: comma-space
23// separation, no newlines, and with limit of 100 items.
24//
25// Policies can be specified:
26//
27// LOG(INFO) << gtl::LogContainer(container, gtl::LogMultiline());
28//
29// The above example will print the container using newlines between
30// elements, enclosed in [] braces.
31//
32// See below for further details on policies.
33
34#ifndef OR_TOOLS_BASE_CONTAINER_LOGGING_H_
35#define OR_TOOLS_BASE_CONTAINER_LOGGING_H_
36
37#include <cstdint>
38#include <limits>
39#include <ostream>
40#include <sstream>
41#include <string>
42#include <type_traits>
43
44#include "absl/base/port.h"
45
46namespace 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_t MaxElements() const;
68//
69// Called to print an indication that MaximumElements() was reached:
70// void LogEllipsis(ostream &out) const;
71
72namespace internal {
73
74struct 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
84struct 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
91struct 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
98struct 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]".
110 int64_t MaxElements() const { return std::numeric_limits<int64_t>::max(); }
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_t max_elements) : max_elements_(max_elements) {}
118 int64_t MaxElements() const { return max_elements_; }
119
120 private:
121 int64_t max_elements_;
122};
123
124// LogShortUpTo100 formats the same as LogShort but prints no more
125// than 100 elements.
129
130// LogMultiline uses [] braces and separates items with
131// newlines. For example "[
132// 1
133// 2
134// 3
135// ]".
137 int64_t MaxElements() const { return std::numeric_limits<int64_t>::max(); }
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_t max_elements)
145 : max_elements_(max_elements) {}
146 int64_t MaxElements() const { return max_elements_; }
147
148 private:
149 int64_t max_elements_;
150};
151
152// LogMultilineUpTo100 formats the same as LogMultiline but
153// prints no more than 100 elements.
157
158// The legacy behavior of LogSequence() does not use braces and
159// separates items with spaces. For example "1 2 3".
161 int64_t MaxElements() const { return 100; }
162};
164 int64_t MaxElements() const { return std::numeric_limits<int64_t>::max(); }
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.
172template <typename IteratorT, typename PolicyT>
173inline void LogRangeToStream(std::ostream& out, // NOLINT
174 IteratorT begin, IteratorT end,
175 const PolicyT& policy) {
176 policy.LogOpening(out);
177 for (int64_t 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
192namespace 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.
200template <typename IteratorT, typename PolicyT>
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) {
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
227template <typename E>
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.
249template <typename IteratorT, typename PolicyT>
251 const IteratorT& end,
252 const PolicyT& 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.
262template <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.
274template <typename ContainerT, typename PolicyT>
275auto 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.
286template <typename ContainerT>
287auto 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);
296template <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_
LogMultilineUpToN(int64_t max_elements)
int64_t MaxElements() const
LogShortUpToN(int64_t max_elements)
friend std::ostream & operator<<(std::ostream &out, const EnumLogger &v)
friend std::ostream & operator<<(std::ostream &out, const RangeLogger &range)
RangeLogger(const IteratorT &begin, const IteratorT &end, const PolicyT &policy)
auto LogContainer(const ContainerT &container, const PolicyT &policy) -> decltype(gtl::LogRange(container.begin(), container.end(), policy))
LogShortUpTo100 LogDefault
The default policy for new code.
detail::EnumLogger< E > LogEnum(E e)
detail::RangeLogger< IteratorT, PolicyT > LogRange(const IteratorT &begin, const IteratorT &end, const PolicyT &policy)
void LogRangeToStream(std::ostream &out, IteratorT begin, IteratorT end, const PolicyT &policy)
std::optional< int64_t > end
const std::optional< Range > & range
Definition statistics.cc:37
int64_t MaxElements() const
int64_t MaxElements() const
int64_t MaxElements() const
int64_t MaxElements() const
void Log(std::ostream &out, const ElementT &element) const
void LogEllipsis(std::ostream &out) const
void LogOpening(std::ostream &out) const
void LogSeparator(std::ostream &out) const
void LogFirstSeparator(std::ostream &out) const
void LogClosing(std::ostream &out) const
void LogSeparator(std::ostream &out) const
void LogClosing(std::ostream &out) const
void LogOpening(std::ostream &out) const
void LogFirstSeparator(std::ostream &out) const
void LogFirstSeparator(std::ostream &out) const
void LogOpening(std::ostream &out) const
void LogClosing(std::ostream &out) const
void LogSeparator(std::ostream &out) const