123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- // Ceres Solver - A fast non-linear least squares minimizer
- // Copyright 2015 Google Inc. All rights reserved.
- // http://ceres-solver.org/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- // * Neither the name of Google Inc. nor the names of its contributors may be
- // used to endorse or promote products derived from this software without
- // specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- //
- // Author: settinger@google.com (Scott Ettinger)
- // mierle@gmail.com (Keir Mierle)
- //
- // Simplified Glog style logging with Android support. Supported macros in
- // decreasing severity level per line:
- //
- // VLOG(2), VLOG(N)
- // VLOG(1),
- // LOG(INFO), VLOG(0), LG
- // LOG(WARNING),
- // LOG(ERROR),
- // LOG(FATAL),
- //
- // With VLOG(n), the output is directed to one of the 5 Android log levels:
- //
- // 2 - Verbose
- // 1 - Debug
- // 0 - Info
- // -1 - Warning
- // -2 - Error
- // -3 - Fatal
- //
- // Any logging of level 2 and above is directed to the Verbose level. All
- // Android log output is tagged with the string "native".
- //
- // If the symbol ANDROID is not defined, all output goes to std::cerr.
- // This allows code to be built on a different system for debug.
- //
- // Portions of this code are taken from the GLOG package. This code is only a
- // small subset of the GLOG functionality. Notable differences from GLOG
- // behavior include lack of support for displaying unprintable characters and
- // lack of stack trace information upon failure of the CHECK macros. On
- // non-Android systems, log output goes to std::cerr and is not written to a
- // file.
- //
- // CHECK macros are defined to test for conditions within code. Any CHECK that
- // fails will log the failure and terminate the application.
- // e.g. CHECK_GE(3, 2) will pass while CHECK_GE(3, 4) will fail after logging
- // "Check failed 3 >= 4".
- //
- // The following CHECK macros are defined:
- //
- // CHECK(condition) - fails if condition is false and logs condition.
- // CHECK_NOTNULL(variable) - fails if the variable is nullptr.
- //
- // The following binary check macros are also defined :
- //
- // Macro Operator equivalent
- // -------------------- -------------------
- // CHECK_EQ(val1, val2) val1 == val2
- // CHECK_NE(val1, val2) val1 != val2
- // CHECK_GT(val1, val2) val1 > val2
- // CHECK_GE(val1, val2) val1 >= val2
- // CHECK_LT(val1, val2) val1 < val2
- // CHECK_LE(val1, val2) val1 <= val2
- //
- // Debug only versions of all of the check macros are also defined. These
- // macros generate no code in a release build, but avoid unused variable
- // warnings / errors.
- //
- // To use the debug only versions, prepend a D to the normal check macros, e.g.
- // DCHECK_EQ(a, b).
- #ifndef CERCES_INTERNAL_MINIGLOG_GLOG_LOGGING_H_
- #define CERCES_INTERNAL_MINIGLOG_GLOG_LOGGING_H_
- #ifdef ANDROID
- #include <android/log.h>
- #endif // ANDROID
- #include <algorithm>
- #include <ctime>
- #include <fstream>
- #include <iostream>
- #include <set>
- #include <sstream>
- #include <string>
- #include <vector>
- #include "ceres/internal/disable_warnings.h"
- #include "ceres/internal/export.h"
- // Log severity level constants.
- // clang-format off
- const int FATAL = -3;
- const int ERROR = -2;
- const int WARNING = -1;
- const int INFO = 0;
- // clang-format on
- // ------------------------- Glog compatibility ------------------------------
- namespace google {
- using LogSeverity = int;
- // clang-format off
- const int INFO = ::INFO;
- const int WARNING = ::WARNING;
- const int ERROR = ::ERROR;
- const int FATAL = ::FATAL;
- // clang-format on
- // Sink class used for integration with mock and test functions. If sinks are
- // added, all log output is also sent to each sink through the send function.
- // In this implementation, WaitTillSent() is called immediately after the send.
- // This implementation is not thread safe.
- class CERES_EXPORT LogSink {
- public:
- virtual ~LogSink() = default;
- virtual void send(LogSeverity severity,
- const char* full_filename,
- const char* base_filename,
- int line,
- const struct tm* tm_time,
- const char* message,
- size_t message_len) = 0;
- virtual void WaitTillSent() = 0;
- };
- // Global set of log sinks. The actual object is defined in logging.cc.
- extern CERES_EXPORT std::set<LogSink*> log_sinks_global;
- inline void InitGoogleLogging(const char* /* argv */) {
- // Do nothing; this is ignored.
- }
- // Note: the Log sink functions are not thread safe.
- inline void AddLogSink(LogSink* sink) {
- // TODO(settinger): Add locks for thread safety.
- log_sinks_global.insert(sink);
- }
- inline void RemoveLogSink(LogSink* sink) { log_sinks_global.erase(sink); }
- } // namespace google
- // ---------------------------- Logger Class --------------------------------
- // Class created for each use of the logging macros.
- // The logger acts as a stream and routes the final stream contents to the
- // Android logcat output at the proper filter level. If ANDROID is not
- // defined, output is directed to std::cerr. This class should not
- // be directly instantiated in code, rather it should be invoked through the
- // use of the log macros LG, LOG, or VLOG.
- class CERES_EXPORT MessageLogger {
- public:
- MessageLogger(const char* file, int line, const char* tag, int severity)
- : file_(file), line_(line), tag_(tag), severity_(severity) {
- // Pre-pend the stream with the file and line number.
- StripBasename(std::string(file), &filename_only_);
- stream_ << filename_only_ << ":" << line << " ";
- }
- // Output the contents of the stream to the proper channel on destruction.
- ~MessageLogger() {
- stream_ << "\n";
- #ifdef ANDROID
- static const int android_log_levels[] = {
- ANDROID_LOG_FATAL, // LOG(FATAL)
- ANDROID_LOG_ERROR, // LOG(ERROR)
- ANDROID_LOG_WARN, // LOG(WARNING)
- ANDROID_LOG_INFO, // LOG(INFO), LG, VLOG(0)
- ANDROID_LOG_DEBUG, // VLOG(1)
- ANDROID_LOG_VERBOSE, // VLOG(2) .. VLOG(N)
- };
- // Bound the logging level.
- const int kMaxVerboseLevel = 2;
- int android_level_index =
- std::min(std::max(FATAL, severity_), kMaxVerboseLevel) - FATAL;
- int android_log_level = android_log_levels[android_level_index];
- // Output the log string the Android log at the appropriate level.
- __android_log_write(android_log_level, tag_.c_str(), stream_.str().c_str());
- // Indicate termination if needed.
- if (severity_ == FATAL) {
- __android_log_write(ANDROID_LOG_FATAL, tag_.c_str(), "terminating.\n");
- }
- #else
- // If not building on Android, log all output to std::cerr.
- std::cerr << stream_.str();
- #endif // ANDROID
- LogToSinks(severity_);
- WaitForSinks();
- // Android logging at level FATAL does not terminate execution, so abort()
- // is still required to stop the program.
- if (severity_ == FATAL) {
- abort();
- }
- }
- // Return the stream associated with the logger object.
- std::stringstream& stream() { return stream_; }
- private:
- void LogToSinks(int severity) {
- time_t rawtime;
- time(&rawtime);
- struct tm timeinfo;
- #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
- // On Windows, use secure localtime_s not localtime.
- localtime_s(&timeinfo, &rawtime);
- #else
- // On non-Windows systems, use threadsafe localtime_r not localtime.
- localtime_r(&rawtime, &timeinfo);
- #endif
- std::set<google::LogSink*>::iterator iter;
- // Send the log message to all sinks.
- for (iter = google::log_sinks_global.begin();
- iter != google::log_sinks_global.end();
- ++iter) {
- (*iter)->send(severity,
- file_.c_str(),
- filename_only_.c_str(),
- line_,
- &timeinfo,
- stream_.str().c_str(),
- stream_.str().size());
- }
- }
- void WaitForSinks() {
- // TODO(settinger): Add locks for thread safety.
- std::set<google::LogSink*>::iterator iter;
- // Call WaitTillSent() for all sinks.
- for (iter = google::log_sinks_global.begin();
- iter != google::log_sinks_global.end();
- ++iter) {
- (*iter)->WaitTillSent();
- }
- }
- void StripBasename(const std::string& full_path, std::string* filename) {
- // TODO(settinger): Add support for OSs with different path separators.
- const char kSeparator = '/';
- size_t pos = full_path.rfind(kSeparator);
- if (pos != std::string::npos) {
- *filename = full_path.substr(pos + 1, std::string::npos);
- } else {
- *filename = full_path;
- }
- }
- std::string file_;
- std::string filename_only_;
- int line_;
- std::string tag_;
- std::stringstream stream_;
- int severity_;
- };
- // ---------------------- Logging Macro definitions --------------------------
- // This class is used to explicitly ignore values in the conditional
- // logging macros. This avoids compiler warnings like "value computed
- // is not used" and "statement has no effect".
- class CERES_EXPORT LoggerVoidify {
- public:
- // This has to be an operator with a precedence lower than << but
- // higher than ?:
- void operator&(const std::ostream& s) {}
- };
- // Log only if condition is met. Otherwise evaluates to void.
- // clang-format off
- #define LOG_IF(severity, condition) \
- !(condition) ? (void) 0 : LoggerVoidify() & \
- MessageLogger((char *)__FILE__, __LINE__, "native", severity).stream()
- // clang-format on
- // Log only if condition is NOT met. Otherwise evaluates to void.
- #define LOG_IF_FALSE(severity, condition) LOG_IF(severity, !(condition))
- // LG is a convenient shortcut for LOG(INFO). Its use is in new
- // google3 code is discouraged and the following shortcut exists for
- // backward compatibility with existing code.
- // clang-format off
- #ifdef MAX_LOG_LEVEL
- # define LOG(n) LOG_IF(n, n <= MAX_LOG_LEVEL)
- # define VLOG(n) LOG_IF(n, n <= MAX_LOG_LEVEL)
- # define LG LOG_IF(INFO, INFO <= MAX_LOG_LEVEL)
- # define VLOG_IF(n, condition) LOG_IF(n, (n <= MAX_LOG_LEVEL) && condition)
- #else
- # define LOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", n).stream() // NOLINT
- # define VLOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", n).stream() // NOLINT
- # define LG MessageLogger((char *)__FILE__, __LINE__, "native", INFO).stream() // NOLINT
- # define VLOG_IF(n, condition) LOG_IF(n, condition)
- #endif
- // Currently, VLOG is always on for levels below MAX_LOG_LEVEL.
- #ifndef MAX_LOG_LEVEL
- # define VLOG_IS_ON(x) (1)
- #else
- # define VLOG_IS_ON(x) (x <= MAX_LOG_LEVEL)
- #endif
- #ifndef NDEBUG
- # define DLOG LOG
- #else
- # define DLOG(severity) true ? (void) 0 : LoggerVoidify() & \
- MessageLogger((char *)__FILE__, __LINE__, "native", severity).stream()
- #endif
- // clang-format on
- // Log a message and terminate.
- template <class T>
- void LogMessageFatal(const char* file, int line, const T& message) {
- MessageLogger((char*)__FILE__, __LINE__, "native", FATAL).stream() << message;
- }
- // ---------------------------- CHECK macros ---------------------------------
- // Check for a given boolean condition.
- #define CHECK(condition) \
- LOG_IF_FALSE(FATAL, condition) << "Check failed: " #condition " "
- #ifndef NDEBUG
- // Debug only version of CHECK
- #define DCHECK(condition) \
- LOG_IF_FALSE(FATAL, condition) << "Check failed: " #condition " "
- #else
- // Optimized version - generates no code.
- #define DCHECK(condition) \
- if (false) LOG_IF_FALSE(FATAL, condition) << "Check failed: " #condition " "
- #endif // NDEBUG
- // ------------------------- CHECK_OP macros ---------------------------------
- // Generic binary operator check macro. This should not be directly invoked,
- // instead use the binary comparison macros defined below.
- #define CHECK_OP(val1, val2, op) \
- LOG_IF_FALSE(FATAL, ((val1)op(val2))) \
- << "Check failed: " #val1 " " #op " " #val2 " "
- // clang-format off
- // Check_op macro definitions
- #define CHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
- #define CHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
- #define CHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
- #define CHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
- #define CHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
- #define CHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
- #ifndef NDEBUG
- // Debug only versions of CHECK_OP macros.
- # define DCHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
- # define DCHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
- # define DCHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
- # define DCHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
- # define DCHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
- # define DCHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
- #else
- // These versions generate no code in optimized mode.
- # define DCHECK_EQ(val1, val2) if (false) CHECK_OP(val1, val2, ==)
- # define DCHECK_NE(val1, val2) if (false) CHECK_OP(val1, val2, !=)
- # define DCHECK_LE(val1, val2) if (false) CHECK_OP(val1, val2, <=)
- # define DCHECK_LT(val1, val2) if (false) CHECK_OP(val1, val2, <)
- # define DCHECK_GE(val1, val2) if (false) CHECK_OP(val1, val2, >=)
- # define DCHECK_GT(val1, val2) if (false) CHECK_OP(val1, val2, >)
- #endif // NDEBUG
- // clang-format on
- // ---------------------------CHECK_NOTNULL macros ---------------------------
- // Helpers for CHECK_NOTNULL(). Two are necessary to support both raw pointers
- // and smart pointers.
- template <typename T>
- T& CheckNotNullCommon(const char* file, int line, const char* names, T& t) {
- if (t == nullptr) {
- LogMessageFatal(file, line, std::string(names));
- }
- return t;
- }
- template <typename T>
- T* CheckNotNull(const char* file, int line, const char* names, T* t) {
- return CheckNotNullCommon(file, line, names, t);
- }
- template <typename T>
- T& CheckNotNull(const char* file, int line, const char* names, T& t) {
- return CheckNotNullCommon(file, line, names, t);
- }
- // Check that a pointer is not null.
- #define CHECK_NOTNULL(val) \
- CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non nullptr", (val))
- #ifndef NDEBUG
- // Debug only version of CHECK_NOTNULL
- #define DCHECK_NOTNULL(val) \
- CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non nullptr", (val))
- #else
- // Optimized version - generates no code.
- #define DCHECK_NOTNULL(val) \
- if (false) \
- CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non nullptr", (val))
- #endif // NDEBUG
- #include "ceres/internal/reenable_warnings.h"
- #endif // CERCES_INTERNAL_MINIGLOG_GLOG_LOGGING_H_
|