YARP
Yet Another Robot Platform
LogStream.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#ifndef YARP_OS_LOGSTREAM_H
7#define YARP_OS_LOGSTREAM_H
8
9#include <yarp/os/api.h>
10
11#include <yarp/os/Log.h>
13#include <yarp/os/Os.h>
14#include <yarp/os/SystemClock.h>
15#include <yarp/os/Time.h>
16
17#include <cstdio>
18#include <cstdlib>
19#include <iosfwd>
20#include <sstream>
21#include <string>
22#include <tuple>
23#include <type_traits>
24#include <utility>
25
26namespace yarp::os {
27
29{
30 struct Stream
31 {
32 Stream(Log::LogType t,
33 const char* fn,
34 unsigned int l,
35 const char* f,
36 const char* id,
37 const double ct,
38 const yarp::os::Log::Predicate pred,
39 const LogComponent& c) :
40 type(t),
41 file(fn),
42 line(l),
43 func(f),
44 id(id),
47 externaltime(ct),
48 pred(pred),
49 comp(c),
50 ref(1)
51 {
52 }
53 std::ostringstream oss;
54 Log::LogType type;
55 const char* file;
56 unsigned int line;
57 const char* func;
58 const char* id;
59 double systemtime;
60 double networktime;
61 double externaltime;
62 const yarp::os::Log::Predicate pred;
63 const LogComponent& comp;
64 int ref;
65 bool nospace {false};
66 } * stream;
67
68public:
70 const char* file,
71 unsigned int line,
72 const char* func,
73 const char* id,
74 const double externaltime,
75 const yarp::os::Log::Predicate pred = nullptr,
76 const LogComponent& comp = Log::defaultLogComponent()) :
77 stream(new Stream(type, file, line, func, id, externaltime, pred, comp))
78 {
79 }
80
81 inline LogStream(const LogStream& o) :
82 stream(o.stream)
83 {
84 ++stream->ref;
85 }
86
87 inline ~LogStream()
88 {
89 if (!--stream->ref) {
90 if (!stream->pred || stream->pred()) {
91 std::string s = stream->oss.str();
92 if (!s.empty()) {
93 // remove the last character if it an empty space (i.e.
94 // always unless the user defined an operator<< that
95 // does not add an empty space.
96 if (s.back() == ' ') {
97 s.pop_back();
98 } else {
99 yarp::os::Log(stream->file, stream->line, stream->func, nullptr, yarp::os::Log::logInternalComponent()).warning(
100 "' ' was expected. Some `operator<<` does not add an extra space at the end");
101 }
102 // remove the last character if it is a \n
103 if (s.back() == '\n') {
104 yarp::os::Log(stream->file, stream->line, stream->func, nullptr, yarp::os::Log::logInternalComponent()).warning(
105 "Removing extra \\n (stream-style)");
106 s.pop_back();
107 }
108 }
109 Log::do_log(stream->type,
110 s.c_str(),
111 stream->file,
112 stream->line,
113 stream->func,
114 stream->systemtime,
115 stream->networktime,
116 stream->externaltime,
117 stream->comp,
118 stream->id);
119 }
120
121 if (stream->type == yarp::os::Log::FatalType) {
122 yarp_print_trace(stderr, stream->file, stream->line);
123 delete stream;
124 std::exit(-1);
125 }
126 delete stream;
127 }
128 }
129
130 inline LogStream& operator<<(bool t)
131 {
132 stream->oss << (t ? "true" : "false");
133 if (!stream->nospace) {
134 stream->oss << ' ';
135 }
136 return *this;
137 }
138 inline LogStream& operator<<(char t)
139 {
140 stream->oss << t;
141 if (!stream->nospace) {
142 stream->oss << ' ';
143 }
144 return *this;
145 }
146 inline LogStream& operator<<(signed short t)
147 {
148 stream->oss << t;
149 if (!stream->nospace) {
150 stream->oss << ' ';
151 }
152 return *this;
153 }
154 inline LogStream& operator<<(unsigned short t)
155 {
156 stream->oss << t;
157 if (!stream->nospace) {
158 stream->oss << ' ';
159 }
160 return *this;
161 }
162 inline LogStream& operator<<(signed int t)
163 {
164 stream->oss << t;
165 if (!stream->nospace) {
166 stream->oss << ' ';
167 }
168 return *this;
169 }
170 inline LogStream& operator<<(unsigned int t)
171 {
172 stream->oss << t;
173 if (!stream->nospace) {
174 stream->oss << ' ';
175 }
176 return *this;
177 }
178 inline LogStream& operator<<(signed long t)
179 {
180 stream->oss << t;
181 if (!stream->nospace) {
182 stream->oss << ' ';
183 }
184 return *this;
185 }
186 inline LogStream& operator<<(unsigned long t)
187 {
188 stream->oss << t;
189 if (!stream->nospace) {
190 stream->oss << ' ';
191 }
192 return *this;
193 }
194 inline LogStream& operator<<(signed long long t)
195 {
196 stream->oss << t;
197 if (!stream->nospace) {
198 stream->oss << ' ';
199 }
200 return *this;
201 }
202 inline LogStream& operator<<(unsigned long long t)
203 {
204 stream->oss << t;
205 if (!stream->nospace) {
206 stream->oss << ' ';
207 }
208 return *this;
209 }
210 inline LogStream& operator<<(float t)
211 {
212 stream->oss << t;
213 if (!stream->nospace) {
214 stream->oss << ' ';
215 }
216 return *this;
217 }
218 inline LogStream& operator<<(double t)
219 {
220 stream->oss << t;
221 if (!stream->nospace) {
222 stream->oss << ' ';
223 }
224 return *this;
225 }
226 inline LogStream& operator<<(const char* t)
227 {
228 stream->oss << t;
229 if (!stream->nospace) {
230 stream->oss << ' ';
231 }
232 return *this;
233 }
234 inline LogStream& operator<<(const void* t)
235 {
236 stream->oss << t;
237 if (!stream->nospace) {
238 stream->oss << ' ';
239 }
240 return *this;
241 }
242
243 inline LogStream& operator<<(const std::string& t)
244 {
245 stream->oss << t.c_str();
246 if (!stream->nospace) {
247 stream->oss << ' ';
248 }
249 return *this;
250 }
251
252#if !defined(SWIG)
253 template <typename T1, typename T2>
254 inline LogStream& operator<<(const std::pair<T1, T2>& t)
255 {
256 bool nospace = stream->nospace;
257 stream->nospace = true;
258 stream->oss << '{';
259 *this << t.first;
260 stream->oss << ", ";
261 *this << t.second << '}';
262 stream->nospace = nospace;
263 if (!stream->nospace) {
264 stream->oss << ' ';
265 }
266 return *this;
267 }
268
269 template <typename Container, typename = typename Container::value_type>
270 inline LogStream& operator<<(const Container& cont)
271 {
272 return streamInternal(cont);
273 }
274
275 template <typename Arr, typename std::enable_if_t<std::is_array_v<Arr>, bool> = true>
276 inline LogStream& operator<<(const Arr& arr)
277 {
278 return streamInternal(arr);
279 }
280
281 template <typename... Args>
282 inline LogStream& operator<<(const std::tuple<Args...>& t)
283 {
284 bool nospace = stream->nospace;
285 stream->nospace = true;
286 return tupleInternal<0>(t, nospace);
287 }
288
289private:
290 template <typename C>
291 inline LogStream& streamInternal(const C& c)
292 {
293 bool nospace = stream->nospace;
294 stream->nospace = true;
295 stream->oss << '[';
296 for (auto it = std::begin(c); it != std::end(c); ++it) {
297 if (it != std::begin(c)) {
298 stream->oss << ", ";
299 }
300 *this << *it;
301 }
302 stream->oss << ']';
303 stream->nospace = nospace;
304 if (!stream->nospace) {
305 stream->oss << ' ';
306 }
307 return *this;
308 }
309
310 template <std::size_t I, typename... Args>
311 inline LogStream& tupleInternal(const std::tuple<Args...>& t, bool nospace)
312 {
313 if constexpr (I == 0) {
314 stream->oss << '{';
315 }
316 if constexpr (I < sizeof...(Args)) {
317 if constexpr (I != 0) {
318 stream->oss << ", ";
319 }
320 *this << std::get<I>(t);
321 return tupleInternal<I + 1>(t, nospace);
322 } else {
323 stream->oss << '}';
324 stream->nospace = nospace;
325 if (!stream->nospace) {
326 stream->oss << ' ';
327 }
328 }
329 return *this;
330 }
331#endif // !defined(SWIG)
332
333}; // class LogStream
334
335} // namespace yarp::os
336
337#endif // YARP_OS_LOGSTREAM_H
float t
void yarp_print_trace(FILE *out, const char *file, unsigned int line)
Low level function for printing a stack trace, if implemented (ACE or gcc/Linux).
Definition: Log.cpp:1127
LogStream & operator<<(const std::pair< T1, T2 > &t)
Definition: LogStream.h:254
LogStream & operator<<(signed short t)
Definition: LogStream.h:146
LogStream & operator<<(const Arr &arr)
Definition: LogStream.h:276
LogStream & operator<<(bool t)
Definition: LogStream.h:130
LogStream & operator<<(double t)
Definition: LogStream.h:218
LogStream & operator<<(const std::tuple< Args... > &t)
Definition: LogStream.h:282
LogStream & operator<<(signed long long t)
Definition: LogStream.h:194
LogStream(Log::LogType type, const char *file, unsigned int line, const char *func, const char *id, const double externaltime, const yarp::os::Log::Predicate pred=nullptr, const LogComponent &comp=Log::defaultLogComponent())
Definition: LogStream.h:69
LogStream & operator<<(unsigned short t)
Definition: LogStream.h:154
LogStream & operator<<(const char *t)
Definition: LogStream.h:226
LogStream & operator<<(float t)
Definition: LogStream.h:210
LogStream & operator<<(unsigned int t)
Definition: LogStream.h:170
LogStream(const LogStream &o)
Definition: LogStream.h:81
LogStream & operator<<(char t)
Definition: LogStream.h:138
LogStream & operator<<(unsigned long long t)
Definition: LogStream.h:202
LogStream & operator<<(const void *t)
Definition: LogStream.h:234
LogStream & operator<<(signed long t)
Definition: LogStream.h:178
LogStream & operator<<(const std::string &t)
Definition: LogStream.h:243
LogStream & operator<<(unsigned long t)
Definition: LogStream.h:186
LogStream & operator<<(signed int t)
Definition: LogStream.h:162
LogStream & operator<<(const Container &cont)
Definition: LogStream.h:270
bool(*)() Predicate
Definition: Log.h:52
void warning(const char *msg,...) const
Definition: Log.cpp:1064
@ FatalType
Definition: Log.h:96
static double nowSystem()
Definition: SystemClock.cpp:34
bool isClockInitialized()
Check if YARP clock is initialized.
Definition: Time.cpp:257
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:121
bool isSystemClock()
Check if YARP is providing system time.
Definition: Time.cpp:262
An interface to the operating system, including Port based communication.
#define YARP_os_API
Definition: api.h:18