Material Definition Language API nvidia_logo_transpbg.gif Up
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ilogger.h
Go to the documentation of this file.
1 /***************************************************************************************************
2  * Copyright 2018 NVIDIA Corporation. All rights reserved.
3  **************************************************************************************************/
8 
9 #ifndef MI_BASE_ILOGGER_H
10 #define MI_BASE_ILOGGER_H
11 
12 #include <cstdarg>
13 #include <cstdio>
14 #include <ostream>
15 #include <sstream>
16 #include <string>
17 
18 #include <mi/base/config.h>
19 #include <mi/base/enums.h>
20 #include <mi/base/handle.h>
21 #include <mi/base/iinterface.h>
23 
24 namespace mi {
25 
26 namespace base {
27 
40 class ILogger : public
68  Interface_declare<0x4afbf19a,0x5fb7,0x4422,0xae,0x4b,0x25,0x13,0x06,0x2c,0x30,0x5f>
69 {
70 public:
90  virtual void message(
91  Message_severity level, const char* module_category, const char* message) = 0;
92 
114  inline void printf(
115  Message_severity level, const char* module_category, const char* message, ...)
116 #ifdef MI_COMPILER_GCC
117  __attribute__((format(printf, 4, 5)))
118 #endif
119  {
120  va_list args;
121  va_start( args, message);
122  char buffer[1024];
123 #ifdef MI_COMPILER_MSC
124  vsnprintf_s( &buffer[0], sizeof( buffer), sizeof( buffer)-1, message, args);
125 #else
126  vsnprintf( &buffer[0], sizeof( buffer), message, args);
127 #endif
128  this->message( level, module_category, &buffer[0]);
129  va_end( args);
130  }
131 };
132 
133 // A specialization of std::stringbuf to be used together with #mi::base::Log_stream.
134 //
135 // Its sync() method is overridden to send the contents of the string buffer to the logger, and an
136 // additional method #set_log_level() allows to specify the log level of the next message.
137 class Log_streambuf : public std::stringbuf
138 {
139 public:
140  // Constructor.
141  //
142  // \param stream The stream used with this string buffer. Used to flush the stream
143  // if the log level is changed.
144  // \param logger The logger that finally receives the contents of this string
145  // buffer.
146  // \param module_category The module and the category which specify the origin and the
147  // functional area of this message. See #mi::base::ILogger::message()
148  // for details.
149  // \param default_level The default log level. Used if no other log level is selected by
150  // one of the manipulators.
151  Log_streambuf(
152  std::ostream& stream,
153  ILogger* logger,
154  const std::string& module_category,
155  Message_severity default_level = MESSAGE_SEVERITY_INFO)
156  : std::stringbuf( std::ios::out),
157  m_stream( stream),
158  m_default_level( default_level),
159  m_logger( logger, DUP_INTERFACE),
160  m_module_category( module_category)
161  {
162  set_log_level( m_default_level);
163  }
164 
165  // Destructor.
166  ~Log_streambuf() throw()
167  {
168  }
169 
170  // Flushes the string buffer if not empty, and sets the log level of the next message to the
171  // given log level.
172  void set_log_level( Message_severity level)
173  {
174  m_stream.flush();
175  m_level = level;
176  }
177 
178 protected:
179 
180  // Sends the contents of the string buffer to the logger, clears the string buffer, and resets
181  // the log level to the default log level.
182  int sync()
183  {
185  const std::string& s = str();
186  if( !s.empty()) {
187  m_logger->message( m_level, m_module_category.c_str(), str().c_str());
188  str( "");
189  m_level = m_default_level;
190  }
191  return 0;
192  }
193 
194 private:
195 
196  std::ostream& m_stream;
197  Message_severity m_default_level;
198  mi::base::Handle<ILogger> m_logger;
199  std::string m_module_category;
200  Message_severity m_level;
201 };
202 
218 class Log_stream : public std::ostream
219 {
220 public:
230  ILogger* logger,
231  const char* module_category,
232  Message_severity default_level = MESSAGE_SEVERITY_INFO)
233  : std::ostream( 0),
234  m_buffer( *this, logger, module_category ? module_category : "APP:MAIN", default_level)
235  {
236  rdbuf( &m_buffer);
237 #if (__cplusplus >= 201402L)
238  this->pword( get_index()) = this;
239 #endif
240  }
241 
251  ILogger* logger,
252  const std::string& module_category,
253  Message_severity default_level = MESSAGE_SEVERITY_INFO)
254  : std::ostream( 0),
255  m_buffer( *this, logger, module_category, default_level)
256  {
257  rdbuf( &m_buffer);
258 #if (__cplusplus >= 201402L)
259  this->pword( get_index()) = this;
260 #endif
261  }
262 
266  ~Log_stream() throw()
267  {
268  flush();
269  }
270 
273  void set_log_level( Message_severity level) { m_buffer.set_log_level( level); }
274 
275 #if (__cplusplus >= 201402L)
276  // Returns the unique index into the private storage of std::ios_base.
277  static int get_index()
278  {
279  // Static initialization is guaranteed to be thread-safe with C++11 and later. The method
280  // std::ios_base::xalloc() is guaranteed to be thread-safe with C++14 and later.
281  static int s_index = std::ios_base::xalloc();
282  return s_index;
283  }
284 #endif
285 
286 private:
287  Log_streambuf m_buffer;
288 };
289 
299 template <typename C, typename T>
301 {
302 #if (__cplusplus >= 201402L)
303  if( ostream.pword( Log_stream::get_index()) == &ostream)
304 #endif
305  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_FATAL);
306  return ostream;
307 }
308 
318 template <typename C, typename T>
320 {
321 #if (__cplusplus >= 201402L)
322  if( ostream.pword( Log_stream::get_index()) == &ostream)
323 #endif
324  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_ERROR);
325  return ostream;
326 }
327 
337 template <typename C, typename T>
339 {
340 #if (__cplusplus >= 201402L)
341  if( ostream.pword( Log_stream::get_index()) == &ostream)
342 #endif
343  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_WARNING);
344  return ostream;
345 }
346 
356 template <typename C, typename T>
358 {
359 #if (__cplusplus >= 201402L)
360  if( ostream.pword( Log_stream::get_index()) == &ostream)
361 #endif
362  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_INFO);
363  return ostream;
364 }
365 
375 template <typename C, typename T>
377 {
378 #if (__cplusplus >= 201402L)
379  if( ostream.pword( Log_stream::get_index()) == &ostream)
380 #endif
381  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_VERBOSE);
382  return ostream;
383 }
384 
394 template <typename C, typename T>
396 {
397 #if (__cplusplus >= 201402L)
398  if( ostream.pword( Log_stream::get_index()) == &ostream)
399 #endif
400  static_cast<Log_stream&>( ostream).set_log_level( base::MESSAGE_SEVERITY_DEBUG);
401  return ostream;
402 }
403  // end group mi_base_ilogger
405 
406 } // namespace base
407 
408 } // namespace mi
409 
410 #endif // MI_BASE_ILOGGER_H