| #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 |