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
This commit is contained in:
parent
44c4b29de4
commit
3aa45ed56e
@ -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@
|
||||
|
||||
4
configure
vendored
4
configure
vendored
@ -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
|
||||
|
||||
@ -17174,6 +17177,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Write generated configuration file
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
100
src/logging.cc
100
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);
|
||||
}
|
||||
|
||||
@ -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" \
|
||||
|
||||
Loading…
Reference in New Issue
Block a user