text:
// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// from google3/util/gtl/shared_ptr.h

#ifndef GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__
#define GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__

#include <google/protobuf/stubs/atomicops.h>

#include <algorithm>  // for swap
#include <stddef.h>
#include <memory>

namespace google {
namespace protobuf {
namespace internal {

// Alias to std::shared_ptr for any C++11 platform,
// and for any supported MSVC compiler.
#if !defined(UTIL_GTL_USE_STD_SHARED_PTR) && \
    (defined(COMPILER_MSVC) || defined(LANG_CXX11))
#define UTIL_GTL_USE_STD_SHARED_PTR 1
#endif

#if defined(UTIL_GTL_USE_STD_SHARED_PTR) && UTIL_GTL_USE_STD_SHARED_PTR

// These are transitional.  They will be going away soon.
// Please just #include <memory> and just type std::shared_ptr yourself, instead
// of relying on this file.
//
// Migration doc: http://go/std-shared-ptr-lsc
using std::enable_shared_from_this;
using std::shared_ptr;
using std::static_pointer_cast;
using std::weak_ptr;

#else  // below, UTIL_GTL_USE_STD_SHARED_PTR not set or set to 0.

// For everything else there is the google3 implementation.
inline bool RefCountDec(volatile Atomic32 *ptr) {
  return Barrier_AtomicIncrement(ptr, -1) != 0;
}

inline void RefCountInc(volatile Atomic32 *ptr) {
  NoBarrier_AtomicIncrement(ptr, 1);
}

template <typename T> class shared_ptr;
template <typename T> class weak_ptr;

// This class is an internal implementation detail for shared_ptr. If two
// shared_ptrs point to the same object, they also share a control block.
// An "empty" shared_pointer refers to NULL and also has a NULL control block.
// It contains all of the state that's needed for reference counting or any
// other kind of resource management. In this implementation the control block
// happens to consist of two atomic words, the reference count (the number
// of shared_ptrs that share ownership of the object) and the weak count
// (the number of weak_ptrs that observe the object, plus 1 if the
// refcount is nonzero).
//
// The "plus 1" is to prevent a race condition in the shared_ptr and
// weak_ptr destructors. We need to make sure the control block is
// only deleted once, so we need to make sure that at most one
// object sees the weak count decremented from 1 to 0.
class SharedPtrControlBlock {
  template <typename T> friend class shared_ptr;
  template <typename T> friend class weak_ptr;
 private:
  SharedPtrControlBlock() : refcount_(1), weak_count_(1) { }
  Atomic32 refcount_;
  Atomic32 weak_count_;
};

// Forward declaration. The class is defined below.
template <typename T> class enable_shared_from_this;

template <typename T>
class shared_ptr {
  template <typename U> friend class weak_ptr;
 public:
  typedef T element_type;

  shared_ptr() : ptr_(NULL), control_block_(NULL) {}

  explicit shared_ptr(T* ptr)
      : ptr_(ptr),
        control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
    // If p is non-null and T inherits from enable_shared_from_this, we
    // set up the data that shared_from_this needs.
    MaybeSetupWeakThis(ptr);
  }

  // Copy constructor: makes this object a copy of ptr, and increments
  // the reference count.
  template <typename U>
  shared_ptr(const shared_ptr<U>& ptr)
      : ptr_(NULL),
        control_block_(NULL) {
    Initialize(ptr);
  }
  // Need non-templated version to prevent the compiler-generated default
  shared_ptr(const shared_ptr<T>& ptr)
      : ptr_(NULL),
        control_block_(NULL) {
    Initialize(ptr);
  }

  // Assignment operator. Replaces the existing shared_ptr with ptr.
  // Increment ptr's reference count and decrement the one being replaced.
  template <typename U>
  shared_ptr<T>& operator=(const shared_ptr<U>& ptr) {
    if (ptr_ != ptr.ptr_) {
      shared_ptr<T> me(ptr);   // will hold our previous state to be destroyed.
      swap(me);
    }
    return *this;
  }

  // Need non-templated version to prevent the compiler-generated default
  shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
    if (ptr_ != ptr.ptr_) {
      shared_ptr<T> me(ptr);   // will hold our previous state to be destroyed.
      swap(me);
    }
    return *this;
  }

  // TODO(austern): Consider providing this constructor. The draft C++ standard
  // (20.8.10.2.1) includes it. However, it says that this constructor throws
  // a bad_weak_ptr exception when ptr is expired. Is it better to provide this
  // constructor and make it do something else, like fail with a CHECK, or to
  // leave this constructor out entirely?
  //
  // template <typename U>
  // shared_ptr(const weak_ptr<U>& ptr);

  ~shared_ptr() {
    if (ptr_ != NULL) {
      if (!RefCountDec(&control_block_->refcount_)) {
        delete ptr_;

        // weak_count_ is defined as the number of weak_ptrs that observe
        // ptr_, plus 1 if refcount_ is nonzero.
        if (!RefCountDec(&control_block_->weak_count_)) {
          delete control_block_;
        }
      }
    }
  }

  // Replaces underlying raw pointer with the one passed in.  The reference
  // count is set to one (or zero if the pointer is NULL) for the pointer
  // being passed in and decremented for the one being replaced.
  //
  // If you have a compilation error with this code, make sure you aren't
  // passing NULL, nullptr, or 0 to this function.  Call reset without an
  // argument to reset to a null ptr.
  template <typename Y>
  void reset(Y* p) {
    if (p != ptr_) {
      shared_ptr<T> tmp(p);
      tmp.swap(*this);
    }
  }

  void reset() {
    reset(static_cast<T*>(NULL));
  }

  // Exchanges the contents of this with the contents of r.  This function
  // supports more efficient swapping since it eliminates the need for a
  // temporary shared_ptr object.
  void swap(shared_ptr<T>& r) {
    using std::swap;  // http://go/using-std-swap
    swap(ptr_, r.ptr_);
    swap(control_block_, r.control_block_);
  }

  // The following function is useful for gaining access to the underlying
  // pointer when a shared_ptr remains in scope so the reference-count is
  // known to be > 0 (e.g. for parameter passing).
  T* get() const {
    return ptr_;
  }

  T& operator*() const {
    return *ptr_;
  }

  T* operator->() const {
    return ptr_;
  }

  long use_count() const {
    return control_block_ ? control_block_->refcount_ : 1;
  }

  bool unique() const {
    return use_count() == 1;
  }

 private:
  // If r is non-empty, initialize *this to share ownership with r,
  // increasing the underlying reference count.
  // If r is empty, *this remains empty.
  // Requires: this is empty, namely this->ptr_ == NULL.
  template <typename U>
  void Initialize(const shared_ptr<U>& r) {
    // This performs a static_cast on r.ptr_ to U*, which is a no-op since it
    // is already a U*. So initialization here requires that r.ptr_ is
    // implicitly convertible to T*.
    InitializeWithStaticCast<U>(r);
  }

  // Initializes *this as described in Initialize, but additionally performs a
  // static_cast from r.ptr_ (V*) to U*.
  // NOTE(gfc): We'd need a more general form to support const_pointer_cast and
  // dynamic_pointer_cast, but those operations are sufficiently discouraged
  // that supporting static_pointer_cast is sufficient.
  template <typename U, typename V>
  void InitializeWithStaticCast(const shared_ptr<V>& r) {
    if (r.control_block_ != NULL) {
      RefCountInc(&r.control_block_->refcount_);

      ptr_ = static_cast<U*>(r.ptr_);
      control_block_ = r.control_block_;
    }
  }

  // Helper function for the constructor that takes a raw pointer. If T
  // doesn't inherit from enable_shared_from_this<T> then we have nothing to
  // do, so this function is trivial and inline. The other version is declared
  // out of line, after the class definition of enable_shared_from_this.
  void MaybeSetupWeakThis(enable_shared_from_this<T>* ptr);
  void MaybeSetupWeakThis(...) { }

  T* ptr_;
  SharedPtrControlBlock* control_block_;

#ifndef SWIG
  template <typename U>
  friend class shared_ptr;

  template <typename U, typename V>
  friend shared_ptr<U> static_pointer_cast(const shared_ptr<V>& rhs);
#endif
};

// Matches the interface of std::swap as an aid to generic programming.
template <typename T> void swap(shared_ptr<T>& r, shared_ptr<T>& s) {
  r.swap(s);
}

template <typename T, typename U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& rhs) {
  shared_ptr<T> lhs;
  lhs.template InitializeWithStaticCast<T>(rhs);
  return lhs;
}

// See comments at the top of the file for a description of why this
// class exists, and the draft C++ standard (as of July 2009 the
// latest draft is N2914) for the detailed specification.
template <typename T>
class weak_ptr {
  template <typename U> friend class weak_ptr;
 public:
  typedef T element_type;

  // Create an empty (i.e. already expired) weak_ptr.
  weak_ptr() : ptr_(NULL), control_block_(NULL) { }

  // Create a weak_ptr that observes the same object that ptr points
  // to.  Note that there is no race condition here: we know that the
  // control block can't disappear while we're looking at it because
  // it is owned by at least one shared_ptr, ptr.
  template <typename U> weak_ptr(const shared_ptr<U>& ptr) {
    CopyFrom(ptr.ptr_, ptr.control_block_);
  }

  // Copy a weak_ptr. The object it points to might disappear, but we
  // don't care: we're only working with the control block, and it can't
  // disappear while we're looking at because it's owned by at least one
  // weak_ptr, ptr.
  template <typename U> weak_ptr(const weak_ptr<U>& ptr) {
    CopyFrom(ptr.ptr_, ptr.control_block_);
  }

  // Need non-templated version to prevent default copy constructor
  weak_ptr(const weak_ptr& ptr) {
    CopyFrom(ptr.ptr_, ptr.control_block_);
  }

  // Destroy the weak_ptr. If no shared_ptr owns the control block, and if
  // we are the last weak_ptr to own it, then it can be deleted. Note that
  // weak_count_ is defined as the number of weak_ptrs sharing this control
  // block, plus 1 if there are any shared_ptrs. We therefore know that it's
  // safe to delete the control block when weak_count_ reaches 0, without
  // having to perform any additional tests.
  ~weak_ptr() {
    if (control_block_ != NULL &&
        !RefCountDec(&control_block_->weak_count_)) {
      delete control_block_;
    }
  }

  weak_ptr& operator=(const weak_ptr& ptr) {
    if (&ptr != this) {
      weak_ptr tmp(ptr);
      tmp.swap(*this);
    }
    return *this;
  }
  template <typename U> weak_ptr& operator=(const weak_ptr<U>& ptr) {
    weak_ptr tmp(ptr);
    tmp.swap(*this);
    return *this;
  }
  template <typename U> weak_ptr& operator=(const shared_ptr<U>& ptr) {
    weak_ptr tmp(ptr);
    tmp.swap(*this);
    return *this;
  }

  void swap(weak_ptr& ptr) {
    using std::swap;  // http://go/using-std-swap
    swap(ptr_, ptr.ptr_);
    swap(control_block_, ptr.control_block_);
  }

  void reset() {
    weak_ptr tmp;
    tmp.swap(*this);
  }

  // Return the number of shared_ptrs that own the object we are observing.
  // Note that this number can be 0 (if this pointer has expired).
  long use_count() const {
    return control_block_ != NULL ? control_block_->refcount_ : 0;
  }

  bool expired() const { return use_count() == 0; }

  // Return a shared_ptr that owns the object we are observing. If we
  // have expired, the shared_ptr will be empty. We have to be careful
  // about concurrency, though, since some other thread might be
  // destroying the last owning shared_ptr while we're in this
  // function.  We want to increment the refcount only if it's nonzero
  // and get the new value, and we want that whole operation to be
  // atomic.
  shared_ptr<T> lock() const {
    shared_ptr<T> result;
    if (control_block_ != NULL) {
      Atomic32 old_refcount;
      do {
        old_refcount = control_block_->refcount_;
        if (old_refcount == 0)
          break;
      } while (old_refcount !=
               NoBarrier_CompareAndSwap(
                   &control_block_->refcount_, old_refcount,
                   old_refcount + 1));
      if (old_refcount > 0) {
        result.ptr_ = ptr_;
        result.control_block_ = control_block_;
      }
    }

    return result;
  }

 private:
  void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) {
    ptr_ = ptr;
    control_block_ = control_block;
    if (control_block_ != NULL)
      RefCountInc(&control_block_->weak_count_);
  }

 private:
  element_type* ptr_;
  SharedPtrControlBlock* control_block_;
};

template <typename T> void swap(weak_ptr<T>& r, weak_ptr<T>& s) {
  r.swap(s);
}

// See comments at the top of the file for a description of why this class
// exists, and section 20.8.10.5 of the draft C++ standard (as of July 2009
// the latest draft is N2914) for the detailed specification.
template <typename T>
class enable_shared_from_this {
  friend class shared_ptr<T>;
 public:
  // Precondition: there must be a shared_ptr that owns *this and that was
  // created, directly or indirectly, from a raw pointer of type T*. (The
  // latter part of the condition is technical but not quite redundant; it
  // rules out some complicated uses involving inheritance hierarchies.)
  shared_ptr<T> shared_from_this() {
    // Behavior is undefined if the precondition isn't satisfied; we choose
    // to die with a CHECK failure.
    GOOGLE_CHECK(!weak_this_.expired()) << "No shared_ptr owns this object";
    return weak_this_.lock();
  }
  shared_ptr<const T> shared_from_this() const {
    GOOGLE_CHECK(!weak_this_.expired()) << "No shared_ptr owns this object";
    return weak_this_.lock();
  }

 protected:
  enable_shared_from_this() { }
  enable_shared_from_this(const enable_shared_from_this& other) { }
  enable_shared_from_this& operator=(const enable_shared_from_this& other) {
    return *this;
  }
  ~enable_shared_from_this() { }

 private:
  weak_ptr<T> weak_this_;
};

// This is a helper function called by shared_ptr's constructor from a raw
// pointer. If T inherits from enable_shared_from_this<T>, it sets up
// weak_this_ so that shared_from_this works correctly. If T does not inherit
// from weak_this we get a different overload, defined inline, which does
// nothing.
template<typename T>
void shared_ptr<T>::MaybeSetupWeakThis(enable_shared_from_this<T>* ptr) {
  if (ptr) {
    GOOGLE_CHECK(ptr->weak_this_.expired())
        << "Object already owned by a shared_ptr";
    ptr->weak_this_ = *this;
  }
}

#endif  // UTIL_GTL_USE_STD_SHARED_PTR

}  // internal
}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// 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 <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/macros.h>
#include <google/protobuf/stubs/platform_macros.h>

// TODO(liujisi): Remove the following includes after the include clean-up.
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/callback.h>

#ifndef PROTOBUF_USE_EXCEPTIONS
#if defined(_MSC_VER) && defined(_CPPUNWIND)
  #define PROTOBUF_USE_EXCEPTIONS 1
#elif defined(__EXCEPTIONS)
  #define PROTOBUF_USE_EXCEPTIONS 1
#else
  #define PROTOBUF_USE_EXCEPTIONS 0
#endif
#endif

#if PROTOBUF_USE_EXCEPTIONS
#include <exception>
#endif
#if defined(__APPLE__)
#include <TargetConditionals.h>  // for TARGET_OS_IPHONE
#endif

#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
#include <pthread.h>
#endif

#if defined(_WIN32) && defined(GetMessage)
// Allow GetMessage to be used as a valid method name in protobuf classes.
// windows.h defines GetMessage() as a macro.  Let's re-define it as an inline
// function.  The inline function should be equivalent for C++ users.
inline BOOL GetMessage_Win32(
    LPMSG lpMsg, HWND hWnd,
    UINT wMsgFilterMin, UINT wMsgFilterMax) {
  return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
}
#undef GetMessage
inline BOOL GetMessage(
    LPMSG lpMsg, HWND hWnd,
    UINT wMsgFilterMin, UINT wMsgFilterMax) {
  return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
}
#endif

namespace std {}

namespace google {
namespace protobuf {
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 3005001

// A suffix string for alpha, beta or rc releases. Empty for stable releases.
#define GOOGLE_PROTOBUF_VERSION_SUFFIX ""

// The minimum library version which works with the current version of the
// headers.
#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3005000

// 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 = 3005000;

// The minimum protoc version which works with the current version of the
// headers.
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3005000

// The minimum header version which works with the current version of
// protoc.  This constant should only be used in VerifyVersion().
static const int kMinHeaderVersionForProtoc = 3005000;

// 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.
std::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/util/utf8/public/unilib.h

class StringPiece;
namespace internal {

// Checks if the buffer contains structurally-valid UTF-8.  Implemented in
// structurally_valid.cc.
LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);

inline bool IsStructurallyValidUTF8(const std::string& str) {
  return IsStructurallyValidUTF8(str.data(), static_cast<int>(str.length()));
}

// Returns initial number of bytes of structually valid UTF-8.
LIBPROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str);

// Coerce UTF-8 byte string in src_str to be
// a structurally-valid equal-length string by selectively
// overwriting illegal bytes with replace_char (typically ' ' or '?').
// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
// src_str is read-only.
//
// Returns pointer to output buffer, src_str.data() if no changes were made,
//  or idst if some bytes were changed. idst is allocated by the caller
//  and must be at least as big as src_str
//
// Optimized for: all structurally valid and no byte copying is done.
//
LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(
    const StringPiece& str, char* dst, char replace_char);

}  // namespace internal

// ===================================================================
// Shutdown support.

// Shut down the entire protocol buffers library, deleting all static-duration
// objects allocated by the library or by generated .pb.cc files.
//
// There are two reasons you might want to call this:
// * You use a draconian definition of "memory leak" in which you expect
//   every single malloc() to have a corresponding free(), even for objects
//   which live until program exit.
// * You are writing a dynamically-loaded library which needs to clean up
//   after itself when the library is unloaded.
//
// It is safe to call this multiple times.  However, it is not safe to use
// any other part of the protocol buffers library after
// ShutdownProtobufLibrary() has been called.
LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary();

namespace internal {

// Register a function to be called when ShutdownProtocolBuffers() is called.
LIBPROTOBUF_EXPORT void OnShutdown(void (*func)());
// Destroy the string (call string destructor)
LIBPROTOBUF_EXPORT void OnShutdownDestroyString(const std::string* ptr);
// Destroy (not delete) the message
LIBPROTOBUF_EXPORT void OnShutdownDestroyMessage(const void* ptr);

}  // namespace internal

#if PROTOBUF_USE_EXCEPTIONS
class FatalException : public std::exception {
 public:
  FatalException(const char* filename, int line, const std::string& message)
      : filename_(filename), line_(line), message_(message) {}
  virtual ~FatalException() throw();

  virtual const char* what() const throw();

  const char* filename() const { return filename_; }
  int line() const { return line_; }
  const std::string& message() const { return message_; }

 private:
  const char* filename_;
  const int line_;
  const std::string message_;
};
#endif

// This is at the end of the file instead of the beginning to work around a bug
// in some versions of MSVC.
// TODO(acozzette): remove these using statements
using std::istream;
using std::ostream;
using std::pair;
using std::string;
using std::vector;

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_COMMON_H__

mime_type: text/plain


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2012 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// This file is an internal atomic implementation, use atomicops.h instead.

#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_

namespace google {
namespace protobuf {
namespace internal {

// This struct is not part of the public API of this module; clients may not
// use it.
// Features of this x86.  Values may not be correct before main() is run,
// but are set conservatively.
struct AtomicOps_x86CPUFeatureStruct {
  bool has_amd_lock_mb_bug;  // Processor has AMD memory-barrier bug; do lfence
                             // after acquire compare-and-swap.
  bool has_sse2;             // Processor has SSE2.
};
extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures;

#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")

// 32-bit low-level operations on any platform.

inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
                                         Atomic32 old_value,
                                         Atomic32 new_value) {
  Atomic32 prev;
  __asm__ __volatile__("lock; cmpxchgl %1,%2"
                       : "=a" (prev)
                       : "q" (new_value), "m" (*ptr), "0" (old_value)
                       : "memory");
  return prev;
}

inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
                                         Atomic32 new_value) {
  __asm__ __volatile__("xchgl %1,%0"  // The lock prefix is implicit for xchg.
                       : "=r" (new_value)
                       : "m" (*ptr), "0" (new_value)
                       : "memory");
  return new_value;  // Now it's the previous value.
}

inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
                                          Atomic32 increment) {
  Atomic32 temp = increment;
  __asm__ __volatile__("lock; xaddl %0,%1"
                       : "+r" (temp), "+m" (*ptr)
                       : : "memory");
  // temp now holds the old value of *ptr
  return temp + increment;
}

inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
                                        Atomic32 increment) {
  Atomic32 temp = increment;
  __asm__ __volatile__("lock; xaddl %0,%1"
                       : "+r" (temp), "+m" (*ptr)
                       : : "memory");
  // temp now holds the old value of *ptr
  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
    __asm__ __volatile__("lfence" : : : "memory");
  }
  return temp + increment;
}

inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
                                       Atomic32 old_value,
                                       Atomic32 new_value) {
  Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
    __asm__ __volatile__("lfence" : : : "memory");
  }
  return x;
}

inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
                                       Atomic32 old_value,
                                       Atomic32 new_value) {
  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}

inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
  *ptr = value;
}

#if defined(__x86_64__)

// 64-bit implementations of memory barrier can be simpler, because it
// "mfence" is guaranteed to exist.
inline void MemoryBarrierInternal() {
  __asm__ __volatile__("mfence" : : : "memory");
}

inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
  *ptr = value;
  MemoryBarrierInternal();
}

#else

inline void MemoryBarrierInternal() {
  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
    __asm__ __volatile__("mfence" : : : "memory");
  } else {  // mfence is faster but not present on PIII
    Atomic32 x = 0;
    NoBarrier_AtomicExchange(&x, 0);  // acts as a barrier on PIII
  }
}

inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
  if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
    *ptr = value;
    __asm__ __volatile__("mfence" : : : "memory");
  } else {
    NoBarrier_AtomicExchange(ptr, value);
                          // acts as a barrier on PIII
  }
}
#endif

inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
  ATOMICOPS_COMPILER_BARRIER();
  *ptr = value;  // An x86 store acts as a release barrier.
  // See comments in Atomic64 version of Release_Store(), below.
}

inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
  return *ptr;
}

inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
  Atomic32 value = *ptr;  // An x86 load acts as a acquire barrier.
  // See comments in Atomic64 version of Release_Store(), below.
  ATOMICOPS_COMPILER_BARRIER();
  return value;
}

inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
  MemoryBarrierInternal();
  return *ptr;
}

#if defined(__x86_64__)

// 64-bit low-level operations on 64-bit platform.

inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
                                         Atomic64 old_value,
                                         Atomic64 new_value) {
  Atomic64 prev;
  __asm__ __volatile__("lock; cmpxchgq %1,%2"
                       : "=a" (prev)
                       : "q" (new_value), "m" (*ptr), "0" (old_value)
                       : "memory");
  return prev;
}

inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
                                         Atomic64 new_value) {
  __asm__ __volatile__("xchgq %1,%0"  // The lock prefix is implicit for xchg.
                       : "=r" (new_value)
                       : "m" (*ptr), "0" (new_value)
                       : "memory");
  return new_value;  // Now it's the previous value.
}

inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
                                          Atomic64 increment) {
  Atomic64 temp = increment;
  __asm__ __volatile__("lock; xaddq %0,%1"
                       : "+r" (temp), "+m" (*ptr)
                       : : "memory");
  // temp now contains the previous value of *ptr
  return temp + increment;
}

inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
                                        Atomic64 increment) {
  Atomic64 temp = increment;
  __asm__ __volatile__("lock; xaddq %0,%1"
                       : "+r" (temp), "+m" (*ptr)
                       : : "memory");
  // temp now contains the previous value of *ptr
  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
    __asm__ __volatile__("lfence" : : : "memory");
  }
  return temp + increment;
}

inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
  *ptr = value;
}

inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
  *ptr = value;
  MemoryBarrierInternal();
}

inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
  ATOMICOPS_COMPILER_BARRIER();

  *ptr = value;  // An x86 store acts as a release barrier
                 // for current AMD/Intel chips as of Jan 2008.
                 // See also Acquire_Load(), below.

  // When new chips come out, check:
  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
  //  System Programming Guide, Chatper 7: Multiple-processor management,
  //  Section 7.2, Memory Ordering.
  // Last seen at:
  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
  //
  // x86 stores/loads fail to act as barriers for a few instructions (clflush
  // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
  // not generated by the compiler, and are rare.  Users of these instructions
  // need to know about cache behaviour in any case since all of these involve
  // either flushing cache lines or non-temporal cache hints.
}

inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
  return *ptr;
}

inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
  Atomic64 value = *ptr;  // An x86 load acts as a acquire barrier,
                          // for current AMD/Intel chips as of Jan 2008.
                          // See also Release_Store(), above.
  ATOMICOPS_COMPILER_BARRIER();
  return value;
}

inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
  MemoryBarrierInternal();
  return *ptr;
}

inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
                                       Atomic64 old_value,
                                       Atomic64 new_value) {
  Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
    __asm__ __volatile__("lfence" : : : "memory");
  }
  return x;
}

inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
                                       Atomic64 old_value,
                                       Atomic64 new_value) {
  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}

#endif  // defined(__x86_64__)

}  // namespace internal
}  // namespace protobuf
}  // namespace google

#undef ATOMICOPS_COMPILER_BARRIER

#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_CASTS_H__
#define GOOGLE_PROTOBUF_CASTS_H__

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/type_traits.h>

namespace google {
namespace protobuf {
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);
  }

#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
  assert(f == NULL || dynamic_cast<To>(f) != NULL);  // RTTI: debug mode only!
#endif
  return static_cast<To>(f);
}

template<typename To, typename From>    // use like this: down_cast<T&>(foo);
inline To down_cast(From& f) {
  typedef typename remove_reference<To>::type* ToAsPointer;
  // 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*, ToAsPointer>(0);
  }

#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
  // RTTI: debug mode only!
  assert(dynamic_cast<ToAsPointer>(&f) != NULL);
#endif
  return *static_cast<ToAsPointer>(&f);
}

template<typename To, typename From>
inline To bit_cast(const From& from) {
  GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
                        bit_cast_with_different_sizes);
  To dest;
  memcpy(&dest, &from, sizeof(dest));
  return dest;
}

}  // 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;
using internal::bit_cast;

}  // namespace protobuf
}  // namespace google
#endif  // GOOGLE_PROTOBUF_CASTS_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2012 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The compilation of extension_set.cc fails when windows.h is included.
// Therefore we move the code depending on windows.h to this separate cc file.

// Don't compile this file for people not concerned about thread safety.
#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY

#include <google/protobuf/stubs/atomicops.h>

#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_

#include <windows.h>

namespace google {
namespace protobuf {
namespace internal {

inline void MemoryBarrierInternal() {
  // On ARM this is a define while on x86/x64 this is
  // a function declared in WinNT.h
  MemoryBarrier();
}

Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
                                  Atomic32 old_value,
                                  Atomic32 new_value) {
  LONG result = InterlockedCompareExchange(
      reinterpret_cast<volatile LONG*>(ptr),
      static_cast<LONG>(new_value),
      static_cast<LONG>(old_value));
  return static_cast<Atomic32>(result);
}

Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
                                  Atomic32 new_value) {
  LONG result = InterlockedExchange(
      reinterpret_cast<volatile LONG*>(ptr),
      static_cast<LONG>(new_value));
  return static_cast<Atomic32>(result);
}

Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
                                 Atomic32 increment) {
  return InterlockedExchangeAdd(
      reinterpret_cast<volatile LONG*>(ptr),
      static_cast<LONG>(increment)) + increment;
}

#if defined(_WIN64)

// 64-bit low-level operations on 64-bit platform.

Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
                                  Atomic64 old_value,
                                  Atomic64 new_value) {
  PVOID result = InterlockedCompareExchangePointer(
    reinterpret_cast<volatile PVOID*>(ptr),
    reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
  return reinterpret_cast<Atomic64>(result);
}

Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
                                  Atomic64 new_value) {
  PVOID result = InterlockedExchangePointer(
    reinterpret_cast<volatile PVOID*>(ptr),
    reinterpret_cast<PVOID>(new_value));
  return reinterpret_cast<Atomic64>(result);
}

Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
                                 Atomic64 increment) {
  return InterlockedExchangeAdd64(
      reinterpret_cast<volatile LONGLONG*>(ptr),
      static_cast<LONGLONG>(increment)) + increment;
}

#endif  // defined(_WIN64)

}  // namespace internal
}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
#endif  // GOOGLE_PROTOBUF_NO_THREAD_SAFETY


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <google/protobuf/stubs/int128.h>

#include <algorithm>
#include <sstream>
#include <utility>

#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>

namespace google {
namespace protobuf {

TEST(Int128, AllTests) {
  uint128 zero(0);
  uint128 one(1);
  uint128 one_2arg(0, 1);
  uint128 two(0, 2);
  uint128 three(0, 3);
  uint128 big(2000, 2);
  uint128 big_minus_one(2000, 1);
  uint128 bigger(2001, 1);
  uint128 biggest(kuint128max);
  uint128 high_low(1, 0);
  uint128 low_high(0, kuint64max);
  EXPECT_LT(one, two);
  EXPECT_GT(two, one);
  EXPECT_LT(one, big);
  EXPECT_LT(one, big);
  EXPECT_EQ(one, one_2arg);
  EXPECT_NE(one, two);
  EXPECT_GT(big, one);
  EXPECT_GE(big, two);
  EXPECT_GE(big, big_minus_one);
  EXPECT_GT(big, big_minus_one);
  EXPECT_LT(big_minus_one, big);
  EXPECT_LE(big_minus_one, big);
  EXPECT_NE(big_minus_one, big);
  EXPECT_LT(big, biggest);
  EXPECT_LE(big, biggest);
  EXPECT_GT(biggest, big);
  EXPECT_GE(biggest, big);
  EXPECT_EQ(big, ~~big);
  EXPECT_EQ(one, one | one);
  EXPECT_EQ(big, big | big);
  EXPECT_EQ(one, one | zero);
  EXPECT_EQ(one, one & one);
  EXPECT_EQ(big, big & big);
  EXPECT_EQ(zero, one & zero);
  EXPECT_EQ(zero, big & ~big);
  EXPECT_EQ(zero, one ^ one);
  EXPECT_EQ(zero, big ^ big);
  EXPECT_EQ(one, one ^ zero);

  // Shift operators.
  EXPECT_EQ(big, big << 0);
  EXPECT_EQ(big, big >> 0);
  EXPECT_GT(big << 1, big);
  EXPECT_LT(big >> 1, big);
  EXPECT_EQ(big, (big << 10) >> 10);
  EXPECT_EQ(big, (big >> 1) << 1);
  EXPECT_EQ(one, (one << 80) >> 80);
  EXPECT_EQ(zero, (one >> 80) << 80);
  EXPECT_EQ(zero, big >> 128);
  EXPECT_EQ(zero, big << 128);

  // Shift assignments.
  uint128 big_copy = big;
  EXPECT_EQ(big << 0, big_copy <<= 0);
  big_copy = big;
  EXPECT_EQ(big >> 0, big_copy >>= 0);
  big_copy = big;
  EXPECT_EQ(big << 1, big_copy <<= 1);
  big_copy = big;
  EXPECT_EQ(big >> 1, big_copy >>= 1);
  big_copy = big;
  EXPECT_EQ(big << 10, big_copy <<= 10);
  big_copy = big;
  EXPECT_EQ(big >> 10, big_copy >>= 10);
  big_copy = big;
  EXPECT_EQ(big << 64, big_copy <<= 64);
  big_copy = big;
  EXPECT_EQ(big >> 64, big_copy >>= 64);
  big_copy = big;
  EXPECT_EQ(big << 73, big_copy <<= 73);
  big_copy = big;
  EXPECT_EQ(big >> 73, big_copy >>= 73);
  big_copy = big;
  EXPECT_EQ(big << 128, big_copy <<= 128);
  big_copy = big;
  EXPECT_EQ(big >> 128, big_copy >>= 128);

  EXPECT_EQ(Uint128High64(biggest), kuint64max);
  EXPECT_EQ(Uint128Low64(biggest), kuint64max);
  EXPECT_EQ(zero + one, one);
  EXPECT_EQ(one + one, two);
  EXPECT_EQ(big_minus_one + one, big);
  EXPECT_EQ(one - one, zero);
  EXPECT_EQ(one - zero, one);
  EXPECT_EQ(zero - one, biggest);
  EXPECT_EQ(big - big, zero);
  EXPECT_EQ(big - one, big_minus_one);
  EXPECT_EQ(big + kuint64max, bigger);
  EXPECT_EQ(biggest + 1, zero);
  EXPECT_EQ(zero - 1, biggest);
  EXPECT_EQ(high_low - one, low_high);
  EXPECT_EQ(low_high + one, high_low);
  EXPECT_EQ(Uint128High64((uint128(1) << 64) - 1), 0);
  EXPECT_EQ(Uint128Low64((uint128(1) << 64) - 1), kuint64max);
  EXPECT_TRUE(!!one);
  EXPECT_TRUE(!!high_low);
  EXPECT_FALSE(!!zero);
  EXPECT_FALSE(!one);
  EXPECT_FALSE(!high_low);
  EXPECT_TRUE(!zero);
  EXPECT_TRUE(zero == 0);
  EXPECT_FALSE(zero != 0);
  EXPECT_FALSE(one == 0);
  EXPECT_TRUE(one != 0);

  uint128 test = zero;
  EXPECT_EQ(++test, one);
  EXPECT_EQ(test, one);
  EXPECT_EQ(test++, one);
  EXPECT_EQ(test, two);
  EXPECT_EQ(test -= 2, zero);
  EXPECT_EQ(test, zero);
  EXPECT_EQ(test += 2, two);
  EXPECT_EQ(test, two);
  EXPECT_EQ(--test, one);
  EXPECT_EQ(test, one);
  EXPECT_EQ(test--, one);
  EXPECT_EQ(test, zero);
  EXPECT_EQ(test |= three, three);
  EXPECT_EQ(test &= one, one);
  EXPECT_EQ(test ^= three, two);
  EXPECT_EQ(test >>= 1, one);
  EXPECT_EQ(test <<= 1, two);

  EXPECT_EQ(big, -(-big));
  EXPECT_EQ(two, -((-one) - 1));
  EXPECT_EQ(kuint128max, -one);
  EXPECT_EQ(zero, -zero);

  GOOGLE_LOG(INFO) << one;
  GOOGLE_LOG(INFO) << big_minus_one;
}

TEST(Int128, PodTests) {
  uint128_pod pod = { 12345, 67890 };
  uint128 from_pod(pod);
  EXPECT_EQ(12345, Uint128High64(from_pod));
  EXPECT_EQ(67890, Uint128Low64(from_pod));

  uint128 zero(0);
  uint128_pod zero_pod = {0, 0};
  uint128 one(1);
  uint128_pod one_pod = {0, 1};
  uint128 two(2);
  uint128_pod two_pod = {0, 2};
  uint128 three(3);
  uint128_pod three_pod = {0, 3};
  uint128 big(1, 0);
  uint128_pod big_pod = {1, 0};

  EXPECT_EQ(zero, zero_pod);
  EXPECT_EQ(zero_pod, zero);
  EXPECT_EQ(zero_pod, zero_pod);
  EXPECT_EQ(one, one_pod);
  EXPECT_EQ(one_pod, one);
  EXPECT_EQ(one_pod, one_pod);
  EXPECT_EQ(two, two_pod);
  EXPECT_EQ(two_pod, two);
  EXPECT_EQ(two_pod, two_pod);

  EXPECT_NE(one, two_pod);
  EXPECT_NE(one_pod, two);
  EXPECT_NE(one_pod, two_pod);

  EXPECT_LT(one, two_pod);
  EXPECT_LT(one_pod, two);
  EXPECT_LT(one_pod, two_pod);
  EXPECT_LE(one, one_pod);
  EXPECT_LE(one_pod, one);
  EXPECT_LE(one_pod, one_pod);
  EXPECT_LE(one, two_pod);
  EXPECT_LE(one_pod, two);
  EXPECT_LE(one_pod, two_pod);

  EXPECT_GT(two, one_pod);
  EXPECT_GT(two_pod, one);
  EXPECT_GT(two_pod, one_pod);
  EXPECT_GE(two, two_pod);
  EXPECT_GE(two_pod, two);
  EXPECT_GE(two_pod, two_pod);
  EXPECT_GE(two, one_pod);
  EXPECT_GE(two_pod, one);
  EXPECT_GE(two_pod, one_pod);

  EXPECT_EQ(three, one | two_pod);
  EXPECT_EQ(three, one_pod | two);
  EXPECT_EQ(three, one_pod | two_pod);
  EXPECT_EQ(one, three & one_pod);
  EXPECT_EQ(one, three_pod & one);
  EXPECT_EQ(one, three_pod & one_pod);
  EXPECT_EQ(two, three ^ one_pod);
  EXPECT_EQ(two, three_pod ^ one);
  EXPECT_EQ(two, three_pod ^ one_pod);
  EXPECT_EQ(two, three & (~one));
  EXPECT_EQ(three, ~~three);

  EXPECT_EQ(two, two_pod << 0);
  EXPECT_EQ(two, one_pod << 1);
  EXPECT_EQ(big, one_pod << 64);
  EXPECT_EQ(zero, one_pod << 128);
  EXPECT_EQ(two, two_pod >> 0);
  EXPECT_EQ(one, two_pod >> 1);
  EXPECT_EQ(one, big_pod >> 64);

  EXPECT_EQ(one, zero + one_pod);
  EXPECT_EQ(one, zero_pod + one);
  EXPECT_EQ(one, zero_pod + one_pod);
  EXPECT_EQ(one, two - one_pod);
  EXPECT_EQ(one, two_pod - one);
  EXPECT_EQ(one, two_pod - one_pod);
}

TEST(Int128, OperatorAssignReturnRef) {
  uint128 v(1);
  (v += 4) -= 3;
  EXPECT_EQ(2, v);
}

TEST(Int128, Multiply) {
  uint128 a, b, c;

  // Zero test.
  a = 0;
  b = 0;
  c = a * b;
  EXPECT_EQ(0, c);

  // Max carries.
  a = uint128(0) - 1;
  b = uint128(0) - 1;
  c = a * b;
  EXPECT_EQ(1, c);

  // Self-operation with max carries.
  c = uint128(0) - 1;
  c *= c;
  EXPECT_EQ(1, c);

  // 1-bit x 1-bit.
  for (int i = 0; i < 64; ++i) {
    for (int j = 0; j < 64; ++j) {
      a = uint128(1) << i;
      b = uint128(1) << j;
      c = a * b;
      EXPECT_EQ(uint128(1) << (i+j), c);
    }
  }

  // Verified with dc.
  a = uint128(GOOGLE_ULONGLONG(0xffffeeeeddddcccc),
              GOOGLE_ULONGLONG(0xbbbbaaaa99998888));
  b = uint128(GOOGLE_ULONGLONG(0x7777666655554444),
              GOOGLE_ULONGLONG(0x3333222211110000));
  c = a * b;
  EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x530EDA741C71D4C3),
                    GOOGLE_ULONGLONG(0xBF25975319080000)), c);
  EXPECT_EQ(0, c - b * a);
  EXPECT_EQ(a*a - b*b, (a+b) * (a-b));

  // Verified with dc.
  a = uint128(GOOGLE_ULONGLONG(0x0123456789abcdef),
              GOOGLE_ULONGLONG(0xfedcba9876543210));
  b = uint128(GOOGLE_ULONGLONG(0x02468ace13579bdf),
              GOOGLE_ULONGLONG(0xfdb97531eca86420));
  c = a * b;
  EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x97a87f4f261ba3f2),
                    GOOGLE_ULONGLONG(0x342d0bbf48948200)), c);
  EXPECT_EQ(0, c - b * a);
  EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
}

TEST(Int128, AliasTests) {
  uint128 x1(1, 2);
  uint128 x2(2, 4);
  x1 += x1;
  EXPECT_EQ(x2, x1);

  uint128 x3(1, static_cast<uint64>(1) << 63);
  uint128 x4(3, 0);
  x3 += x3;
  EXPECT_EQ(x4, x3);
}

#ifdef PROTOBUF_HAS_DEATH_TEST
TEST(Int128, DivideByZeroCheckFails) {
  uint128 a = 0;
  uint128 b = 0;
  EXPECT_DEATH(a / b, "Division or mod by zero:");
  a = 123;
  EXPECT_DEATH(a / b, "Division or mod by zero:");
}

TEST(Int128, ModByZeroCheckFails) {
  uint128 a = 0;
  uint128 b = 0;
  EXPECT_DEATH(a % b, "Division or mod by zero:");
  a = 123;
  EXPECT_DEATH(a % b, "Division or mod by zero:");
}
#endif  // PROTOBUF_HAS_DEATH_TEST

TEST(Int128, DivideAndMod) {
  // a := q * b + r
  uint128 a, b, q, r;

  // Zero test.
  a = 0;
  b = 123;
  q = a / b;
  r = a % b;
  EXPECT_EQ(0, q);
  EXPECT_EQ(0, r);

  a = uint128(GOOGLE_ULONGLONG(0x530eda741c71d4c3),
              GOOGLE_ULONGLONG(0xbf25975319080000));
  q = uint128(GOOGLE_ULONGLONG(0x4de2cab081),
              GOOGLE_ULONGLONG(0x14c34ab4676e4bab));
  b = uint128(0x1110001);
  r = uint128(0x3eb455);
  ASSERT_EQ(a, q * b + r);  // Sanity-check.

  uint128 result_q, result_r;
  result_q = a / b;
  result_r = a % b;
  EXPECT_EQ(q, result_q);
  EXPECT_EQ(r, result_r);

  // Try the other way around.
  std::swap(q, b);
  result_q = a / b;
  result_r = a % b;
  EXPECT_EQ(q, result_q);
  EXPECT_EQ(r, result_r);
  // Restore.
  std::swap(b, q);

  // Dividend < divisor; result should be q:0 r:<dividend>.
  std::swap(a, b);
  result_q = a / b;
  result_r = a % b;
  EXPECT_EQ(0, result_q);
  EXPECT_EQ(a, result_r);
  // Try the other way around.
  std::swap(a, q);
  result_q = a / b;
  result_r = a % b;
  EXPECT_EQ(0, result_q);
  EXPECT_EQ(a, result_r);
  // Restore.
  std::swap(q, a);
  std::swap(b, a);

  // Try a large remainder.
  b = a / 2 + 1;
  uint128 expected_r(GOOGLE_ULONGLONG(0x29876d3a0e38ea61),
                     GOOGLE_ULONGLONG(0xdf92cba98c83ffff));
  // Sanity checks.
  ASSERT_EQ(a / 2 - 1, expected_r);
  ASSERT_EQ(a, b + expected_r);
  result_q = a / b;
  result_r = a % b;
  EXPECT_EQ(1, result_q);
  EXPECT_EQ(expected_r, result_r);
}

static uint64 RandomUint64() {
  uint64 v1 = rand();
  uint64 v2 = rand();
  uint64 v3 = rand();
  return v1 * v2 + v3;
}

TEST(Int128, DivideAndModRandomInputs) {
  const int kNumIters = 1 << 18;
  for (int i = 0; i < kNumIters; ++i) {
    const uint128 a(RandomUint64(), RandomUint64());
    const uint128 b(RandomUint64(), RandomUint64());
    if (b == 0) {
      continue;  // Avoid a div-by-zero.
    }
    const uint128 q = a / b;
    const uint128 r = a % b;
    ASSERT_EQ(a, b * q + r);
  }
}

#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
TEST(Int128, ConstexprTest) {
  constexpr uint128 zero;
  constexpr uint128 one = 1;
  constexpr uint128_pod pod = {2, 3};
  constexpr uint128 from_pod = pod;
  constexpr uint128 minus_two = -2;
  EXPECT_EQ(one, uint128(1));
  EXPECT_EQ(from_pod, uint128(2, 3));
  EXPECT_EQ(minus_two, uint128(-1ULL, -2ULL));
}

TEST(Int128, Traits) {
  EXPECT_TRUE(std::is_trivially_copy_constructible<uint128>::value);
  EXPECT_TRUE(std::is_trivially_copy_assignable<uint128>::value);
  EXPECT_TRUE(std::is_trivially_destructible<uint128>::value);
}
#endif  // GOOGLE_PROTOBUF_HAS_CONSTEXPR

TEST(Int128, OStream) {
  struct {
    uint128 val;
    std::ios_base::fmtflags flags;
    std::streamsize width;
    char fill;
    const char* rep;
  } cases[] = {
        // zero with different bases
        {uint128(0), std::ios::dec, 0, '_', "0"},
        {uint128(0), std::ios::oct, 0, '_', "0"},
        {uint128(0), std::ios::hex, 0, '_', "0"},
        // crossover between lo_ and hi_
        {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"},
        {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"},
        {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"},
        {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"},
        {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"},
        {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"},
        // just the top bit
        {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0, '_',
         "170141183460469231731687303715884105728"},
        {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0, '_',
         "2000000000000000000000000000000000000000000"},
        {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0, '_',
         "80000000000000000000000000000000"},
        // maximum uint128 value
        {uint128(-1, -1), std::ios::dec, 0, '_',
         "340282366920938463463374607431768211455"},
        {uint128(-1, -1), std::ios::oct, 0, '_',
         "3777777777777777777777777777777777777777777"},
        {uint128(-1, -1), std::ios::hex, 0, '_',
         "ffffffffffffffffffffffffffffffff"},
        // uppercase
        {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_',
         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
        // showbase
        {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"},
        {uint128(1), std::ios::oct | std::ios::showbase, 0, '_', "01"},
        {uint128(1), std::ios::hex | std::ios::showbase, 0, '_', "0x1"},
        // showbase does nothing on zero
        {uint128(0), std::ios::dec | std::ios::showbase, 0, '_', "0"},
        {uint128(0), std::ios::oct | std::ios::showbase, 0, '_', "0"},
        {uint128(0), std::ios::hex | std::ios::showbase, 0, '_', "0"},
        // showpos does nothing on unsigned types
        {uint128(1), std::ios::dec | std::ios::showpos, 0, '_', "1"},
        // padding
        {uint128(9), std::ios::dec, 6, '_', "_____9"},
        {uint128(12345), std::ios::dec, 6, '_', "_12345"},
        // left adjustment
        {uint128(9), std::ios::dec | std::ios::left, 6, '_', "9_____"},
        {uint128(12345), std::ios::dec | std::ios::left, 6, '_', "12345_"},
  };
  for (size_t i = 0; i < GOOGLE_ARRAYSIZE(cases); ++i) {
    std::ostringstream os;
    os.flags(cases[i].flags);
    os.width(cases[i].width);
    os.fill(cases[i].fill);
    os << cases[i].val;
    EXPECT_EQ(cases[i].rep, os.str());
  }
}
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2012 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_

#define GOOGLE_PROTOBUF_PLATFORM_ERROR \
#error "Host platform was not detected as supported by protobuf"

// Processor architecture detection.  For more info on what's defined, see:
//   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
//   http://www.agner.org/optimize/calling_conventions.pdf
//   or with gcc, run: "echo | gcc -E -dM -"
#if defined(_M_X64) || defined(__x86_64__)
#define GOOGLE_PROTOBUF_ARCH_X64 1
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#elif defined(_M_IX86) || defined(__i386__)
#define GOOGLE_PROTOBUF_ARCH_IA32 1
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#elif defined(__QNX__)
#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#elif defined(_M_ARM) || defined(__ARMEL__)
#define GOOGLE_PROTOBUF_ARCH_ARM 1
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#elif defined(_M_ARM64)
#define GOOGLE_PROTOBUF_ARCH_ARM 1
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#elif defined(__aarch64__)
#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#elif defined(__MIPSEL__)
#if defined(__LP64__)
#define GOOGLE_PROTOBUF_ARCH_MIPS64 1
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#else
#define GOOGLE_PROTOBUF_ARCH_MIPS 1
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#endif
#elif defined(__pnacl__)
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#elif defined(sparc)
#define GOOGLE_PROTOBUF_ARCH_SPARC 1
#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#else
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#endif
#elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__)
#define GOOGLE_PROTOBUF_ARCH_POWER 1
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#elif defined(__PPC__)
#define GOOGLE_PROTOBUF_ARCH_PPC 1
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#elif defined(__GNUC__)
# if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
# elif defined(__clang__)
#  if !__has_extension(c_atomic)
GOOGLE_PROTOBUF_PLATFORM_ERROR
#  endif
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
# endif
# if __LP64__
#  define GOOGLE_PROTOBUF_ARCH_64_BIT 1
# else
#  define GOOGLE_PROTOBUF_ARCH_32_BIT 1
# endif
#else
GOOGLE_PROTOBUF_PLATFORM_ERROR
#endif

#if defined(__APPLE__)
#define GOOGLE_PROTOBUF_OS_APPLE
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
#define GOOGLE_PROTOBUF_OS_IPHONE
#endif
#elif defined(__EMSCRIPTEN__)
#define GOOGLE_PROTOBUF_OS_EMSCRIPTEN
#elif defined(__native_client__)
#define GOOGLE_PROTOBUF_OS_NACL
#elif defined(sun)
#define GOOGLE_PROTOBUF_OS_SOLARIS
#elif defined(_AIX)
#define GOOGLE_PROTOBUF_OS_AIX
#elif defined(__ANDROID__)
#define GOOGLE_PROTOBUF_OS_ANDROID
#endif

#undef GOOGLE_PROTOBUF_PLATFORM_ERROR

#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) || defined(__OpenBSD__)
// Android ndk does not support the __thread keyword very well yet. Here
// we use pthread_key_create()/pthread_getspecific()/... methods for
// TLS support on android.
// iOS and OpenBSD also do not support the __thread keyword.
#define GOOGLE_PROTOBUF_NO_THREADLOCAL
#endif

#endif  // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_


text:
// Copyright 2014 Bloomberg Finance LP. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Bloomberg Finance LP. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// This file is an internal atomic implementation, use atomicops.h instead.

#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_

namespace google {
namespace protobuf {
namespace internal {

inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
                                         Atomic32 old_value,
                                         Atomic32 new_value) {
  Atomic32 result;

  asm volatile (
      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       cmpw %[cmp], %[res]             \n\t"  // compare values
      "       bne- 2f                         \n\t"
      "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
      "       bne- 1b                         \n\t"
      "2:                                     \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [cmp]  "b"   (old_value),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
                                         Atomic32 new_value) {
  Atomic32 result;

  asm volatile (
      "1:     lwarx %[res], %[zero], %[obj]       \n\t"
      "       stwcx. %[val], %[zero], %[obj]      \n\t"
      "       bne- 1b                             \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
                                          Atomic32 increment) {
  Atomic32 result;

  asm volatile (
      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       add %[res], %[val], %[res]      \n\t"  // add the operand
      "       stwcx. %[res], %[zero], %[obj]  \n\t"  // store old value
                                                     // if still reserved
      "       bne- 1b                         \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [val]  "b"   (increment),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline void MemoryBarrierInternal(void) {
  asm volatile (
      "       lwsync                          \n\t"
      "       isync                           \n\t"
              :
              :
              : "memory");
}

inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
                                        Atomic32 increment) {
  Atomic32 result;

  asm volatile (
      "       lwsync                          \n\t"

      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       add %[res], %[val], %[res]      \n\t"  // add the operand
      "       stwcx. %[res], %[zero], %[obj]  \n\t"  // store old value
                                                     // if still reserved
      "       bne- 1b                         \n\t"
      "       isync                           \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [val]  "b"   (increment),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
                                       Atomic32 old_value,
                                       Atomic32 new_value) {
  Atomic32 result;

  asm volatile (
      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       cmpw %[cmp], %[res]             \n\t"  // compare values
      "       bne- 2f                         \n\t"
      "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
      "       bne- 1b                         \n\t"

      "       isync                           \n\t"
      "2:                                     \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [cmp]  "b"   (old_value),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
                                       Atomic32 old_value,
                                       Atomic32 new_value) {
  Atomic32 result;

  asm volatile (
      "       lwsync                          \n\t"

      "1:     lwarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       cmpw %[cmp], %[res]             \n\t"  // compare values
      "       bne- 2f                         \n\t"
      "       stwcx. %[val], %[zero], %[obj]  \n\t"  // store new value
      "       bne- 1b                         \n\t"

      "2:                                     \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [cmp]  "b"   (old_value),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
  *ptr = value;
}

inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
  asm volatile (
      "       stw %[val], %[obj]      \n\t"
      "       isync                   \n\t"
              : [obj] "=m" (*ptr)
              : [val]  "b"  (value));
}

inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
  asm volatile (
      "       lwsync                  \n\t"
      "       stw %[val], %[obj]      \n\t"
              : [obj] "=m" (*ptr)
              : [val]  "b"  (value));
}

inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
  return *ptr;
}

inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
  Atomic32 result;

  asm volatile (
      "1:     lwz %[res], %[obj]              \n\t"
      "       cmpw %[res], %[res]             \n\t" // create data
                                                    // dependency for
                                                    // load/load ordering
      "       bne- 1b                         \n\t" // never taken

      "       isync                           \n\t"
              : [res]  "=b" (result)
              : [obj]  "m"  (*ptr),
                [zero] "i"  (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
  Atomic32 result;

  asm volatile (
      "       lwsync                          \n\t"

      "1:     lwz %[res], %[obj]              \n\t"
      "       cmpw %[res], %[res]             \n\t" // create data
                                                    // dependency for
                                                    // load/load ordering
      "       bne- 1b                         \n\t" // never taken
              : [res]  "=b" (result)
              : [obj]  "m"  (*ptr),
                [zero] "i"  (0)
              : "cr0", "ctr");

  return result;
}

#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
                                         Atomic64 old_value,
                                         Atomic64 new_value) {
  Atomic64 result;

  asm volatile (
      "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       cmpd %[cmp], %[res]             \n\t"  // compare values
      "       bne- 2f                         \n\t"

      "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
      "       bne- 1b                         \n\t"
      "2:                                     \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [cmp]  "b"   (old_value),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
                                         Atomic64 new_value) {
  Atomic64 result;

  asm volatile (
      "1:     ldarx %[res], %[zero], %[obj]       \n\t"
      "       stdcx. %[val], %[zero], %[obj]      \n\t"
      "       bne- 1b                             \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
                                          Atomic64 increment) {
  Atomic64 result;

  asm volatile (
      "1:     ldarx %[res], %[zero], %[obj]   \n\t" // load and reserve
      "       add %[res], %[res], %[val]      \n\t" // add the operand
      "       stdcx. %[res], %[zero], %[obj]  \n\t" // store old value if
                                                    // still reserved

      "       bne- 1b                         \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [val]  "b"   (increment),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
                                        Atomic64 increment) {

  Atomic64 result;

  asm volatile (
      "       lwsync                          \n\t"

      "1:     ldarx %[res], %[zero], %[obj]   \n\t" // load and reserve
      "       add %[res], %[res], %[val]      \n\t" // add the operand
      "       stdcx. %[res], %[zero], %[obj]  \n\t" // store old value if
                                                    // still reserved

      "       bne- 1b                         \n\t"

      "       isync                           \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [val]  "b"   (increment),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
                                       Atomic64 old_value,
                                       Atomic64 new_value) {
  Atomic64 result;

  asm volatile (
      "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       cmpd %[cmp], %[res]             \n\t"  // compare values
      "       bne- 2f                         \n\t"

      "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
      "       bne- 1b                         \n\t"
      "       isync                           \n\t"
      "2:                                     \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [cmp]  "b"   (old_value),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
                                       Atomic64 old_value,
                                       Atomic64 new_value) {
  Atomic64 result;

  asm volatile (
      "       lwsync                          \n\t"

      "1:     ldarx %[res], %[zero], %[obj]   \n\t"  // load and reserve
      "       cmpd %[cmp], %[res]             \n\t"  // compare values
      "       bne- 2f                         \n\t"

      "       stdcx. %[val], %[zero], %[obj]  \n\t"  // store the new value
      "       bne- 1b                         \n\t"
      "2:                                     \n\t"
              : [res]  "=&b" (result)
              : [obj]  "b"   (ptr),
                [cmp]  "b"   (old_value),
                [val]  "b"   (new_value),
                [zero] "i"   (0)
              : "cr0", "ctr");

  return result;
}

inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
  *ptr = value;
}

inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
  asm volatile (
      "       std %[val], %[obj]          \n\t"
      "       isync                       \n\t"
              : [obj] "=m" (*ptr)
              : [val] "b"  (value));
}

inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
  asm volatile (
      "       lwsync                      \n\t"
      "       std %[val], %[obj]          \n\t"
              : [obj] "=m" (*ptr)
              : [val] "b"  (value));
}

inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
  return *ptr;
}

inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
  Atomic64 result;

  asm volatile (
      "1:     ld %[res], %[obj]                   \n\t"
      "       cmpd %[res], %[res]                 \n\t" // create data
                                                        // dependency for
                                                        // load/load ordering
      "       bne- 1b                             \n\t" // never taken

      "       isync                               \n\t"
              : [res]  "=b" (result)
              : [obj]  "m"  (*ptr),
                [zero] "i"  (0)
              : "cr0", "ctr");

  return result;
}

inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
  Atomic64 result;

  asm volatile (
      "       lwsync                              \n\t"

      "1:     ld %[res], %[obj]                   \n\t"
      "       cmpd %[res], %[res]                 \n\t" // create data
                                                        // dependency for
                                                        // load/load ordering
      "       bne- 1b                             \n\t" // never taken
              : [res]  "=b" (result)
              : [obj]  "m"  (*ptr),
                [zero] "i"  (0)
              : "cr0", "ctr");

  return result;
}
#endif

}  // namespace internal
}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// 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_