Add libjingle-style stream-style logging.

Add a highly stripped-down version of libjingle's base/logging.h. It is
a thin wrapper around WEBRTC_TRACE, maintaining the libjingle log
semantics to ease a transition to that format.

Also add some helper macros for easy API and function failure logging.

Review URL: https://webrtc-codereview.appspot.com/931010

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3099 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/system_wrappers/interface/logging.h b/webrtc/system_wrappers/interface/logging.h
new file mode 100644
index 0000000..ef6fb8d
--- /dev/null
+++ b/webrtc/system_wrappers/interface/logging.h
@@ -0,0 +1,166 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This is a highly stripped-down version of libjingle's talk/base/logging.h.
+// It is a thin wrapper around WEBRTC_TRACE, maintaining the libjingle log
+// semantics to ease a transition to that format.
+
+//   LOG(...) an ostream target that can be used to send formatted
+// output to a variety of logging targets, such as debugger console, stderr,
+// file, or any StreamInterface.
+//   The severity level passed as the first argument to the LOGging
+// functions is used as a filter, to limit the verbosity of the logging.
+//   Static members of LogMessage documented below are used to control the
+// verbosity and target of the output.
+//   There are several variations on the LOG macro which facilitate logging
+// of common error conditions, detailed below.
+
+// LOG(sev) logs the given stream at severity "sev", which must be a
+//     compile-time constant of the LoggingSeverity type, without the namespace
+//     prefix.
+// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity
+//     type (basically, it just doesn't prepend the namespace).
+// LOG_F(sev) Like LOG(), but includes the name of the current function.
+
+// Additional helper macros added by WebRTC:
+// LOG_API is a shortcut for API call logging. Pass in the input parameters of
+// the method. For example:
+//   Foo(int bar, int baz) {
+//     LOG_API2(bar, baz);
+//   }
+//
+// LOG_FERR is a shortcut for logging a failed function call. For example:
+//   if (!Foo(bar)) {
+//     LOG_FERR1(WARNING, Foo, bar);
+//   }
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
+
+#include <sstream>
+
+namespace webrtc {
+
+//////////////////////////////////////////////////////////////////////
+
+// Note that the non-standard LoggingSeverity aliases exist because they are
+// still in broad use.  The meanings of the levels are:
+//  LS_SENSITIVE: Information which should only be logged with the consent
+//   of the user, due to privacy concerns.
+//  LS_VERBOSE: This level is for data which we do not want to appear in the
+//   normal debug log, but should appear in diagnostic logs.
+//  LS_INFO: Chatty level used in debugging for all sorts of things, the default
+//   in debug builds.
+//  LS_WARNING: Something that may warrant investigation.
+//  LS_ERROR: Something that should not have occurred.
+enum LoggingSeverity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR,
+                       INFO = LS_INFO,
+                       WARNING = LS_WARNING,
+                       LERROR = LS_ERROR };
+
+class LogMessage {
+ public:
+  LogMessage(const char* file, int line, LoggingSeverity sev);
+  ~LogMessage();
+
+  std::ostream& stream() { return print_stream_; }
+
+ private:
+  // These assist in formatting some parts of the debug output.
+  static const char* DescribeFile(const char* file);
+
+  // The ostream that buffers the formatted message before output
+  std::ostringstream print_stream_;
+
+  // The severity level of this message
+  LoggingSeverity severity_;
+};
+
+//////////////////////////////////////////////////////////////////////
+// Macros which automatically disable logging when LOGGING == 0
+//////////////////////////////////////////////////////////////////////
+
+// If LOGGING is not explicitly defined, default to enabled in debug mode
+// TODO(andrew): We explictly enable here; handle in gyp instead.
+#define LOGGING 1
+#if !defined(LOGGING)
+#if defined(_DEBUG) && !defined(NDEBUG)
+#define LOGGING 1
+#else
+#define LOGGING 0
+#endif
+#endif  // !defined(LOGGING)
+
+#ifndef LOG
+#if LOGGING
+
+// The following non-obvious technique for implementation of a
+// conditional log stream was stolen from google3/base/logging.h.
+
+// 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 LogMessageVoidify {
+ public:
+  LogMessageVoidify() { }
+  // This has to be an operator with a precedence lower than << but
+  // higher than ?:
+  void operator&(std::ostream&) { }
+};
+
+#define LOG(sev) \
+    webrtc::LogMessage(__FILE__, __LINE__, webrtc::sev).stream()
+
+// The _V version is for when a variable is passed in.  It doesn't do the
+// namespace concatination.
+#define LOG_V(sev) \
+    webrtc::LogMessage(__FILE__, __LINE__, sev).stream()
+
+// The _F version prefixes the message with the current function name.
+#if (defined(__GNUC__) && defined(_DEBUG)) || defined(WANT_PRETTY_LOG_F)
+#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
+#else
+#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
+#endif
+
+#else  // !LOGGING
+
+// Hopefully, the compiler will optimize away some of this code.
+// Note: syntax of "1 ? (void)0 : LogMessage" was causing errors in g++,
+//   converted to "while (false)"
+#define LOG(sev) \
+  while (false)webrtc::LogMessage(NULL, 0, webrtc::sev).stream()
+#define LOG_V(sev) \
+  while (false) webrtc::LogMessage(NULL, 0, sev).stream()
+#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
+
+#endif  // !LOGGING
+
+#define LOG_API0() LOG_F(LS_INFO)
+#define LOG_API1(v1) LOG_API0() << #v1 << "=" << v1
+#define LOG_API2(v1, v2) LOG_API1(v1) \
+    << ", " << #v2 << "=" << v2
+#define LOG_API3(v1, v2, v3) LOG_API2(v1, v2) \
+    << ", " << #v3 << "=" << v3
+
+#define LOG_FERR0(sev, func) LOG(sev) << #func << " failed"
+#define LOG_FERR1(sev, func, v1) LOG_FERR0(sev, func) \
+    << ": " << #v1 << "=" << v1
+#define LOG_FERR2(sev, func, v1, v2) LOG_FERR1(sev, func, v1) \
+    << ", " << #v2 << "=" << v2
+#define LOG_FERR3(sev, func, v1, v2, v3) LOG_FERR2(sev, func, v1, v2) \
+    << ", " << #v3 << "=" << v3
+
+#endif  // LOG
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_