diff --git a/src/Makefile.am b/src/Makefile.am index 2bc2aad9..cd832b2f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -83,10 +83,6 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/stubs/map-util.h \ google/protobuf/stubs/stl_util-inl.cc \ google/protobuf/stubs/stl_util-inl.h \ - google/protobuf/stubs/strutil.cc \ - google/protobuf/stubs/strutil.h \ - google/protobuf/stubs/substitute.cc \ - google/protobuf/stubs/substitute.h \ google/protobuf/extension_set.cc \ google/protobuf/generated_message_util.cc \ google/protobuf/message_lite.cc \ @@ -100,6 +96,10 @@ libprotobuf_la_LIBADD = $(PTHREAD_LIBS) libprotobuf_la_LDFLAGS = -version-info 3:0:0 libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ + google/protobuf/stubs/strutil.cc \ + google/protobuf/stubs/strutil.h \ + google/protobuf/stubs/substitute.cc \ + google/protobuf/stubs/substitute.h \ google/protobuf/stubs/structurally_valid.cc \ google/protobuf/descriptor.cc \ google/protobuf/descriptor.pb.cc \ @@ -311,6 +311,7 @@ protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \ protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ -I$(top_builddir)/gtest/include \ -DPROTOBUF_TEST_NO_DESCRIPTORS +protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lazy_descriptor_test_SOURCES = \ google/protobuf/compiler/cpp/cpp_unittest.cc \ $(COMMON_TEST_SOURCES) @@ -318,6 +319,7 @@ nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs) # Build lite_unittest separately, since it doesn't use gtest. protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la +protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lite_test_SOURCES = \ google/protobuf/lite_unittest.cc \ google/protobuf/test_util_lite.cc \ diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 5e156f25..a53740ad 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include namespace google { @@ -55,11 +54,23 @@ namespace { string InitializationErrorMessage(const char* action, const MessageLite& message) { - return strings::Substitute( - "Can't $0 message of type \"$1\" because it is missing required " - "fields: $2", - action, message.GetTypeName(), - message.InitializationErrorString()); + // Note: We want to avoid depending on strutil in the lite library, otherwise + // we'd use: + // + // return strings::Substitute( + // "Can't $0 message of type \"$1\" because it is missing required " + // "fields: $2", + // action, message.GetTypeName(), + // message.InitializationErrorString()); + + string result; + result += "Can't "; + result += action; + result += " message of type \""; + result += message.GetTypeName(); + result += "\" because it is missing required fields: "; + result += message.InitializationErrorString(); + return result; } // Several of the Parse methods below just do one thing and then call another diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc index 302be7ae..1e2d68d2 100644 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -32,8 +32,6 @@ #include #include -#include -#include #include #include #include @@ -43,6 +41,7 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN // We only need minimal includes #include +#define snprintf _snprintf // see comment in strutil.cc #elif defined(HAVE_PTHREAD) #include #else @@ -87,7 +86,15 @@ string VersionString(int version) { int minor = (version / 1000) % 1000; int micro = version % 1000; - return strings::Substitute("$0.$1.$2", major, minor, micro); + // 128 bytes should always be enough, but we use snprintf() anyway to be + // safe. + char buffer[128]; + snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro); + + // Guard against broken MSVC snprintf(). + buffer[sizeof(buffer)-1] = '\0'; + + return buffer; } } // namespace internal @@ -131,23 +138,39 @@ void InitLogSilencerCountOnce() { GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount); } -static string SimpleCtoa(char c) { return string(1, c); } +LogMessage& LogMessage::operator<<(const string& value) { + message_ += value; + return *this; +} +LogMessage& LogMessage::operator<<(const char* value) { + message_ += value; + return *this; +} + +// Since this is just for logging, we don't care if the current locale changes +// the results -- in fact, we probably prefer that. So we use snprintf() +// instead of Simple*toa(). #undef DECLARE_STREAM_OPERATOR -#define DECLARE_STREAM_OPERATOR(TYPE, TOSTRING) \ +#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT) \ LogMessage& LogMessage::operator<<(TYPE value) { \ - message_ += TOSTRING(value); \ + /* 128 bytes should be big enough for any of the primitive */ \ + /* values which we print with this, but well use snprintf() */ \ + /* anyway to be extra safe. */ \ + char buffer[128]; \ + snprintf(buffer, sizeof(buffer), FORMAT, value); \ + /* Guard against broken MSVC snprintf(). */ \ + buffer[sizeof(buffer)-1] = '\0'; \ + message_ += buffer; \ return *this; \ } -DECLARE_STREAM_OPERATOR(const string&, ) -DECLARE_STREAM_OPERATOR(const char* , ) -DECLARE_STREAM_OPERATOR(char , SimpleCtoa) -DECLARE_STREAM_OPERATOR(int , SimpleItoa) -DECLARE_STREAM_OPERATOR(uint , SimpleItoa) -DECLARE_STREAM_OPERATOR(long , SimpleItoa) -DECLARE_STREAM_OPERATOR(unsigned long, SimpleItoa) -DECLARE_STREAM_OPERATOR(double , SimpleDtoa) +DECLARE_STREAM_OPERATOR(char , "%c" ) +DECLARE_STREAM_OPERATOR(int , "%d" ) +DECLARE_STREAM_OPERATOR(uint , "%u" ) +DECLARE_STREAM_OPERATOR(long , "%ld") +DECLARE_STREAM_OPERATOR(unsigned long, "%lu") +DECLARE_STREAM_OPERATOR(double , "%g" ) #undef DECLARE_STREAM_OPERATOR LogMessage::LogMessage(LogLevel level, const char* filename, int line)