| // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by the GPL v2 license that can |
| // be found in the LICENSE file. |
| // |
| // A very simple logging library to fill the void when Chrome's libbase |
| // is not available. |
| |
| #ifndef VERITY_LOGGING_LOGGING_H_ |
| #define VERITY_LOGGING_LOGGING_H_ |
| |
| #include <errno.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include <iostream> |
| |
| namespace logging { |
| |
| enum MessageType { TYPE_NORMAL, TYPE_DEBUG, TYPE_ERRNO, TYPE_NULL }; |
| enum MessageLevel { LEVEL_INFO, LEVEL_WARNING, LEVEL_ERROR, LEVEL_FATAL }; |
| |
| static MessageLevel min_level = LEVEL_INFO; |
| |
| class Message { |
| public: |
| Message(MessageLevel level, |
| MessageType type, |
| int errn, |
| const char *file, |
| unsigned long line) : type_(type), |
| log_errno_(errn), |
| file_(file), |
| line_(line) { |
| #ifdef NDEBUG |
| if (type == TYPE_DEBUG) |
| return; |
| #endif |
| if (level > LEVEL_FATAL) |
| level = LEVEL_FATAL; |
| level_ = level; |
| |
| if (type == TYPE_NULL || level < min_level) |
| return; |
| |
| static const char *kLevels[] = { "INFO", "WARNING", "ERROR", "FATAL" }; |
| std::cerr << "[" << kLevels[level] |
| << ":" << file << ":" << line << "] "; |
| } |
| |
| // The Message object is expected to be destroyed at the end of the line. |
| // So far this works reliably with the macros below, which is good enough |
| // as a bandaid for when libbase is missing. |
| virtual ~Message() { |
| if (type_ == TYPE_NULL) |
| return; |
| #ifdef NDEBUG |
| if (type_ == TYPE_DEBUG) |
| return; |
| #endif |
| if (type_ == TYPE_ERRNO) { |
| static const unsigned int kErrnoBufSize = 256; |
| char errbuf[kErrnoBufSize]; |
| // This uses the GNU variant of strerror_r(3). |
| std::cerr << ": " << strerror_r(log_errno_, errbuf, sizeof(errbuf)); |
| } |
| |
| std::cerr << std::endl; |
| std::cerr.flush(); |
| if (level_ == LEVEL_FATAL) |
| exit(1); |
| } |
| |
| template<typename T> |
| const Message& operator<<(const T& t) const { |
| #ifdef NDEBUG |
| if (type() == TYPE_DEBUG) |
| return *this; |
| #endif |
| |
| if (type() == TYPE_NULL || level() < min_level) |
| return *this; |
| |
| std::cerr << t; |
| return *this; |
| } |
| |
| MessageLevel level() const { return level_; } |
| MessageType type() const { return type_; } |
| int log_errno() const { return log_errno_; } |
| const char *file() const { return file_; } |
| unsigned long line() const { return line_; } |
| |
| void set_level(MessageLevel l) { level_ = l; } |
| |
| private: |
| MessageLevel level_; |
| MessageType type_; |
| int log_errno_; |
| const char *file_; |
| unsigned long line_; |
| }; |
| } // namespace logging |
| |
| // Interface macros |
| #define LOG(_level) \ |
| logging::Message(logging::LEVEL_##_level, \ |
| logging::TYPE_NORMAL, \ |
| 0, \ |
| __FILE__, \ |
| __LINE__) |
| #define PLOG(_level) \ |
| logging::Message(logging::LEVEL_##_level, \ |
| logging::TYPE_ERRNO,\ |
| errno, \ |
| __FILE__, \ |
| __LINE__) |
| #define DLOG(_level) \ |
| logging::Message(logging::LEVEL_##_level,\ |
| logging::TYPE_DEBUG, \ |
| 0, \ |
| __FILE__, \ |
| __LINE__) |
| #define LOG_NULL \ |
| logging::Message(logging::LEVEL_INFO, \ |
| logging::TYPE_NULL, \ |
| 0, \ |
| __FILE__, \ |
| __LINE__) |
| |
| #define LOG_IF(_level, cond) ((cond) ? LOG(_level) : LOG_NULL) |
| #define PLOG_IF(_level, cond) ((cond) ? PLOG(_level) : LOG_NULL) |
| |
| #endif // VERITY_LOGGING_LOGGING_H_ |