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