Google OR-Tools v9.15
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-2025 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 ORTOOLS_BASE_CONTAINER_LOGGING_H_
35#define ORTOOLS_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
44namespace gtl {
45
46// Several policy classes below determine how LogRangeToStream will
47// format a range of items. A Policy class should have these methods:
48//
49// Called to print an individual container element.
50// void Log(ostream &out, const ElementT &element) const;
51//
52// Called before printing the set of elements:
53// void LogOpening(ostream &out) const;
54//
55// Called after printing the set of elements:
56// void LogClosing(ostream &out) const;
57//
58// Called before printing the first element:
59// void LogFirstSeparator(ostream &out) const;
60//
61// Called before printing the remaining elements:
62// void LogSeparator(ostream &out) const;
63//
64// Returns the maximum number of elements to print:
65// int64_t MaxElements() const;
66//
67// Called to print an indication that MaximumElements() was reached:
68// void LogEllipsis(ostream &out) const;
69
70namespace internal {
71
72struct LogBase {
73 template <typename ElementT>
74 void Log(std::ostream& out, const ElementT& element) const { // NOLINT
75 out << element;
76 }
77 void LogEllipsis(std::ostream& out) const { // NOLINT
78 out << "...";
79 }
80};
81
82struct LogShortBase : public LogBase {
83 void LogOpening(std::ostream& out) const { out << "["; } // NOLINT
84 void LogClosing(std::ostream& out) const { out << "]"; } // NOLINT
85 void LogFirstSeparator(std::ostream& out) const { out << ""; } // NOLINT
86 void LogSeparator(std::ostream& out) const { out << ", "; } // NOLINT
87};
88
89struct LogMultilineBase : public LogBase {
90 void LogOpening(std::ostream& out) const { out << "["; } // NOLINT
91 void LogClosing(std::ostream& out) const { out << "\n]"; } // NOLINT
92 void LogFirstSeparator(std::ostream& out) const { out << "\n"; } // NOLINT
93 void LogSeparator(std::ostream& out) const { out << "\n"; } // NOLINT
94};
95
96struct LogLegacyBase : public LogBase {
97 void LogOpening(std::ostream& out) const { out << ""; } // NOLINT
98 void LogClosing(std::ostream& out) const { out << ""; } // NOLINT
99 void LogFirstSeparator(std::ostream& out) const { out << ""; } // NOLINT
100 void LogSeparator(std::ostream& out) const { out << " "; } // NOLINT
101};
102
103} // namespace internal
104
105// LogShort uses [] braces and separates items with comma-spaces. For
106// example "[1, 2, 3]".
108 int64_t MaxElements() const { return std::numeric_limits<int64_t>::max(); }
109};
110
111// LogShortUpToN(max_elements) formats the same as LogShort but prints no more
112// than the max_elements elements.
114 public:
115 explicit LogShortUpToN(int64_t max_elements) : max_elements_(max_elements) {}
116 int64_t MaxElements() const { return max_elements_; }
117
118 private:
119 int64_t max_elements_;
120};
121
122// LogShortUpTo100 formats the same as LogShort but prints no more
123// than 100 elements.
127
128// LogMultiline uses [] braces and separates items with
129// newlines. For example "[
130// 1
131// 2
132// 3
133// ]".
135 int64_t MaxElements() const { return std::numeric_limits<int64_t>::max(); }
136};
137
138// LogMultilineUpToN(max_elements) formats the same as LogMultiline but
139// prints no more than max_elements elements.
141 public:
142 explicit LogMultilineUpToN(int64_t max_elements)
143 : max_elements_(max_elements) {}
144 int64_t MaxElements() const { return max_elements_; }
145
146 private:
147 int64_t max_elements_;
148};
149
150// LogMultilineUpTo100 formats the same as LogMultiline but
151// prints no more than 100 elements.
155
156// The legacy behavior of LogSequence() does not use braces and
157// separates items with spaces. For example "1 2 3".
159 int64_t MaxElements() const { return 100; }
160};
162 int64_t MaxElements() const { return std::numeric_limits<int64_t>::max(); }
163};
164
165// The default policy for new code.
167
168// LogRangeToStream should be used to define operator<< for
169// STL and STL-like containers. For example, see stl_logging.h.
170template <typename IteratorT, typename PolicyT>
171inline void LogRangeToStream(std::ostream& out, // NOLINT
172 IteratorT begin, IteratorT end,
173 const PolicyT& policy) {
174 policy.LogOpening(out);
175 for (int64_t i = 0; begin != end && i < policy.MaxElements(); ++i, ++begin) {
176 if (i == 0) {
177 policy.LogFirstSeparator(out);
178 } else {
179 policy.LogSeparator(out);
180 }
181 policy.Log(out, *begin);
182 }
183 if (begin != end) {
184 policy.LogSeparator(out);
185 policy.LogEllipsis(out);
186 }
187 policy.LogClosing(out);
188}
189
190namespace detail {
191
192// RangeLogger is a helper class for gtl::LogRange and
193// gtl::LogContainer; do not use it directly. This object
194// captures iterators into the argument of the LogRange and
195// LogContainer functions, so its lifetime should be confined to a
196// single logging statement. Objects of this type should not be
197// assigned to local variables.
198template <typename IteratorT, typename PolicyT>
200 public:
201 RangeLogger(const IteratorT& begin, const IteratorT& end,
202 const PolicyT& policy)
203 : begin_(begin), end_(end), policy_(policy) {}
204
205 friend std::ostream& operator<<(std::ostream& out, const RangeLogger& range) {
206 gtl::LogRangeToStream<IteratorT, PolicyT>(out, range.begin_, range.end_,
207 range.policy_);
208 return out;
209 }
210
211 // operator<< above is generally recommended. However, some situations may
212 // require a string, so a convenience str() method is provided as well.
213 std::string str() const {
214 std::stringstream ss;
215 ss << *this;
216 return ss.str();
217 }
218
219 private:
220 IteratorT begin_;
221 IteratorT end_;
222 PolicyT policy_;
223};
224
225template <typename E>
227 public:
228 explicit EnumLogger(E e) : e_(e) {}
229
230 friend std::ostream& operator<<(std::ostream& out, const EnumLogger& v) {
231 using I = typename std::underlying_type<E>::type;
232 return out << static_cast<I>(v.e_);
233 }
234
235 private:
236 E e_;
237};
238
239} // namespace detail
240
241// Log a range using "policy". For example:
242//
243// LOG(INFO) << gtl::LogRange(start_pos, end_pos, gtl::LogMultiline());
244//
245// The above example will print the range using newlines between
246// elements, enclosed in [] braces.
247template <typename IteratorT, typename PolicyT>
249 const IteratorT& end,
250 const PolicyT& policy) {
251 return gtl::detail::RangeLogger<IteratorT, PolicyT>(begin, end, policy);
252}
253
254// Log a range. For example:
255//
256// LOG(INFO) << gtl::LogRange(start_pos, end_pos);
257//
258// By default, Range() uses the LogShortUpTo100 policy: comma-space
259// separation, no newlines, and with limit of 100 items.
260template <typename IteratorT>
262 const IteratorT& end) {
263 return gtl::LogRange(begin, end, LogDefault());
264}
265
266// Log a container using "policy". For example:
267//
268// LOG(INFO) << gtl::LogContainer(container, gtl::LogMultiline());
269//
270// The above example will print the container using newlines between
271// elements, enclosed in [] braces.
272template <typename ContainerT, typename PolicyT>
273auto LogContainer(const ContainerT& container, const PolicyT& policy)
274 -> decltype(gtl::LogRange(container.begin(), container.end(), policy)) {
275 return gtl::LogRange(container.begin(), container.end(), policy);
276}
277
278// Log a container. For example:
279//
280// LOG(INFO) << gtl::LogContainer(container);
281//
282// By default, Container() uses the LogShortUpTo100 policy: comma-space
283// separation, no newlines, and with limit of 100 items.
284template <typename ContainerT>
285auto LogContainer(const ContainerT& container)
286 -> decltype(gtl::LogContainer(container, LogDefault())) {
287 return gtl::LogContainer(container, LogDefault());
288}
289
290// Log a (possibly scoped) enum. For example:
291//
292// enum class Color { kRed, kGreen, kBlue };
293// LOG(INFO) << gtl::LogEnum(kRed);
294template <typename E>
296 static_assert(std::is_enum<E>::value, "must be an enum");
297 return detail::EnumLogger<E>(e);
298}
299
300} // namespace gtl
301
302#endif // ORTOOLS_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)
Definition array.h:25
auto LogContainer(const ContainerT &container, const PolicyT &policy) -> decltype(gtl::LogRange(container.begin(), container.end(), policy))
LogShortUpTo100 LogDefault
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)
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