GSLAM  3.0.0
Glog.h
1 // GSLAM - A general SLAM framework and benchmark
2 // Copyright 2018 PILAB Inc. All rights reserved.
3 // https://github.com/zdzhaoyong/GSLAM
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors may be
14 // used to endorse or promote products derived from this software without
15 // specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Author: zd5945@126.com (Yong Zhao)
30 // Redistribution and use in source and binary forms, with or without
31 // modification, are permitted provided that the following conditions are met:
32 //
33 // * Redistributions of source code must retain the above copyright notice,
34 // this list of conditions and the following disclaimer.
35 // * Redistributions in binary form must reproduce the above copyright notice,
36 // this list of conditions and the following disclaimer in the documentation
37 // and/or other materials provided with the distribution.
38 // * Neither the name of Google Inc. nor the names of its contributors may be
39 // used to endorse or promote products derived from this software without
40 // specific prior written permission.
41 //
42 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
46 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
47 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
48 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52 // POSSIBILITY OF SUCH DAMAGE.
53 //
54 // Author: settinger@google.com (Scott Ettinger)
55 // mierle@gmail.com (Keir Mierle)
56 //
57 // Simplified Glog style logging with Android support. Supported macros in
58 // decreasing severity level per line:
59 //
60 // VLOG(2), VLOG(N)
61 // VLOG(1),
62 // LOG(INFO), VLOG(0), LG
63 // LOG(WARNING),
64 // LOG(ERROR),
65 // LOG(FATAL),
66 //
67 // With VLOG(n), the output is directed to one of the 5 Android log levels:
68 //
69 // 2 - Verbose
70 // 1 - Debug
71 // 0 - Info
72 // -1 - Warning
73 // -2 - Error
74 // -3 - Fatal
75 //
76 // Any logging of level 2 and above is directed to the Verbose level. All
77 // Android log output is tagged with the string "native".
78 //
79 // If the symbol ANDROID is not defined, all output goes to std::cerr.
80 // This allows code to be built on a different system for debug.
81 //
82 // Portions of this code are taken from the GLOG package. This code is only a
83 // small subset of the GLOG functionality. Notable differences from GLOG
84 // behavior include lack of support for displaying unprintable characters and
85 // lack of stack trace information upon failure of the CHECK macros. On
86 // non-Android systems, log output goes to std::cerr and is not written to a
87 // file.
88 //
89 // CHECK macros are defined to test for conditions within code. Any CHECK that
90 // fails will log the failure and terminate the application.
91 // e.g. CHECK_GE(3, 2) will pass while CHECK_GE(3, 4) will fail after logging
92 // "Check failed 3 >= 4".
93 //
94 // The following CHECK macros are defined:
95 //
96 // CHECK(condition) - fails if condition is false and logs condition.
97 // CHECK_NOTNULL(variable) - fails if the variable is NULL.
98 //
99 // The following binary check macros are also defined :
100 //
101 // Macro Operator equivalent
102 // -------------------- -------------------
103 // CHECK_EQ(val1, val2) val1 == val2
104 // CHECK_NE(val1, val2) val1 != val2
105 // CHECK_GT(val1, val2) val1 > val2
106 // CHECK_GE(val1, val2) val1 >= val2
107 // CHECK_LT(val1, val2) val1 < val2
108 // CHECK_LE(val1, val2) val1 <= val2
109 //
110 // Debug only versions of all of the check macros are also defined. These
111 // macros generate no code in a release build, but avoid unused variable
112 // warnings / errors.
113 //
114 // To use the debug only versions, prepend a D to the normal check macros, e.g.
115 // DCHECK_EQ(a, b).
116 
117 #ifndef GSLAM_MINIGLOG_GLOG_LOGGING_H_
118 #define GSLAM_MINIGLOG_GLOG_LOGGING_H_
119 
120 #ifdef ANDROID
121 # include <android/log.h>
122 #endif // ANDROID
123 
124 #include <stdint.h>
125 #include <stdio.h>
126 #include <string.h>
127 
128 #include <algorithm>
129 #include <ctime>
130 #include <fstream>
131 #include <iostream>
132 #include <iomanip>
133 #include <set>
134 #include <map>
135 #include <sstream>
136 #include <string>
137 #include <vector>
138 #include <memory>
139 
140 
141 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
142 # define OS_WINDOWS
143 #elif defined(__CYGWIN__) || defined(__CYGWIN32__)
144 # define OS_CYGWIN
145 #elif defined(linux) || defined(__linux) || defined(__linux__)
146 # ifndef OS_LINUX
147 # define OS_LINUX
148 # endif
149 #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
150 # define OS_MACOSX
151 #elif defined(__FreeBSD__)
152 # define OS_FREEBSD
153 #elif defined(__NetBSD__)
154 # define OS_NETBSD
155 #elif defined(__OpenBSD__)
156 # define OS_OPENBSD
157 #else
158 // TODO(hamaji): Add other platforms.
159 #endif
160 
161 #if defined(OS_LINUX)
162  #include <unistd.h>
163 #elif defined(OS_WINDOWS)
164  #include <windows.h>
165 #endif
166 
167 
168 #if defined(_MSC_VER)
169 # define GSLAM_EXPORT __declspec(dllexport)
170 #elif defined(_MSC_VER) && 0
171 # define GSLAM_EXPORT __declspec(dllimport)
172 #else
173 # define GSLAM_EXPORT __attribute__ ((visibility("default")))
174 #endif
175 
176 #ifdef ERROR
177 #undef ERROR
178 #endif
179 #ifdef LOG
180 #undef LOG
181 #endif
182 
183 // Log severity level constants.
184 const int FATAL = -3;
185 const int ERROR = -2;
186 const int WARNING = -1;
187 const int INFO = 0;
188 
189 // ------------------------- Glog compatibility ------------------------------
190 
191 namespace GSLAM {
192 
193 typedef int LogSeverity;
194 
195 const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
196  NUM_SEVERITIES = 4;
197 
198 const char*const LogSeverityNames[NUM_SEVERITIES] = {
199  "INFO", "WARNING", "ERROR", "FATAL"
200 };
201 
202 
203 
204 inline void get_timeinfo(struct tm& ti)
205 {
206  time_t rawtime;
207  time (&rawtime);
208 
209 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
210  // On Windows, use secure localtime_s not localtime.
211  localtime_s(&ti, &rawtime);
212 #else
213  // On non-Windows systems, use threadsafe localtime_r not localtime.
214  localtime_r(&rawtime, &ti);
215 #endif
216 }
217 
218 // FIXME: How to get tid on Windows?
219 inline int64_t GetTID()
220 {
221  // If gettid() could not be used, we use one of the following.
222 #if defined(OS_LINUX)
223  return getpid(); // Linux: getpid returns thread ID when gettid is absent
224 #elif defined(OS_WINDOWS)
225  return GetCurrentThreadId();
226 #else
227  return 0;
228 #endif
229 }
230 
231 
232 // Sink class used for integration with mock and test functions. If sinks are
233 // added, all log output is also sent to each sink through the send function.
234 // In this implementation, WaitTillSent() is called immediately after the send.
235 // This implementation is not thread safe.
236 class LogSink {
237 public:
238  virtual ~LogSink() {}
239  virtual void send(LogSeverity severity,
240  const char* full_filename,
241  const char* base_filename,
242  int line,
243  const struct tm* tm_time,
244  const char* message,
245  size_t message_len) = 0;
246  virtual void WaitTillSent() = 0;
247 
248  static std::string ToString(LogSeverity severity, const char* file, int line,
249  const struct ::tm* tm_time,
250  const char* message, size_t message_len) {
251  std::ostringstream stream(std::string(message, message_len));
252  stream.fill('0');
253 
254  // FIXME(jrvb): Updating this to use the correct value for usecs
255  // requires changing the signature for both this method and
256  // LogSink::send(). This change needs to be done in a separate CL
257  // so subclasses of LogSink can be updated at the same time.
258  int usecs = 0;
259 
260  stream << LogSeverityNames[severity+NUM_SEVERITIES-1][0]
261  << std::setw(2) << 1+tm_time->tm_mon
262  << std::setw(2) << tm_time->tm_mday
263  << ' '
264  << std::setw(2) << tm_time->tm_hour << ':'
265  << std::setw(2) << tm_time->tm_min << ':'
266  << std::setw(2) << tm_time->tm_sec << '.'
267  << std::setw(6) << usecs
268  << ' '
269  << std::setfill(' ') << std::setw(5) << GetTID() << std::setfill('0')
270  << ' '
271  << file << ':' << line << "] ";
272 
273  stream << std::string(message, message_len);
274  return stream.str();
275  }
276 };
277 
278 inline std::shared_ptr<std::set<LogSink *> >& getLogSinksGlobal()
279 {
280  static std::shared_ptr<std::set<LogSink *> > sink(new std::set<LogSink *>());
281  return sink;
282 }
283 
284 inline void InitGoogleLogging(char *argv) {
285  // Do nothing; this is ignored.
286 }
287 
288 // Note: the Log sink functions are not thread safe.
289 inline void AddLogSink(LogSink *sink) {
290  // TODO(settinger): Add locks for thread safety.
291  getLogSinksGlobal()->insert(sink);
292 }
293 inline void RemoveLogSink(LogSink *sink) {
294  getLogSinksGlobal()->erase(sink);
295 }
296 
297 
298 
299 class LogFileSink : public LogSink
300 {
301 public:
302  LogFileSink(LogSeverity severity, const char* base_filename)
303  {
304  m_severity = severity;
305  m_baseFileName = base_filename;
306 
307  char fname[4096];
308  struct tm ti;
309  get_timeinfo(ti);
310  sprintf(fname, "%s%04d%02d%02d-%02d%02d%02d",
311  base_filename,
312  ti.tm_year+1900, ti.tm_mon+1, ti.tm_mday,
313  ti.tm_hour, ti.tm_min, ti.tm_sec);
314  m_logFileName = fname;
315 
316  m_logFile = fopen(fname, "wt+");
317  }
318 
319  virtual ~LogFileSink()
320  {
321  if( m_logFile )
322  {
323  fclose(m_logFile);
324  m_logFile = NULL;
325  }
326  }
327 
328  virtual void send(LogSeverity severity,
329  const char* full_filename,
330  const char* base_filename,
331  int line,
332  const struct tm* tm_time,
333  const char* message,
334  size_t message_len)
335  {
336  if( severity >= m_severity && m_logFile )
337  {
338  std::string ls = LogSink::ToString(severity, base_filename, line, tm_time, message, message_len);
339  fwrite(ls.c_str(), ls.size(), 1, m_logFile);
340  }
341  }
342 
343  virtual void WaitTillSent()
344  {
345  return;
346  }
347 
348 protected:
349  LogSeverity m_severity;
350  const char* m_baseFileName;
351  std::string m_logFileName;
352  FILE* m_logFile;
353 };
354 
355 
356 
357 
358 typedef std::map<LogSeverity, LogFileSink*> LogSinkMap;
359 
360 inline LogSinkMap& getLogSinkMapGlobal()
361 {
362  static std::shared_ptr<LogSinkMap > logSinkMap(new LogSinkMap());
363  return (*logSinkMap);
364 }
365 
366 
367 inline void SetLogDestination(LogSeverity severity,
368  const char* base_filename)
369 {
370  LogSinkMap& g_logSinks = getLogSinkMapGlobal();
371 
372  LogSinkMap::iterator it = g_logSinks.find(severity);
373  if( it == g_logSinks.end() )
374  {
375  if( strlen(base_filename) == 0 ) return;
376 
377  // add a log file
378  LogFileSink* logFile = new LogFileSink(severity, base_filename);
379  g_logSinks[severity] = logFile;
380  AddLogSink(logFile);
381  }
382  else
383  {
384  LogFileSink* logFile = g_logSinks[severity];
385 
386  // close old log file
387  if( logFile )
388  {
389  RemoveLogSink(logFile);
390  g_logSinks.erase(it);
391  delete logFile;
392  }
393 
394  // open new log file
395  if( strlen(base_filename) > 0 )
396  {
397  logFile = new LogFileSink(severity, base_filename);
398  g_logSinks[severity] = logFile;
399  AddLogSink(logFile);
400  }
401  }
402 }
403 
404 
405 
406 } // namespace google
407 
408 // ---------------------------- Logger Class --------------------------------
409 
410 // Class created for each use of the logging macros.
411 // The logger acts as a stream and routes the final stream contents to the
412 // Android logcat output at the proper filter level. If ANDROID is not
413 // defined, output is directed to std::cerr. This class should not
414 // be directly instantiated in code, rather it should be invoked through the
415 // use of the log macros LG, LOG, or VLOG.
417  public:
418  MessageLogger(const char *file, int line, const char *tag, int severity)
419  : file_(file), line_(line), tag_(tag), severity_(severity) {
420  StripBasename(std::string(file), &filename_only_);
421  }
422 
423  // Output the contents of the stream to the proper channel on destruction.
424  ~MessageLogger() {
425  stream_ << "\n";
426 
427 #ifdef ANDROID
428  static const int android_log_levels[] = {
429  ANDROID_LOG_FATAL, // LOG(FATAL)
430  ANDROID_LOG_ERROR, // LOG(ERROR)
431  ANDROID_LOG_WARN, // LOG(WARNING)
432  ANDROID_LOG_INFO, // LOG(INFO), LG, VLOG(0)
433  ANDROID_LOG_DEBUG, // VLOG(1)
434  ANDROID_LOG_VERBOSE, // VLOG(2) .. VLOG(N)
435  };
436 
437  // Bound the logging level.
438  const int kMaxVerboseLevel = 2;
439  int android_level_index = std::min(std::max(FATAL, severity_),
440  kMaxVerboseLevel) - FATAL;
441  int android_log_level = android_log_levels[android_level_index];
442 
443  // Output the log string the Android log at the appropriate level.
444  __android_log_write(android_log_level, tag_.c_str(), stream_.str().c_str());
445 
446  // Indicate termination if needed.
447  if (severity_ == FATAL) {
448  __android_log_write(ANDROID_LOG_FATAL,
449  tag_.c_str(),
450  "terminating.\n");
451  }
452 #else
453  // If not building on Android, log all output to std::cerr.
454  std::cerr << filename_only_ << ":" << line_ << " " << stream_.str();
455 #endif // ANDROID
456 
457  LogToSinks(severity_);
458  WaitForSinks();
459 
460  // Android logging at level FATAL does not terminate execution, so abort()
461  // is still required to stop the program.
462  if (severity_ == FATAL) {
463  abort();
464  }
465  }
466 
467  // Return the stream associated with the logger object.
468  std::stringstream &stream() { return stream_; }
469 
470  private:
471  void LogToSinks(int severity) {
472  struct tm timeinfo;
473  GSLAM::get_timeinfo(timeinfo);
474 
475  std::set<GSLAM::LogSink*>::iterator iter;
476  // Send the log message to all sinks.
477  for (iter = GSLAM::getLogSinksGlobal()->begin();
478  iter != GSLAM::getLogSinksGlobal()->end(); ++iter) {
479  (*iter)->send(severity, file_.c_str(), filename_only_.c_str(), line_,
480  &timeinfo, stream_.str().c_str(), stream_.str().size());
481  }
482  }
483 
484  void WaitForSinks() {
485  // TODO(settinger): Add locks for thread safety.
486  std::set<GSLAM::LogSink *>::iterator iter;
487 
488  // Call WaitTillSent() for all sinks.
489  for (iter = GSLAM::getLogSinksGlobal()->begin();
490  iter != GSLAM::getLogSinksGlobal()->end(); ++iter) {
491  (*iter)->WaitTillSent();
492  }
493  }
494 
495  void StripBasename(const std::string &full_path, std::string *filename) {
496  // TODO(settinger): Add support for OSs with different path separators.
497  const char kSeparator = '/';
498  size_t pos = full_path.rfind(kSeparator);
499  if (pos != std::string::npos) {
500  *filename = full_path.substr(pos + 1, std::string::npos);
501  } else {
502  *filename = full_path;
503  }
504  }
505 
506  std::string file_;
507  std::string filename_only_;
508  int line_;
509  std::string tag_;
510  std::stringstream stream_;
511  int severity_;
512 };
513 
514 // ---------------------- Logging Macro definitions --------------------------
515 
516 // This class is used to explicitly ignore values in the conditional
517 // logging macros. This avoids compiler warnings like "value computed
518 // is not used" and "statement has no effect".
520  public:
521  LoggerVoidify() { }
522  // This has to be an operator with a precedence lower than << but
523  // higher than ?:
524  void operator&(const std::ostream &s) { }
525 };
526 
527 // Log only if condition is met. Otherwise evaluates to void.
528 #define LOG_IF(severity, condition) \
529  !(condition) ? (void) 0 : LoggerVoidify() & \
530  MessageLogger((char *)__FILE__, __LINE__, "native", severity).stream()
531 
532 // Log only if condition is NOT met. Otherwise evaluates to void.
533 #define LOG_IF_FALSE(severity, condition) LOG_IF(severity, !(condition))
534 
535 // LG is a convenient shortcut for LOG(INFO). Its use is in new
536 // google3 code is discouraged and the following shortcut exists for
537 // backward compatibility with existing code.
538 #ifdef MAX_LOG_LEVEL
539 # define LOG(n) LOG_IF(n, n <= MAX_LOG_LEVEL)
540 # define VLOG(n) LOG_IF(n, n <= MAX_LOG_LEVEL)
541 # define LG LOG_IF(INFO, INFO <= MAX_LOG_LEVEL)
542 # define VLOG_IF(n, condition) LOG_IF(n, (n <= MAX_LOG_LEVEL) && condition)
543 #else
544 # define LOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", n).stream() // NOLINT
545 # define VLOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", n).stream() // NOLINT
546 # define LG MessageLogger((char *)__FILE__, __LINE__, "native", INFO).stream() // NOLINT
547 # define VLOG_IF(n, condition) LOG_IF(n, condition)
548 #endif
549 
550 // Currently, VLOG is always on for levels below MAX_LOG_LEVEL.
551 #ifndef MAX_LOG_LEVEL
552 # define VLOG_IS_ON(x) (1)
553 #else
554 # define VLOG_IS_ON(x) (x <= MAX_LOG_LEVEL)
555 #endif
556 
557 #ifndef NDEBUG
558 # define DLOG LOG
559 #else
560 # define DLOG(severity) true ? (void) 0 : LoggerVoidify() & \
561  MessageLogger((char *)__FILE__, __LINE__, "native", severity).stream()
562 #endif
563 
564 
565 // Log a message and terminate.
566 template<class T>
567 void LogMessageFatal(const char *file, int line, const T &message) {
568  MessageLogger((char *)__FILE__, __LINE__, "native", FATAL).stream()
569  << message;
570 }
571 
572 // ---------------------------- CHECK macros ---------------------------------
573 
574 // Check for a given boolean condition.
575 #define CHECK(condition) LOG_IF_FALSE(FATAL, condition) \
576  << "Check failed: " #condition " "
577 
578 #ifndef NDEBUG
579 // Debug only version of CHECK
580 # define DCHECK(condition) LOG_IF_FALSE(FATAL, condition) \
581  << "Check failed: " #condition " "
582 #else
583 // Optimized version - generates no code.
584 # define DCHECK(condition) if (false) LOG_IF_FALSE(FATAL, condition) \
585  << "Check failed: " #condition " "
586 #endif // NDEBUG
587 
588 // ------------------------- CHECK_OP macros ---------------------------------
589 
590 // Generic binary operator check macro. This should not be directly invoked,
591 // instead use the binary comparison macros defined below.
592 #define CHECK_OP(val1, val2, op) LOG_IF_FALSE(FATAL, ((val1) op (val2))) \
593  << "Check failed: " #val1 " " #op " " #val2 " "
594 
595 // Check_op macro definitions
596 #define CHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
597 #define CHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
598 #define CHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
599 #define CHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
600 #define CHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
601 #define CHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
602 
603 #ifndef NDEBUG
604 // Debug only versions of CHECK_OP macros.
605 # define DCHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
606 # define DCHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
607 # define DCHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
608 # define DCHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
609 # define DCHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
610 # define DCHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
611 #else
612 // These versions generate no code in optimized mode.
613 # define DCHECK_EQ(val1, val2) if (false) CHECK_OP(val1, val2, ==)
614 # define DCHECK_NE(val1, val2) if (false) CHECK_OP(val1, val2, !=)
615 # define DCHECK_LE(val1, val2) if (false) CHECK_OP(val1, val2, <=)
616 # define DCHECK_LT(val1, val2) if (false) CHECK_OP(val1, val2, <)
617 # define DCHECK_GE(val1, val2) if (false) CHECK_OP(val1, val2, >=)
618 # define DCHECK_GT(val1, val2) if (false) CHECK_OP(val1, val2, >)
619 #endif // NDEBUG
620 
621 // ---------------------------CHECK_NOTNULL macros ---------------------------
622 
623 // Helpers for CHECK_NOTNULL(). Two are necessary to support both raw pointers
624 // and smart pointers.
625 template <typename T>
626 T& CheckNotNullCommon(const char *file, int line, const char *names, T& t) {
627  if (t == NULL) {
628  LogMessageFatal(file, line, std::string(names));
629  }
630  return t;
631 }
632 
633 template <typename T>
634 T* CheckNotNull(const char *file, int line, const char *names, T* t) {
635  return CheckNotNullCommon(file, line, names, t);
636 }
637 
638 template <typename T>
639 T& CheckNotNull(const char *file, int line, const char *names, T& t) {
640  return CheckNotNullCommon(file, line, names, t);
641 }
642 
643 // Check that a pointer is not null.
644 #define CHECK_NOTNULL(val) \
645  CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
646 
647 #ifndef NDEBUG
648 // Debug only version of CHECK_NOTNULL
649 #define DCHECK_NOTNULL(val) \
650  CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
651 #else
652 // Optimized version - generates no code.
653 #define DCHECK_NOTNULL(val) if (false)\
654  CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
655 #endif // NDEBUG
656 
657 #endif // GSLAM_MINIGLOG_GLOG_LOGGING_H_
Definition: Glog.h:299
Definition: Camera.h:45
Definition: Glog.h:416
Definition: Glog.h:519
Definition: Glog.h:236