Commit 3aa45ed5 authored by 's avatar

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
parent 44c4b29d
......@@ -415,6 +415,7 @@ ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_cv___attribute___noinline = @ac_cv___attribute___noinline@
ac_cv___attribute___noreturn = @ac_cv___attribute___noreturn@
ac_cv___attribute___printf_4_5 = @ac_cv___attribute___printf_4_5@
ac_cv_cxx_using_operator = @ac_cv_cxx_using_operator@
......
......@@ -632,6 +632,7 @@ ac_cv_have_systypes_h
ac_cv_have_stdint_h
ac_cv_have___builtin_expect
ac_cv___attribute___printf_4_5
ac_cv___attribute___noinline
ac_cv___attribute___noreturn
ac_cv_cxx_using_operator
ac_google_namespace
......@@ -15825,9 +15826,11 @@ $as_echo "$ac_cv___attribute__" >&6; }
# We only care about these two attributes.
if test x"$ac_cv___attribute__" = x"yes"; then
ac_cv___attribute___noreturn="__attribute__ ((noreturn))"
ac_cv___attribute___noinline="__attribute__ ((noinline))"
ac_cv___attribute___printf_4_5="__attribute__((__format__ (__printf__, 4, 5)))"
else
ac_cv___attribute___noreturn=
ac_cv___attribute___noinline=
ac_cv___attribute___printf_4_5=
fi
......@@ -17173,6 +17176,7 @@ _ACEOF
......
......@@ -69,9 +69,11 @@ AX_C___ATTRIBUTE__
# We only care about these two attributes.
if test x"$ac_cv___attribute__" = x"yes"; then
ac_cv___attribute___noreturn="__attribute__ ((noreturn))"
ac_cv___attribute___noinline="__attribute__ ((noinline))"
ac_cv___attribute___printf_4_5="__attribute__((__format__ (__printf__, 4, 5)))"
else
ac_cv___attribute___noreturn=
ac_cv___attribute___noinline=
ac_cv___attribute___printf_4_5=
fi
......@@ -195,6 +197,7 @@ AC_SUBST(ac_google_end_namespace)
AC_SUBST(ac_google_namespace)
AC_SUBST(ac_cv_cxx_using_operator)
AC_SUBST(ac_cv___attribute___noreturn)
AC_SUBST(ac_cv___attribute___noinline)
AC_SUBST(ac_cv___attribute___printf_4_5)
AC_SUBST(ac_cv_have___builtin_expect)
AC_SUBST(ac_cv_have_stdint_h)
......
......@@ -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
};
......
......@@ -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,8 +787,7 @@ 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
......@@ -800,13 +797,14 @@ void LogFileObject::Write(bool force_flush,
<< setw(2) << tm_time.tm_min
<< setw(2) << tm_time.tm_sec
<< '.'
<< GetMainThreadPid()
<< '\0';
<< 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);
}
......
......@@ -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.
}
......
......@@ -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
};
......
......@@ -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" \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment