text:
// Copyright (c) 2006, Google Inc.
// 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 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: Matt Austern

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

#include <stdlib.h>   // for exit()
#include <stdio.h>
#include <string>
#include <vector>

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

typedef int int32;
// IBM AIX typedefs `int64` in `sys/inttypes.h`, included transitively above.
#ifndef _AIX
typedef long int64;
#endif

using std::string;
using std::vector;
using std::pair;

// This assertion produces errors like "error: invalid use of
// incomplete type 'struct <unnamed>::AssertTypesEq<const int, int>'"
// when it fails.
template<typename T, typename U> struct AssertTypesEq;
template<typename T> struct AssertTypesEq<T, T> {};
#define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast<void>(AssertTypesEq<T, U>())

// A user-defined POD type.
struct A {
  int n_;
};

// A user-defined non-POD type with a trivial copy constructor.
class B {
 public:
  explicit B(int n) : n_(n) { }
 private:
  int n_;
};

// Another user-defined non-POD type with a trivial copy constructor.
// We will explicitly declare C to have a trivial copy constructor
// by specializing has_trivial_copy.
class C {
 public:
  explicit C(int n) : n_(n) { }
 private:
  int n_;
};

namespace google {
namespace protobuf {
namespace internal {
template<> struct has_trivial_copy<C> : true_type { };
}  // namespace internal
}  // namespace protobuf
}  // namespace google

// Another user-defined non-POD type with a trivial assignment operator.
// We will explicitly declare C to have a trivial assignment operator
// by specializing has_trivial_assign.
class D {
 public:
  explicit D(int n) : n_(n) { }
 private:
  int n_;
};

namespace google {
namespace protobuf {
namespace internal {
template<> struct has_trivial_assign<D> : true_type { };
}  // namespace internal
}  // namespace protobuf
}  // namespace google

// Another user-defined non-POD type with a trivial constructor.
// We will explicitly declare E to have a trivial constructor
// by specializing has_trivial_constructor.
class E {
 public:
  int n_;
};

namespace google {
namespace protobuf {
namespace internal {
template<> struct has_trivial_constructor<E> : true_type { };
}  // namespace internal
}  // namespace protobuf
}  // namespace google

// Another user-defined non-POD type with a trivial destructor.
// We will explicitly declare E to have a trivial destructor
// by specializing has_trivial_destructor.
class F {
 public:
  explicit F(int n) : n_(n) { }
 private:
  int n_;
};

namespace google {
namespace protobuf {
namespace internal {
template<> struct has_trivial_destructor<F> : true_type { };
}  // namespace internal
}  // namespace protobuf
}  // namespace google

enum G {};

union H {};

class I {
 public:
  operator int() const;
};

class J {
 private:
  operator int() const;
};

namespace google {
namespace protobuf {
namespace internal {
namespace {

// A base class and a derived class that inherits from it, used for
// testing conversion type traits.
class Base {
 public:
  virtual ~Base() { }
};

class Derived : public Base {
};

TEST(TypeTraitsTest, TestIsInteger) {
  // Verify that is_integral is true for all integer types.
  EXPECT_TRUE(is_integral<bool>::value);
  EXPECT_TRUE(is_integral<char>::value);
  EXPECT_TRUE(is_integral<unsigned char>::value);
  EXPECT_TRUE(is_integral<signed char>::value);
  EXPECT_TRUE(is_integral<wchar_t>::value);
  EXPECT_TRUE(is_integral<int>::value);
  EXPECT_TRUE(is_integral<unsigned int>::value);
  EXPECT_TRUE(is_integral<short>::value);
  EXPECT_TRUE(is_integral<unsigned short>::value);
  EXPECT_TRUE(is_integral<long>::value);
  EXPECT_TRUE(is_integral<unsigned long>::value);

  // Verify that is_integral is false for a few non-integer types.
  EXPECT_FALSE(is_integral<void>::value);
  EXPECT_FALSE(is_integral<float>::value);
  EXPECT_FALSE(is_integral<string>::value);
  EXPECT_FALSE(is_integral<int*>::value);
  EXPECT_FALSE(is_integral<A>::value);
  EXPECT_FALSE((is_integral<pair<int, int> >::value));

  // Verify that cv-qualified integral types are still integral, and
  // cv-qualified non-integral types are still non-integral.
  EXPECT_TRUE(is_integral<const char>::value);
  EXPECT_TRUE(is_integral<volatile bool>::value);
  EXPECT_TRUE(is_integral<const volatile unsigned int>::value);
  EXPECT_FALSE(is_integral<const float>::value);
  EXPECT_FALSE(is_integral<int* volatile>::value);
  EXPECT_FALSE(is_integral<const volatile string>::value);
}

TEST(TypeTraitsTest, TestIsFloating) {
  // Verify that is_floating_point is true for all floating-point types.
  EXPECT_TRUE(is_floating_point<float>::value);
  EXPECT_TRUE(is_floating_point<double>::value);
  EXPECT_TRUE(is_floating_point<long double>::value);

  // Verify that is_floating_point is false for a few non-float types.
  EXPECT_FALSE(is_floating_point<void>::value);
  EXPECT_FALSE(is_floating_point<long>::value);
  EXPECT_FALSE(is_floating_point<string>::value);
  EXPECT_FALSE(is_floating_point<float*>::value);
  EXPECT_FALSE(is_floating_point<A>::value);
  EXPECT_FALSE((is_floating_point<pair<int, int> >::value));

  // Verify that cv-qualified floating point types are still floating, and
  // cv-qualified non-floating types are still non-floating.
  EXPECT_TRUE(is_floating_point<const float>::value);
  EXPECT_TRUE(is_floating_point<volatile double>::value);
  EXPECT_TRUE(is_floating_point<const volatile long double>::value);
  EXPECT_FALSE(is_floating_point<const int>::value);
  EXPECT_FALSE(is_floating_point<volatile string>::value);
  EXPECT_FALSE(is_floating_point<const volatile char>::value);
}

TEST(TypeTraitsTest, TestIsPointer) {
  // Verify that is_pointer is true for some pointer types.
  EXPECT_TRUE(is_pointer<int*>::value);
  EXPECT_TRUE(is_pointer<void*>::value);
  EXPECT_TRUE(is_pointer<string*>::value);
  EXPECT_TRUE(is_pointer<const void*>::value);
  EXPECT_TRUE(is_pointer<volatile float* const*>::value);

  // Verify that is_pointer is false for some non-pointer types.
  EXPECT_FALSE(is_pointer<void>::value);
  EXPECT_FALSE(is_pointer<float&>::value);
  EXPECT_FALSE(is_pointer<long>::value);
  EXPECT_FALSE(is_pointer<vector<int*> >::value);
  EXPECT_FALSE(is_pointer<int[5]>::value);

  // A function pointer is a pointer, but a function type, or a function
  // reference type, is not.
  EXPECT_TRUE(is_pointer<int (*)(int x)>::value);
  EXPECT_FALSE(is_pointer<void(char x)>::value);
  EXPECT_FALSE(is_pointer<double (&)(string x)>::value);

  // Verify that is_pointer<T> is true for some cv-qualified pointer types,
  // and false for some cv-qualified non-pointer types.
  EXPECT_TRUE(is_pointer<int* const>::value);
  EXPECT_TRUE(is_pointer<const void* volatile>::value);
  EXPECT_TRUE(is_pointer<char** const volatile>::value);
  EXPECT_FALSE(is_pointer<const int>::value);
  EXPECT_FALSE(is_pointer<volatile vector<int*> >::value);
  EXPECT_FALSE(is_pointer<const volatile double>::value);
}

TEST(TypeTraitsTest, TestIsEnum) {
// is_enum isn't supported on MSVC or gcc 3.x
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
  // Verify that is_enum is true for enum types.
  EXPECT_TRUE(is_enum<G>::value);
  EXPECT_TRUE(is_enum<const G>::value);
  EXPECT_TRUE(is_enum<volatile G>::value);
  EXPECT_TRUE(is_enum<const volatile G>::value);

  // Verify that is_enum is false for a few non-enum types.
  EXPECT_FALSE(is_enum<void>::value);
  EXPECT_FALSE(is_enum<G&>::value);
  EXPECT_FALSE(is_enum<G[1]>::value);
  EXPECT_FALSE(is_enum<const G[1]>::value);
  EXPECT_FALSE(is_enum<G[]>::value);
  EXPECT_FALSE(is_enum<int>::value);
  EXPECT_FALSE(is_enum<float>::value);
  EXPECT_FALSE(is_enum<A>::value);
  EXPECT_FALSE(is_enum<A*>::value);
  EXPECT_FALSE(is_enum<const A>::value);
  EXPECT_FALSE(is_enum<H>::value);
  EXPECT_FALSE(is_enum<I>::value);
  EXPECT_FALSE(is_enum<J>::value);
  EXPECT_FALSE(is_enum<void()>::value);
  EXPECT_FALSE(is_enum<void(*)()>::value);
  EXPECT_FALSE(is_enum<int A::*>::value);
  EXPECT_FALSE(is_enum<void (A::*)()>::value);
#endif
}

TEST(TypeTraitsTest, TestIsReference) {
  // Verifies that is_reference is true for all reference types.
  typedef float& RefFloat;
  EXPECT_TRUE(is_reference<float&>::value);
  EXPECT_TRUE(is_reference<const int&>::value);
  EXPECT_TRUE(is_reference<const int*&>::value);
  EXPECT_TRUE(is_reference<int (&)(bool)>::value);
  EXPECT_TRUE(is_reference<RefFloat>::value);
  EXPECT_TRUE(is_reference<const RefFloat>::value);
  EXPECT_TRUE(is_reference<volatile RefFloat>::value);
  EXPECT_TRUE(is_reference<const volatile RefFloat>::value);

  // Verifies that is_reference is false for all non-reference types.
  EXPECT_FALSE(is_reference<float>::value);
  EXPECT_FALSE(is_reference<const float>::value);
  EXPECT_FALSE(is_reference<volatile float>::value);
  EXPECT_FALSE(is_reference<const volatile float>::value);
  EXPECT_FALSE(is_reference<const int*>::value);
  EXPECT_FALSE(is_reference<int()>::value);
  EXPECT_FALSE(is_reference<void(*)(const char&)>::value);
}

TEST(TypeTraitsTest, TestAddReference) {
  COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int>::type);
  COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int>::type);
  COMPILE_ASSERT_TYPES_EQ(volatile int&,
                          add_reference<volatile int>::type);
  COMPILE_ASSERT_TYPES_EQ(const volatile int&,
                          add_reference<const volatile int>::type);
  COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int&>::type);
  COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int&>::type);
  COMPILE_ASSERT_TYPES_EQ(volatile int&,
                          add_reference<volatile int&>::type);
  COMPILE_ASSERT_TYPES_EQ(const volatile int&,
                          add_reference<const volatile int&>::type);
}

TEST(TypeTraitsTest, TestIsPod) {
  // Verify that arithmetic types and pointers are marked as PODs.
  EXPECT_TRUE(is_pod<bool>::value);
  EXPECT_TRUE(is_pod<char>::value);
  EXPECT_TRUE(is_pod<unsigned char>::value);
  EXPECT_TRUE(is_pod<signed char>::value);
  EXPECT_TRUE(is_pod<wchar_t>::value);
  EXPECT_TRUE(is_pod<int>::value);
  EXPECT_TRUE(is_pod<unsigned int>::value);
  EXPECT_TRUE(is_pod<short>::value);
  EXPECT_TRUE(is_pod<unsigned short>::value);
  EXPECT_TRUE(is_pod<long>::value);
  EXPECT_TRUE(is_pod<unsigned long>::value);
  EXPECT_TRUE(is_pod<float>::value);
  EXPECT_TRUE(is_pod<double>::value);
  EXPECT_TRUE(is_pod<long double>::value);
  EXPECT_TRUE(is_pod<string*>::value);
  EXPECT_TRUE(is_pod<A*>::value);
  EXPECT_TRUE(is_pod<const B*>::value);
  EXPECT_TRUE(is_pod<C**>::value);
  EXPECT_TRUE(is_pod<const int>::value);
  EXPECT_TRUE(is_pod<char* volatile>::value);
  EXPECT_TRUE(is_pod<const volatile double>::value);
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
  EXPECT_TRUE(is_pod<G>::value);
  EXPECT_TRUE(is_pod<const G>::value);
  EXPECT_TRUE(is_pod<volatile G>::value);
  EXPECT_TRUE(is_pod<const volatile G>::value);
#endif

  // Verify that some non-POD types are not marked as PODs.
  EXPECT_FALSE(is_pod<void>::value);
  EXPECT_FALSE(is_pod<string>::value);
  EXPECT_FALSE((is_pod<pair<int, int> >::value));
  EXPECT_FALSE(is_pod<A>::value);
  EXPECT_FALSE(is_pod<B>::value);
  EXPECT_FALSE(is_pod<C>::value);
  EXPECT_FALSE(is_pod<const string>::value);
  EXPECT_FALSE(is_pod<volatile A>::value);
  EXPECT_FALSE(is_pod<const volatile B>::value);
}

TEST(TypeTraitsTest, TestHasTrivialConstructor) {
  // Verify that arithmetic types and pointers have trivial constructors.
  EXPECT_TRUE(has_trivial_constructor<bool>::value);
  EXPECT_TRUE(has_trivial_constructor<char>::value);
  EXPECT_TRUE(has_trivial_constructor<unsigned char>::value);
  EXPECT_TRUE(has_trivial_constructor<signed char>::value);
  EXPECT_TRUE(has_trivial_constructor<wchar_t>::value);
  EXPECT_TRUE(has_trivial_constructor<int>::value);
  EXPECT_TRUE(has_trivial_constructor<unsigned int>::value);
  EXPECT_TRUE(has_trivial_constructor<short>::value);
  EXPECT_TRUE(has_trivial_constructor<unsigned short>::value);
  EXPECT_TRUE(has_trivial_constructor<long>::value);
  EXPECT_TRUE(has_trivial_constructor<unsigned long>::value);
  EXPECT_TRUE(has_trivial_constructor<float>::value);
  EXPECT_TRUE(has_trivial_constructor<double>::value);
  EXPECT_TRUE(has_trivial_constructor<long double>::value);
  EXPECT_TRUE(has_trivial_constructor<string*>::value);
  EXPECT_TRUE(has_trivial_constructor<A*>::value);
  EXPECT_TRUE(has_trivial_constructor<const B*>::value);
  EXPECT_TRUE(has_trivial_constructor<C**>::value);

  // Verify that pairs and arrays of such types have trivial
  // constructors.
  typedef int int10[10];
  EXPECT_TRUE((has_trivial_constructor<pair<int, char*> >::value));
  EXPECT_TRUE(has_trivial_constructor<int10>::value);

  // Verify that pairs of types without trivial constructors
  // are not marked as trivial.
  EXPECT_FALSE((has_trivial_constructor<pair<int, string> >::value));
  EXPECT_FALSE((has_trivial_constructor<pair<string, int> >::value));

  // Verify that types without trivial constructors are
  // correctly marked as such.
  EXPECT_FALSE(has_trivial_constructor<string>::value);
  EXPECT_FALSE(has_trivial_constructor<vector<int> >::value);

  // Verify that E, which we have declared to have a trivial
  // constructor, is correctly marked as such.
  EXPECT_TRUE(has_trivial_constructor<E>::value);
}

TEST(TypeTraitsTest, TestHasTrivialCopy) {
  // Verify that arithmetic types and pointers have trivial copy
  // constructors.
  EXPECT_TRUE(has_trivial_copy<bool>::value);
  EXPECT_TRUE(has_trivial_copy<char>::value);
  EXPECT_TRUE(has_trivial_copy<unsigned char>::value);
  EXPECT_TRUE(has_trivial_copy<signed char>::value);
  EXPECT_TRUE(has_trivial_copy<wchar_t>::value);
  EXPECT_TRUE(has_trivial_copy<int>::value);
  EXPECT_TRUE(has_trivial_copy<unsigned int>::value);
  EXPECT_TRUE(has_trivial_copy<short>::value);
  EXPECT_TRUE(has_trivial_copy<unsigned short>::value);
  EXPECT_TRUE(has_trivial_copy<long>::value);
  EXPECT_TRUE(has_trivial_copy<unsigned long>::value);
  EXPECT_TRUE(has_trivial_copy<float>::value);
  EXPECT_TRUE(has_trivial_copy<double>::value);
  EXPECT_TRUE(has_trivial_copy<long double>::value);
  EXPECT_TRUE(has_trivial_copy<string*>::value);
  EXPECT_TRUE(has_trivial_copy<A*>::value);
  EXPECT_TRUE(has_trivial_copy<const B*>::value);
  EXPECT_TRUE(has_trivial_copy<C**>::value);

  // Verify that pairs and arrays of such types have trivial
  // copy constructors.
  typedef int int10[10];
  EXPECT_TRUE((has_trivial_copy<pair<int, char*> >::value));
  EXPECT_TRUE(has_trivial_copy<int10>::value);

  // Verify that pairs of types without trivial copy constructors
  // are not marked as trivial.
  EXPECT_FALSE((has_trivial_copy<pair<int, string> >::value));
  EXPECT_FALSE((has_trivial_copy<pair<string, int> >::value));

  // Verify that types without trivial copy constructors are
  // correctly marked as such.
  EXPECT_FALSE(has_trivial_copy<string>::value);
  EXPECT_FALSE(has_trivial_copy<vector<int> >::value);

  // Verify that C, which we have declared to have a trivial
  // copy constructor, is correctly marked as such.
  EXPECT_TRUE(has_trivial_copy<C>::value);
}

TEST(TypeTraitsTest, TestHasTrivialAssign) {
  // Verify that arithmetic types and pointers have trivial assignment
  // operators.
  EXPECT_TRUE(has_trivial_assign<bool>::value);
  EXPECT_TRUE(has_trivial_assign<char>::value);
  EXPECT_TRUE(has_trivial_assign<unsigned char>::value);
  EXPECT_TRUE(has_trivial_assign<signed char>::value);
  EXPECT_TRUE(has_trivial_assign<wchar_t>::value);
  EXPECT_TRUE(has_trivial_assign<int>::value);
  EXPECT_TRUE(has_trivial_assign<unsigned int>::value);
  EXPECT_TRUE(has_trivial_assign<short>::value);
  EXPECT_TRUE(has_trivial_assign<unsigned short>::value);
  EXPECT_TRUE(has_trivial_assign<long>::value);
  EXPECT_TRUE(has_trivial_assign<unsigned long>::value);
  EXPECT_TRUE(has_trivial_assign<float>::value);
  EXPECT_TRUE(has_trivial_assign<double>::value);
  EXPECT_TRUE(has_trivial_assign<long double>::value);
  EXPECT_TRUE(has_trivial_assign<string*>::value);
  EXPECT_TRUE(has_trivial_assign<A*>::value);
  EXPECT_TRUE(has_trivial_assign<const B*>::value);
  EXPECT_TRUE(has_trivial_assign<C**>::value);

  // Verify that pairs and arrays of such types have trivial
  // assignment operators.
  typedef int int10[10];
  EXPECT_TRUE((has_trivial_assign<pair<int, char*> >::value));
  EXPECT_TRUE(has_trivial_assign<int10>::value);

  // Verify that pairs of types without trivial assignment operators
  // are not marked as trivial.
  EXPECT_FALSE((has_trivial_assign<pair<int, string> >::value));
  EXPECT_FALSE((has_trivial_assign<pair<string, int> >::value));

  // Verify that types without trivial assignment operators are
  // correctly marked as such.
  EXPECT_FALSE(has_trivial_assign<string>::value);
  EXPECT_FALSE(has_trivial_assign<vector<int> >::value);

  // Verify that D, which we have declared to have a trivial
  // assignment operator, is correctly marked as such.
  EXPECT_TRUE(has_trivial_assign<D>::value);
}

TEST(TypeTraitsTest, TestHasTrivialDestructor) {
  // Verify that arithmetic types and pointers have trivial destructors.
  EXPECT_TRUE(has_trivial_destructor<bool>::value);
  EXPECT_TRUE(has_trivial_destructor<char>::value);
  EXPECT_TRUE(has_trivial_destructor<unsigned char>::value);
  EXPECT_TRUE(has_trivial_destructor<signed char>::value);
  EXPECT_TRUE(has_trivial_destructor<wchar_t>::value);
  EXPECT_TRUE(has_trivial_destructor<int>::value);
  EXPECT_TRUE(has_trivial_destructor<unsigned int>::value);
  EXPECT_TRUE(has_trivial_destructor<short>::value);
  EXPECT_TRUE(has_trivial_destructor<unsigned short>::value);
  EXPECT_TRUE(has_trivial_destructor<long>::value);
  EXPECT_TRUE(has_trivial_destructor<unsigned long>::value);
  EXPECT_TRUE(has_trivial_destructor<float>::value);
  EXPECT_TRUE(has_trivial_destructor<double>::value);
  EXPECT_TRUE(has_trivial_destructor<long double>::value);
  EXPECT_TRUE(has_trivial_destructor<string*>::value);
  EXPECT_TRUE(has_trivial_destructor<A*>::value);
  EXPECT_TRUE(has_trivial_destructor<const B*>::value);
  EXPECT_TRUE(has_trivial_destructor<C**>::value);

  // Verify that pairs and arrays of such types have trivial
  // destructors.
  typedef int int10[10];
  EXPECT_TRUE((has_trivial_destructor<pair<int, char*> >::value));
  EXPECT_TRUE(has_trivial_destructor<int10>::value);

  // Verify that pairs of types without trivial destructors
  // are not marked as trivial.
  EXPECT_FALSE((has_trivial_destructor<pair<int, string> >::value));
  EXPECT_FALSE((has_trivial_destructor<pair<string, int> >::value));

  // Verify that types without trivial destructors are
  // correctly marked as such.
  EXPECT_FALSE(has_trivial_destructor<string>::value);
  EXPECT_FALSE(has_trivial_destructor<vector<int> >::value);

  // Verify that F, which we have declared to have a trivial
  // destructor, is correctly marked as such.
  EXPECT_TRUE(has_trivial_destructor<F>::value);
}

// Tests remove_pointer.
TEST(TypeTraitsTest, TestRemovePointer) {
  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int*>::type);
  COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer<const int*>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* const>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* volatile>::type);
}

TEST(TypeTraitsTest, TestRemoveConst) {
  COMPILE_ASSERT_TYPES_EQ(int, remove_const<int>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_const<const int>::type);
  COMPILE_ASSERT_TYPES_EQ(int *, remove_const<int * const>::type);
  // TR1 examples.
  COMPILE_ASSERT_TYPES_EQ(const int *, remove_const<const int *>::type);
  COMPILE_ASSERT_TYPES_EQ(volatile int,
                          remove_const<const volatile int>::type);
}

TEST(TypeTraitsTest, TestRemoveVolatile) {
  COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<int>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<volatile int>::type);
  COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile<int * volatile>::type);
  // TR1 examples.
  COMPILE_ASSERT_TYPES_EQ(volatile int *,
                          remove_volatile<volatile int *>::type);
  COMPILE_ASSERT_TYPES_EQ(const int,
                          remove_volatile<const volatile int>::type);
}

TEST(TypeTraitsTest, TestRemoveCV) {
  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<int>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<volatile int>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<const int>::type);
  COMPILE_ASSERT_TYPES_EQ(int *, remove_cv<int * const volatile>::type);
  // TR1 examples.
  COMPILE_ASSERT_TYPES_EQ(const volatile int *,
                          remove_cv<const volatile int *>::type);
  COMPILE_ASSERT_TYPES_EQ(int,
                          remove_cv<const volatile int>::type);
}

TEST(TypeTraitsTest, TestRemoveReference) {
  COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int>::type);
  COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int&>::type);
  COMPILE_ASSERT_TYPES_EQ(const int, remove_reference<const int&>::type);
  COMPILE_ASSERT_TYPES_EQ(int*, remove_reference<int * &>::type);
}

TEST(TypeTraitsTest, TestIsSame) {
  EXPECT_TRUE((is_same<int32, int32>::value));
  EXPECT_FALSE((is_same<int32, int64>::value));
  EXPECT_FALSE((is_same<int64, int32>::value));
  EXPECT_FALSE((is_same<int, const int>::value));

  EXPECT_TRUE((is_same<void, void>::value));
  EXPECT_FALSE((is_same<void, int>::value));
  EXPECT_FALSE((is_same<int, void>::value));

  EXPECT_TRUE((is_same<int*, int*>::value));
  EXPECT_TRUE((is_same<void*, void*>::value));
  EXPECT_FALSE((is_same<int*, void*>::value));
  EXPECT_FALSE((is_same<void*, int*>::value));
  EXPECT_FALSE((is_same<void*, const void*>::value));
  EXPECT_FALSE((is_same<void*, void* const>::value));

  EXPECT_TRUE((is_same<Base*, Base*>::value));
  EXPECT_TRUE((is_same<Derived*, Derived*>::value));
  EXPECT_FALSE((is_same<Base*, Derived*>::value));
  EXPECT_FALSE((is_same<Derived*, Base*>::value));
}

TEST(TypeTraitsTest, TestConvertible) {
#if !(defined(__GNUC__) && __GNUC__ <= 3)
  EXPECT_TRUE((is_convertible<int, int>::value));
  EXPECT_TRUE((is_convertible<int, long>::value));
  EXPECT_TRUE((is_convertible<long, int>::value));

  EXPECT_TRUE((is_convertible<int*, void*>::value));
  EXPECT_FALSE((is_convertible<void*, int*>::value));

  EXPECT_TRUE((is_convertible<Derived*, Base*>::value));
  EXPECT_FALSE((is_convertible<Base*, Derived*>::value));
  EXPECT_TRUE((is_convertible<Derived*, const Base*>::value));
  EXPECT_FALSE((is_convertible<const Derived*, Base*>::value));
#endif
}

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


text:
#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_

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

// ===================================================================
// emulates google3/base/callback.h

namespace google {
namespace protobuf {

// 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);
};

template<typename R>
class ResultCallback {
 public:
  ResultCallback() {}
  virtual ~ResultCallback() {}

  virtual R Run() = 0;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback);
};

template<typename R, typename A1>
class LIBPROTOBUF_EXPORT ResultCallback1 {
 public:
  ResultCallback1() {}
  virtual ~ResultCallback1() {}

  virtual R Run(A1) = 0;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1);
};

template<typename R, typename A1, typename A2>
class LIBPROTOBUF_EXPORT ResultCallback2 {
 public:
  ResultCallback2() {}
  virtual ~ResultCallback2() {}

  virtual R Run(A1,A2) = 0;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2);
};

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() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    function_();
    if (needs_delete) 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() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    (object_->*method_)();
    if (needs_delete) 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() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    function_(arg1_);
    if (needs_delete) 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() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    (object_->*method_)(arg1_);
    if (needs_delete) 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() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    function_(arg1_, arg2_);
    if (needs_delete) 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() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    (object_->*method_)(arg1_, arg2_);
    if (needs_delete) delete this;
  }

 private:
  Class* object_;
  MethodType method_;
  bool self_deleting_;
  Arg1 arg1_;
  Arg2 arg2_;
};

template<typename R>
class FunctionResultCallback_0_0 : public ResultCallback<R> {
 public:
  typedef R (*FunctionType)();

  FunctionResultCallback_0_0(FunctionType function, bool self_deleting)
      : function_(function), self_deleting_(self_deleting) {}
  ~FunctionResultCallback_0_0() {}

  R Run() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    R result = function_();
    if (needs_delete) delete this;
    return result;
  }

 private:
  FunctionType function_;
  bool self_deleting_;
};

template<typename R, typename P1>
class FunctionResultCallback_1_0 : public ResultCallback<R> {
 public:
  typedef R (*FunctionType)(P1);

  FunctionResultCallback_1_0(FunctionType function, bool self_deleting,
                             P1 p1)
      : function_(function), self_deleting_(self_deleting), p1_(p1) {}
  ~FunctionResultCallback_1_0() {}

  R Run() {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    R result = function_(p1_);
    if (needs_delete) delete this;
    return result;
  }

 private:
  FunctionType function_;
  bool self_deleting_;
  P1 p1_;
};

template<typename R, typename Arg1>
class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
 public:
  typedef R (*FunctionType)(Arg1 arg1);

  FunctionResultCallback_0_1(FunctionType function, bool self_deleting)
      : function_(function), self_deleting_(self_deleting) {}
  ~FunctionResultCallback_0_1() {}

  R Run(Arg1 a1) {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    R result = function_(a1);
    if (needs_delete) delete this;
    return result;
  }

 private:
  FunctionType function_;
  bool self_deleting_;
};

template<typename R, typename P1, typename A1>
class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> {
 public:
  typedef R (*FunctionType)(P1, A1);

  FunctionResultCallback_1_1(FunctionType function, bool self_deleting,
                             P1 p1)
      : function_(function), self_deleting_(self_deleting), p1_(p1) {}
  ~FunctionResultCallback_1_1() {}

  R Run(A1 a1) {
    bool needs_delete = self_deleting_;  // read in case callback deletes
    R result = function_(p1_, a1);
    if (needs_delete) delete this;
    return result;
  }

 private:
  FunctionType function_;
  bool self_deleting_;
  P1 p1_;
};

template <typename T>
struct InternalConstRef {
  typedef typename remove_reference<T>::type base_type;
  typedef const base_type& type;
};

template<typename R, typename T>
class MethodResultCallback_0_0 : public ResultCallback<R> {
 public:
  typedef R (T::*MethodType)();
  MethodResultCallback_0_0(T* object, MethodType method, bool self_deleting)
      : object_(object),
        method_(method),
        self_deleting_(self_deleting) {}
  ~MethodResultCallback_0_0() {}

  R Run() {
    bool needs_delete = self_deleting_;
    R result = (object_->*method_)();
    if (needs_delete) delete this;
    return result;
  }

 private:
  T* object_;
  MethodType method_;
  bool self_deleting_;
};

template <typename R, typename T, typename P1, typename P2, typename P3,
          typename P4, typename P5, typename A1, typename A2>
class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
 public:
  typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2);
  MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting,
                           P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
      : object_(object),
        method_(method),
        self_deleting_(self_deleting),
        p1_(p1),
        p2_(p2),
        p3_(p3),
        p4_(p4),
        p5_(p5) {}
  ~MethodResultCallback_5_2() {}

  R Run(A1 a1, A2 a2) {
    bool needs_delete = self_deleting_;
    R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2);
    if (needs_delete) delete this;
    return result;
  }

 private:
  T* object_;
  MethodType method_;
  bool self_deleting_;
  typename remove_reference<P1>::type p1_;
  typename remove_reference<P2>::type p2_;
  typename remove_reference<P3>::type p3_;
  typename remove_reference<P4>::type p4_;
  typename remove_reference<P5>::type p5_;
};

}  // 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);
}

// See ResultCallback
template<typename R>
inline ResultCallback<R>* NewCallback(R (*function)()) {
  return new internal::FunctionResultCallback_0_0<R>(function, true);
}

// See ResultCallback
template<typename R>
inline ResultCallback<R>* NewPermanentCallback(R (*function)()) {
  return new internal::FunctionResultCallback_0_0<R>(function, false);
}

// See ResultCallback
template<typename R, typename P1>
inline ResultCallback<R>* NewCallback(R (*function)(P1), P1 p1) {
  return new internal::FunctionResultCallback_1_0<R, P1>(
      function, true, p1);
}

// See ResultCallback
template<typename R, typename P1>
inline ResultCallback<R>* NewPermanentCallback(
    R (*function)(P1), P1 p1) {
  return new internal::FunctionResultCallback_1_0<R, P1>(
      function, false, p1);
}

// See ResultCallback1
template<typename R, typename A1>
inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
  return new internal::FunctionResultCallback_0_1<R, A1>(function, true);
}

// See ResultCallback1
template<typename R, typename A1>
inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) {
  return new internal::FunctionResultCallback_0_1<R, A1>(function, false);
}

// See ResultCallback1
template<typename R, typename P1, typename A1>
inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) {
  return new internal::FunctionResultCallback_1_1<R, P1, A1>(
      function, true, p1);
}

// See ResultCallback1
template<typename R, typename P1, typename A1>
inline ResultCallback1<R, A1>* NewPermanentCallback(
    R (*function)(P1, A1), P1 p1) {
  return new internal::FunctionResultCallback_1_1<R, P1, A1>(
      function, false, p1);
}

// See MethodResultCallback_0_0
template <typename R, typename T1, typename T2>
inline ResultCallback<R>* NewPermanentCallback(
    T1* object, R (T2::*function)()) {
  return new internal::MethodResultCallback_0_0<R, T1>(object, function, false);
}

// See MethodResultCallback_5_2
template <typename R, typename T, typename P1, typename P2, typename P3,
          typename P4, typename P5, typename A1, typename A2>
inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
    T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2),
    typename internal::InternalConstRef<P1>::type p1,
    typename internal::InternalConstRef<P2>::type p2,
    typename internal::InternalConstRef<P3>::type p3,
    typename internal::InternalConstRef<P4>::type p4,
    typename internal::InternalConstRef<P5>::type p5) {
  return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1,
                                                A2>(object, function, false, p1,
                                                    p2, p3, p4, p5);
}

// A function which does nothing.  Useful for creating no-op callbacks, e.g.:
//   Closure* nothing = NewCallback(&DoNothing);
void LIBPROTOBUF_EXPORT DoNothing();

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_

mime_type: text/plain


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

#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1

// Use C++11 unordered_{map|set} if available.
#if ((defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) || \
    (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \
    (__GLIBCXX__ > 20090421)))
# define GOOGLE_PROTOBUF_HAS_CXX11_HASH

// For XCode >= 4.6:  the compiler is clang with libc++.
// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++.
// libc++ provides <unordered_map> and friends even in non C++11 mode,
// and it does not provide the tr1 library. Therefore the following macro
// checks against this special case.
// Note that we should not test the __APPLE_CC__ version number or the
// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in
// which case <unordered_map> is not compilable without -std=c++11
#elif defined(__APPLE_CC__)
# if __GNUC__ >= 4
#  define GOOGLE_PROTOBUF_HAS_TR1
# else
// Not tested for gcc < 4... These setting can compile under 4.2.1 though.
#  define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx
#  include <ext/hash_map>
#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
#  include <ext/hash_set>
#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
# endif

// Version checks for gcc.
#elif defined(__GNUC__)
// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the
// instructions from:
// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html
# if __GNUC__ >= 4
#  define GOOGLE_PROTOBUF_HAS_TR1
# elif __GNUC__ >= 3
#  include <backward/hash_map>
#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
#  include <backward/hash_set>
#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
#  if __GNUC__ == 3 && __GNUC_MINOR__ == 0
#   define GOOGLE_PROTOBUF_HASH_NAMESPACE std       // GCC 3.0
#  else
#   define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later
#  endif
# else
#  define GOOGLE_PROTOBUF_HASH_NAMESPACE
#  include <hash_map>
#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
#  include <hash_set>
#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
# endif

// GCC <= 4.1 does not define std::tr1::hash for `long long int` or `long long unsigned int`
# if __GNUC__ == 4 && defined(__GNUC__MINOR__) && __GNUC__MINOR__ <= 1
#  undef GOOGLE_PROTOBUF_HAS_TR1
#  undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
#  undef GOOGLE_PROTOBUF_HAVE_HASH_SET
# endif

// Version checks for MSC.
// Apparently Microsoft decided to move hash_map *back* to the std namespace in
// MSVC 2010:
// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
// said, use unordered_map for MSVC 2010 and beyond is our safest bet.
#elif defined(_MSC_VER)
# if _MSC_VER >= 1600  // Since Visual Studio 2010
#  define GOOGLE_PROTOBUF_HAS_CXX11_HASH
#  define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare
# elif _MSC_VER >= 1500  // Since Visual Studio 2008
#  define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
#  include <hash_map>
#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
#  include <hash_set>
#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
#  define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
#  define GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
# elif _MSC_VER >= 1310
#  define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
#  include <hash_map>
#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
#  include <hash_set>
#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
#  define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
# else
#  define GOOGLE_PROTOBUF_HASH_NAMESPACE std
#  include <hash_map>
#  define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
#  include <hash_set>
#  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
#  define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
# endif

// **ADD NEW COMPILERS SUPPORT HERE.**
// For other compilers, undefine the macro and fallback to use std::map, in
// google/protobuf/stubs/hash.h
#else
# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
# undef GOOGLE_PROTOBUF_HAVE_HASH_SET
#endif

#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH)
# define GOOGLE_PROTOBUF_HASH_NAMESPACE std
# include <unordered_map>
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
# include <unordered_set>
# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
#elif defined(GOOGLE_PROTOBUF_HAS_TR1)
# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1
# include <tr1/unordered_map>
# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
# include <tr1/unordered_set>
# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
#endif

# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
  namespace google {                                      \
  namespace protobuf {
# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}

#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH
#undef GOOGLE_PROTOBUF_HAS_TR1

#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
    defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
#else
#define GOOGLE_PROTOBUF_MISSING_HASH
#include <map>
#include <set>
#endif

namespace google {
namespace protobuf {

#ifdef GOOGLE_PROTOBUF_MISSING_HASH
#undef GOOGLE_PROTOBUF_MISSING_HASH

// This system doesn't have hash_map or hash_set.  Emulate them using map and
// set.

// Make hash<T> be the same as less<T>.  Note that everywhere where custom
// hash functions are defined in the protobuf code, they are also defined such
// that they can be used as "less" functions, which is required by MSVC anyway.
template <typename Key>
struct hash {
  // Dummy, just to make derivative hash functions compile.
  int operator()(const Key& key) {
    GOOGLE_LOG(FATAL) << "Should never be called.";
    return 0;
  }

  inline bool operator()(const Key& a, const Key& b) const {
    return a < b;
  }
};

// Make sure char* is compared by value.
template <>
struct hash<const char*> {
  // Dummy, just to make derivative hash functions compile.
  int operator()(const char* key) {
    GOOGLE_LOG(FATAL) << "Should never be called.";
    return 0;
  }

  inline bool operator()(const char* a, const char* b) const {
    return strcmp(a, b) < 0;
  }
};

template <typename Key, typename Data,
          typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key>,
          typename Alloc = std::allocator< std::pair<const Key, Data> > >
class hash_map : public std::map<Key, Data, HashFcn, Alloc> {
  typedef std::map<Key, Data, HashFcn, Alloc> BaseClass;

 public:
  hash_map(int a = 0, const HashFcn& b = HashFcn(),
           const EqualKey& c = EqualKey(),
           const Alloc& d = Alloc()) : BaseClass(b, d) {}

  HashFcn hash_function() const { return HashFcn(); }
};

template <typename Key,
          typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key> >
class hash_set : public std::set<Key, HashFcn> {
 public:
  hash_set(int = 0) {}

  HashFcn hash_function() const { return HashFcn(); }
};

#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)

template <typename Key>
struct hash : public GOOGLE_PROTOBUF_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 GOOGLE_PROTOBUF_HASH_COMPARE<const char*, CstringLess> {};

#ifdef GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE

template <typename Key, typename HashFcn, typename EqualKey>
struct InternalHashCompare : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
  InternalHashCompare() {}
  InternalHashCompare(HashFcn hashfcn, EqualKey equalkey)
      : hashfcn_(hashfcn), equalkey_(equalkey) {}
  size_t operator()(const Key& key) const { return hashfcn_(key); }
  bool operator()(const Key& key1, const Key& key2) const {
    return !equalkey_(key1, key2);
  }
  HashFcn hashfcn_;
  EqualKey equalkey_;
};

template <typename Key, typename Data,
          typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key>,
          typename Alloc = std::allocator< std::pair<const Key, Data> > >
class hash_map
    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
          Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> {
  typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
      Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> BaseClass;

 public:
  hash_map(int a = 0, const HashFcn& b = HashFcn(),
           const EqualKey& c = EqualKey(), const Alloc& d = Alloc())
      : BaseClass(InternalHashCompare<Key, HashFcn, EqualKey>(b, c), d) {}

  HashFcn hash_function() const { return HashFcn(); }
};

template <typename Key, typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key> >
class hash_set
    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
          Key, InternalHashCompare<Key, HashFcn, EqualKey> > {
 public:
  hash_set(int = 0) {}

  HashFcn hash_function() const { return HashFcn(); }
};

#else  // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE

template <typename Key, typename Data,
          typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key>,
          typename Alloc = std::allocator< std::pair<const Key, Data> > >
class hash_map
    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
          Key, Data, HashFcn, EqualKey, Alloc> {
  typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
      Key, Data, HashFcn, EqualKey, Alloc> BaseClass;

 public:
  hash_map(int a = 0, const HashFcn& b = HashFcn(),
           const EqualKey& c = EqualKey(),
           const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}

  HashFcn hash_function() const { return HashFcn(); }
};

template <typename Key, typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key> >
class hash_set
    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
          Key, HashFcn, EqualKey> {
 public:
  hash_set(int = 0) {}

  HashFcn hash_function() const { return HashFcn(); }
};
#endif  // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE

#else  // defined(_MSC_VER) && !defined(_STLPORT_VERSION)

template <typename Key>
struct hash : public GOOGLE_PROTOBUF_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);
  }
};

// Unlike the old SGI version, the TR1 "hash" does not special-case char*.  So,
// we go ahead and provide our own implementation.
template <>
struct hash<const char*> {
  inline size_t operator()(const char* str) const {
    size_t result = 0;
    for (; *str != '\0'; str++) {
      result = 5 * result + static_cast<size_t>(*str);
    }
    return result;
  }
};

template<>
struct hash<bool> {
  size_t operator()(bool x) const {
    return static_cast<size_t>(x);
  }
};

template <typename Key, typename Data,
          typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key>,
          typename Alloc = std::allocator< std::pair<const Key, Data> > >
class hash_map
    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
          Key, Data, HashFcn, EqualKey, Alloc> {
  typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
      Key, Data, HashFcn, EqualKey, Alloc> BaseClass;

 public:
  hash_map(int a = 0, const HashFcn& b = HashFcn(),
           const EqualKey& c = EqualKey(),
           const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}

  HashFcn hash_function() const { return HashFcn(); }
};

template <typename Key, typename HashFcn = hash<Key>,
          typename EqualKey = std::equal_to<Key> >
class hash_set
    : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
          Key, HashFcn, EqualKey> {
 public:
  hash_set(int = 0) {}

  HashFcn hash_function() const { return HashFcn(); }
};

#endif  // !GOOGLE_PROTOBUF_MISSING_HASH

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 bool operator()(const string& a, const string& b) const {
    return a < b;
  }
};

template <typename First, typename Second>
struct hash<pair<First, Second> > {
  inline size_t operator()(const pair<First, Second>& key) const {
    size_t first_hash = hash<First>()(key.first);
    size_t second_hash = hash<Second>()(key.second);

    // FIXME(kenton):  What is the best way to compute this hash?  I have
    // no idea!  This seems a bit better than an XOR.
    return first_hash * ((1 << 16) - 1) + second_hash;
  }

  static const size_t bucket_size = 4;
  static const size_t min_buckets = 8;
  inline bool operator()(const pair<First, Second>& a,
                           const pair<First, Second>& b) const {
    return a < b;
  }
};

// Used by GCC/SGI STL only.  (Why isn't this provided by the standard
// library?  :( )
struct streq {
  inline bool operator()(const char* a, const char* b) const {
    return strcmp(a, b) == 0;
  }
};

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_HASH_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.
#ifndef GOOGLE_PROTOBUF_STUBS_INT128_H_
#define GOOGLE_PROTOBUF_STUBS_INT128_H_

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

#include <iosfwd>

namespace google {
namespace protobuf {

struct uint128_pod;

// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
// available.
#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
# define UINT128_CONSTEXPR constexpr
#else
# define UINT128_CONSTEXPR
#endif

// An unsigned 128-bit integer type. Thread-compatible.
class LIBPROTOBUF_EXPORT uint128 {
 public:
  UINT128_CONSTEXPR uint128();  // Sets to 0, but don't trust on this behavior.
  UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom);
#ifndef SWIG
  UINT128_CONSTEXPR uint128(int bottom);
  UINT128_CONSTEXPR uint128(uint32 bottom);   // Top 96 bits = 0
#endif
  UINT128_CONSTEXPR uint128(uint64 bottom);   // hi_ = 0
  UINT128_CONSTEXPR uint128(const uint128_pod &val);

  // Trivial copy constructor, assignment operator and destructor.

  void Initialize(uint64 top, uint64 bottom);

  // Arithmetic operators.
  uint128& operator+=(const uint128& b);
  uint128& operator-=(const uint128& b);
  uint128& operator*=(const uint128& b);
  // Long division/modulo for uint128.
  uint128& operator/=(const uint128& b);
  uint128& operator%=(const uint128& b);
  uint128 operator++(int);
  uint128 operator--(int);
  uint128& operator<<=(int);
  uint128& operator>>=(int);
  uint128& operator&=(const uint128& b);
  uint128& operator|=(const uint128& b);
  uint128& operator^=(const uint128& b);
  uint128& operator++();
  uint128& operator--();

  friend uint64 Uint128Low64(const uint128& v);
  friend uint64 Uint128High64(const uint128& v);

  // We add "std::" to avoid including all of port.h.
  LIBPROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
                                                     const uint128& b);

 private:
  static void DivModImpl(uint128 dividend, uint128 divisor,
                         uint128* quotient_ret, uint128* remainder_ret);

  // Little-endian memory order optimizations can benefit from
  // having lo_ first, hi_ last.
  // See util/endian/endian.h and Load128/Store128 for storing a uint128.
  uint64        lo_;
  uint64        hi_;

  // Not implemented, just declared for catching automatic type conversions.
  uint128(uint8);
  uint128(uint16);
  uint128(float v);
  uint128(double v);
};

// This is a POD form of uint128 which can be used for static variables which
// need to be operated on as uint128.
struct uint128_pod {
  // Note: The ordering of fields is different than 'class uint128' but the
  // same as its 2-arg constructor.  This enables more obvious initialization
  // of static instances, which is the primary reason for this struct in the
  // first place.  This does not seem to defeat any optimizations wrt
  // operations involving this struct.
  uint64 hi;
  uint64 lo;
};

LIBPROTOBUF_EXPORT extern const uint128_pod kuint128max;

// allow uint128 to be logged
LIBPROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
                                                   const uint128& b);

// Methods to access low and high pieces of 128-bit value.
// Defined externally from uint128 to facilitate conversion
// to native 128-bit types when compilers support them.
inline uint64 Uint128Low64(const uint128& v) { return v.lo_; }
inline uint64 Uint128High64(const uint128& v) { return v.hi_; }

// TODO: perhaps it would be nice to have int128, a signed 128-bit type?

// --------------------------------------------------------------------------
//                      Implementation details follow
// --------------------------------------------------------------------------
inline bool operator==(const uint128& lhs, const uint128& rhs) {
  return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
          Uint128High64(lhs) == Uint128High64(rhs));
}
inline bool operator!=(const uint128& lhs, const uint128& rhs) {
  return !(lhs == rhs);
}

inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom)
    : lo_(bottom), hi_(top) {}
inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
    : lo_(v.lo), hi_(v.hi) {}
inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom)
    : lo_(bottom), hi_(0) {}
#ifndef SWIG
inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom)
    : lo_(bottom), hi_(0) {}
inline UINT128_CONSTEXPR uint128::uint128(int bottom)
    : lo_(bottom), hi_(static_cast<int64>((bottom < 0) ? -1 : 0)) {}
#endif

#undef UINT128_CONSTEXPR

inline void uint128::Initialize(uint64 top, uint64 bottom) {
  hi_ = top;
  lo_ = bottom;
}

// Comparison operators.

#define CMP128(op)                                                \
inline bool operator op(const uint128& lhs, const uint128& rhs) { \
  return (Uint128High64(lhs) == Uint128High64(rhs)) ?             \
      (Uint128Low64(lhs) op Uint128Low64(rhs)) :                  \
      (Uint128High64(lhs) op Uint128High64(rhs));                 \
}

CMP128(<)
CMP128(>)
CMP128(>=)
CMP128(<=)

#undef CMP128

// Unary operators

inline uint128 operator-(const uint128& val) {
  const uint64 hi_flip = ~Uint128High64(val);
  const uint64 lo_flip = ~Uint128Low64(val);
  const uint64 lo_add = lo_flip + 1;
  if (lo_add < lo_flip) {
    return uint128(hi_flip + 1, lo_add);
  }
  return uint128(hi_flip, lo_add);
}

inline bool operator!(const uint128& val) {
  return !Uint128High64(val) && !Uint128Low64(val);
}

// Logical operators.

inline uint128 operator~(const uint128& val) {
  return uint128(~Uint128High64(val), ~Uint128Low64(val));
}

#define LOGIC128(op)                                                 \
inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
  return uint128(Uint128High64(lhs) op Uint128High64(rhs),           \
                 Uint128Low64(lhs) op Uint128Low64(rhs));            \
}

LOGIC128(|)
LOGIC128(&)
LOGIC128(^)

#undef LOGIC128

#define LOGICASSIGN128(op)                                   \
inline uint128& uint128::operator op(const uint128& other) { \
  hi_ op other.hi_;                                          \
  lo_ op other.lo_;                                          \
  return *this;                                              \
}

LOGICASSIGN128(|=)
LOGICASSIGN128(&=)
LOGICASSIGN128(^=)

#undef LOGICASSIGN128

// Shift operators.

inline uint128 operator<<(const uint128& val, int amount) {
  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
  if (amount < 64) {
    if (amount == 0) {
      return val;
    }
    uint64 new_hi = (Uint128High64(val) << amount) |
                    (Uint128Low64(val) >> (64 - amount));
    uint64 new_lo = Uint128Low64(val) << amount;
    return uint128(new_hi, new_lo);
  } else if (amount < 128) {
    return uint128(Uint128Low64(val) << (amount - 64), 0);
  } else {
    return uint128(0, 0);
  }
}

inline uint128 operator>>(const uint128& val, int amount) {
  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
  if (amount < 64) {
    if (amount == 0) {
      return val;
    }
    uint64 new_hi = Uint128High64(val) >> amount;
    uint64 new_lo = (Uint128Low64(val) >> amount) |
                    (Uint128High64(val) << (64 - amount));
    return uint128(new_hi, new_lo);
  } else if (amount < 128) {
    return uint128(0, Uint128High64(val) >> (amount - 64));
  } else {
    return uint128(0, 0);
  }
}

inline uint128& uint128::operator<<=(int amount) {
  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
  if (amount < 64) {
    if (amount != 0) {
      hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
      lo_ = lo_ << amount;
    }
  } else if (amount < 128) {
    hi_ = lo_ << (amount - 64);
    lo_ = 0;
  } else {
    hi_ = 0;
    lo_ = 0;
  }
  return *this;
}

inline uint128& uint128::operator>>=(int amount) {
  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
  if (amount < 64) {
    if (amount != 0) {
      lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
      hi_ = hi_ >> amount;
    }
  } else if (amount < 128) {
    lo_ = hi_ >> (amount - 64);
    hi_ = 0;
  } else {
    lo_ = 0;
    hi_ = 0;
  }
  return *this;
}

inline uint128 operator+(const uint128& lhs, const uint128& rhs) {
  return uint128(lhs) += rhs;
}

inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
  return uint128(lhs) -= rhs;
}

inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
  return uint128(lhs) *= rhs;
}

inline uint128 operator/(const uint128& lhs, const uint128& rhs) {
  return uint128(lhs) /= rhs;
}

inline uint128 operator%(const uint128& lhs, const uint128& rhs) {
  return uint128(lhs) %= rhs;
}

inline uint128& uint128::operator+=(const uint128& b) {
  hi_ += b.hi_;
  uint64 lolo = lo_ + b.lo_;
  if (lolo < lo_)
    ++hi_;
  lo_ = lolo;
  return *this;
}

inline uint128& uint128::operator-=(const uint128& b) {
  hi_ -= b.hi_;
  if (b.lo_ > lo_)
    --hi_;
  lo_ -= b.lo_;
  return *this;
}

inline uint128& uint128::operator*=(const uint128& b) {
  uint64 a96 = hi_ >> 32;
  uint64 a64 = hi_ & 0xffffffffu;
  uint64 a32 = lo_ >> 32;
  uint64 a00 = lo_ & 0xffffffffu;
  uint64 b96 = b.hi_ >> 32;
  uint64 b64 = b.hi_ & 0xffffffffu;
  uint64 b32 = b.lo_ >> 32;
  uint64 b00 = b.lo_ & 0xffffffffu;
  // multiply [a96 .. a00] x [b96 .. b00]
  // terms higher than c96 disappear off the high side
  // terms c96 and c64 are safe to ignore carry bit
  uint64 c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
  uint64 c64 = a64 * b00 + a32 * b32 + a00 * b64;
  this->hi_ = (c96 << 32) + c64;
  this->lo_ = 0;
  // add terms after this one at a time to capture carry
  *this += uint128(a32 * b00) << 32;
  *this += uint128(a00 * b32) << 32;
  *this += a00 * b00;
  return *this;
}

inline uint128 uint128::operator++(int) {
  uint128 tmp(*this);
  *this += 1;
  return tmp;
}

inline uint128 uint128::operator--(int) {
  uint128 tmp(*this);
  *this -= 1;
  return tmp;
}

inline uint128& uint128::operator++() {
  *this += 1;
  return *this;
}

inline uint128& uint128::operator--() {
  *this -= 1;
  return *this;
}

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_INT128_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.

// from google3/base/stringprintf.h
//
// Printf variants that place their output in a C++ string.
//
// Usage:
//      string result = StringPrintf("%d %s\n", 10, "hello");
//      SStringPrintf(&result, "%d %s\n", 10, "hello");
//      StringAppendF(&result, "%d %s\n", 20, "there");

#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H

#include <stdarg.h>
#include <string>
#include <vector>

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

namespace google {
namespace protobuf {

// Return a C++ string
LIBPROTOBUF_EXPORT extern string StringPrintf(const char* format, ...);

// Store result into a supplied string and return it
LIBPROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, const char* format, ...);

// Append result to a supplied string
LIBPROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...);

// Lower-level routine that takes a va_list and appends to a specified
// string.  All other routines are just convenience wrappers around it.
LIBPROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, va_list ap);

// The max arguments supported by StringPrintfVector
LIBPROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs;

// You can use this version when all your arguments are strings, but
// you don't know how many arguments you'll have at compile time.
// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const vector<string>& v);

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_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)

#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/stl_util.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])) {
        unsigned int index = format[i+1] - '0';
        assert(index < 10);
        const SubstituteArg* src = args_array[index];
        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


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: laszlocsomor@google.com (Laszlo Csomor)
//
// Unit tests for long-path-aware open/mkdir/access/etc. on Windows, as well as
// for the supporting utility functions.
//
// This file is only used on Windows, it's empty on other platforms.

#if defined(_WIN32)

#define WIN32_LEAN_AND_MEAN
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <wchar.h>
#include <windows.h>

#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/scoped_ptr.h>
#include <gtest/gtest.h>

#include <memory>
#include <sstream>
#include <string>

namespace google {
namespace protobuf {
namespace internal {
namespace win32 {
namespace {

const char kUtf8Text[] = {
    'h', 'i', ' ',
    // utf-8: 11010000 10011111, utf-16: 100 0001 1111 = 0x041F
    0xd0, 0x9f,
    // utf-8: 11010001 10000000, utf-16: 100 0100 0000 = 0x0440
    0xd1, 0x80,
    // utf-8: 11010000 10111000, utf-16: 100 0011 1000 = 0x0438
    0xd0, 0xb8,
    // utf-8: 11010000 10110010, utf-16: 100 0011 0010 = 0x0432
    0xd0, 0xb2,
    // utf-8: 11010000 10110101, utf-16: 100 0011 0101 = 0x0435
    0xd0, 0xb5,
    // utf-8: 11010001 10000010, utf-16: 100 0100 0010 = 0x0442
    0xd1, 0x82, 0
};

const wchar_t kUtf16Text[] = {
  L'h', L'i', L' ',
  L'\x41f', L'\x440', L'\x438', L'\x432', L'\x435', L'\x442', 0
};

using std::string;
using std::wstring;

class IoWin32Test : public ::testing::Test {
 public:
  void SetUp();
  void TearDown();

 protected:
  bool CreateAllUnder(wstring path);
  bool DeleteAllUnder(wstring path);

  WCHAR working_directory[MAX_PATH];
  string test_tmpdir;
  wstring wtest_tmpdir;
};

#define ASSERT_INITIALIZED              \
  {                                     \
    EXPECT_FALSE(test_tmpdir.empty());  \
    EXPECT_FALSE(wtest_tmpdir.empty()); \
  }

namespace {
void StripTrailingSlashes(string* str) {
  int i = str->size() - 1;
  for (; i >= 0 && ((*str)[i] == '/' || (*str)[i] == '\\'); --i) {}
  str->resize(i+1);
}

bool GetEnvVarAsUtf8(const WCHAR* name, string* result) {
  DWORD size = ::GetEnvironmentVariableW(name, NULL, 0);
  if (size > 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
    scoped_array<WCHAR> wcs(new WCHAR[size]);
    ::GetEnvironmentVariableW(name, wcs.get(), size);
    // GetEnvironmentVariableA retrieves an Active-Code-Page-encoded text which
    // we'd first need to convert to UTF-16 then to UTF-8, because there seems
    // to be no API function to do that conversion directly.
    // GetEnvironmentVariableW retrieves an UTF-16-encoded text, which we need
    // to convert to UTF-8.
    return strings::wcs_to_utf8(wcs.get(), result);
  } else {
    return false;
  }
}

bool GetCwdAsUtf8(string* result) {
  DWORD size = ::GetCurrentDirectoryW(0, NULL);
  if (size > 0) {
    scoped_array<WCHAR> wcs(new WCHAR[size]);
    ::GetCurrentDirectoryW(size, wcs.get());
    // GetCurrentDirectoryA retrieves an Active-Code-Page-encoded text which
    // we'd first need to convert to UTF-16 then to UTF-8, because there seems
    // to be no API function to do that conversion directly.
    // GetCurrentDirectoryW retrieves an UTF-16-encoded text, which we need
    // to convert to UTF-8.
    return strings::wcs_to_utf8(wcs.get(), result);
  } else {
    return false;
  }
}

}  // namespace

void IoWin32Test::SetUp() {
  test_tmpdir.clear();
  wtest_tmpdir.clear();
  EXPECT_GT(::GetCurrentDirectoryW(MAX_PATH, working_directory), 0);

  string tmp;
  bool ok = false;
  if (!ok) {
    // Bazel sets this environment variable when it runs tests.
    ok = GetEnvVarAsUtf8(L"TEST_TMPDIR", &tmp);
  }
  if (!ok) {
    // Bazel 0.8.0 sets this environment for every build and test action.
    ok = GetEnvVarAsUtf8(L"TEMP", &tmp);
  }
  if (!ok) {
    // Bazel 0.8.0 sets this environment for every build and test action.
    ok = GetEnvVarAsUtf8(L"TMP", &tmp);
  }
  if (!ok) {
    // Fall back to using the current directory.
    ok = GetCwdAsUtf8(&tmp);
  }
  if (!ok || tmp.empty()) {
    FAIL() << "Cannot find a temp directory.";
  }

  StripTrailingSlashes(&tmp);
  std::stringstream result;
  // Deleting files and directories is asynchronous on Windows, and if TearDown
  // just deleted the previous temp directory, sometimes we cannot recreate the
  // same directory.
  // Use a counter so every test method gets its own temp directory.
  static unsigned int counter = 0;
  result << tmp << "\\w32tst" << counter++ << ".tmp";
  test_tmpdir = result.str();
  wtest_tmpdir = testonly_utf8_to_winpath(test_tmpdir.c_str());
  ASSERT_FALSE(wtest_tmpdir.empty());
  ASSERT_TRUE(DeleteAllUnder(wtest_tmpdir));
  ASSERT_TRUE(CreateAllUnder(wtest_tmpdir));
}

void IoWin32Test::TearDown() {
  if (!wtest_tmpdir.empty()) {
    DeleteAllUnder(wtest_tmpdir);
  }
  ::SetCurrentDirectoryW(working_directory);
}

bool IoWin32Test::CreateAllUnder(wstring path) {
  // Prepend UNC prefix if the path doesn't have it already. Don't bother
  // checking if the path is shorter than MAX_PATH, let's just do it
  // unconditionally.
  if (path.find(L"\\\\?\\") != 0) {
    path = wstring(L"\\\\?\\") + path;
  }
  if (::CreateDirectoryW(path.c_str(), NULL) ||
      GetLastError() == ERROR_ALREADY_EXISTS ||
      GetLastError() == ERROR_ACCESS_DENIED) {
    return true;
  }
  if (GetLastError() == ERROR_PATH_NOT_FOUND) {
    size_t pos = path.find_last_of(L'\\');
    if (pos != wstring::npos) {
      wstring parent(path, 0, pos);
      if (CreateAllUnder(parent) && CreateDirectoryW(path.c_str(), NULL)) {
        return true;
      }
    }
  }
  return false;
}

bool IoWin32Test::DeleteAllUnder(wstring path) {
  static const wstring kDot(L".");
  static const wstring kDotDot(L"..");

  // Prepend UNC prefix if the path doesn't have it already. Don't bother
  // checking if the path is shorter than MAX_PATH, let's just do it
  // unconditionally.
  if (path.find(L"\\\\?\\") != 0) {
    path = wstring(L"\\\\?\\") + path;
  }
  // Append "\" if necessary.
  if (path[path.size() - 1] != L'\\') {
    path.push_back(L'\\');
  }

  WIN32_FIND_DATAW metadata;
  HANDLE handle = ::FindFirstFileW((path + L"*").c_str(), &metadata);
  if (handle == INVALID_HANDLE_VALUE) {
    return true;  // directory doesn't exist
  }

  bool result = true;
  do {
    wstring childname = metadata.cFileName;
    if (kDot != childname && kDotDot != childname) {
      wstring childpath = path + childname;
      if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
        // If this is not a junction, delete its contents recursively.
        // Finally delete this directory/junction too.
        if (((metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 &&
             !DeleteAllUnder(childpath)) ||
            !::RemoveDirectoryW(childpath.c_str())) {
          result = false;
          break;
        }
      } else {
        if (!::DeleteFileW(childpath.c_str())) {
          result = false;
          break;
        }
      }
    }
  } while (::FindNextFileW(handle, &metadata));
  ::FindClose(handle);
  return result;
}

TEST_F(IoWin32Test, AccessTest) {
  ASSERT_INITIALIZED;

  string path = test_tmpdir;
  while (path.size() < MAX_PATH - 30) {
    path += "\\accesstest";
    EXPECT_EQ(mkdir(path.c_str(), 0644), 0);
  }
  string file = path + "\\file.txt";
  int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644);
  if (fd > 0) {
    EXPECT_EQ(close(fd), 0);
  } else {
    EXPECT_TRUE(false);
  }

  EXPECT_EQ(access(test_tmpdir.c_str(), F_OK), 0);
  EXPECT_EQ(access(path.c_str(), F_OK), 0);
  EXPECT_EQ(access(path.c_str(), W_OK), 0);
  EXPECT_EQ(access(file.c_str(), F_OK | W_OK), 0);
  EXPECT_NE(access((file + ".blah").c_str(), F_OK), 0);
  EXPECT_NE(access((file + ".blah").c_str(), W_OK), 0);

  EXPECT_EQ(access(".", F_OK), 0);
  EXPECT_EQ(access(".", W_OK), 0);
  EXPECT_EQ(access((test_tmpdir + "/accesstest").c_str(), F_OK | W_OK), 0);
  ASSERT_EQ(access((test_tmpdir + "/./normalize_me/.././accesstest").c_str(),
                   F_OK | W_OK),
            0);
  EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", F_OK), 0);
  EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", W_OK), 0);

  ASSERT_EQ(access("c:bad", F_OK), -1);
  ASSERT_EQ(errno, ENOENT);
  ASSERT_EQ(access("/tmp/bad", F_OK), -1);
  ASSERT_EQ(errno, ENOENT);
  ASSERT_EQ(access("\\bad", F_OK), -1);
  ASSERT_EQ(errno, ENOENT);
}

TEST_F(IoWin32Test, OpenTest) {
  ASSERT_INITIALIZED;

  string path = test_tmpdir;
  while (path.size() < MAX_PATH) {
    path += "\\opentest";
    EXPECT_EQ(mkdir(path.c_str(), 0644), 0);
  }
  string file = path + "\\file.txt";
  int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644);
  if (fd > 0) {
    EXPECT_EQ(write(fd, "hello", 5), 5);
    EXPECT_EQ(close(fd), 0);
  } else {
    EXPECT_TRUE(false);
  }

  ASSERT_EQ(open("c:bad.txt", O_CREAT | O_WRONLY, 0644), -1);
  ASSERT_EQ(errno, ENOENT);
  ASSERT_EQ(open("/tmp/bad.txt", O_CREAT | O_WRONLY, 0644), -1);
  ASSERT_EQ(errno, ENOENT);
  ASSERT_EQ(open("\\bad.txt", O_CREAT | O_WRONLY, 0644), -1);
  ASSERT_EQ(errno, ENOENT);
}

TEST_F(IoWin32Test, MkdirTest) {
  ASSERT_INITIALIZED;

  string path = test_tmpdir;
  do {
    path += "\\mkdirtest";
    ASSERT_EQ(mkdir(path.c_str(), 0644), 0);
  } while (path.size() <= MAX_PATH);

  ASSERT_EQ(mkdir("c:bad", 0644), -1);
  ASSERT_EQ(errno, ENOENT);
  ASSERT_EQ(mkdir("/tmp/bad", 0644), -1);
  ASSERT_EQ(errno, ENOENT);
  ASSERT_EQ(mkdir("\\bad", 0644), -1);
  ASSERT_EQ(errno, ENOENT);
}

TEST_F(IoWin32Test, MkdirTestNonAscii) {
  ASSERT_INITIALIZED;

  // Create a non-ASCII path.
  // Ensure that we can create the directory using SetCurrentDirectoryW.
  EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L"\\1").c_str(), NULL));
  EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L"\\1\\" + kUtf16Text).c_str(), NULL));
  // Ensure that we can create a very similarly named directory using mkdir.
  // We don't attemp to delete and recreate the same directory, because on
  // Windows, deleting files and directories seems to be asynchronous.
  EXPECT_EQ(mkdir((test_tmpdir + "\\2").c_str(), 0644), 0);
  EXPECT_EQ(mkdir((test_tmpdir + "\\2\\" + kUtf8Text).c_str(), 0644), 0);
}

TEST_F(IoWin32Test, ChdirTest) {
  string path("C:\\");
  EXPECT_EQ(access(path.c_str(), F_OK), 0);
  ASSERT_EQ(chdir(path.c_str()), 0);

  // Do not try to chdir into the test_tmpdir, it may already contain directory
  // names with trailing dots.
  // Instead test here with an obviously dot-trailed path. If the win32_chdir
  // function would not convert the path to absolute and prefix with "\\?\" then
  // the Win32 API would ignore the trailing dot, but because of the prefixing
  // there'll be no path processing done, so we'll actually attempt to chdir
  // into "C:\some\path\foo."
  path = test_tmpdir + "/foo.";
  EXPECT_EQ(mkdir(path.c_str(), 644), 0);
  EXPECT_EQ(access(path.c_str(), F_OK), 0);
  ASSERT_NE(chdir(path.c_str()), 0);
}

TEST_F(IoWin32Test, ChdirTestNonAscii) {
  ASSERT_INITIALIZED;

  // Create a directory with a non-ASCII path and ensure we can cd into it.
  wstring wNonAscii(wtest_tmpdir + L"\\" + kUtf16Text);
  string nonAscii;
  EXPECT_TRUE(strings::wcs_to_utf8(wNonAscii.c_str(), &nonAscii));
  EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(), NULL));
  WCHAR cwd[MAX_PATH];
  EXPECT_TRUE(GetCurrentDirectoryW(MAX_PATH, cwd));
  // Ensure that we can cd into the path using SetCurrentDirectoryW.
  EXPECT_TRUE(SetCurrentDirectoryW(wNonAscii.c_str()));
  EXPECT_TRUE(SetCurrentDirectoryW(cwd));
  // Ensure that we can cd into the path using chdir.
  ASSERT_EQ(chdir(nonAscii.c_str()), 0);
  // Ensure that the GetCurrentDirectoryW returns the desired path.
  EXPECT_TRUE(GetCurrentDirectoryW(MAX_PATH, cwd));
  ASSERT_EQ(wNonAscii, cwd);
}

TEST_F(IoWin32Test, AsWindowsPathTest) {
  DWORD size = GetCurrentDirectoryW(0, NULL);
  scoped_array<wchar_t> cwd_str(new wchar_t[size]);
  EXPECT_GT(GetCurrentDirectoryW(size, cwd_str.get()), 0);
  wstring cwd = wstring(L"\\\\?\\") + cwd_str.get();

  ASSERT_EQ(testonly_utf8_to_winpath("relative_mkdirtest"),
            cwd + L"\\relative_mkdirtest");
  ASSERT_EQ(testonly_utf8_to_winpath("preserve//\\trailing///"),
            cwd + L"\\preserve\\trailing\\");
  ASSERT_EQ(testonly_utf8_to_winpath("./normalize_me\\/../blah"),
            cwd + L"\\blah");
  std::ostringstream relpath;
  for (wchar_t* p = cwd_str.get(); *p; ++p) {
    if (*p == '/' || *p == '\\') {
      relpath << "../";
    }
  }
  relpath << ".\\/../\\./beyond-toplevel";
  ASSERT_EQ(testonly_utf8_to_winpath(relpath.str().c_str()),
            wstring(L"\\\\?\\") + cwd_str.get()[0] + L":\\beyond-toplevel");

  // Absolute unix paths lack drive letters, driveless absolute windows paths
  // do too. Neither can be converted to a drive-specifying absolute Windows
  // path.
  ASSERT_EQ(testonly_utf8_to_winpath("/absolute/unix/path"), L"");
  // Though valid on Windows, we also don't support UNC paths (\\UNC\\blah).
  ASSERT_EQ(testonly_utf8_to_winpath("\\driveless\\absolute"), L"");
  // Though valid in cmd.exe, drive-relative paths are not supported.
  ASSERT_EQ(testonly_utf8_to_winpath("c:foo"), L"");
  ASSERT_EQ(testonly_utf8_to_winpath("c:/foo"), L"\\\\?\\c:\\foo");
  ASSERT_EQ(testonly_utf8_to_winpath("\\\\?\\C:\\foo"), L"\\\\?\\C:\\foo");
}

TEST_F(IoWin32Test, Utf8Utf16ConversionTest) {
  string mbs;
  wstring wcs;
  ASSERT_TRUE(strings::utf8_to_wcs(kUtf8Text, &wcs));
  ASSERT_TRUE(strings::wcs_to_utf8(kUtf16Text, &mbs));
  ASSERT_EQ(wcs, kUtf16Text);
  ASSERT_EQ(mbs, kUtf8Text);
}

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

#endif  // defined(_WIN32)