aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/stubs
diff options
context:
space:
mode:
authorGravatar temporal <temporal@630680e5-0e50-0410-840e-4b1c322b438d>2008-07-10 02:12:20 +0000
committerGravatar temporal <temporal@630680e5-0e50-0410-840e-4b1c322b438d>2008-07-10 02:12:20 +0000
commit40ee551715c3a784ea6132dbf604b0e665ca2def (patch)
tree6e3ea9674be5b0f59106f88f3afa1313854beebf /src/google/protobuf/stubs
Initial checkin.
Diffstat (limited to 'src/google/protobuf/stubs')
-rw-r--r--src/google/protobuf/stubs/common.cc261
-rw-r--r--src/google/protobuf/stubs/common.h1061
-rw-r--r--src/google/protobuf/stubs/common_unittest.cc319
-rw-r--r--src/google/protobuf/stubs/hash.cc27
-rw-r--r--src/google/protobuf/stubs/hash.h123
-rw-r--r--src/google/protobuf/stubs/map-util.cc28
-rw-r--r--src/google/protobuf/stubs/map-util.h90
-rw-r--r--src/google/protobuf/stubs/stl_util-inl.cc27
-rw-r--r--src/google/protobuf/stubs/stl_util-inl.h107
-rw-r--r--src/google/protobuf/stubs/strutil.cc1121
-rw-r--r--src/google/protobuf/stubs/strutil.h432
-rw-r--r--src/google/protobuf/stubs/strutil_unittest.cc68
-rw-r--r--src/google/protobuf/stubs/substitute.cc120
-rw-r--r--src/google/protobuf/stubs/substitute.h156
14 files changed, 3940 insertions, 0 deletions
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
new file mode 100644
index 00000000..d7182841
--- /dev/null
+++ b/src/google/protobuf/stubs/common.cc
@@ -0,0 +1,261 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "config.h"
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN // We only need minimal includes
+#include <windows.h>
+#elif defined(HAVE_PTHREAD)
+#include <pthread.h>
+#else
+#error "No suitable threading library available."
+#endif
+
+namespace google {
+namespace protobuf {
+
+namespace internal {
+
+void VerifyVersion(int headerVersion,
+ int minLibraryVersion,
+ const char* filename) {
+ if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) {
+ // Library is too old for headers.
+ GOOGLE_LOG(FATAL)
+ << "This program requires version " << VersionString(minLibraryVersion)
+ << " of the Protocol Buffer runtime library, but the installed version "
+ "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update "
+ "your library. If you compiled the program yourself, make sure that "
+ "your headers are from the same version of Protocol Buffers as your "
+ "link-time library. (Version verification failed in \""
+ << filename << "\".)";
+ }
+ if (headerVersion < kMinHeaderVersionForLibrary) {
+ // Headers are too old for library.
+ GOOGLE_LOG(FATAL)
+ << "This program was compiled against version "
+ << VersionString(headerVersion) << " of the Protocol Buffer runtime "
+ "library, which is not compatible with the installed version ("
+ << VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program "
+ "author for an update. If you compiled the program yourself, make "
+ "sure that your headers are from the same version of Protocol Buffers "
+ "as your link-time library. (Version verification failed in \""
+ << filename << "\".)";
+ }
+}
+
+string VersionString(int version) {
+ int major = version / 1000000;
+ int minor = (version / 1000) % 1000;
+ int micro = version % 1000;
+
+ return strings::Substitute("$0.$1.$2", major, minor, micro);
+}
+
+} // namespace internal
+
+// ===================================================================
+// emulates google3/base/logging.cc
+
+namespace internal {
+
+void DefaultLogHandler(LogLevel level, const char* filename, int line,
+ const string& message) {
+ static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" };
+
+ // We use fprintf() instead of cerr because we want this to work at static
+ // initialization time.
+ fprintf(stderr, "libprotobuf %s %s:%d] %s\n",
+ level_names[level], filename, line, message.c_str());
+ fflush(stderr); // Needed on MSVC.
+}
+
+void NullLogHandler(LogLevel level, const char* filename, int line,
+ const string& message) {
+ // Nothing.
+}
+
+static LogHandler* log_handler_ = &DefaultLogHandler;
+static int log_silencer_count_ = 0;
+static Mutex log_silencer_count_mutex_;
+
+static string SimpleCtoa(char c) { return string(1, c); }
+
+#undef DECLARE_STREAM_OPERATOR
+#define DECLARE_STREAM_OPERATOR(TYPE, TOSTRING) \
+ LogMessage& LogMessage::operator<<(TYPE value) { \
+ message_ += TOSTRING(value); \
+ 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(double , SimpleDtoa)
+#undef DECLARE_STREAM_OPERATOR
+
+LogMessage::LogMessage(LogLevel level, const char* filename, int line)
+ : level_(level), filename_(filename), line_(line) {}
+LogMessage::~LogMessage() {}
+
+void LogMessage::Finish() {
+ bool suppress = false;
+
+ if (level_ != LOGLEVEL_FATAL) {
+ MutexLock lock(&internal::log_silencer_count_mutex_);
+ suppress = internal::log_silencer_count_ > 0;
+ }
+
+ if (!suppress) {
+ internal::log_handler_(level_, filename_, line_, message_);
+ }
+
+ if (level_ == LOGLEVEL_FATAL) {
+ abort();
+ }
+}
+
+void LogFinisher::operator=(LogMessage& other) {
+ other.Finish();
+}
+
+} // namespace internal
+
+LogHandler* SetLogHandler(LogHandler* new_func) {
+ LogHandler* old = internal::log_handler_;
+ if (old == &internal::NullLogHandler) {
+ old = NULL;
+ }
+ if (new_func == NULL) {
+ internal::log_handler_ = &internal::NullLogHandler;
+ } else {
+ internal::log_handler_ = new_func;
+ }
+ return old;
+}
+
+LogSilencer::LogSilencer() {
+ MutexLock lock(&internal::log_silencer_count_mutex_);
+ ++internal::log_silencer_count_;
+};
+
+LogSilencer::~LogSilencer() {
+ MutexLock lock(&internal::log_silencer_count_mutex_);
+ --internal::log_silencer_count_;
+};
+
+// ===================================================================
+// emulates google3/base/callback.cc
+
+Closure::~Closure() {}
+
+namespace internal { FunctionClosure0::~FunctionClosure0() {} }
+
+void DoNothing() {}
+
+// ===================================================================
+// emulates google3/base/mutex.cc
+
+#ifdef _WIN32
+
+struct Mutex::Internal {
+ CRITICAL_SECTION mutex;
+#ifndef NDEBUG
+ // Used only to implement AssertHeld().
+ DWORD thread_id;
+#endif
+};
+
+Mutex::Mutex()
+ : mInternal(new Internal) {
+ InitializeCriticalSection(&mInternal->mutex);
+}
+
+Mutex::~Mutex() {
+ DeleteCriticalSection(&mInternal->mutex);
+ delete mInternal;
+}
+
+void Mutex::Lock() {
+ EnterCriticalSection(&mInternal->mutex);
+#ifndef NDEBUG
+ mInternal->thread_id = GetCurrentThreadId();
+#endif
+}
+
+void Mutex::Unlock() {
+#ifndef NDEBUG
+ mInternal->thread_id = 0;
+#endif
+ LeaveCriticalSection(&mInternal->mutex);
+}
+
+void Mutex::AssertHeld() {
+#ifndef NDEBUG
+ GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId());
+#endif
+}
+
+#elif defined(HAVE_PTHREAD)
+
+struct Mutex::Internal {
+ pthread_mutex_t mutex;
+};
+
+Mutex::Mutex()
+ : mInternal(new Internal) {
+ pthread_mutex_init(&mInternal->mutex, NULL);
+}
+
+Mutex::~Mutex() {
+ pthread_mutex_destroy(&mInternal->mutex);
+ delete mInternal;
+}
+
+void Mutex::Lock() {
+ int result = pthread_mutex_lock(&mInternal->mutex);
+ if (result != 0) {
+ GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result);
+ }
+}
+
+void Mutex::Unlock() {
+ int result = pthread_mutex_unlock(&mInternal->mutex);
+ if (result != 0) {
+ GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result);
+ }
+}
+
+void Mutex::AssertHeld() {
+ // pthreads dosn't provide a way to check which thread holds the mutex.
+ // TODO(kenton): Maybe keep track of locking thread ID like with WIN32?
+}
+
+#endif
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
new file mode 100644
index 00000000..03b176a3
--- /dev/null
+++ b/src/google/protobuf/stubs/common.h
@@ -0,0 +1,1061 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda) and others
+//
+// Contains basic types and utilities used by the rest of the library.
+
+#ifndef GOOGLE_PROTOBUF_COMMON_H__
+#define GOOGLE_PROTOBUF_COMMON_H__
+
+#include <assert.h>
+#include <stdlib.h>
+#include <cstddef>
+#include <string>
+#include <string.h>
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+
+namespace std {}
+
+namespace google {
+namespace protobuf {
+
+using namespace std; // Don't do this at home, kids.
+
+#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
+#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+#ifdef _MSC_VER
+ #ifdef LIBPROTOBUF_EXPORTS
+ #define LIBPROTOBUF_EXPORT __declspec(dllexport)
+ #else
+ #define LIBPROTOBUF_EXPORT __declspec(dllimport)
+ #endif
+ #ifdef LIBPROTOC_EXPORTS
+ #define LIBPROTOC_EXPORT __declspec(dllexport)
+ #else
+ #define LIBPROTOC_EXPORT __declspec(dllimport)
+ #endif
+#else
+ #define LIBPROTOBUF_EXPORT
+ #define LIBPROTOC_EXPORT
+#endif
+
+namespace internal {
+
+// Some of these constants are macros rather than const ints so that they can
+// be used in #if directives.
+
+// The current version, represented as a single integer to make comparison
+// easier: major * 10^6 + minor * 10^3 + micro
+#define GOOGLE_PROTOBUF_VERSION 2000001
+
+// The minimum library version which works with the current version of the
+// headers.
+#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2000000
+
+// The minimum header version which works with the current version of
+// the library. This constant should only be used by protoc's C++ code
+// generator.
+static const int kMinHeaderVersionForLibrary = 2000000;
+
+// The minimum protoc version which works with the current version of the
+// headers.
+#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2000000
+
+// The minimum header version which works with the current version of
+// protoc. This constant should only be used in VerifyVersion().
+static const int kMinHeaderVersionForProtoc = 2000000;
+
+// Verifies that the headers and libraries are compatible. Use the macro
+// below to call this.
+void LIBPROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion,
+ const char* filename);
+
+// Converts a numeric version number to a string.
+string LIBPROTOBUF_EXPORT VersionString(int version);
+
+} // namespace internal
+
+// Place this macro in your main() function (or somewhere before you attempt
+// to use the protobuf library) to verify that the version you link against
+// matches the headers you compiled against. If a version mismatch is
+// detected, the process will abort.
+#define GOOGLE_PROTOBUF_VERIFY_VERSION \
+ ::google::protobuf::internal::VerifyVersion( \
+ GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \
+ __FILE__)
+
+// ===================================================================
+// from google3/base/port.h
+
+typedef unsigned int uint;
+
+#ifdef _MSC_VER
+typedef __int8 int8;
+typedef __int16 int16;
+typedef __int32 int32;
+typedef __int64 int64;
+
+typedef unsigned __int8 uint8;
+typedef unsigned __int16 uint16;
+typedef unsigned __int32 uint32;
+typedef unsigned __int64 uint64;
+#else
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+#endif
+
+// long long macros to be used because gcc and vc++ use different suffixes,
+// and different size specifiers in format strings
+#undef GOOGLE_LONGLONG
+#undef GOOGLE_ULONGLONG
+#undef GOOGLE_LL_FORMAT
+
+#ifdef _MSC_VER
+#define GOOGLE_LONGLONG(x) x##I64
+#define GOOGLE_ULONGLONG(x) x##UI64
+#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...)
+#else
+#define GOOGLE_LONGLONG(x) x##LL
+#define GOOGLE_ULONGLONG(x) x##ULL
+#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also.
+#endif
+
+static const int32 kint32max = 0x7FFFFFFF;
+static const int32 kint32min = -kint32min - 1;
+static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF);
+static const int64 kint64min = -kint64max - 1;
+static const uint32 kuint32max = 0xFFFFFFFFu;
+static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
+
+#undef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+// For functions we want to force inline.
+// Introduced in gcc 3.1.
+#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline))
+#else
+// Other compilers will have to figure it out for themselves.
+#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+#endif
+
+// ===================================================================
+// from google3/base/basictypes.h
+
+// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example.
+//
+// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error
+//
+// "warning: division by zero in ..."
+//
+// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
+// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
+//
+// The following comments are on the implementation details, and can
+// be ignored by the users.
+//
+// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
+// the array) and sizeof(*(arr)) (the # of bytes in one array
+// element). If the former is divisible by the latter, perhaps arr is
+// indeed an array, in which case the division result is the # of
+// elements in the array. Otherwise, arr cannot possibly be an array,
+// and we generate a compiler error to prevent the code from
+// compiling.
+//
+// Since the size of bool is implementation-defined, we need to cast
+// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
+// result has type size_t.
+//
+// This macro is not perfect as it wrongfully accepts certain
+// pointers, namely where the pointer size is divisible by the pointee
+// size. Since all our code has to go through a 32-bit compiler,
+// where a pointer is 4 bytes, this means all pointers to a type whose
+// size is 3 or greater than 4 will be (righteously) rejected.
+//
+// Kudos to Jorg Brown for this simple and elegant implementation.
+
+#undef GOOGLE_ARRAYSIZE
+#define GOOGLE_ARRAYSIZE(a) \
+ ((sizeof(a) / sizeof(*(a))) / \
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+namespace internal {
+
+// Use implicit_cast as a safe version of static_cast or const_cast
+// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
+// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
+// a const pointer to Foo).
+// When you use implicit_cast, the compiler checks that the cast is safe.
+// Such explicit implicit_casts are necessary in surprisingly many
+// situations where C++ demands an exact type match instead of an
+// argument type convertable to a target type.
+//
+// The From type can be inferred, so the preferred syntax for using
+// implicit_cast is the same as for static_cast etc.:
+//
+// implicit_cast<ToType>(expr)
+//
+// implicit_cast would have been part of the C++ standard library,
+// but the proposal was submitted too late. It will probably make
+// its way into the language in the future.
+template<typename To, typename From>
+inline To implicit_cast(From const &f) {
+ return f;
+}
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
+// always succeed. When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo? It
+// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
+// when you downcast, you should use this macro. In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not). In normal mode, we do the efficient static_cast<>
+// instead. Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+// This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+
+template<typename To, typename From> // use like this: down_cast<T*>(foo);
+inline To down_cast(From* f) { // so we only accept pointers
+ // Ensures that To is a sub-type of From *. This test is here only
+ // for compile-time type checking, and has no overhead in an
+ // optimized build at run-time, as it will be optimized away
+ // completely.
+ if (false) {
+ implicit_cast<From*, To>(0);
+ }
+
+ assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
+ return static_cast<To>(f);
+}
+
+} // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::implicit_cast;
+using internal::down_cast;
+
+// The COMPILE_ASSERT macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+// content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+namespace internal {
+
+template <bool>
+struct CompileAssert {
+};
+
+} // namespace internal
+
+#undef GOOGLE_COMPILE_ASSERT
+#define GOOGLE_COMPILE_ASSERT(expr, msg) \
+ typedef ::google::protobuf::internal::CompileAssert<(bool(expr))> \
+ msg[bool(expr) ? 1 : -1]
+
+// Implementation details of COMPILE_ASSERT:
+//
+// - COMPILE_ASSERT works by defining an array type that has -1
+// elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+// does not work, as gcc supports variable-length arrays whose sizes
+// are determined at run-time (this is gcc's extension and not part
+// of the C++ standard). As a result, gcc fails to reject the
+// following code with the simple definition:
+//
+// int foo;
+// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
+// // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+// expr is a compile-time constant. (Template arguments must be
+// determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
+//
+// CompileAssert<bool(expr)>
+//
+// instead, these compilers will refuse to compile
+//
+// COMPILE_ASSERT(5 > 0, some_message);
+//
+// (They seem to think the ">" in "5 > 0" marks the end of the
+// template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+// ((expr) ? 1 : -1).
+//
+// This is to avoid running into a bug in MS VC 7.1, which
+// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// ===================================================================
+// from google3/base/scoped_ptr.h
+
+namespace internal {
+
+// This is an implementation designed to match the anticipated future TR2
+// implementation of the scoped_ptr class, and its closely-related brethren,
+// scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
+
+template <class C> class scoped_ptr;
+template <class C> class scoped_array;
+
+// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
+// automatically deletes the pointer it holds (if any).
+// That is, scoped_ptr<T> owns the T object that it points to.
+// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
+//
+// The size of a scoped_ptr is small:
+// sizeof(scoped_ptr<C>) == sizeof(C*)
+template <class C>
+class scoped_ptr {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to intializing with NULL.
+ // There is no way to create an uninitialized scoped_ptr.
+ // The input parameter must be allocated with new.
+ explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_ptr() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete ptr_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != ptr_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete ptr_;
+ ptr_ = p;
+ }
+ }
+
+ // Accessors to get the owned object.
+ // operator* and operator-> will assert() if there is no current object.
+ C& operator*() const {
+ assert(ptr_ != NULL);
+ return *ptr_;
+ }
+ C* operator->() const {
+ assert(ptr_ != NULL);
+ return ptr_;
+ }
+ C* get() const { return ptr_; }
+
+ // Comparison operators.
+ // These return whether two scoped_ptr refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(C* p) const { return ptr_ == p; }
+ bool operator!=(C* p) const { return ptr_ != p; }
+
+ // Swap two scoped pointers.
+ void swap(scoped_ptr& p2) {
+ C* tmp = ptr_;
+ ptr_ = p2.ptr_;
+ p2.ptr_ = tmp;
+ }
+
+ // Release a pointer.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = ptr_;
+ ptr_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* ptr_;
+
+ // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
+ // make sense, and if C2 == C, it still doesn't make sense because you should
+ // never have the same object owned by two different scoped_ptrs.
+ template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
+
+ // Disallow evil constructors
+ scoped_ptr(const scoped_ptr&);
+ void operator=(const scoped_ptr&);
+};
+
+// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
+// with new [] and the destructor deletes objects with delete [].
+//
+// As with scoped_ptr<C>, a scoped_array<C> either points to an object
+// or is NULL. A scoped_array<C> owns the object that it points to.
+//
+// Size: sizeof(scoped_array<C>) == sizeof(C*)
+template <class C>
+class scoped_array {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to intializing with NULL.
+ // There is no way to create an uninitialized scoped_array.
+ // The input parameter must be allocated with new [].
+ explicit scoped_array(C* p = NULL) : array_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_array() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != array_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ array_ = p;
+ }
+ }
+
+ // Get one element of the current object.
+ // Will assert() if there is no current object, or index i is negative.
+ C& operator[](std::ptrdiff_t i) const {
+ assert(i >= 0);
+ assert(array_ != NULL);
+ return array_[i];
+ }
+
+ // Get a pointer to the zeroth element of the current object.
+ // If there is no current object, return NULL.
+ C* get() const {
+ return array_;
+ }
+
+ // Comparison operators.
+ // These return whether two scoped_array refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(C* p) const { return array_ == p; }
+ bool operator!=(C* p) const { return array_ != p; }
+
+ // Swap two scoped arrays.
+ void swap(scoped_array& p2) {
+ C* tmp = array_;
+ array_ = p2.array_;
+ p2.array_ = tmp;
+ }
+
+ // Release an array.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = array_;
+ array_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* array_;
+
+ // Forbid comparison of different scoped_array types.
+ template <class C2> bool operator==(scoped_array<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
+
+ // Disallow evil constructors
+ scoped_array(const scoped_array&);
+ void operator=(const scoped_array&);
+};
+
+} // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::scoped_ptr;
+using internal::scoped_array;
+
+// ===================================================================
+// emulates google3/base/logging.h
+
+enum LogLevel {
+ LOGLEVEL_INFO, // Informational. This is never actually used by
+ // libprotobuf.
+ LOGLEVEL_WARNING, // Warns about issues that, although not technically a
+ // problem now, could cause problems in the future. For
+ // example, a // warning will be printed when parsing a
+ // message that is near the message size limit.
+ LOGLEVEL_ERROR, // An error occurred which should never happen during
+ // normal use.
+ LOGLEVEL_FATAL, // An error occurred from which the library cannot
+ // recover. This usually indicates a programming error
+ // in the code which calls the library, especially when
+ // compiled in debug mode.
+
+#ifdef NDEBUG
+ LOGLEVEL_DFATAL = LOGLEVEL_ERROR
+#else
+ LOGLEVEL_DFATAL = LOGLEVEL_FATAL
+#endif
+};
+
+namespace internal {
+
+class LogFinisher;
+
+class LIBPROTOBUF_EXPORT LogMessage {
+ public:
+ LogMessage(LogLevel level, const char* filename, int line);
+ ~LogMessage();
+
+ LogMessage& operator<<(const string& value);
+ LogMessage& operator<<(const char* value);
+ LogMessage& operator<<(char value);
+ LogMessage& operator<<(int value);
+ LogMessage& operator<<(uint value);
+ LogMessage& operator<<(double value);
+
+ private:
+ friend class LogFinisher;
+ void Finish();
+
+ LogLevel level_;
+ const char* filename_;
+ int line_;
+ string message_;
+};
+
+// Used to make the entire "LOG(BLAH) << etc." expression have a void return
+// type and print a newline after each message.
+class LIBPROTOBUF_EXPORT LogFinisher {
+ public:
+ void operator=(LogMessage& other);
+};
+
+} // namespace internal
+
+// Undef everything in case we're being mixed with some other Google library
+// which already defined them itself. Presumably all Google libraries will
+// support the same syntax for these so it should not be a big deal if they
+// end up using our definitions instead.
+#undef GOOGLE_LOG
+#undef GOOGLE_LOG_IF
+
+#undef GOOGLE_CHECK
+#undef GOOGLE_CHECK_EQ
+#undef GOOGLE_CHECK_NE
+#undef GOOGLE_CHECK_LT
+#undef GOOGLE_CHECK_LE
+#undef GOOGLE_CHECK_GT
+#undef GOOGLE_CHECK_GE
+
+#undef GOOGLE_DLOG
+#undef GOOGLE_DCHECK
+#undef GOOGLE_DCHECK_EQ
+#undef GOOGLE_DCHECK_NE
+#undef GOOGLE_DCHECK_LT
+#undef GOOGLE_DCHECK_LE
+#undef GOOGLE_DCHECK_GT
+#undef GOOGLE_DCHECK_GE
+
+#define GOOGLE_LOG(LEVEL) \
+ ::google::protobuf::internal::LogFinisher() = \
+ ::google::protobuf::internal::LogMessage( \
+ ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
+#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
+ !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL)
+
+#define GOOGLE_CHECK(EXPRESSION) \
+ GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
+#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK(A == B)
+#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK(A != B)
+#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK(A < B)
+#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK(A <= B)
+#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK(A > B)
+#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK(A >= B)
+
+#ifdef NDEBUG
+
+#define GOOGLE_DLOG GOOGLE_LOG_IF(false, INFO)
+
+#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
+#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK(A == B)
+#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK(A != B)
+#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK(A < B)
+#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK(A <= B)
+#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK(A > B)
+#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK(A >= B)
+
+#else // NDEBUG
+
+#define GOOGLE_DLOG GOOGLE_LOG
+
+#define GOOGLE_DCHECK GOOGLE_CHECK
+#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ
+#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE
+#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT
+#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE
+#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT
+#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE
+
+#endif // !NDEBUG
+
+typedef void LogHandler(LogLevel level, const char* filename, int line,
+ const string& message);
+
+// The protobuf library sometimes writes warning and error messages to
+// stderr. These messages are primarily useful for developers, but may
+// also help end users figure out a problem. If you would prefer that
+// these messages be sent somewhere other than stderr, call SetLogHandler()
+// to set your own handler. This returns the old handler. Set the handler
+// to NULL to ignore log messages (but see also LogSilencer, below).
+//
+// Obviously, SetLogHandler is not thread-safe. You should only call it
+// at initialization time, and probably not from library code. If you
+// simply want to suppress log messages temporarily (e.g. because you
+// have some code that tends to trigger them frequently and you know
+// the warnings are not important to you), use the LogSilencer class
+// below.
+LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func);
+
+// Create a LogSilencer if you want to temporarily suppress all log
+// messages. As long as any LogSilencer objects exist, non-fatal
+// log messages will be discarded (the current LogHandler will *not*
+// be called). Constructing a LogSilencer is thread-safe. You may
+// accidentally suppress log messages occurring in another thread, but
+// since messages are generally for debugging purposes only, this isn't
+// a big deal. If you want to intercept log messages, use SetLogHandler().
+class LIBPROTOBUF_EXPORT LogSilencer {
+ public:
+ LogSilencer();
+ ~LogSilencer();
+};
+
+// ===================================================================
+// emulates google3/base/callback.h
+
+// Abstract interface for a callback. When calling an RPC, you must provide
+// a Closure to call when the procedure completes. See the Service interface
+// in service.h.
+//
+// To automatically construct a Closure which calls a particular function or
+// method with a particular set of parameters, use the NewCallback() function.
+// Example:
+// void FooDone(const FooResponse* response) {
+// ...
+// }
+//
+// void CallFoo() {
+// ...
+// // When done, call FooDone() and pass it a pointer to the response.
+// Closure* callback = NewCallback(&FooDone, response);
+// // Make the call.
+// service->Foo(controller, request, response, callback);
+// }
+//
+// Example that calls a method:
+// class Handler {
+// public:
+// ...
+//
+// void FooDone(const FooResponse* response) {
+// ...
+// }
+//
+// void CallFoo() {
+// ...
+// // When done, call FooDone() and pass it a pointer to the response.
+// Closure* callback = NewCallback(this, &Handler::FooDone, response);
+// // Make the call.
+// service->Foo(controller, request, response, callback);
+// }
+// };
+//
+// Currently NewCallback() supports binding zero, one, or two arguments.
+//
+// Callbacks created with NewCallback() automatically delete themselves when
+// executed. They should be used when a callback is to be called exactly
+// once (usually the case with RPC callbacks). If a callback may be called
+// a different number of times (including zero), create it with
+// NewPermanentCallback() instead. You are then responsible for deleting the
+// callback (using the "delete" keyword as normal).
+//
+// Note that NewCallback() is a bit touchy regarding argument types. Generally,
+// the values you provide for the parameter bindings must exactly match the
+// types accepted by the callback function. For example:
+// void Foo(string s);
+// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string
+// NewCallback(&Foo, string("foo")); // WORKS
+// Also note that the arguments cannot be references:
+// void Foo(const string& s);
+// string my_str;
+// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes.
+// However, correctly-typed pointers will work just fine.
+class LIBPROTOBUF_EXPORT Closure {
+ public:
+ Closure() {}
+ virtual ~Closure();
+
+ virtual void Run() = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
+};
+
+namespace internal {
+
+class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure {
+ public:
+ typedef void (*FunctionType)();
+
+ FunctionClosure0(FunctionType function, bool self_deleting)
+ : function_(function), self_deleting_(self_deleting) {}
+ ~FunctionClosure0();
+
+ void Run() {
+ function_();
+ if (self_deleting_) delete this;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+};
+
+template <typename Class>
+class MethodClosure0 : public Closure {
+ public:
+ typedef void (Class::*MethodType)();
+
+ MethodClosure0(Class* object, MethodType method, bool self_deleting)
+ : object_(object), method_(method), self_deleting_(self_deleting) {}
+ ~MethodClosure0() {}
+
+ void Run() {
+ (object_->*method_)();
+ if (self_deleting_) delete this;
+ }
+
+ private:
+ Class* object_;
+ MethodType method_;
+ bool self_deleting_;
+};
+
+template <typename Arg1>
+class FunctionClosure1 : public Closure {
+ public:
+ typedef void (*FunctionType)(Arg1 arg1);
+
+ FunctionClosure1(FunctionType function, bool self_deleting,
+ Arg1 arg1)
+ : function_(function), self_deleting_(self_deleting),
+ arg1_(arg1) {}
+ ~FunctionClosure1() {}
+
+ void Run() {
+ function_(arg1_);
+ if (self_deleting_) delete this;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+ Arg1 arg1_;
+};
+
+template <typename Class, typename Arg1>
+class MethodClosure1 : public Closure {
+ public:
+ typedef void (Class::*MethodType)(Arg1 arg1);
+
+ MethodClosure1(Class* object, MethodType method, bool self_deleting,
+ Arg1 arg1)
+ : object_(object), method_(method), self_deleting_(self_deleting),
+ arg1_(arg1) {}
+ ~MethodClosure1() {}
+
+ void Run() {
+ (object_->*method_)(arg1_);
+ if (self_deleting_) delete this;
+ }
+
+ private:
+ Class* object_;
+ MethodType method_;
+ bool self_deleting_;
+ Arg1 arg1_;
+};
+
+template <typename Arg1, typename Arg2>
+class FunctionClosure2 : public Closure {
+ public:
+ typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2);
+
+ FunctionClosure2(FunctionType function, bool self_deleting,
+ Arg1 arg1, Arg2 arg2)
+ : function_(function), self_deleting_(self_deleting),
+ arg1_(arg1), arg2_(arg2) {}
+ ~FunctionClosure2() {}
+
+ void Run() {
+ function_(arg1_, arg2_);
+ if (self_deleting_) delete this;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+};
+
+template <typename Class, typename Arg1, typename Arg2>
+class MethodClosure2 : public Closure {
+ public:
+ typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2);
+
+ MethodClosure2(Class* object, MethodType method, bool self_deleting,
+ Arg1 arg1, Arg2 arg2)
+ : object_(object), method_(method), self_deleting_(self_deleting),
+ arg1_(arg1), arg2_(arg2) {}
+ ~MethodClosure2() {}
+
+ void Run() {
+ (object_->*method_)(arg1_, arg2_);
+ if (self_deleting_) delete this;
+ }
+
+ private:
+ Class* object_;
+ MethodType method_;
+ bool self_deleting_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+};
+
+} // namespace internal
+
+// See Closure.
+inline Closure* NewCallback(void (*function)()) {
+ return new internal::FunctionClosure0(function, true);
+}
+
+// See Closure.
+inline Closure* NewPermanentCallback(void (*function)()) {
+ return new internal::FunctionClosure0(function, false);
+}
+
+// See Closure.
+template <typename Class>
+inline Closure* NewCallback(Class* object, void (Class::*method)()) {
+ return new internal::MethodClosure0<Class>(object, method, true);
+}
+
+// See Closure.
+template <typename Class>
+inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) {
+ return new internal::MethodClosure0<Class>(object, method, false);
+}
+
+// See Closure.
+template <typename Arg1>
+inline Closure* NewCallback(void (*function)(Arg1),
+ Arg1 arg1) {
+ return new internal::FunctionClosure1<Arg1>(function, true, arg1);
+}
+
+// See Closure.
+template <typename Arg1>
+inline Closure* NewPermanentCallback(void (*function)(Arg1),
+ Arg1 arg1) {
+ return new internal::FunctionClosure1<Arg1>(function, false, arg1);
+}
+
+// See Closure.
+template <typename Class, typename Arg1>
+inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1),
+ Arg1 arg1) {
+ return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1);
+}
+
+// See Closure.
+template <typename Class, typename Arg1>
+inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1),
+ Arg1 arg1) {
+ return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1);
+}
+
+// See Closure.
+template <typename Arg1, typename Arg2>
+inline Closure* NewCallback(void (*function)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::FunctionClosure2<Arg1, Arg2>(
+ function, true, arg1, arg2);
+}
+
+// See Closure.
+template <typename Arg1, typename Arg2>
+inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::FunctionClosure2<Arg1, Arg2>(
+ function, false, arg1, arg2);
+}
+
+// See Closure.
+template <typename Class, typename Arg1, typename Arg2>
+inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::MethodClosure2<Class, Arg1, Arg2>(
+ object, method, true, arg1, arg2);
+}
+
+// See Closure.
+template <typename Class, typename Arg1, typename Arg2>
+inline Closure* NewPermanentCallback(
+ Class* object, void (Class::*method)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::MethodClosure2<Class, Arg1, Arg2>(
+ object, method, false, arg1, arg2);
+}
+
+// A function which does nothing. Useful for creating no-op callbacks, e.g.:
+// Closure* nothing = NewCallback(&DoNothing);
+void LIBPROTOBUF_EXPORT DoNothing();
+
+// ===================================================================
+// emulates google3/base/mutex.h
+
+namespace internal {
+
+// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T
+// may hold a mutex at a given time. If T attempts to Lock() the same Mutex
+// while holding it, T will deadlock.
+class LIBPROTOBUF_EXPORT Mutex {
+ public:
+ // Create a Mutex that is not held by anybody.
+ Mutex();
+
+ // Destructor
+ ~Mutex();
+
+ // Block if necessary until this Mutex is free, then acquire it exclusively.
+ void Lock();
+
+ // Release this Mutex. Caller must hold it exclusively.
+ void Unlock();
+
+ // Crash if this Mutex is not held exclusively by this thread.
+ // May fail to crash when it should; will never crash when it should not.
+ void AssertHeld();
+
+ private:
+ struct Internal;
+ Internal* mInternal;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
+};
+
+// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
+class LIBPROTOBUF_EXPORT MutexLock {
+ public:
+ explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
+ ~MutexLock() { this->mu_->Unlock(); }
+ private:
+ Mutex *const mu_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
+};
+
+// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
+class LIBPROTOBUF_EXPORT MutexLockMaybe {
+ public:
+ explicit MutexLockMaybe(Mutex *mu) :
+ mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
+ ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } }
+ private:
+ Mutex *const mu_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
+};
+
+} // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::Mutex;
+using internal::MutexLock;
+using internal::MutexLockMaybe;
+
+// ===================================================================
+// from google3/base/type_traits.h
+
+namespace internal {
+
+// Specified by TR1 [4.7.4] Pointer modifications.
+template<typename T> struct remove_pointer { typedef T type; };
+template<typename T> struct remove_pointer<T*> { typedef T type; };
+template<typename T> struct remove_pointer<T* const> { typedef T type; };
+template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
+template<typename T> struct remove_pointer<T* const volatile> {
+ typedef T type; };
+
+} // namespace internal
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMMON_H__
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
new file mode 100644
index 00000000..f12422be
--- /dev/null
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -0,0 +1,319 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+#include "config.h"
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// TODO(kenton): More tests.
+
+#ifdef PACKAGE_VERSION // only defined when using automake, not MSVC
+
+TEST(VersionTest, VersionMatchesConfig) {
+ // Verify that the version string specified in config.h matches the one
+ // in common.h. The config.h version is a string which may have a suffix
+ // like "beta", so we remove that.
+ string version = PACKAGE_VERSION;
+ int pos = version.size();
+ while (pos > 0 && !ascii_isdigit(version[pos-1])) {
+ --pos;
+ }
+ version.erase(pos);
+
+ EXPECT_EQ(version, internal::VersionString(GOOGLE_PROTOBUF_VERSION));
+}
+
+#endif // PACKAGE_VERSION
+
+vector<string> captured_messages_;
+
+void CaptureLog(LogLevel level, const char* filename, int line,
+ const string& message) {
+ captured_messages_.push_back(
+ strings::Substitute("$0 $1:$2: $3",
+ implicit_cast<int>(level), filename, line, message));
+}
+
+TEST(LoggingTest, DefaultLogging) {
+ CaptureTestStderr();
+ int line = __LINE__;
+ GOOGLE_LOG(INFO ) << "A message.";
+ GOOGLE_LOG(WARNING) << "A warning.";
+ GOOGLE_LOG(ERROR ) << "An error.";
+
+ string text = GetCapturedTestStderr();
+ EXPECT_EQ(
+ "libprotobuf INFO "__FILE__":" + SimpleItoa(line + 1) + "] A message.\n"
+ "libprotobuf WARNING "__FILE__":" + SimpleItoa(line + 2) + "] A warning.\n"
+ "libprotobuf ERROR "__FILE__":" + SimpleItoa(line + 3) + "] An error.\n",
+ text);
+}
+
+TEST(LoggingTest, NullLogging) {
+ LogHandler* old_handler = SetLogHandler(NULL);
+
+ CaptureTestStderr();
+ GOOGLE_LOG(INFO ) << "A message.";
+ GOOGLE_LOG(WARNING) << "A warning.";
+ GOOGLE_LOG(ERROR ) << "An error.";
+
+ EXPECT_TRUE(SetLogHandler(old_handler) == NULL);
+
+ string text = GetCapturedTestStderr();
+ EXPECT_EQ("", text);
+}
+
+TEST(LoggingTest, CaptureLogging) {
+ captured_messages_.clear();
+
+ LogHandler* old_handler = SetLogHandler(&CaptureLog);
+
+ int start_line = __LINE__;
+ GOOGLE_LOG(ERROR) << "An error.";
+ GOOGLE_LOG(WARNING) << "A warning.";
+
+ EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog);
+
+ ASSERT_EQ(2, captured_messages_.size());
+ EXPECT_EQ(
+ "2 "__FILE__":" + SimpleItoa(start_line + 1) + ": An error.",
+ captured_messages_[0]);
+ EXPECT_EQ(
+ "1 "__FILE__":" + SimpleItoa(start_line + 2) + ": A warning.",
+ captured_messages_[1]);
+}
+
+TEST(LoggingTest, SilenceLogging) {
+ captured_messages_.clear();
+
+ LogHandler* old_handler = SetLogHandler(&CaptureLog);
+
+ int line1 = __LINE__; GOOGLE_LOG(INFO) << "Visible1";
+ LogSilencer* silencer1 = new LogSilencer;
+ GOOGLE_LOG(INFO) << "Not visible.";
+ LogSilencer* silencer2 = new LogSilencer;
+ GOOGLE_LOG(INFO) << "Not visible.";
+ delete silencer1;
+ GOOGLE_LOG(INFO) << "Not visible.";
+ delete silencer2;
+ int line2 = __LINE__; GOOGLE_LOG(INFO) << "Visible2";
+
+ EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog);
+
+ ASSERT_EQ(2, captured_messages_.size());
+ EXPECT_EQ(
+ "0 "__FILE__":" + SimpleItoa(line1) + ": Visible1",
+ captured_messages_[0]);
+ EXPECT_EQ(
+ "0 "__FILE__":" + SimpleItoa(line2) + ": Visible2",
+ captured_messages_[1]);
+}
+
+class ClosureTest : public testing::Test {
+ public:
+ void SetA123Method() { a_ = 123; }
+ static void SetA123Function() { current_instance_->a_ = 123; }
+
+ void SetAMethod(int a) { a_ = a; }
+ void SetCMethod(string c) { c_ = c; }
+
+ static void SetAFunction(int a) { current_instance_->a_ = a; }
+ static void SetCFunction(string c) { current_instance_->c_ = c; }
+
+ void SetABMethod(int a, const char* b) { a_ = a; b_ = b; }
+ static void SetABFunction(int a, const char* b) {
+ current_instance_->a_ = a;
+ current_instance_->b_ = b;
+ }
+
+ virtual void SetUp() {
+ current_instance_ = this;
+ a_ = 0;
+ b_ = NULL;
+ c_.clear();
+ }
+
+ int a_;
+ const char* b_;
+ string c_;
+
+ static ClosureTest* current_instance_;
+};
+
+ClosureTest* ClosureTest::current_instance_ = NULL;
+
+TEST_F(ClosureTest, TestClosureFunction0) {
+ Closure* closure = NewCallback(&SetA123Function);
+ EXPECT_NE(123, a_);
+ closure->Run();
+ EXPECT_EQ(123, a_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod0) {
+ Closure* closure = NewCallback(current_instance_,
+ &ClosureTest::SetA123Method);
+ EXPECT_NE(123, a_);
+ closure->Run();
+ EXPECT_EQ(123, a_);
+}
+
+TEST_F(ClosureTest, TestClosureFunction1) {
+ Closure* closure = NewCallback(&SetAFunction, 456);
+ EXPECT_NE(456, a_);
+ closure->Run();
+ EXPECT_EQ(456, a_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod1) {
+ Closure* closure = NewCallback(current_instance_,
+ &ClosureTest::SetAMethod, 456);
+ EXPECT_NE(456, a_);
+ closure->Run();
+ EXPECT_EQ(456, a_);
+}
+
+TEST_F(ClosureTest, TestClosureFunction1String) {
+ Closure* closure = NewCallback(&SetCFunction, string("test"));
+ EXPECT_NE("test", c_);
+ closure->Run();
+ EXPECT_EQ("test", c_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod1String) {
+ Closure* closure = NewCallback(current_instance_,
+ &ClosureTest::SetCMethod, string("test"));
+ EXPECT_NE("test", c_);
+ closure->Run();
+ EXPECT_EQ("test", c_);
+}
+
+TEST_F(ClosureTest, TestClosureFunction2) {
+ const char* cstr = "hello";
+ Closure* closure = NewCallback(&SetABFunction, 789, cstr);
+ EXPECT_NE(789, a_);
+ EXPECT_NE(cstr, b_);
+ closure->Run();
+ EXPECT_EQ(789, a_);
+ EXPECT_EQ(cstr, b_);
+}
+
+TEST_F(ClosureTest, TestClosureMethod2) {
+ const char* cstr = "hello";
+ Closure* closure = NewCallback(current_instance_,
+ &ClosureTest::SetABMethod, 789, cstr);
+ EXPECT_NE(789, a_);
+ EXPECT_NE(cstr, b_);
+ closure->Run();
+ EXPECT_EQ(789, a_);
+ EXPECT_EQ(cstr, b_);
+}
+
+// Repeat all of the above with NewPermanentCallback()
+
+TEST_F(ClosureTest, TestPermanentClosureFunction0) {
+ Closure* closure = NewPermanentCallback(&SetA123Function);
+ EXPECT_NE(123, a_);
+ closure->Run();
+ EXPECT_EQ(123, a_);
+ a_ = 0;
+ closure->Run();
+ EXPECT_EQ(123, a_);
+ delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureMethod0) {
+ Closure* closure = NewPermanentCallback(current_instance_,
+ &ClosureTest::SetA123Method);
+ EXPECT_NE(123, a_);
+ closure->Run();
+ EXPECT_EQ(123, a_);
+ a_ = 0;
+ closure->Run();
+ EXPECT_EQ(123, a_);
+ delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureFunction1) {
+ Closure* closure = NewPermanentCallback(&SetAFunction, 456);
+ EXPECT_NE(456, a_);
+ closure->Run();
+ EXPECT_EQ(456, a_);
+ a_ = 0;
+ closure->Run();
+ EXPECT_EQ(456, a_);
+ delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureMethod1) {
+ Closure* closure = NewPermanentCallback(current_instance_,
+ &ClosureTest::SetAMethod, 456);
+ EXPECT_NE(456, a_);
+ closure->Run();
+ EXPECT_EQ(456, a_);
+ a_ = 0;
+ closure->Run();
+ EXPECT_EQ(456, a_);
+ delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureFunction2) {
+ const char* cstr = "hello";
+ Closure* closure = NewPermanentCallback(&SetABFunction, 789, cstr);
+ EXPECT_NE(789, a_);
+ EXPECT_NE(cstr, b_);
+ closure->Run();
+ EXPECT_EQ(789, a_);
+ EXPECT_EQ(cstr, b_);
+ a_ = 0;
+ b_ = NULL;
+ closure->Run();
+ EXPECT_EQ(789, a_);
+ EXPECT_EQ(cstr, b_);
+ delete closure;
+}
+
+TEST_F(ClosureTest, TestPermanentClosureMethod2) {
+ const char* cstr = "hello";
+ Closure* closure = NewPermanentCallback(current_instance_,
+ &ClosureTest::SetABMethod, 789, cstr);
+ EXPECT_NE(789, a_);
+ EXPECT_NE(cstr, b_);
+ closure->Run();
+ EXPECT_EQ(789, a_);
+ EXPECT_EQ(cstr, b_);
+ a_ = 0;
+ b_ = NULL;
+ closure->Run();
+ EXPECT_EQ(789, a_);
+ EXPECT_EQ(cstr, b_);
+ delete closure;
+}
+
+} // anonymous namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/hash.cc b/src/google/protobuf/stubs/hash.cc
new file mode 100644
index 00000000..43fb9d73
--- /dev/null
+++ b/src/google/protobuf/stubs/hash.cc
@@ -0,0 +1,27 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/stubs/hash.h>
+
+namespace google {
+namespace protobuf {
+
+// Nothing needed here right now.
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
new file mode 100644
index 00000000..a62b3f6e
--- /dev/null
+++ b/src/google/protobuf/stubs/hash.h
@@ -0,0 +1,123 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Deals with the fact that hash_map is not defined everywhere.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
+#define GOOGLE_PROTOBUF_STUBS_HASH_H__
+
+#include <string.h>
+#include <google/protobuf/stubs/common.h>
+#include "config.h"
+
+#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
+#include HASH_MAP_H
+#include HASH_SET_H
+#else
+// TODO(kenton): Deal with non-existence of hash_map somehow. Maybe emulate
+// it with map?
+#error "Your STL implementation lacks hash_map and/or hash_set."
+#endif
+
+namespace google {
+namespace protobuf {
+
+#ifdef _MSC_VER
+
+template <typename Key>
+struct hash : public HASH_NAMESPACE::hash_compare<Key> {
+};
+
+// MSVC's hash_compare<const char*> hashes based on the string contents but
+// compares based on the string pointer. WTF?
+class CstringLess {
+ public:
+ inline bool operator()(const char* a, const char* b) const {
+ return strcmp(a, b) < 0;
+ }
+};
+
+template <>
+struct hash<const char*>
+ : public HASH_NAMESPACE::hash_compare<const char*, CstringLess> {
+};
+
+template <typename Key, typename Data,
+ typename HashFcn = hash<Key>,
+ typename EqualKey = int >
+class hash_map : public HASH_NAMESPACE::hash_map<
+ Key, Data, HashFcn> {
+};
+
+template <typename Key,
+ typename HashFcn = hash<Key>,
+ typename EqualKey = int >
+class hash_set : public HASH_NAMESPACE::hash_set<
+ Key, HashFcn> {
+};
+
+#else
+
+template <typename Key>
+struct hash : public HASH_NAMESPACE::hash<Key> {
+};
+
+template <typename Key>
+struct hash<const Key*> {
+ inline size_t operator()(const Key* key) const {
+ return reinterpret_cast<size_t>(key);
+ }
+};
+
+template <>
+struct hash<const char*> : public HASH_NAMESPACE::hash<const char*> {
+};
+
+template <typename Key, typename Data,
+ typename HashFcn = hash<Key>,
+ typename EqualKey = std::equal_to<Key> >
+class hash_map : public HASH_NAMESPACE::hash_map<
+ Key, Data, HashFcn, EqualKey> {
+};
+
+template <typename Key,
+ typename HashFcn = hash<Key>,
+ typename EqualKey = std::equal_to<Key> >
+class hash_set : public HASH_NAMESPACE::hash_set<
+ Key, HashFcn, EqualKey> {
+};
+
+#endif
+
+template <>
+struct hash<string> {
+ inline size_t operator()(const string& key) const {
+ return hash<const char*>()(key.c_str());
+ }
+
+ static const size_t bucket_size = 4;
+ static const size_t min_buckets = 8;
+ inline size_t operator()(const string& a, const string& b) const {
+ return a < b;
+ }
+};
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__
diff --git a/src/google/protobuf/stubs/map-util.cc b/src/google/protobuf/stubs/map-util.cc
new file mode 100644
index 00000000..af05af30
--- /dev/null
+++ b/src/google/protobuf/stubs/map-util.cc
@@ -0,0 +1,28 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// from google3/util/gtl/map-util.cc
+// Author: Anton Carver
+
+#include <google/protobuf/stubs/map-util.h>
+
+namespace google {
+namespace protobuf {
+
+// Template module. Nothing to see here.
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/map-util.h b/src/google/protobuf/stubs/map-util.h
new file mode 100644
index 00000000..ee8073fe
--- /dev/null
+++ b/src/google/protobuf/stubs/map-util.h
@@ -0,0 +1,90 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// from google3/util/gtl/map-util.h
+// Author: Anton Carver
+
+#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
+#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// Perform a lookup in a map or hash_map.
+// If the key is present a const pointer to the associated value is returned,
+// otherwise a NULL pointer is returned.
+template <class Collection>
+const typename Collection::value_type::second_type*
+FindOrNull(const Collection& collection,
+ const typename Collection::value_type::first_type& key) {
+ typename Collection::const_iterator it = collection.find(key);
+ if (it == collection.end()) {
+ return 0;
+ }
+ return &it->second;
+}
+
+// Perform a lookup in a map or hash_map whose values are pointers.
+// If the key is present a const pointer to the associated value is returned,
+// otherwise a NULL pointer is returned.
+// This function does not distinguish between a missing key and a key mapped
+// to a NULL value.
+template <class Collection>
+const typename Collection::value_type::second_type
+FindPtrOrNull(const Collection& collection,
+ const typename Collection::value_type::first_type& key) {
+ typename Collection::const_iterator it = collection.find(key);
+ if (it == collection.end()) {
+ return 0;
+ }
+ return it->second;
+}
+
+// Change the value associated with a particular key in a map or hash_map.
+// If the key is not present in the map the key and value are inserted,
+// otherwise the value is updated to be a copy of the value provided.
+// True indicates that an insert took place, false indicates an update.
+template <class Collection, class Key, class Value>
+bool InsertOrUpdate(Collection * const collection,
+ const Key& key, const Value& value) {
+ pair<typename Collection::iterator, bool> ret =
+ collection->insert(typename Collection::value_type(key, value));
+ if (!ret.second) {
+ // update
+ ret.first->second = value;
+ return false;
+ }
+ return true;
+}
+
+// Insert a new key and value into a map or hash_map.
+// If the key is not present in the map the key and value are
+// inserted, otherwise nothing happens. True indicates that an insert
+// took place, false indicates the key was already present.
+template <class Collection, class Key, class Value>
+bool InsertIfNotPresent(Collection * const collection,
+ const Key& key, const Value& value) {
+ pair<typename Collection::iterator, bool> ret =
+ collection->insert(typename Collection::value_type(key, value));
+ return ret.second;
+}
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
diff --git a/src/google/protobuf/stubs/stl_util-inl.cc b/src/google/protobuf/stubs/stl_util-inl.cc
new file mode 100644
index 00000000..445c646e
--- /dev/null
+++ b/src/google/protobuf/stubs/stl_util-inl.cc
@@ -0,0 +1,27 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// from google3/util/gtl/stl_util-inl.cc
+
+#include <google/protobuf/stubs/stl_util-inl.h>
+
+namespace google {
+namespace protobuf {
+
+// Template module. Nothing to see here.
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/stl_util-inl.h b/src/google/protobuf/stubs/stl_util-inl.h
new file mode 100644
index 00000000..db079a77
--- /dev/null
+++ b/src/google/protobuf/stubs/stl_util-inl.h
@@ -0,0 +1,107 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// from google3/util/gtl/stl_util-inl.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_INL_H__
+#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_INL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// STLDeleteContainerPointers()
+// For a range within a container of pointers, calls delete
+// (non-array version) on these pointers.
+// NOTE: for these three functions, we could just implement a DeleteObject
+// functor and then call for_each() on the range and functor, but this
+// requires us to pull in all of algorithm.h, which seems expensive.
+// For hash_[multi]set, it is important that this deletes behind the iterator
+// because the hash_set may call the hash function on the iterator when it is
+// advanced, which could result in the hash function trying to deference a
+// stale pointer.
+template <class ForwardIterator>
+void STLDeleteContainerPointers(ForwardIterator begin,
+ ForwardIterator end) {
+ while (begin != end) {
+ ForwardIterator temp = begin;
+ ++begin;
+ delete *temp;
+ }
+}
+
+// Inside Google, this function implements a horrible, disgusting hack in which
+// we reach into the string's private implementation and resize it without
+// initializing the new bytes. In some cases doing this can significantly
+// improve performance. However, since it's totally non-portable it has no
+// place in open source code. Feel free to fill this function in with your
+// own disgusting hack if you want the perf boost.
+inline void STLStringResizeUninitialized(string* s, size_t new_size) {
+ s->resize(new_size);
+}
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
+// proposes this as the method. According to Matt Austern, this should
+// already work on all current implementations.
+inline char* string_as_array(string* str) {
+ // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
+ return str->empty() ? NULL : &*str->begin();
+}
+
+// STLDeleteElements() deletes all the elements in an STL container and clears
+// the container. This function is suitable for use with a vector, set,
+// hash_set, or any other STL container which defines sensible begin(), end(),
+// and clear() methods.
+//
+// If container is NULL, this function is a no-op.
+//
+// As an alternative to calling STLDeleteElements() directly, consider
+// ElementDeleter (defined below), which ensures that your container's elements
+// are deleted when the ElementDeleter goes out of scope.
+template <class T>
+void STLDeleteElements(T *container) {
+ if (!container) return;
+ STLDeleteContainerPointers(container->begin(), container->end());
+ container->clear();
+}
+
+// Given an STL container consisting of (key, value) pairs, STLDeleteValues
+// deletes all the "value" components and clears the container. Does nothing
+// in the case it's given a NULL pointer.
+
+template <class T>
+void STLDeleteValues(T *v) {
+ if (!v) return;
+ for (typename T::iterator i = v->begin(); i != v->end(); ++i) {
+ delete i->second;
+ }
+ v->clear();
+}
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_INL_H__
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
new file mode 100644
index 00000000..07caaf76
--- /dev/null
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -0,0 +1,1121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// from google3/strings/strutil.cc
+
+#include <google/protobuf/stubs/strutil.h>
+#include <errno.h>
+#include <float.h> // FLT_DIG and DBL_DIG
+#include <limits>
+#include <limits.h>
+
+#ifdef _WIN32
+// MSVC has only _snprintf, not snprintf.
+//
+// MinGW has both snprintf and _snprintf, but they appear to be different
+// functions. The former is buggy. When invoked like so:
+// char buffer[32];
+// snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f);
+// it prints "1.23000e+10". This is plainly wrong: %g should never print
+// trailing zeros after the decimal point. For some reason this bug only
+// occurs with some input values, not all. In any case, _snprintf does the
+// right thing, so we use it.
+#define snprintf _snprintf
+#endif
+
+namespace google {
+namespace protobuf {
+
+inline bool IsNaN(double value) {
+ // NaN is never equal to anything, even itself.
+ return value != value;
+}
+
+// The definitions of these in ctype.h change based on locale. Since our
+// string manipulation is all in relation to the protocol buffer and C++
+// languages, we always want to use the C locale. So, we re-define these
+// exactly as we want them.
+static bool isxdigit(char c) {
+ return ('0' <= c && c <= '9') ||
+ ('a' <= c && c <= 'f') ||
+ ('A' <= c && c <= 'F');
+}
+
+static bool isprint(char c) {
+ return c >= 0x20 && c <= 0x7E;
+}
+
+// ----------------------------------------------------------------------
+// StripString
+// Replaces any occurrence of the character 'remove' (or the characters
+// in 'remove') with the character 'replacewith'.
+// ----------------------------------------------------------------------
+void StripString(string* s, const char* remove, char replacewith) {
+ const char * str_start = s->c_str();
+ const char * str = str_start;
+ for (str = strpbrk(str, remove);
+ str != NULL;
+ str = strpbrk(str + 1, remove)) {
+ (*s)[str - str_start] = replacewith;
+ }
+}
+
+// ----------------------------------------------------------------------
+// StringReplace()
+// Replace the "old" pattern with the "new" pattern in a string,
+// and append the result to "res". If replace_all is false,
+// it only replaces the first instance of "old."
+// ----------------------------------------------------------------------
+
+void StringReplace(const string& s, const string& oldsub,
+ const string& newsub, bool replace_all,
+ string* res) {
+ if (oldsub.empty()) {
+ res->append(s); // if empty, append the given string.
+ return;
+ }
+
+ string::size_type start_pos = 0;
+ string::size_type pos;
+ do {
+ pos = s.find(oldsub, start_pos);
+ if (pos == string::npos) {
+ break;
+ }
+ res->append(s, start_pos, pos - start_pos);
+ res->append(newsub);
+ start_pos = pos + oldsub.size(); // start searching again after the "old"
+ } while (replace_all);
+ res->append(s, start_pos, s.length() - start_pos);
+}
+
+// ----------------------------------------------------------------------
+// StringReplace()
+// Give me a string and two patterns "old" and "new", and I replace
+// the first instance of "old" in the string with "new", if it
+// exists. If "global" is true; call this repeatedly until it
+// fails. RETURN a new string, regardless of whether the replacement
+// happened or not.
+// ----------------------------------------------------------------------
+
+string StringReplace(const string& s, const string& oldsub,
+ const string& newsub, bool replace_all) {
+ string ret;
+ StringReplace(s, oldsub, newsub, replace_all, &ret);
+ return ret;
+}
+
+// ----------------------------------------------------------------------
+// SplitStringUsing()
+// Split a string using a character delimiter. Append the components
+// to 'result'.
+//
+// Note: For multi-character delimiters, this routine will split on *ANY* of
+// the characters in the string, not the entire string as a single delimiter.
+// ----------------------------------------------------------------------
+template <typename ITR>
+static inline
+void SplitStringToIteratorUsing(const string& full,
+ const char* delim,
+ ITR& result) {
+ // Optimize the common case where delim is a single character.
+ if (delim[0] != '\0' && delim[1] == '\0') {
+ char c = delim[0];
+ const char* p = full.data();
+ const char* end = p + full.size();
+ while (p != end) {
+ if (*p == c) {
+ ++p;
+ } else {
+ const char* start = p;
+ while (++p != end && *p != c);
+ *result++ = string(start, p - start);
+ }
+ }
+ return;
+ }
+
+ string::size_type begin_index, end_index;
+ begin_index = full.find_first_not_of(delim);
+ while (begin_index != string::npos) {
+ end_index = full.find_first_of(delim, begin_index);
+ if (end_index == string::npos) {
+ *result++ = full.substr(begin_index);
+ return;
+ }
+ *result++ = full.substr(begin_index, (end_index - begin_index));
+ begin_index = full.find_first_not_of(delim, end_index);
+ }
+}
+
+void SplitStringUsing(const string& full,
+ const char* delim,
+ vector<string>* result) {
+ back_insert_iterator< vector<string> > it(*result);
+ SplitStringToIteratorUsing(full, delim, it);
+}
+
+// ----------------------------------------------------------------------
+// JoinStrings()
+// This merges a vector of string components with delim inserted
+// as separaters between components.
+//
+// ----------------------------------------------------------------------
+template <class ITERATOR>
+static void JoinStringsIterator(const ITERATOR& start,
+ const ITERATOR& end,
+ const char* delim,
+ string* result) {
+ GOOGLE_CHECK(result != NULL);
+ result->clear();
+ int delim_length = strlen(delim);
+
+ // Precompute resulting length so we can reserve() memory in one shot.
+ int length = 0;
+ for (ITERATOR iter = start; iter != end; ++iter) {
+ if (iter != start) {
+ length += delim_length;
+ }
+ length += iter->size();
+ }
+ result->reserve(length);
+
+ // Now combine everything.
+ for (ITERATOR iter = start; iter != end; ++iter) {
+ if (iter != start) {
+ result->append(delim, delim_length);
+ }
+ result->append(iter->data(), iter->size());
+ }
+}
+
+void JoinStrings(const vector<string>& components,
+ const char* delim,
+ string * result) {
+ JoinStringsIterator(components.begin(), components.end(), delim, result);
+}
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeSequences()
+// This does all the unescaping that C does: \ooo, \r, \n, etc
+// Returns length of resulting string.
+// The implementation of \x parses any positive number of hex digits,
+// but it is an error if the value requires more than 8 bits, and the
+// result is truncated to 8 bits.
+//
+// The second call stores its errors in a supplied string vector.
+// If the string vector pointer is NULL, it reports the errors with LOG().
+// ----------------------------------------------------------------------
+
+#define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7'))
+
+inline int hex_digit_to_int(char c) {
+ /* Assume ASCII. */
+ assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61);
+ assert(isxdigit(c));
+ int x = static_cast<unsigned char>(c);
+ if (x > '9') {
+ x += 9;
+ }
+ return x & 0xf;
+}
+
+// Protocol buffers doesn't ever care about errors, but I don't want to remove
+// the code.
+#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false)
+
+int UnescapeCEscapeSequences(const char* source, char* dest) {
+ return UnescapeCEscapeSequences(source, dest, NULL);
+}
+
+int UnescapeCEscapeSequences(const char* source, char* dest,
+ vector<string> *errors) {
+ GOOGLE_DCHECK(errors == NULL) << "Error reporting not implemented.";
+
+ char* d = dest;
+ const char* p = source;
+
+ // Small optimization for case where source = dest and there's no escaping
+ while ( p == d && *p != '\0' && *p != '\\' )
+ p++, d++;
+
+ while (*p != '\0') {
+ if (*p != '\\') {
+ *d++ = *p++;
+ } else {
+ switch ( *++p ) { // skip past the '\\'
+ case '\0':
+ LOG_STRING(ERROR, errors) << "String cannot end with \\";
+ *d = '\0';
+ return d - dest; // we're done with p
+ case 'a': *d++ = '\a'; break;
+ case 'b': *d++ = '\b'; break;
+ case 'f': *d++ = '\f'; break;
+ case 'n': *d++ = '\n'; break;
+ case 'r': *d++ = '\r'; break;
+ case 't': *d++ = '\t'; break;
+ case 'v': *d++ = '\v'; break;
+ case '\\': *d++ = '\\'; break;
+ case '?': *d++ = '\?'; break; // \? Who knew?
+ case '\'': *d++ = '\''; break;
+ case '"': *d++ = '\"'; break;
+ case '0': case '1': case '2': case '3': // octal digit: 1 to 3 digits
+ case '4': case '5': case '6': case '7': {
+ char ch = *p - '0';
+ if ( IS_OCTAL_DIGIT(p[1]) )
+ ch = ch * 8 + *++p - '0';
+ if ( IS_OCTAL_DIGIT(p[1]) ) // safe (and easy) to do this twice
+ ch = ch * 8 + *++p - '0'; // now points at last digit
+ *d++ = ch;
+ break;
+ }
+ case 'x': case 'X': {
+ if (!isxdigit(p[1])) {
+ if (p[1] == '\0') {
+ LOG_STRING(ERROR, errors) << "String cannot end with \\x";
+ } else {
+ LOG_STRING(ERROR, errors) <<
+ "\\x cannot be followed by non-hex digit: \\" << *p << p[1];
+ }
+ break;
+ }
+ unsigned int ch = 0;
+ const char *hex_start = p;
+ while (isxdigit(p[1])) // arbitrarily many hex digits
+ ch = (ch << 4) + hex_digit_to_int(*++p);
+ if (ch > 0xFF)
+ LOG_STRING(ERROR, errors) << "Value of " <<
+ "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits";
+ *d++ = ch;
+ break;
+ }
+#if 0 // TODO(kenton): Support \u and \U? Requires runetochar().
+ case 'u': {
+ // \uhhhh => convert 4 hex digits to UTF-8
+ char32 rune = 0;
+ const char *hex_start = p;
+ for (int i = 0; i < 4; ++i) {
+ if (isxdigit(p[1])) { // Look one char ahead.
+ rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p.
+ } else {
+ LOG_STRING(ERROR, errors)
+ << "\\u must be followed by 4 hex digits: \\"
+ << string(hex_start, p+1-hex_start);
+ break;
+ }
+ }
+ d += runetochar(d, &rune);
+ break;
+ }
+ case 'U': {
+ // \Uhhhhhhhh => convert 8 hex digits to UTF-8
+ char32 rune = 0;
+ const char *hex_start = p;
+ for (int i = 0; i < 8; ++i) {
+ if (isxdigit(p[1])) { // Look one char ahead.
+ // Don't change rune until we're sure this
+ // is within the Unicode limit, but do advance p.
+ char32 newrune = (rune << 4) + hex_digit_to_int(*++p);
+ if (newrune > 0x10FFFF) {
+ LOG_STRING(ERROR, errors)
+ << "Value of \\"
+ << string(hex_start, p + 1 - hex_start)
+ << " exceeds Unicode limit (0x10FFFF)";
+ break;
+ } else {
+ rune = newrune;
+ }
+ } else {
+ LOG_STRING(ERROR, errors)
+ << "\\U must be followed by 8 hex digits: \\"
+ << string(hex_start, p+1-hex_start);
+ break;
+ }
+ }
+ d += runetochar(d, &rune);
+ break;
+ }
+#endif
+ default:
+ LOG_STRING(ERROR, errors) << "Unknown escape sequence: \\" << *p;
+ }
+ p++; // read past letter we escaped
+ }
+ }
+ *d = '\0';
+ return d - dest;
+}
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeString()
+// This does the same thing as UnescapeCEscapeSequences, but creates
+// a new string. The caller does not need to worry about allocating
+// a dest buffer. This should be used for non performance critical
+// tasks such as printing debug messages. It is safe for src and dest
+// to be the same.
+//
+// The second call stores its errors in a supplied string vector.
+// If the string vector pointer is NULL, it reports the errors with LOG().
+//
+// In the first and second calls, the length of dest is returned. In the
+// the third call, the new string is returned.
+// ----------------------------------------------------------------------
+int UnescapeCEscapeString(const string& src, string* dest) {
+ return UnescapeCEscapeString(src, dest, NULL);
+}
+
+int UnescapeCEscapeString(const string& src, string* dest,
+ vector<string> *errors) {
+ scoped_array<char> unescaped(new char[src.size() + 1]);
+ int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors);
+ GOOGLE_CHECK(dest);
+ dest->assign(unescaped.get(), len);
+ return len;
+}
+
+string UnescapeCEscapeString(const string& src) {
+ scoped_array<char> unescaped(new char[src.size() + 1]);
+ int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), NULL);
+ return string(unescaped.get(), len);
+}
+
+// ----------------------------------------------------------------------
+// CEscapeString()
+// CHexEscapeString()
+// Copies 'src' to 'dest', escaping dangerous characters using
+// C-style escape sequences. This is very useful for preparing query
+// flags. 'src' and 'dest' should not overlap. The 'Hex' version uses
+// hexadecimal rather than octal sequences.
+// Returns the number of bytes written to 'dest' (not including the \0)
+// or -1 if there was insufficient space.
+//
+// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
+// ----------------------------------------------------------------------
+static int CEscapeInternal(const char* src, int src_len, char* dest,
+ int dest_len, bool use_hex) {
+ const char* src_end = src + src_len;
+ int used = 0;
+ bool last_hex_escape = false; // true if last output char was \xNN
+
+ for (; src < src_end; src++) {
+ if (dest_len - used < 2) // Need space for two letter escape
+ return -1;
+
+ bool is_hex_escape = false;
+ switch (*src) {
+ case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break;
+ case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break;
+ case '\t': dest[used++] = '\\'; dest[used++] = 't'; break;
+ case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break;
+ case '\'': dest[used++] = '\\'; dest[used++] = '\''; break;
+ case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break;
+ default:
+ // Note that if we emit \xNN and the src character after that is a hex
+ // digit then that digit must be escaped too to prevent it being
+ // interpreted as part of the character code by C.
+ if (!isprint(*src) || (last_hex_escape && isxdigit(*src))) {
+ if (dest_len - used < 4) // need space for 4 letter escape
+ return -1;
+ sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
+ static_cast<uint8>(*src));
+ is_hex_escape = use_hex;
+ used += 4;
+ } else {
+ dest[used++] = *src; break;
+ }
+ }
+ last_hex_escape = is_hex_escape;
+ }
+
+ if (dest_len - used < 1) // make sure that there is room for \0
+ return -1;
+
+ dest[used] = '\0'; // doesn't count towards return value though
+ return used;
+}
+
+int CEscapeString(const char* src, int src_len, char* dest, int dest_len) {
+ return CEscapeInternal(src, src_len, dest, dest_len, false);
+}
+
+// ----------------------------------------------------------------------
+// CEscape()
+// CHexEscape()
+// Copies 'src' to result, escaping dangerous characters using
+// C-style escape sequences. This is very useful for preparing query
+// flags. 'src' and 'dest' should not overlap. The 'Hex' version
+// hexadecimal rather than octal sequences.
+//
+// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
+// ----------------------------------------------------------------------
+string CEscape(const string& src) {
+ const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
+ scoped_array<char> dest(new char[dest_length]);
+ const int len = CEscapeInternal(src.data(), src.size(),
+ dest.get(), dest_length, false);
+ GOOGLE_DCHECK_GE(len, 0);
+ return string(dest.get(), len);
+}
+
+// ----------------------------------------------------------------------
+// strto32_adaptor()
+// strtou32_adaptor()
+// Implementation of strto[u]l replacements that have identical
+// overflow and underflow characteristics for both ILP-32 and LP-64
+// platforms, including errno preservation in error-free calls.
+// ----------------------------------------------------------------------
+
+int32 strto32_adaptor(const char *nptr, char **endptr, int base) {
+ const int saved_errno = errno;
+ errno = 0;
+ const long result = strtol(nptr, endptr, base);
+ if (errno == ERANGE && result == LONG_MIN) {
+ return kint32min;
+ } else if (errno == ERANGE && result == LONG_MAX) {
+ return kint32max;
+ } else if (errno == 0 && result < kint32min) {
+ errno = ERANGE;
+ return kint32min;
+ } else if (errno == 0 && result > kint32max) {
+ errno = ERANGE;
+ return kint32max;
+ }
+ if (errno == 0)
+ errno = saved_errno;
+ return static_cast<int32>(result);
+}
+
+uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) {
+ const int saved_errno = errno;
+ errno = 0;
+ const unsigned long result = strtoul(nptr, endptr, base);
+ if (errno == ERANGE && result == ULONG_MAX) {
+ return kuint32max;
+ } else if (errno == 0 && result > kuint32max) {
+ errno = ERANGE;
+ return kuint32max;
+ }
+ if (errno == 0)
+ errno = saved_errno;
+ return static_cast<uint32>(result);
+}
+
+// ----------------------------------------------------------------------
+// FastIntToBuffer()
+// FastInt64ToBuffer()
+// FastHexToBuffer()
+// FastHex64ToBuffer()
+// FastHex32ToBuffer()
+// ----------------------------------------------------------------------
+
+// Offset into buffer where FastInt64ToBuffer places the end of string
+// null character. Also used by FastInt64ToBufferLeft.
+static const int kFastInt64ToBufferOffset = 21;
+
+char *FastInt64ToBuffer(int64 i, char* buffer) {
+ // We could collapse the positive and negative sections, but that
+ // would be slightly slower for positive numbers...
+ // 22 bytes is enough to store -2**64, -18446744073709551616.
+ char* p = buffer + kFastInt64ToBufferOffset;
+ *p-- = '\0';
+ if (i >= 0) {
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ return p + 1;
+ } else {
+ // On different platforms, % and / have different behaviors for
+ // negative numbers, so we need to jump through hoops to make sure
+ // we don't divide negative numbers.
+ if (i > -10) {
+ i = -i;
+ *p-- = '0' + i;
+ *p = '-';
+ return p;
+ } else {
+ // Make sure we aren't at MIN_INT, in which case we can't say i = -i
+ i = i + 10;
+ i = -i;
+ *p-- = '0' + i % 10;
+ // Undo what we did a moment ago
+ i = i / 10 + 1;
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ *p = '-';
+ return p;
+ }
+ }
+}
+
+// Offset into buffer where FastInt32ToBuffer places the end of string
+// null character. Also used by FastInt32ToBufferLeft
+static const int kFastInt32ToBufferOffset = 11;
+
+// Yes, this is a duplicate of FastInt64ToBuffer. But, we need this for the
+// compiler to generate 32 bit arithmetic instructions. It's much faster, at
+// least with 32 bit binaries.
+char *FastInt32ToBuffer(int32 i, char* buffer) {
+ // We could collapse the positive and negative sections, but that
+ // would be slightly slower for positive numbers...
+ // 12 bytes is enough to store -2**32, -4294967296.
+ char* p = buffer + kFastInt32ToBufferOffset;
+ *p-- = '\0';
+ if (i >= 0) {
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ return p + 1;
+ } else {
+ // On different platforms, % and / have different behaviors for
+ // negative numbers, so we need to jump through hoops to make sure
+ // we don't divide negative numbers.
+ if (i > -10) {
+ i = -i;
+ *p-- = '0' + i;
+ *p = '-';
+ return p;
+ } else {
+ // Make sure we aren't at MIN_INT, in which case we can't say i = -i
+ i = i + 10;
+ i = -i;
+ *p-- = '0' + i % 10;
+ // Undo what we did a moment ago
+ i = i / 10 + 1;
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ *p = '-';
+ return p;
+ }
+ }
+}
+
+char *FastHexToBuffer(int i, char* buffer) {
+ GOOGLE_CHECK(i >= 0) << "FastHexToBuffer() wants non-negative integers, not " << i;
+
+ static const char *hexdigits = "0123456789abcdef";
+ char *p = buffer + 21;
+ *p-- = '\0';
+ do {
+ *p-- = hexdigits[i & 15]; // mod by 16
+ i >>= 4; // divide by 16
+ } while (i > 0);
+ return p + 1;
+}
+
+char *InternalFastHexToBuffer(uint64 value, char* buffer, int num_byte) {
+ static const char *hexdigits = "0123456789abcdef";
+ buffer[num_byte] = '\0';
+ for (int i = num_byte - 1; i >= 0; i--) {
+ buffer[i] = hexdigits[uint32(value) & 0xf];
+ value >>= 4;
+ }
+ return buffer;
+}
+
+char *FastHex64ToBuffer(uint64 value, char* buffer) {
+ return InternalFastHexToBuffer(value, buffer, 16);
+}
+
+char *FastHex32ToBuffer(uint32 value, char* buffer) {
+ return InternalFastHexToBuffer(value, buffer, 8);
+}
+
+static inline char* PlaceNum(char* p, int num, char prev_sep) {
+ *p-- = '0' + num % 10;
+ *p-- = '0' + num / 10;
+ *p-- = prev_sep;
+ return p;
+}
+
+// ----------------------------------------------------------------------
+// FastInt32ToBufferLeft()
+// FastUInt32ToBufferLeft()
+// FastInt64ToBufferLeft()
+// FastUInt64ToBufferLeft()
+//
+// Like the Fast*ToBuffer() functions above, these are intended for speed.
+// Unlike the Fast*ToBuffer() functions, however, these functions write
+// their output to the beginning of the buffer (hence the name, as the
+// output is left-aligned). The caller is responsible for ensuring that
+// the buffer has enough space to hold the output.
+//
+// Returns a pointer to the end of the string (i.e. the null character
+// terminating the string).
+// ----------------------------------------------------------------------
+
+static const char two_ASCII_digits[100][2] = {
+ {'0','0'}, {'0','1'}, {'0','2'}, {'0','3'}, {'0','4'},
+ {'0','5'}, {'0','6'}, {'0','7'}, {'0','8'}, {'0','9'},
+ {'1','0'}, {'1','1'}, {'1','2'}, {'1','3'}, {'1','4'},
+ {'1','5'}, {'1','6'}, {'1','7'}, {'1','8'}, {'1','9'},
+ {'2','0'}, {'2','1'}, {'2','2'}, {'2','3'}, {'2','4'},
+ {'2','5'}, {'2','6'}, {'2','7'}, {'2','8'}, {'2','9'},
+ {'3','0'}, {'3','1'}, {'3','2'}, {'3','3'}, {'3','4'},
+ {'3','5'}, {'3','6'}, {'3','7'}, {'3','8'}, {'3','9'},
+ {'4','0'}, {'4','1'}, {'4','2'}, {'4','3'}, {'4','4'},
+ {'4','5'}, {'4','6'}, {'4','7'}, {'4','8'}, {'4','9'},
+ {'5','0'}, {'5','1'}, {'5','2'}, {'5','3'}, {'5','4'},
+ {'5','5'}, {'5','6'}, {'5','7'}, {'5','8'}, {'5','9'},
+ {'6','0'}, {'6','1'}, {'6','2'}, {'6','3'}, {'6','4'},
+ {'6','5'}, {'6','6'}, {'6','7'}, {'6','8'}, {'6','9'},
+ {'7','0'}, {'7','1'}, {'7','2'}, {'7','3'}, {'7','4'},
+ {'7','5'}, {'7','6'}, {'7','7'}, {'7','8'}, {'7','9'},
+ {'8','0'}, {'8','1'}, {'8','2'}, {'8','3'}, {'8','4'},
+ {'8','5'}, {'8','6'}, {'8','7'}, {'8','8'}, {'8','9'},
+ {'9','0'}, {'9','1'}, {'9','2'}, {'9','3'}, {'9','4'},
+ {'9','5'}, {'9','6'}, {'9','7'}, {'9','8'}, {'9','9'}
+};
+
+char* FastUInt32ToBufferLeft(uint32 u, char* buffer) {
+ int digits;
+ const char *ASCII_digits = NULL;
+ // The idea of this implementation is to trim the number of divides to as few
+ // as possible by using multiplication and subtraction rather than mod (%),
+ // and by outputting two digits at a time rather than one.
+ // The huge-number case is first, in the hopes that the compiler will output
+ // that case in one branch-free block of code, and only output conditional
+ // branches into it from below.
+ if (u >= 1000000000) { // >= 1,000,000,000
+ digits = u / 100000000; // 100,000,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+sublt100_000_000:
+ u -= digits * 100000000; // 100,000,000
+lt100_000_000:
+ digits = u / 1000000; // 1,000,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+sublt1_000_000:
+ u -= digits * 1000000; // 1,000,000
+lt1_000_000:
+ digits = u / 10000; // 10,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+sublt10_000:
+ u -= digits * 10000; // 10,000
+lt10_000:
+ digits = u / 100;
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+sublt100:
+ u -= digits * 100;
+lt100:
+ digits = u;
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+done:
+ *buffer = 0;
+ return buffer;
+ }
+
+ if (u < 100) {
+ digits = u;
+ if (u >= 10) goto lt100;
+ *buffer++ = '0' + digits;
+ goto done;
+ }
+ if (u < 10000) { // 10,000
+ if (u >= 1000) goto lt10_000;
+ digits = u / 100;
+ *buffer++ = '0' + digits;
+ goto sublt100;
+ }
+ if (u < 1000000) { // 1,000,000
+ if (u >= 100000) goto lt1_000_000;
+ digits = u / 10000; // 10,000
+ *buffer++ = '0' + digits;
+ goto sublt10_000;
+ }
+ if (u < 100000000) { // 100,000,000
+ if (u >= 10000000) goto lt100_000_000;
+ digits = u / 1000000; // 1,000,000
+ *buffer++ = '0' + digits;
+ goto sublt1_000_000;
+ }
+ // we already know that u < 1,000,000,000
+ digits = u / 100000000; // 100,000,000
+ *buffer++ = '0' + digits;
+ goto sublt100_000_000;
+}
+
+char* FastInt32ToBufferLeft(int32 i, char* buffer) {
+ uint32 u = i;
+ if (i < 0) {
+ *buffer++ = '-';
+ u = -i;
+ }
+ return FastUInt32ToBufferLeft(u, buffer);
+}
+
+char* FastUInt64ToBufferLeft(uint64 u64, char* buffer) {
+ int digits;
+ const char *ASCII_digits = NULL;
+
+ uint32 u = static_cast<uint32>(u64);
+ if (u == u64) return FastUInt32ToBufferLeft(u, buffer);
+
+ uint64 top_11_digits = u64 / 1000000000;
+ buffer = FastUInt64ToBufferLeft(top_11_digits, buffer);
+ u = u64 - (top_11_digits * 1000000000);
+
+ digits = u / 10000000; // 10,000,000
+ GOOGLE_DCHECK_LT(digits, 100);
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 10000000; // 10,000,000
+ digits = u / 100000; // 100,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 100000; // 100,000
+ digits = u / 1000; // 1,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 1000; // 1,000
+ digits = u / 10;
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 10;
+ digits = u;
+ *buffer++ = '0' + digits;
+ *buffer = 0;
+ return buffer;
+}
+
+char* FastInt64ToBufferLeft(int64 i, char* buffer) {
+ uint64 u = i;
+ if (i < 0) {
+ *buffer++ = '-';
+ u = -i;
+ }
+ return FastUInt64ToBufferLeft(u, buffer);
+}
+
+// ----------------------------------------------------------------------
+// SimpleItoa()
+// Description: converts an integer to a string.
+//
+// Return value: string
+// ----------------------------------------------------------------------
+
+string SimpleItoa(int i) {
+ char buffer[kFastToBufferSize];
+ return (sizeof(i) == 4) ?
+ FastInt32ToBuffer(i, buffer) :
+ FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned int i) {
+ char buffer[kFastToBufferSize];
+ return string(buffer, (sizeof(i) == 4) ?
+ FastUInt32ToBufferLeft(i, buffer) :
+ FastUInt64ToBufferLeft(i, buffer));
+}
+
+string SimpleItoa(long i) {
+ char buffer[kFastToBufferSize];
+ return (sizeof(i) == 4) ?
+ FastInt32ToBuffer(i, buffer) :
+ FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned long i) {
+ char buffer[kFastToBufferSize];
+ return string(buffer, (sizeof(i) == 4) ?
+ FastUInt32ToBufferLeft(i, buffer) :
+ FastUInt64ToBufferLeft(i, buffer));
+}
+
+string SimpleItoa(long long i) {
+ char buffer[kFastToBufferSize];
+ return (sizeof(i) == 4) ?
+ FastInt32ToBuffer(i, buffer) :
+ FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned long long i) {
+ char buffer[kFastToBufferSize];
+ return string(buffer, (sizeof(i) == 4) ?
+ FastUInt32ToBufferLeft(i, buffer) :
+ FastUInt64ToBufferLeft(i, buffer));
+}
+
+// ----------------------------------------------------------------------
+// SimpleDtoa()
+// SimpleFtoa()
+// DoubleToBuffer()
+// FloatToBuffer()
+// We want to print the value without losing precision, but we also do
+// not want to print more digits than necessary. This turns out to be
+// trickier than it sounds. Numbers like 0.2 cannot be represented
+// exactly in binary. If we print 0.2 with a very large precision,
+// e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167".
+// On the other hand, if we set the precision too low, we lose
+// significant digits when printing numbers that actually need them.
+// It turns out there is no precision value that does the right thing
+// for all numbers.
+//
+// Our strategy is to first try printing with a precision that is never
+// over-precise, then parse the result with strtod() to see if it
+// matches. If not, we print again with a precision that will always
+// give a precise result, but may use more digits than necessary.
+//
+// An arguably better strategy would be to use the algorithm described
+// in "How to Print Floating-Point Numbers Accurately" by Steele &
+// White, e.g. as implemented by David M. Gay's dtoa(). It turns out,
+// however, that the following implementation is about as fast as
+// DMG's code. Furthermore, DMG's code locks mutexes, which means it
+// will not scale well on multi-core machines. DMG's code is slightly
+// more accurate (in that it will never use more digits than
+// necessary), but this is probably irrelevant for most users.
+//
+// Rob Pike and Ken Thompson also have an implementation of dtoa() in
+// third_party/fmt/fltfmt.cc. Their implementation is similar to this
+// one in that it makes guesses and then uses strtod() to check them.
+// Their implementation is faster because they use their own code to
+// generate the digits in the first place rather than use snprintf(),
+// thus avoiding format string parsing overhead. However, this makes
+// it considerably more complicated than the following implementation,
+// and it is embedded in a larger library. If speed turns out to be
+// an issue, we could re-implement this in terms of their
+// implementation.
+// ----------------------------------------------------------------------
+
+string SimpleDtoa(double value) {
+ char buffer[kDoubleToBufferSize];
+ return DoubleToBuffer(value, buffer);
+}
+
+string SimpleFtoa(float value) {
+ char buffer[kFloatToBufferSize];
+ return FloatToBuffer(value, buffer);
+}
+
+static inline bool IsValidFloatChar(char c) {
+ return ('0' <= c && c <= '9') ||
+ c == 'e' || c == 'E' ||
+ c == '+' || c == '-';
+}
+
+void DelocalizeRadix(char* buffer) {
+ // Fast check: if the buffer has a normal decimal point, assume no
+ // translation is needed.
+ if (strchr(buffer, '.') != NULL) return;
+
+ // Find the first unknown character.
+ while (IsValidFloatChar(*buffer)) ++buffer;
+
+ if (*buffer == '\0') {
+ // No radix character found.
+ return;
+ }
+
+ // We are now pointing at the locale-specific radix character. Replace it
+ // with '.'.
+ *buffer = '.';
+ ++buffer;
+
+ if (!IsValidFloatChar(*buffer) && *buffer != '\0') {
+ // It appears the radix was a multi-byte character. We need to remove the
+ // extra bytes.
+ char* target = buffer;
+ do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0');
+ memmove(target, buffer, strlen(buffer) + 1);
+ }
+}
+
+char* DoubleToBuffer(double value, char* buffer) {
+ // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all
+ // platforms these days. Just in case some system exists where DBL_DIG
+ // is significantly larger -- and risks overflowing our buffer -- we have
+ // this assert.
+ GOOGLE_COMPILE_ASSERT(DBL_DIG < 20, DBL_DIG_is_too_big);
+
+ if (value == numeric_limits<double>::infinity()) {
+ strcpy(buffer, "inf");
+ return buffer;
+ } else if (value == -numeric_limits<double>::infinity()) {
+ strcpy(buffer, "-inf");
+ return buffer;
+ } else if (IsNaN(value)) {
+ strcpy(buffer, "nan");
+ return buffer;
+ }
+
+ int snprintf_result =
+ snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value);
+
+ // The snprintf should never overflow because the buffer is significantly
+ // larger than the precision we asked for.
+ GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
+
+ // We need to make parsed_value volatile in order to force the compiler to
+ // write it out to the stack. Otherwise, it may keep the value in a
+ // register, and if it does that, it may keep it as a long double instead
+ // of a double. This long double may have extra bits that make it compare
+ // unequal to "value" even though it would be exactly equal if it were
+ // truncated to a double.
+ volatile double parsed_value = strtod(buffer, NULL);
+ if (parsed_value != value) {
+ int snprintf_result =
+ snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG+2, value);
+
+ // Should never overflow; see above.
+ GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
+ }
+
+ DelocalizeRadix(buffer);
+ return buffer;
+}
+
+bool safe_strtof(const char* str, float* value) {
+ char* endptr;
+ errno = 0; // errno only gets set on errors
+#ifdef _WIN32 // has no strtof()
+ *value = strtod(str, &endptr);
+#else
+ *value = strtof(str, &endptr);
+#endif
+ return *str != 0 && *endptr == 0 && errno == 0;
+}
+
+char* FloatToBuffer(float value, char* buffer) {
+ // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all
+ // platforms these days. Just in case some system exists where FLT_DIG
+ // is significantly larger -- and risks overflowing our buffer -- we have
+ // this assert.
+ GOOGLE_COMPILE_ASSERT(FLT_DIG < 10, FLT_DIG_is_too_big);
+
+ if (value == numeric_limits<double>::infinity()) {
+ strcpy(buffer, "inf");
+ return buffer;
+ } else if (value == -numeric_limits<double>::infinity()) {
+ strcpy(buffer, "-inf");
+ return buffer;
+ } else if (IsNaN(value)) {
+ strcpy(buffer, "nan");
+ return buffer;
+ }
+
+ int snprintf_result =
+ snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value);
+
+ // The snprintf should never overflow because the buffer is significantly
+ // larger than the precision we asked for.
+ GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
+
+ float parsed_value;
+ if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) {
+ int snprintf_result =
+ snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+2, value);
+
+ // Should never overflow; see above.
+ GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
+ }
+
+ DelocalizeRadix(buffer);
+ return buffer;
+}
+
+// ----------------------------------------------------------------------
+// NoLocaleStrtod()
+// This code will make you cry.
+// ----------------------------------------------------------------------
+
+// Returns a string identical to *input except that the character pointed to
+// by radix_pos (which should be '.') is replaced with the locale-specific
+// radix character.
+string LocalizeRadix(const char* input, const char* radix_pos) {
+ // Determine the locale-specific radix character by calling sprintf() to
+ // print the number 1.5, then stripping off the digits. As far as I can
+ // tell, this is the only portable, thread-safe way to get the C library
+ // to divuldge the locale's radix character. No, localeconv() is NOT
+ // thread-safe.
+ char temp[16];
+ int size = sprintf(temp, "%.1f", 1.5);
+ GOOGLE_CHECK_EQ(temp[0], '1');
+ GOOGLE_CHECK_EQ(temp[size-1], '5');
+ GOOGLE_CHECK_LE(size, 6);
+
+ // Now replace the '.' in the input with it.
+ string result;
+ result.reserve(strlen(input) + size - 3);
+ result.append(input, radix_pos);
+ result.append(temp + 1, size - 2);
+ result.append(radix_pos + 1);
+ return result;
+}
+
+double NoLocaleStrtod(const char* text, char** original_endptr) {
+ // We cannot simply set the locale to "C" temporarily with setlocale()
+ // as this is not thread-safe. Instead, we try to parse in the current
+ // locale first. If parsing stops at a '.' character, then this is a
+ // pretty good hint that we're actually in some other locale in which
+ // '.' is not the radix character.
+
+ char* temp_endptr;
+ double result = strtod(text, &temp_endptr);
+ if (original_endptr != NULL) *original_endptr = temp_endptr;
+ if (*temp_endptr != '.') return result;
+
+ // Parsing halted on a '.'. Perhaps we're in a different locale? Let's
+ // try to replace the '.' with a locale-specific radix character and
+ // try again.
+ string localized = LocalizeRadix(text, temp_endptr);
+ const char* localized_cstr = localized.c_str();
+ char* localized_endptr;
+ result = strtod(localized_cstr, &localized_endptr);
+ if ((localized_endptr - localized_cstr) >
+ (temp_endptr - text)) {
+ // This attempt got further, so replacing the decimal must have helped.
+ // Update original_endptr to point at the right location.
+ if (original_endptr != NULL) {
+ // size_diff is non-zero if the localized radix has multiple bytes.
+ int size_diff = localized.size() - strlen(text);
+ // const_cast is necessary to match the strtod() interface.
+ *original_endptr = const_cast<char*>(
+ text + (localized_endptr - localized_cstr - size_diff));
+ }
+ }
+
+ return result;
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
new file mode 100644
index 00000000..ff919617
--- /dev/null
+++ b/src/google/protobuf/stubs/strutil.h
@@ -0,0 +1,432 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// from google3/strings/strutil.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
+#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
+
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _MSC_VER
+#define strtoll _strtoi64
+#define strtoull _strtoui64
+#endif
+
+// ----------------------------------------------------------------------
+// ascii_isalnum()
+// Check if an ASCII character is alphanumeric. We can't use ctype's
+// isalnum() because it is affected by locale. This function is applied
+// to identifiers in the protocol buffer language, not to natural-language
+// strings, so locale should not be taken into account.
+// ascii_isdigit()
+// Like above, but only accepts digits.
+// ----------------------------------------------------------------------
+
+inline bool ascii_isalnum(char c) {
+ return ('a' <= c && c <= 'z') ||
+ ('A' <= c && c <= 'Z') ||
+ ('0' <= c && c <= '9');
+}
+
+inline bool ascii_isdigit(char c) {
+ return ('0' <= c && c <= '9');
+}
+
+// ----------------------------------------------------------------------
+// HasPrefixString()
+// Check if a string begins with a given prefix.
+// StripPrefixString()
+// Given a string and a putative prefix, returns the string minus the
+// prefix string if the prefix matches, otherwise the original
+// string.
+// ----------------------------------------------------------------------
+inline bool HasPrefixString(const string& str,
+ const string& prefix) {
+ return str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0;
+}
+
+inline string StripPrefixString(const string& str, const string& prefix) {
+ if (HasPrefixString(str, prefix)) {
+ return str.substr(prefix.size());
+ } else {
+ return str;
+ }
+}
+
+// ----------------------------------------------------------------------
+// HasSuffixString()
+// Return true if str ends in suffix.
+// StripSuffixString()
+// Given a string and a putative suffix, returns the string minus the
+// suffix string if the suffix matches, otherwise the original
+// string.
+// ----------------------------------------------------------------------
+inline bool HasSuffixString(const string& str,
+ const string& suffix) {
+ return str.size() >= suffix.size() &&
+ str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+}
+
+inline string StripSuffixString(const string& str, const string& suffix) {
+ if (HasSuffixString(str, suffix)) {
+ return str.substr(0, str.size() - suffix.size());
+ } else {
+ return str;
+ }
+}
+
+// ----------------------------------------------------------------------
+// StripString
+// Replaces any occurrence of the character 'remove' (or the characters
+// in 'remove') with the character 'replacewith'.
+// Good for keeping html characters or protocol characters (\t) out
+// of places where they might cause a problem.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove,
+ char replacewith);
+
+// ----------------------------------------------------------------------
+// LowerString()
+// UpperString()
+// Convert the characters in "s" to lowercase or uppercase. ASCII-only:
+// these functions intentionally ignore locale because they are applied to
+// identifiers used in the Protocol Buffer language, not to natural-language
+// strings.
+// ----------------------------------------------------------------------
+
+inline void LowerString(string * s) {
+ string::iterator end = s->end();
+ for (string::iterator i = s->begin(); i != end; ++i) {
+ // tolower() changes based on locale. We don't want this!
+ if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
+ }
+}
+
+inline void UpperString(string * s) {
+ string::iterator end = s->end();
+ for (string::iterator i = s->begin(); i != end; ++i) {
+ // toupper() changes based on locale. We don't want this!
+ if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
+ }
+}
+
+// ----------------------------------------------------------------------
+// StringReplace()
+// Give me a string and two patterns "old" and "new", and I replace
+// the first instance of "old" in the string with "new", if it
+// exists. RETURN a new string, regardless of whether the replacement
+// happened or not.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub,
+ const string& newsub, bool replace_all);
+
+// ----------------------------------------------------------------------
+// SplitStringUsing()
+// Split a string using a character delimiter. Append the components
+// to 'result'. If there are consecutive delimiters, this function skips
+// over all of them.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
+ vector<string>* res);
+
+// ----------------------------------------------------------------------
+// JoinStrings()
+// These methods concatenate a vector of strings into a C++ string, using
+// the C-string "delim" as a separator between components. There are two
+// flavors of the function, one flavor returns the concatenated string,
+// another takes a pointer to the target string. In the latter case the
+// target string is cleared and overwritten.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void JoinStrings(const vector<string>& components,
+ const char* delim, string* result);
+
+inline string JoinStrings(const vector<string>& components,
+ const char* delim) {
+ string result;
+ JoinStrings(components, delim, &result);
+ return result;
+}
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeSequences()
+// Copies "source" to "dest", rewriting C-style escape sequences
+// -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII
+// equivalents. "dest" must be sufficiently large to hold all
+// the characters in the rewritten string (i.e. at least as large
+// as strlen(source) + 1 should be safe, since the replacements
+// are always shorter than the original escaped sequences). It's
+// safe for source and dest to be the same. RETURNS the length
+// of dest.
+//
+// It allows hex sequences \xhh, or generally \xhhhhh with an
+// arbitrary number of hex digits, but all of them together must
+// specify a value of a single byte (e.g. \x0045 is equivalent
+// to \x45, and \x1234 is erroneous).
+//
+// It also allows escape sequences of the form \uhhhh (exactly four
+// hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight
+// hex digits, upper or lower case) to specify a Unicode code
+// point. The dest array will contain the UTF8-encoded version of
+// that code-point (e.g., if source contains \u2019, then dest will
+// contain the three bytes 0xE2, 0x80, and 0x99). For the inverse
+// transformation, use UniLib::UTF8EscapeString
+// (util/utf8/unilib.h), not CEscapeString.
+//
+// Errors: In the first form of the call, errors are reported with
+// LOG(ERROR). The same is true for the second form of the call if
+// the pointer to the string vector is NULL; otherwise, error
+// messages are stored in the vector. In either case, the effect on
+// the dest array is not defined, but rest of the source will be
+// processed.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
+LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
+ vector<string> *errors);
+
+// ----------------------------------------------------------------------
+// UnescapeCEscapeString()
+// This does the same thing as UnescapeCEscapeSequences, but creates
+// a new string. The caller does not need to worry about allocating
+// a dest buffer. This should be used for non performance critical
+// tasks such as printing debug messages. It is safe for src and dest
+// to be the same.
+//
+// The second call stores its errors in a supplied string vector.
+// If the string vector pointer is NULL, it reports the errors with LOG().
+//
+// In the first and second calls, the length of dest is returned. In the
+// the third call, the new string is returned.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest);
+LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest,
+ vector<string> *errors);
+LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src);
+
+// ----------------------------------------------------------------------
+// CEscapeString()
+// Copies 'src' to 'dest', escaping dangerous characters using
+// C-style escape sequences. This is very useful for preparing query
+// flags. 'src' and 'dest' should not overlap.
+// Returns the number of bytes written to 'dest' (not including the \0)
+// or -1 if there was insufficient space.
+//
+// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int CEscapeString(const char* src, int src_len,
+ char* dest, int dest_len);
+
+// ----------------------------------------------------------------------
+// CEscape()
+// More convenient form of CEscapeString: returns result as a "string".
+// This version is slower than CEscapeString() because it does more
+// allocation. However, it is much more convenient to use in
+// non-speed-critical code like logging messages etc.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT string CEscape(const string& src);
+
+// ----------------------------------------------------------------------
+// strto32()
+// strtou32()
+// strto64()
+// strtou64()
+// Architecture-neutral plug compatible replacements for strtol() and
+// strtoul(). Long's have different lengths on ILP-32 and LP-64
+// platforms, so using these is safer, from the point of view of
+// overflow behavior, than using the standard libc functions.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int32 strto32_adaptor(const char *nptr, char **endptr,
+ int base);
+LIBPROTOBUF_EXPORT uint32 strtou32_adaptor(const char *nptr, char **endptr,
+ int base);
+
+inline int32 strto32(const char *nptr, char **endptr, int base) {
+ if (sizeof(int32) == sizeof(long))
+ return strtol(nptr, endptr, base);
+ else
+ return strto32_adaptor(nptr, endptr, base);
+}
+
+inline uint32 strtou32(const char *nptr, char **endptr, int base) {
+ if (sizeof(uint32) == sizeof(unsigned long))
+ return strtoul(nptr, endptr, base);
+ else
+ return strtou32_adaptor(nptr, endptr, base);
+}
+
+// For now, long long is 64-bit on all the platforms we care about, so these
+// functions can simply pass the call to strto[u]ll.
+inline int64 strto64(const char *nptr, char **endptr, int base) {
+ GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
+ sizeof_int64_is_not_sizeof_long_long);
+ return strtoll(nptr, endptr, base);
+}
+
+inline uint64 strtou64(const char *nptr, char **endptr, int base) {
+ GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
+ sizeof_uint64_is_not_sizeof_long_long);
+ return strtoull(nptr, endptr, base);
+}
+
+// ----------------------------------------------------------------------
+// FastIntToBuffer()
+// FastHexToBuffer()
+// FastHex64ToBuffer()
+// FastHex32ToBuffer()
+// FastTimeToBuffer()
+// These are intended for speed. FastIntToBuffer() assumes the
+// integer is non-negative. FastHexToBuffer() puts output in
+// hex rather than decimal. FastTimeToBuffer() puts the output
+// into RFC822 format.
+//
+// FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format,
+// padded to exactly 16 bytes (plus one byte for '\0')
+//
+// FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format,
+// padded to exactly 8 bytes (plus one byte for '\0')
+//
+// All functions take the output buffer as an arg.
+// They all return a pointer to the beginning of the output,
+// which may not be the beginning of the input buffer.
+// ----------------------------------------------------------------------
+
+// Suggested buffer size for FastToBuffer functions. Also works with
+// DoubleToBuffer() and FloatToBuffer().
+static const int kFastToBufferSize = 32;
+
+LIBPROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer);
+char* FastUInt32ToBuffer(uint32 i, char* buffer); // inline below
+char* FastUInt64ToBuffer(uint64 i, char* buffer); // inline below
+LIBPROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer);
+
+// at least 22 bytes long
+inline char* FastIntToBuffer(int i, char* buffer) {
+ return (sizeof(i) == 4 ?
+ FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
+}
+inline char* FastUIntToBuffer(unsigned int i, char* buffer) {
+ return (sizeof(i) == 4 ?
+ FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
+}
+inline char* FastLongToBuffer(long i, char* buffer) {
+ return (sizeof(i) == 4 ?
+ FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
+}
+inline char* FastULongToBuffer(unsigned long i, char* buffer) {
+ return (sizeof(i) == 4 ?
+ FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
+}
+
+// ----------------------------------------------------------------------
+// FastInt32ToBufferLeft()
+// FastUInt32ToBufferLeft()
+// FastInt64ToBufferLeft()
+// FastUInt64ToBufferLeft()
+//
+// Like the Fast*ToBuffer() functions above, these are intended for speed.
+// Unlike the Fast*ToBuffer() functions, however, these functions write
+// their output to the beginning of the buffer (hence the name, as the
+// output is left-aligned). The caller is responsible for ensuring that
+// the buffer has enough space to hold the output.
+//
+// Returns a pointer to the end of the string (i.e. the null character
+// terminating the string).
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer);
+LIBPROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer);
+
+// Just define these in terms of the above.
+inline char* FastUInt32ToBuffer(uint32 i, char* buffer) {
+ FastUInt32ToBufferLeft(i, buffer);
+ return buffer;
+}
+inline char* FastUInt64ToBuffer(uint64 i, char* buffer) {
+ FastUInt64ToBufferLeft(i, buffer);
+ return buffer;
+}
+
+// ----------------------------------------------------------------------
+// SimpleItoa()
+// Description: converts an integer to a string.
+//
+// Return value: string
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT string SimpleItoa(int i);
+LIBPROTOBUF_EXPORT string SimpleItoa(unsigned int i);
+LIBPROTOBUF_EXPORT string SimpleItoa(long i);
+LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long i);
+LIBPROTOBUF_EXPORT string SimpleItoa(long long i);
+LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i);
+
+// ----------------------------------------------------------------------
+// SimpleDtoa()
+// SimpleFtoa()
+// DoubleToBuffer()
+// FloatToBuffer()
+// Description: converts a double or float to a string which, if
+// passed to NoLocaleStrtod(), will produce the exact same original double
+// (except in case of NaN; all NaNs are considered the same value).
+// We try to keep the string short but it's not guaranteed to be as
+// short as possible.
+//
+// DoubleToBuffer() and FloatToBuffer() write the text to the given
+// buffer and return it. The buffer must be at least
+// kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
+// bytes for floats. kFastToBufferSize is also guaranteed to be large
+// enough to hold either.
+//
+// Return value: string
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT string SimpleDtoa(double value);
+LIBPROTOBUF_EXPORT string SimpleFtoa(float value);
+
+LIBPROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer);
+LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
+
+// In practice, doubles should never need more than 24 bytes and floats
+// should never need more than 14 (including null terminators), but we
+// overestimate to be safe.
+static const int kDoubleToBufferSize = 32;
+static const int kFloatToBufferSize = 24;
+
+// ----------------------------------------------------------------------
+// NoLocaleStrtod()
+// Exactly like strtod(), except it always behaves as if in the "C"
+// locale (i.e. decimal points must be '.'s).
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT double NoLocaleStrtod(const char* text, char** endptr);
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
+
+
diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc
new file mode 100644
index 00000000..58ffd32e
--- /dev/null
+++ b/src/google/protobuf/stubs/strutil_unittest.cc
@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// TODO(kenton): Copy strutil tests from google3?
+
+TEST(StringUtilityTest, ImmuneToLocales) {
+ // Remember the old locale.
+ char* old_locale_cstr = setlocale(LC_NUMERIC, NULL);
+ ASSERT_TRUE(old_locale_cstr != NULL);
+ string old_locale = old_locale_cstr;
+
+ // Set the locale to "C".
+ ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != NULL);
+
+ EXPECT_EQ(1.5, NoLocaleStrtod("1.5", NULL));
+ EXPECT_EQ("1.5", SimpleDtoa(1.5));
+ EXPECT_EQ("1.5", SimpleFtoa(1.5));
+
+ // Verify that the endptr is set correctly even if not all text was parsed.
+ const char* text = "1.5f";
+ char* endptr;
+ EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr));
+ EXPECT_EQ(3, endptr - text);
+
+ if (setlocale(LC_NUMERIC, "es_ES") == NULL &&
+ setlocale(LC_NUMERIC, "es_ES.utf8") == NULL) {
+ // Some systems may not have the desired locale available.
+ GOOGLE_LOG(WARNING)
+ << "Couldn't set locale to es_ES. Skipping this test.";
+ } else {
+ EXPECT_EQ(1.5, NoLocaleStrtod("1.5", NULL));
+ EXPECT_EQ("1.5", SimpleDtoa(1.5));
+ EXPECT_EQ("1.5", SimpleFtoa(1.5));
+ EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr));
+ EXPECT_EQ(3, endptr - text);
+ }
+
+ // Return to original locale.
+ setlocale(LC_NUMERIC, old_locale.c_str());
+}
+
+} // anonymous namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc
new file mode 100644
index 00000000..340be5e8
--- /dev/null
+++ b/src/google/protobuf/stubs/substitute.cc
@@ -0,0 +1,120 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+using internal::SubstituteArg;
+
+// Returns the number of args in arg_array which were passed explicitly
+// to Substitute().
+static int CountSubstituteArgs(const SubstituteArg* const* args_array) {
+ int count = 0;
+ while (args_array[count] != NULL && args_array[count]->size() != -1) {
+ ++count;
+ }
+ return count;
+}
+
+string Substitute(
+ const char* format,
+ const SubstituteArg& arg0, const SubstituteArg& arg1,
+ const SubstituteArg& arg2, const SubstituteArg& arg3,
+ const SubstituteArg& arg4, const SubstituteArg& arg5,
+ const SubstituteArg& arg6, const SubstituteArg& arg7,
+ const SubstituteArg& arg8, const SubstituteArg& arg9) {
+ string result;
+ SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4,
+ arg5, arg6, arg7, arg8, arg9);
+ return result;
+}
+
+void SubstituteAndAppend(
+ string* output, const char* format,
+ const SubstituteArg& arg0, const SubstituteArg& arg1,
+ const SubstituteArg& arg2, const SubstituteArg& arg3,
+ const SubstituteArg& arg4, const SubstituteArg& arg5,
+ const SubstituteArg& arg6, const SubstituteArg& arg7,
+ const SubstituteArg& arg8, const SubstituteArg& arg9) {
+ const SubstituteArg* const args_array[] = {
+ &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, NULL
+ };
+
+ // Determine total size needed.
+ int size = 0;
+ for (int i = 0; format[i] != '\0'; i++) {
+ if (format[i] == '$') {
+ if (ascii_isdigit(format[i+1])) {
+ int index = format[i+1] - '0';
+ if (args_array[index]->size() == -1) {
+ GOOGLE_LOG(DFATAL)
+ << "strings::Substitute format string invalid: asked for \"$"
+ << index << "\", but only " << CountSubstituteArgs(args_array)
+ << " args were given. Full format string was: \""
+ << CEscape(format) << "\".";
+ return;
+ }
+ size += args_array[index]->size();
+ ++i; // Skip next char.
+ } else if (format[i+1] == '$') {
+ ++size;
+ ++i; // Skip next char.
+ } else {
+ GOOGLE_LOG(DFATAL)
+ << "Invalid strings::Substitute() format string: \""
+ << CEscape(format) << "\".";
+ return;
+ }
+ } else {
+ ++size;
+ }
+ }
+
+ if (size == 0) return;
+
+ // Build the string.
+ int original_size = output->size();
+ STLStringResizeUninitialized(output, original_size + size);
+ char* target = string_as_array(output) + original_size;
+ for (int i = 0; format[i] != '\0'; i++) {
+ if (format[i] == '$') {
+ if (ascii_isdigit(format[i+1])) {
+ const SubstituteArg* src = args_array[format[i+1] - '0'];
+ memcpy(target, src->data(), src->size());
+ target += src->size();
+ ++i; // Skip next char.
+ } else if (format[i+1] == '$') {
+ *target++ = '$';
+ ++i; // Skip next char.
+ }
+ } else {
+ *target++ = format[i];
+ }
+ }
+
+ GOOGLE_DCHECK_EQ(target - output->data(), output->size());
+}
+
+} // namespace strings
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/substitute.h b/src/google/protobuf/stubs/substitute.h
new file mode 100644
index 00000000..143e4828
--- /dev/null
+++ b/src/google/protobuf/stubs/substitute.h
@@ -0,0 +1,156 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+// from google3/strings/substitute.h
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
+#define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+// ----------------------------------------------------------------------
+// strings::Substitute()
+// strings::SubstituteAndAppend()
+// Kind of like StringPrintf, but different.
+//
+// Example:
+// string GetMessage(string first_name, string last_name, int age) {
+// return strings::Substitute("My name is $0 $1 and I am $2 years old.",
+// first_name, last_name, age);
+// }
+//
+// Differences from StringPrintf:
+// * The format string does not identify the types of arguments.
+// Instead, the magic of C++ deals with this for us. See below
+// for a list of accepted types.
+// * Substitutions in the format string are identified by a '$'
+// followed by a digit. So, you can use arguments out-of-order and
+// use the same argument multiple times.
+// * It's much faster than StringPrintf.
+//
+// Supported types:
+// * Strings (const char*, const string&)
+// * Note that this means you do not have to add .c_str() to all of
+// your strings. In fact, you shouldn't; it will be slower.
+// * int32, int64, uint32, uint64: Formatted using SimpleItoa().
+// * float, double: Formatted using SimpleFtoa() and SimpleDtoa().
+// * bool: Printed as "true" or "false".
+//
+// SubstituteAndAppend() is like Substitute() but appends the result to
+// *output. Example:
+//
+// string str;
+// strings::SubstituteAndAppend(&str,
+// "My name is $0 $1 and I am $2 years old.",
+// first_name, last_name, age);
+//
+// Substitute() is significantly faster than StringPrintf(). For very
+// large strings, it may be orders of magnitude faster.
+// ----------------------------------------------------------------------
+
+namespace internal { // Implementation details.
+
+class SubstituteArg {
+ public:
+ inline SubstituteArg(const char* value)
+ : text_(value), size_(strlen(text_)) {}
+ inline SubstituteArg(const string& value)
+ : text_(value.data()), size_(value.size()) {}
+
+ // Indicates that no argument was given.
+ inline explicit SubstituteArg()
+ : text_(NULL), size_(-1) {}
+
+ // Primitives
+ // We don't overload for signed and unsigned char because if people are
+ // explicitly declaring their chars as signed or unsigned then they are
+ // probably actually using them as 8-bit integers and would probably
+ // prefer an integer representation. But, we don't really know. So, we
+ // make the caller decide what to do.
+ inline SubstituteArg(char value)
+ : text_(scratch_), size_(1) { scratch_[0] = value; }
+ inline SubstituteArg(short value)
+ : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(unsigned short value)
+ : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(int value)
+ : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(unsigned int value)
+ : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(long value)
+ : text_(FastLongToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(unsigned long value)
+ : text_(FastULongToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(long long value)
+ : text_(FastInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(unsigned long long value)
+ : text_(FastUInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(float value)
+ : text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(double value)
+ : text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {}
+ inline SubstituteArg(bool value)
+ : text_(value ? "true" : "false"), size_(strlen(text_)) {}
+
+ inline const char* data() const { return text_; }
+ inline int size() const { return size_; }
+
+ private:
+ const char* text_;
+ int size_;
+ char scratch_[kFastToBufferSize];
+};
+
+} // namespace internal
+
+LIBPROTOBUF_EXPORT string Substitute(
+ const char* format,
+ const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg9 = internal::SubstituteArg());
+
+LIBPROTOBUF_EXPORT void SubstituteAndAppend(
+ string* output, const char* format,
+ const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
+ const internal::SubstituteArg& arg9 = internal::SubstituteArg());
+
+} // namespace strings
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_