summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author <shinichiro.hamaji@gmail.com>2013-01-09 16:06:21 +0000
committer <shinichiro.hamaji@gmail.com>2013-01-09 16:06:21 +0000
commit3aa45ed56e6b13f73e35e15f45826bce9d84cb57 (patch)
tree10f7a3c05c6fd69a1e8b33032efc24539d8d0410 /src
parent44c4b29de47d4e9b888b14c98d8718d1dba803b8 (diff)
downloadglog-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.in162
-rw-r--r--src/logging.cc100
-rw-r--r--src/stl_logging_unittest.cc52
-rwxr-xr-xsrc/windows/glog/logging.h162
-rwxr-xr-xsrc/windows/preprocess.sh1
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(&timestamp, &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" \