| #ifndef _H_Debug |
| #define _H_Debug |
| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| #ifndef _WINDOWS |
| // TODO(jat): remove, for snprintf prototypes which should go away |
| #include <stdio.h> |
| #endif |
| |
| #include <ostream> |
| #include <string> |
| |
| #include "Platform.h" |
| |
| // Get a default debug config if none supplied. |
| #ifndef GWT_DEBUGLEVEL |
| #include "DebugLevel.h" |
| #endif |
| |
| /** |
| * Debugging class to get debugging output to a platform-specific location, with multiple |
| * levels supported. |
| * |
| * To use: |
| * #define GWT_DEBUGLEVEL level // where level is in LogLevel |
| * #include "Debug.h" |
| * Debug::log(Debug::Warning) << ... |
| * |
| * Zero overhead if GWT_DEBUGDISABLE is defined, other than the effort spent on side |
| * effects for stream object construction. If that is expensive, use something like |
| * Debug::level(Debug::Warning) to conditionalize expensive logging computations. |
| */ |
| class Debug { |
| public: |
| enum LogLevel { |
| None, |
| Error, |
| Warning, |
| Info, |
| Debugging, |
| Spam |
| }; |
| |
| private: |
| static const LogLevel minLogLevel = GWT_DEBUGLEVEL; |
| |
| public: |
| /** |
| * Return true if the requested level would be logged. Use to protect |
| * expensive computations for logging. |
| */ |
| static bool level(LogLevel testLevel) { |
| #ifdef GWT_DEBUGDISABLE |
| return false; |
| #else |
| return testLevel <= minLogLevel; |
| #endif |
| } |
| |
| private: |
| // complete the current log message |
| static void logFinish(); |
| |
| // begin a new log message |
| static void logStart(LogLevel level); |
| |
| // add a string to the current log message |
| static void logString(const char* str); |
| static void logString(const std::string& str) { |
| logString(str.c_str()); |
| } |
| |
| public: |
| // Note that flush is special-cased in the manipulator output operator, |
| // and its implementation is inlined there. If its implementation is |
| // modified, the implementation of the manipulator output operator will |
| // need to be modified as well. |
| class DebugStream; |
| static DebugStream& flush(DebugStream& dbg); |
| |
| class DebugStream { |
| |
| const bool shouldLog; |
| |
| // TODO(jat): better implementations of output operators |
| public: |
| DebugStream(LogLevel level) : shouldLog(Debug::level(level)) { |
| if (shouldLog) { |
| Debug::logStart(level); |
| } |
| } |
| |
| bool isActive() const { |
| return shouldLog; |
| } |
| |
| DebugStream& operator<<(long v) { |
| if (shouldLog) { |
| char buf[20]; |
| snprintf(buf, sizeof(buf), "%ld", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(unsigned long v) { |
| if (shouldLog) { |
| char buf[20]; |
| snprintf(buf, sizeof(buf), "%lu", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(long long v) { |
| if (shouldLog) { |
| char buf[40]; |
| snprintf(buf, sizeof(buf), "%lld", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(unsigned long long v) { |
| if (shouldLog) { |
| char buf[40]; |
| snprintf(buf, sizeof(buf), "%llu", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(int v) { |
| if (shouldLog) { |
| char buf[20]; |
| snprintf(buf, sizeof(buf), "%d", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(unsigned int v) { |
| if (shouldLog) { |
| char buf[20]; |
| snprintf(buf, sizeof(buf), "%u", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(double v) { |
| if (shouldLog) { |
| char buf[20]; |
| snprintf(buf, sizeof(buf), "%g", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(const std::string& str) { |
| if (shouldLog) { |
| Debug::logString(str); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(const char* str) { |
| if (shouldLog) { |
| Debug::logString(str); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(const void* v) { |
| if (shouldLog) { |
| char buf[20]; |
| snprintf(buf, sizeof(buf), "%p", v); |
| Debug::logString(buf); |
| } |
| return *this; |
| } |
| |
| DebugStream& operator<<(DebugStream& (*manip)(DebugStream&)) { |
| if (shouldLog) { |
| // Special-case flush for efficiency. |
| if (manip == Debug::flush) { |
| Debug::logFinish(); |
| } else { |
| return manip(*this); |
| } |
| } |
| return *this; |
| } |
| }; |
| |
| static DebugStream log(LogLevel testLevel) { |
| return DebugStream(testLevel); |
| } |
| }; |
| |
| #endif |