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>
12 #include <yarp/os/LogComponent.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 
26 namespace 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 
68 public:
69  inline LogStream(Log::LogType type,
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 
289 private:
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<<(unsigned short t)
Definition: LogStream.h:154
LogStream & operator<<(const void *t)
Definition: LogStream.h:234
LogStream & operator<<(unsigned int t)
Definition: LogStream.h:170
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<<(char t)
Definition: LogStream.h:138
LogStream & operator<<(bool t)
Definition: LogStream.h:130
LogStream & operator<<(unsigned long long t)
Definition: LogStream.h:202
LogStream & operator<<(const Container &cont)
Definition: LogStream.h:270
LogStream & operator<<(const std::tuple< Args... > &t)
Definition: LogStream.h:282
LogStream & operator<<(double t)
Definition: LogStream.h:218
LogStream & operator<<(unsigned long t)
Definition: LogStream.h:186
LogStream & operator<<(float t)
Definition: LogStream.h:210
LogStream & operator<<(const std::string &t)
Definition: LogStream.h:243
LogStream & operator<<(signed long long t)
Definition: LogStream.h:194
LogStream & operator<<(const char *t)
Definition: LogStream.h:226
LogStream & operator<<(signed int t)
Definition: LogStream.h:162
LogStream(const LogStream &o)
Definition: LogStream.h:81
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<<(signed long t)
Definition: LogStream.h:178
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