|
@@ -32,8 +32,6 @@
|
|
|
|
|
|
#include <google/protobuf/stubs/common.h>
|
|
|
#include <google/protobuf/stubs/once.h>
|
|
|
-#include <google/protobuf/stubs/strutil.h>
|
|
|
-#include <google/protobuf/stubs/substitute.h>
|
|
|
#include <stdio.h>
|
|
|
#include <errno.h>
|
|
|
#include <vector>
|
|
@@ -43,6 +41,7 @@
|
|
|
#ifdef _WIN32
|
|
|
#define WIN32_LEAN_AND_MEAN // We only need minimal includes
|
|
|
#include <windows.h>
|
|
|
+#define snprintf _snprintf // see comment in strutil.cc
|
|
|
#elif defined(HAVE_PTHREAD)
|
|
|
#include <pthread.h>
|
|
|
#else
|
|
@@ -87,7 +86,15 @@ string VersionString(int version) {
|
|
|
int minor = (version / 1000) % 1000;
|
|
|
int micro = version % 1000;
|
|
|
|
|
|
- return strings::Substitute("$0.$1.$2", major, minor, micro);
|
|
|
+ // 128 bytes should always be enough, but we use snprintf() anyway to be
|
|
|
+ // safe.
|
|
|
+ char buffer[128];
|
|
|
+ snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro);
|
|
|
+
|
|
|
+ // Guard against broken MSVC snprintf().
|
|
|
+ buffer[sizeof(buffer)-1] = '\0';
|
|
|
+
|
|
|
+ return buffer;
|
|
|
}
|
|
|
|
|
|
} // namespace internal
|
|
@@ -131,23 +138,39 @@ void InitLogSilencerCountOnce() {
|
|
|
GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount);
|
|
|
}
|
|
|
|
|
|
-static string SimpleCtoa(char c) { return string(1, c); }
|
|
|
+LogMessage& LogMessage::operator<<(const string& value) {
|
|
|
+ message_ += value;
|
|
|
+ return *this;
|
|
|
+}
|
|
|
+
|
|
|
+LogMessage& LogMessage::operator<<(const char* value) {
|
|
|
+ message_ += value;
|
|
|
+ return *this;
|
|
|
+}
|
|
|
|
|
|
+// Since this is just for logging, we don't care if the current locale changes
|
|
|
+// the results -- in fact, we probably prefer that. So we use snprintf()
|
|
|
+// instead of Simple*toa().
|
|
|
#undef DECLARE_STREAM_OPERATOR
|
|
|
-#define DECLARE_STREAM_OPERATOR(TYPE, TOSTRING) \
|
|
|
+#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT) \
|
|
|
LogMessage& LogMessage::operator<<(TYPE value) { \
|
|
|
- message_ += TOSTRING(value); \
|
|
|
+ /* 128 bytes should be big enough for any of the primitive */ \
|
|
|
+ /* values which we print with this, but well use snprintf() */ \
|
|
|
+ /* anyway to be extra safe. */ \
|
|
|
+ char buffer[128]; \
|
|
|
+ snprintf(buffer, sizeof(buffer), FORMAT, value); \
|
|
|
+ /* Guard against broken MSVC snprintf(). */ \
|
|
|
+ buffer[sizeof(buffer)-1] = '\0'; \
|
|
|
+ message_ += buffer; \
|
|
|
return *this; \
|
|
|
}
|
|
|
|
|
|
-DECLARE_STREAM_OPERATOR(const string&, )
|
|
|
-DECLARE_STREAM_OPERATOR(const char* , )
|
|
|
-DECLARE_STREAM_OPERATOR(char , SimpleCtoa)
|
|
|
-DECLARE_STREAM_OPERATOR(int , SimpleItoa)
|
|
|
-DECLARE_STREAM_OPERATOR(uint , SimpleItoa)
|
|
|
-DECLARE_STREAM_OPERATOR(long , SimpleItoa)
|
|
|
-DECLARE_STREAM_OPERATOR(unsigned long, SimpleItoa)
|
|
|
-DECLARE_STREAM_OPERATOR(double , SimpleDtoa)
|
|
|
+DECLARE_STREAM_OPERATOR(char , "%c" )
|
|
|
+DECLARE_STREAM_OPERATOR(int , "%d" )
|
|
|
+DECLARE_STREAM_OPERATOR(uint , "%u" )
|
|
|
+DECLARE_STREAM_OPERATOR(long , "%ld")
|
|
|
+DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
|
|
|
+DECLARE_STREAM_OPERATOR(double , "%g" )
|
|
|
#undef DECLARE_STREAM_OPERATOR
|
|
|
|
|
|
LogMessage::LogMessage(LogLevel level, const char* filename, int line)
|