diff options
author | <shinichiro.hamaji@gmail.com> | 2013-01-09 16:06:21 +0000 |
---|---|---|
committer | <shinichiro.hamaji@gmail.com> | 2013-01-09 16:06:21 +0000 |
commit | 3aa45ed56e6b13f73e35e15f45826bce9d84cb57 (patch) | |
tree | 10f7a3c05c6fd69a1e8b33032efc24539d8d0410 /src | |
parent | 44c4b29de47d4e9b888b14c98d8718d1dba803b8 (diff) | |
download | glog-3aa45ed56e6b13f73e35e15f45826bce9d84cb57.tar.gz glog-3aa45ed56e6b13f73e35e15f45826bce9d84cb57.tar.bz2 glog-3aa45ed56e6b13f73e35e15f45826bce9d84cb57.zip |
Eliminate use of strstream based on internal changes
http://code.google.com/p/google-glog/issues/detail?id=110
git-svn-id: https://google-glog.googlecode.com/svn/trunk@119 eb4d4688-79bd-11dd-afb4-1d65580434c0
Diffstat (limited to 'src')
-rw-r--r-- | src/glog/logging.h.in | 162 | ||||
-rw-r--r-- | src/logging.cc | 100 | ||||
-rw-r--r-- | src/stl_logging_unittest.cc | 52 | ||||
-rwxr-xr-x | src/windows/glog/logging.h | 162 | ||||
-rwxr-xr-x | src/windows/preprocess.sh | 1 |
5 files changed, 339 insertions, 138 deletions
diff --git a/src/glog/logging.h.in b/src/glog/logging.h.in index b0b3240..ec47ffd 100644 --- a/src/glog/logging.h.in +++ b/src/glog/logging.h.in @@ -39,18 +39,13 @@ #include <errno.h> #include <string.h> #include <time.h> +#include <iosfwd> +#include <ostream> +#include <sstream> #include <string> #if @ac_cv_have_unistd_h@ # include <unistd.h> #endif -#ifdef __DEPRECATED -// Make GCC quiet. -# undef __DEPRECATED -# include <strstream> -# define __DEPRECATED -#else -# include <strstream> -#endif #include <vector> // Annoying stuff for windows -- makes sure clients can import these functions @@ -134,8 +129,12 @@ typedef unsigned __int64 uint64; #ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN #if @ac_cv_have___builtin_expect@ #define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0)) +#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) #else #define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x +#define GOOGLE_PREDICT_FALSE(x) x +#define GOOGLE_PREDICT_TRUE(x) x #endif #endif @@ -606,18 +605,68 @@ inline std::ostream& operator<<( @ac_google_start_namespace@ -// Build the error message string. -template<class t1, class t2> -std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { - // It means that we cannot use stl_logging if compiler doesn't - // support using expression for operator. - // TODO(hamaji): Figure out a way to fix. -#if @ac_cv_cxx_using_operator@ - using ::operator<<; -#endif - std::strstream ss; - ss << names << " (" << v1 << " vs. " << v2 << ")"; - return new std::string(ss.str(), static_cast<unsigned int>(ss.pcount())); +// This formats a value for a failing CHECK_XX statement. Ordinarily, +// it uses the definition for operator<<, with a few special cases below. +template <typename T> +inline void MakeCheckOpValueString(std::ostream* os, const T& v) { + (*os) << v; +} + +// Overrides for char types provide readable values for unprintable +// characters. +template <> +void MakeCheckOpValueString(std::ostream* os, const char& v); +template <> +void MakeCheckOpValueString(std::ostream* os, const signed char& v); +template <> +void MakeCheckOpValueString(std::ostream* os, const unsigned char& v); + +// Build the error message string. Specify no inlining for code size. +template <typename T1, typename T2> +std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) + @ac_cv___attribute___noinline@; + +namespace base { +namespace internal { + +// If "s" is less than base_logging::INFO, returns base_logging::INFO. +// If "s" is greater than base_logging::FATAL, returns +// base_logging::ERROR. Otherwise, returns "s". +LogSeverity NormalizeSeverity(LogSeverity s); + +} // namespace internal + +// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX +// statement. See MakeCheckOpString for sample usage. Other +// approaches were considered: use of a template method (e.g., +// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1, +// base::Print<T2>, &v2), however this approach has complications +// related to volatile arguments and function-pointer arguments). +class CheckOpMessageBuilder { + public: + // Inserts "exprtext" and " (" to the stream. + explicit CheckOpMessageBuilder(const char *exprtext); + // Deletes "stream_". + ~CheckOpMessageBuilder(); + // For inserting the first variable. + std::ostream* ForVar1() { return stream_; } + // For inserting the second variable (adds an intermediate " vs. "). + std::ostream* ForVar2(); + // Get the result (inserts the closing ")"). + std::string* NewString(); + + private: + std::ostringstream *stream_; +}; + +} // namespace base + +template <typename T1, typename T2> +std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) { + base::CheckOpMessageBuilder comb(exprtext); + MakeCheckOpValueString(comb.ForVar1(), v1); + MakeCheckOpValueString(comb.ForVar2(), v2); + return comb.NewString(); } // Helper functions for CHECK_OP macro. @@ -625,26 +674,26 @@ std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { // will not instantiate the template version of the function on values of // unnamed enum type - see comment below. #define DEFINE_CHECK_OP_IMPL(name, op) \ - template <class t1, class t2> \ - inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ - const char* names) { \ - if (v1 op v2) return NULL; \ - else return MakeCheckOpString(v1, v2, names); \ + template <typename T1, typename T2> \ + inline std::string* name##Impl(const T1& v1, const T2& v2, \ + const char* exprtext) { \ + if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \ + else return MakeCheckOpString(v1, v2, exprtext); \ } \ - inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ - return Check##name##Impl<int, int>(v1, v2, names); \ + inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \ + return name##Impl<int, int>(v1, v2, exprtext); \ } -// Use _EQ, _NE, _LE, etc. in case the file including base/logging.h -// provides its own #defines for the simpler names EQ, NE, LE, etc. +// We use the full name Check_EQ, Check_NE, etc. in case the file including +// base/logging.h provides its own #defines for the simpler names EQ, NE, etc. // This happens if, for example, those are used as token names in a // yacc grammar. -DEFINE_CHECK_OP_IMPL(_EQ, ==) -DEFINE_CHECK_OP_IMPL(_NE, !=) -DEFINE_CHECK_OP_IMPL(_LE, <=) -DEFINE_CHECK_OP_IMPL(_LT, < ) -DEFINE_CHECK_OP_IMPL(_GE, >=) -DEFINE_CHECK_OP_IMPL(_GT, > ) +DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)? +DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead. +DEFINE_CHECK_OP_IMPL(Check_LE, <=) +DEFINE_CHECK_OP_IMPL(Check_LT, < ) +DEFINE_CHECK_OP_IMPL(Check_GE, >=) +DEFINE_CHECK_OP_IMPL(Check_GT, > ) #undef DEFINE_CHECK_OP_IMPL // Helper macro for binary operators. @@ -1022,6 +1071,29 @@ const LogSeverity GLOG_0 = GLOG_ERROR; #define VLOG_IF_EVERY_N(verboselevel, condition, n) \ LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n) +namespace base_logging { + +// LogMessage::LogStream is a std::ostream backed by this streambuf. +// This class ignores overflow and leaves two bytes at the end of the +// buffer to allow for a '\n' and '\0'. +class LogStreamBuf : public std::streambuf { + public: + // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'. + LogStreamBuf(char *buf, int len) { + setp(buf, buf + len - 2); + } + // This effectively ignores overflow. + virtual int_type overflow(int_type ch) { + return ch; + } + + // Legacy public ostrstream method. + size_t pcount() const { return pptr() - pbase(); } + char* pbase() const { return std::streambuf::pbase(); } +}; + +} // namespace base_logging + // // This class more or less represents a particular log message. You // create an instance of LogMessage and then stream stuff to it. @@ -1051,22 +1123,30 @@ public: #ifdef _MSC_VER # pragma warning(disable: 4275) #endif - class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostrstream { + class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream { #ifdef _MSC_VER # pragma warning(default: 4275) #endif public: - LogStream(char *buf, int len, int ctr_in) - : ostrstream(buf, len), - ctr_(ctr_in) { - self_ = this; + LogStream(char *buf, int len, int ctr) + : std::ostream(NULL), + streambuf_(buf, len), + ctr_(ctr), + self_(this) { + rdbuf(&streambuf_); } int ctr() const { return ctr_; } - void set_ctr(int ctr_in) { ctr_ = ctr_in; } + void set_ctr(int ctr) { ctr_ = ctr; } LogStream* self() const { return self_; } + // Legacy std::streambuf methods. + size_t pcount() const { return streambuf_.pcount(); } + char* pbase() const { return streambuf_.pbase(); } + char* str() const { return pbase(); } + private: + base_logging::LogStreamBuf streambuf_; int ctr_; // Counter hack (for the LOG_EVERY_X() macro) LogStream *self_; // Consistency check hack }; diff --git a/src/logging.cc b/src/logging.cc index 6d00952..54d8e34 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -68,7 +68,6 @@ using std::string; using std::vector; -using std::ostrstream; using std::setw; using std::setfill; using std::hex; @@ -76,7 +75,6 @@ using std::dec; using std::min; using std::ostream; using std::ostringstream; -using std::strstream; using std::FILE; using std::fwrite; @@ -289,7 +287,7 @@ class LogFileObject : public base::Logger { // Actually create a logfile using the value of base_filename_ and the // supplied argument time_pid_string // REQUIRES: lock_ is held - bool CreateLogfile(const char* time_pid_string); + bool CreateLogfile(const string& time_pid_string); }; } // namespace @@ -701,7 +699,7 @@ void LogFileObject::FlushUnlocked(){ next_flush_time_ = CycleClock_Now() + UsecToCycles(next); } -bool LogFileObject::CreateLogfile(const char* time_pid_string) { +bool LogFileObject::CreateLogfile(const string& time_pid_string) { string string_filename = base_filename_+filename_extension_+ time_pid_string; const char* filename = string_filename.c_str(); @@ -789,24 +787,24 @@ void LogFileObject::Write(bool force_flush, localtime_r(×tamp, &tm_time); // The logfile's filename will have the date/time & pid in it - char time_pid_string[256]; // More than enough chars for time, pid, \0 - ostrstream time_pid_stream(time_pid_string, sizeof(time_pid_string)); + ostringstream time_pid_stream; time_pid_stream.fill('0'); time_pid_stream << 1900+tm_time.tm_year - << setw(2) << 1+tm_time.tm_mon - << setw(2) << tm_time.tm_mday - << '-' - << setw(2) << tm_time.tm_hour - << setw(2) << tm_time.tm_min - << setw(2) << tm_time.tm_sec - << '.' - << GetMainThreadPid() - << '\0'; + << setw(2) << 1+tm_time.tm_mon + << setw(2) << tm_time.tm_mday + << '-' + << setw(2) << tm_time.tm_hour + << setw(2) << tm_time.tm_min + << setw(2) << tm_time.tm_sec + << '.' + << GetMainThreadPid(); + const string& time_pid_string = time_pid_stream.str(); if (base_filename_selected_) { if (!CreateLogfile(time_pid_string)) { perror("Could not create log file"); - fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n", time_pid_string); + fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n", + time_pid_string.c_str()); return; } } else { @@ -854,15 +852,14 @@ void LogFileObject::Write(bool force_flush, // If we never succeeded, we have to give up if ( success == false ) { perror("Could not create logging file"); - fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE %s!", time_pid_string); + fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE %s!", + time_pid_string.c_str()); return; } } // Write a header message into the log file - char file_header_string[512]; // Enough chars for time and binary info - ostrstream file_header_stream(file_header_string, - sizeof(file_header_string)); + ostringstream file_header_stream; file_header_stream.fill('0'); file_header_stream << "Log file created at: " << 1900+tm_time.tm_year << '/' @@ -875,10 +872,11 @@ void LogFileObject::Write(bool force_flush, << "Running on machine: " << LogDestination::hostname() << '\n' << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu " - << "threadid file:line] msg" << '\n' - << '\0'; - int header_len = strlen(file_header_string); - fwrite(file_header_string, 1, header_len, file_); + << "threadid file:line] msg" << '\n'; + const string& file_header_string = file_header_stream.str(); + + const int header_len = file_header_string.size(); + fwrite(file_header_string.data(), 1, header_len, file_); file_length_ += header_len; bytes_since_flush_ += header_len; } @@ -1741,11 +1739,11 @@ void TruncateStdoutStderr() { bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \ if (equal == expected) return NULL; \ else { \ - strstream ss; \ + ostringstream ss; \ if (!s1) s1 = ""; \ if (!s2) s2 = ""; \ ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \ - return new string(ss.str(), ss.pcount()); \ + return new string(ss.str()); \ } \ } DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true) @@ -1816,6 +1814,56 @@ LogMessageFatal::~LogMessageFatal() { LogMessage::Fail(); } +namespace base { + +CheckOpMessageBuilder::CheckOpMessageBuilder(const char *exprtext) + : stream_(new ostringstream) { + *stream_ << exprtext << " ("; +} + +CheckOpMessageBuilder::~CheckOpMessageBuilder() { + delete stream_; +} + +ostream* CheckOpMessageBuilder::ForVar2() { + *stream_ << " vs. "; + return stream_; +} + +string* CheckOpMessageBuilder::NewString() { + *stream_ << ")"; + return new string(stream_->str()); +} + +} // namespace base + +template <> +void MakeCheckOpValueString(std::ostream* os, const char& v) { + if (v >= 32 && v <= 126) { + (*os) << "'" << v << "'"; + } else { + (*os) << "char value " << (short)v; + } +} + +template <> +void MakeCheckOpValueString(std::ostream* os, const signed char& v) { + if (v >= 32 && v <= 126) { + (*os) << "'" << v << "'"; + } else { + (*os) << "signed char value " << (short)v; + } +} + +template <> +void MakeCheckOpValueString(std::ostream* os, const unsigned char& v) { + if (v >= 32 && v <= 126) { + (*os) << "'" << v << "'"; + } else { + (*os) << "unsigned char value " << (unsigned short)v; + } +} + void InitGoogleLogging(const char* argv0) { glog_internal_namespace_::InitGoogleLoggingUtilities(argv0); } diff --git a/src/stl_logging_unittest.cc b/src/stl_logging_unittest.cc index f932e95..5dcbc44 100644 --- a/src/stl_logging_unittest.cc +++ b/src/stl_logging_unittest.cc @@ -35,8 +35,8 @@ #include <iostream> #include <map> +#include <ostream> #include <string> -#include <strstream> #include <vector> #ifdef __GNUC__ @@ -63,11 +63,9 @@ void TestSTLLogging() { v.push_back(10); v.push_back(20); v.push_back(30); - char ss_buf[1000]; - ostrstream ss(ss_buf, sizeof(ss_buf)); - // Just ostrstream s1; leaks heap. - ss << v << ends; - CHECK_STREQ(ss.str(), "10 20 30"); + ostringstream ss; + ss << v; + EXPECT_EQ(ss.str(), "10 20 30"); vector<int> copied_v(v); CHECK_EQ(v, copied_v); // This must compile. } @@ -78,10 +76,9 @@ void TestSTLLogging() { m[20] = "twenty"; m[10] = "ten"; m[30] = "thirty"; - char ss_buf[1000]; - ostrstream ss(ss_buf, sizeof(ss_buf)); - ss << m << ends; - CHECK_STREQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)"); + ostringstream ss; + ss << m; + EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)"); map< int, string > copied_m(m); CHECK_EQ(m, copied_m); // This must compile. } @@ -93,10 +90,9 @@ void TestSTLLogging() { hs.insert(10); hs.insert(20); hs.insert(30); - char ss_buf[1000]; - ostrstream ss(ss_buf, sizeof(ss_buf)); - ss << hs << ends; - CHECK_STREQ(ss.str(), "10 20 30"); + ostringstream ss; + ss << hs; + EXPECT_EQ(ss.str(), "10 20 30"); hash_set<int> copied_hs(hs); CHECK_EQ(hs, copied_hs); // This must compile. } @@ -109,10 +105,9 @@ void TestSTLLogging() { hm[10] = "ten"; hm[20] = "twenty"; hm[30] = "thirty"; - char ss_buf[1000]; - ostrstream ss(ss_buf, sizeof(ss_buf)); - ss << hm << ends; - CHECK_STREQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)"); + ostringstream ss; + ss << hm; + EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)"); hash_map<int, string> copied_hm(hm); CHECK_EQ(hm, copied_hm); // this must compile } @@ -131,10 +126,9 @@ void TestSTLLogging() { } v.push_back(100); expected += " ..."; - char ss_buf[1000]; - ostrstream ss(ss_buf, sizeof(ss_buf)); - ss << v << ends; - CHECK_STREQ(ss.str(), expected.c_str()); + ostringstream ss; + ss << v; + CHECK_EQ(ss.str(), expected.c_str()); } { @@ -144,10 +138,9 @@ void TestSTLLogging() { m[20] = "twenty"; m[10] = "ten"; m[30] = "thirty"; - char ss_buf[1000]; - ostrstream ss(ss_buf, sizeof(ss_buf)); - ss << m << ends; - CHECK_STREQ(ss.str(), "(30, thirty) (20, twenty) (10, ten)"); + ostringstream ss; + ss << m; + EXPECT_EQ(ss.str(), "(30, thirty) (20, twenty) (10, ten)"); map< int, string, greater<int> > copied_m(m); CHECK_EQ(m, copied_m); // This must compile. } @@ -160,10 +153,9 @@ void TestSTLLogging() { hs.insert(10); hs.insert(20); hs.insert(30); - char ss_buf[1000]; - ostrstream ss(ss_buf, sizeof(ss_buf)); - ss << hs << ends; - CHECK_STREQ(ss.str(), "10 20 30"); + ostringstream ss; + ss << hs; + EXPECT_EQ(ss.str(), "10 20 30"); hash_set<int, user_hash> copied_hs(hs); CHECK_EQ(hs, copied_hs); // This must compile. } diff --git a/src/windows/glog/logging.h b/src/windows/glog/logging.h index 1e01e26..35565ff 100755 --- a/src/windows/glog/logging.h +++ b/src/windows/glog/logging.h @@ -43,18 +43,13 @@ #include <errno.h> #include <string.h> #include <time.h> +#include <iosfwd> +#include <ostream> +#include <sstream> #include <string> #if 0 # include <unistd.h> #endif -#ifdef __DEPRECATED -// Make GCC quiet. -# undef __DEPRECATED -# include <strstream> -# define __DEPRECATED -#else -# include <strstream> -#endif #include <vector> // Annoying stuff for windows -- makes sure clients can import these functions @@ -138,8 +133,12 @@ typedef unsigned __int64 uint64; #ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN #if 0 #define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0)) +#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) #else #define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x +#define GOOGLE_PREDICT_FALSE(x) x +#define GOOGLE_PREDICT_TRUE(x) x #endif #endif @@ -610,18 +609,68 @@ inline std::ostream& operator<<( namespace google { -// Build the error message string. -template<class t1, class t2> -std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { - // It means that we cannot use stl_logging if compiler doesn't - // support using expression for operator. - // TODO(hamaji): Figure out a way to fix. -#if 1 - using ::operator<<; -#endif - std::strstream ss; - ss << names << " (" << v1 << " vs. " << v2 << ")"; - return new std::string(ss.str(), static_cast<unsigned int>(ss.pcount())); +// This formats a value for a failing CHECK_XX statement. Ordinarily, +// it uses the definition for operator<<, with a few special cases below. +template <typename T> +inline void MakeCheckOpValueString(std::ostream* os, const T& v) { + (*os) << v; +} + +// Overrides for char types provide readable values for unprintable +// characters. +template <> +void MakeCheckOpValueString(std::ostream* os, const char& v); +template <> +void MakeCheckOpValueString(std::ostream* os, const signed char& v); +template <> +void MakeCheckOpValueString(std::ostream* os, const unsigned char& v); + +// Build the error message string. Specify no inlining for code size. +template <typename T1, typename T2> +std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) + ; + +namespace base { +namespace internal { + +// If "s" is less than base_logging::INFO, returns base_logging::INFO. +// If "s" is greater than base_logging::FATAL, returns +// base_logging::ERROR. Otherwise, returns "s". +LogSeverity NormalizeSeverity(LogSeverity s); + +} // namespace internal + +// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX +// statement. See MakeCheckOpString for sample usage. Other +// approaches were considered: use of a template method (e.g., +// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1, +// base::Print<T2>, &v2), however this approach has complications +// related to volatile arguments and function-pointer arguments). +class CheckOpMessageBuilder { + public: + // Inserts "exprtext" and " (" to the stream. + explicit CheckOpMessageBuilder(const char *exprtext); + // Deletes "stream_". + ~CheckOpMessageBuilder(); + // For inserting the first variable. + std::ostream* ForVar1() { return stream_; } + // For inserting the second variable (adds an intermediate " vs. "). + std::ostream* ForVar2(); + // Get the result (inserts the closing ")"). + std::string* NewString(); + + private: + std::ostringstream *stream_; +}; + +} // namespace base + +template <typename T1, typename T2> +std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) { + base::CheckOpMessageBuilder comb(exprtext); + MakeCheckOpValueString(comb.ForVar1(), v1); + MakeCheckOpValueString(comb.ForVar2(), v2); + return comb.NewString(); } // Helper functions for CHECK_OP macro. @@ -629,26 +678,26 @@ std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { // will not instantiate the template version of the function on values of // unnamed enum type - see comment below. #define DEFINE_CHECK_OP_IMPL(name, op) \ - template <class t1, class t2> \ - inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ - const char* names) { \ - if (v1 op v2) return NULL; \ - else return MakeCheckOpString(v1, v2, names); \ + template <typename T1, typename T2> \ + inline std::string* name##Impl(const T1& v1, const T2& v2, \ + const char* exprtext) { \ + if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \ + else return MakeCheckOpString(v1, v2, exprtext); \ } \ - inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ - return Check##name##Impl<int, int>(v1, v2, names); \ + inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \ + return name##Impl<int, int>(v1, v2, exprtext); \ } -// Use _EQ, _NE, _LE, etc. in case the file including base/logging.h -// provides its own #defines for the simpler names EQ, NE, LE, etc. +// We use the full name Check_EQ, Check_NE, etc. in case the file including +// base/logging.h provides its own #defines for the simpler names EQ, NE, etc. // This happens if, for example, those are used as token names in a // yacc grammar. -DEFINE_CHECK_OP_IMPL(_EQ, ==) -DEFINE_CHECK_OP_IMPL(_NE, !=) -DEFINE_CHECK_OP_IMPL(_LE, <=) -DEFINE_CHECK_OP_IMPL(_LT, < ) -DEFINE_CHECK_OP_IMPL(_GE, >=) -DEFINE_CHECK_OP_IMPL(_GT, > ) +DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)? +DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead. +DEFINE_CHECK_OP_IMPL(Check_LE, <=) +DEFINE_CHECK_OP_IMPL(Check_LT, < ) +DEFINE_CHECK_OP_IMPL(Check_GE, >=) +DEFINE_CHECK_OP_IMPL(Check_GT, > ) #undef DEFINE_CHECK_OP_IMPL // Helper macro for binary operators. @@ -1026,6 +1075,29 @@ const LogSeverity GLOG_0 = GLOG_ERROR; #define VLOG_IF_EVERY_N(verboselevel, condition, n) \ LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n) +namespace base_logging { + +// LogMessage::LogStream is a std::ostream backed by this streambuf. +// This class ignores overflow and leaves two bytes at the end of the +// buffer to allow for a '\n' and '\0'. +class LogStreamBuf : public std::streambuf { + public: + // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'. + LogStreamBuf(char *buf, int len) { + setp(buf, buf + len - 2); + } + // This effectively ignores overflow. + virtual int_type overflow(int_type ch) { + return ch; + } + + // Legacy public ostrstream method. + size_t pcount() const { return pptr() - pbase(); } + char* pbase() const { return std::streambuf::pbase(); } +}; + +} // namespace base_logging + // // This class more or less represents a particular log message. You // create an instance of LogMessage and then stream stuff to it. @@ -1055,22 +1127,30 @@ public: #ifdef _MSC_VER # pragma warning(disable: 4275) #endif - class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostrstream { + class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream { #ifdef _MSC_VER # pragma warning(default: 4275) #endif public: - LogStream(char *buf, int len, int ctr_in) - : ostrstream(buf, len), - ctr_(ctr_in) { - self_ = this; + LogStream(char *buf, int len, int ctr) + : std::ostream(NULL), + streambuf_(buf, len), + ctr_(ctr), + self_(this) { + rdbuf(&streambuf_); } int ctr() const { return ctr_; } - void set_ctr(int ctr_in) { ctr_ = ctr_in; } + void set_ctr(int ctr) { ctr_ = ctr; } LogStream* self() const { return self_; } + // Legacy std::streambuf methods. + size_t pcount() const { return streambuf_.pcount(); } + char* pbase() const { return streambuf_.pbase(); } + char* str() const { return pbase(); } + private: + base_logging::LogStreamBuf streambuf_; int ctr_; // Counter hack (for the LOG_EVERY_X() macro) LogStream *self_; // Consistency check hack }; diff --git a/src/windows/preprocess.sh b/src/windows/preprocess.sh index ea4352e..5398988 100755 --- a/src/windows/preprocess.sh +++ b/src/windows/preprocess.sh @@ -96,6 +96,7 @@ DLLDEF_DEFINES="\ -e "s!@ac_cv_have___builtin_expect@!0!g" \ -e "s!@ac_cv_cxx_using_operator@!1!g" \ -e "s!@ac_cv___attribute___noreturn@!!g" \ + -e "s!@ac_cv___attribute___noinline@!!g" \ -e "s!@ac_cv___attribute___printf_4_5@!!g" \ -e "s!@ac_google_attribute@!${HAVE___ATTRIBUTE__:-0}!g" \ -e "s!@ac_google_end_namespace@!$_END_GOOGLE_NAMESPACE_!g" \ |