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.

// StatusOr<T> is the union of a Status object and a T
// object. StatusOr models the concept of an object that is either a
// usable value, or an error Status explaining why such a value is
// not present. To this end, StatusOr<T> does not allow its Status
// value to be Status::OK. Further, StatusOr<T*> does not allow the
// contained pointer to be NULL.
//
// The primary use-case for StatusOr<T> is as the return value of a
// function which may fail.
//
// Example client usage for a StatusOr<T>, where T is not a pointer:
//
//  StatusOr<float> result = DoBigCalculationThatCouldFail();
//  if (result.ok()) {
//    float answer = result.ValueOrDie();
//    printf("Big calculation yielded: %f", answer);
//  } else {
//    LOG(ERROR) << result.status();
//  }
//
// Example client usage for a StatusOr<T*>:
//
//  StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
//  if (result.ok()) {
//    std::unique_ptr<Foo> foo(result.ValueOrDie());
//    foo->DoSomethingCool();
//  } else {
//    LOG(ERROR) << result.status();
//  }
//
// Example client usage for a StatusOr<std::unique_ptr<T>>:
//
//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
//  if (result.ok()) {
//    std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
//    foo->DoSomethingCool();
//  } else {
//    LOG(ERROR) << result.status();
//  }
//
// Example factory implementation returning StatusOr<T*>:
//
//  StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
//    if (arg <= 0) {
//      return ::util::Status(::util::error::INVALID_ARGUMENT,
//                            "Arg must be positive");
//    } else {
//      return new Foo(arg);
//    }
//  }
//

#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_

#include <new>
#include <string>
#include <utility>

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

namespace google {
namespace protobuf {
namespace util {

template<typename T>
class StatusOr {
  template<typename U> friend class StatusOr;

 public:
  // Construct a new StatusOr with Status::UNKNOWN status
  StatusOr();

  // Construct a new StatusOr with the given non-ok status. After calling
  // this constructor, calls to ValueOrDie() will CHECK-fail.
  //
  // NOTE: Not explicit - we want to use StatusOr<T> as a return
  // value, so it is convenient and sensible to be able to do 'return
  // Status()' when the return type is StatusOr<T>.
  //
  // REQUIRES: status != Status::OK. This requirement is DCHECKed.
  // In optimized builds, passing Status::OK here will have the effect
  // of passing PosixErrorSpace::EINVAL as a fallback.
  StatusOr(const Status& status);  // NOLINT

  // Construct a new StatusOr with the given value. If T is a plain pointer,
  // value must not be NULL. After calling this constructor, calls to
  // ValueOrDie() will succeed, and calls to status() will return OK.
  //
  // NOTE: Not explicit - we want to use StatusOr<T> as a return type
  // so it is convenient and sensible to be able to do 'return T()'
  // when when the return type is StatusOr<T>.
  //
  // REQUIRES: if T is a plain pointer, value != NULL. This requirement is
  // DCHECKed. In optimized builds, passing a NULL pointer here will have
  // the effect of passing PosixErrorSpace::EINVAL as a fallback.
  StatusOr(const T& value);  // NOLINT

  // Copy constructor.
  StatusOr(const StatusOr& other);

  // Conversion copy constructor, T must be copy constructible from U
  template<typename U>
  StatusOr(const StatusOr<U>& other);

  // Assignment operator.
  StatusOr& operator=(const StatusOr& other);

  // Conversion assignment operator, T must be assignable from U
  template<typename U>
  StatusOr& operator=(const StatusOr<U>& other);

  // Returns a reference to our status. If this contains a T, then
  // returns Status::OK.
  const Status& status() const;

  // Returns this->status().ok()
  bool ok() const;

  // Returns a reference to our current value, or CHECK-fails if !this->ok().
  // If you need to initialize a T object from the stored value,
  // ConsumeValueOrDie() may be more efficient.
  const T& ValueOrDie() const;

 private:
  Status status_;
  T value_;
};

////////////////////////////////////////////////////////////////////////////////
// Implementation details for StatusOr<T>

namespace internal {

class LIBPROTOBUF_EXPORT StatusOrHelper {
 public:
  // Move type-agnostic error handling to the .cc.
  static void Crash(const util::Status& status);

  // Customized behavior for StatusOr<T> vs. StatusOr<T*>
  template<typename T>
  struct Specialize;
};

template<typename T>
struct StatusOrHelper::Specialize {
  // For non-pointer T, a reference can never be NULL.
  static inline bool IsValueNull(const T& t) { return false; }
};

template<typename T>
struct StatusOrHelper::Specialize<T*> {
  static inline bool IsValueNull(const T* t) { return t == NULL; }
};

}  // namespace internal

template<typename T>
inline StatusOr<T>::StatusOr()
    : status_(util::Status::UNKNOWN) {
}

template<typename T>
inline StatusOr<T>::StatusOr(const Status& status) {
  if (status.ok()) {
    status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
  } else {
    status_ = status;
  }
}

template<typename T>
inline StatusOr<T>::StatusOr(const T& value) {
  if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
    status_ = Status(error::INTERNAL, "NULL is not a vaild argument.");
  } else {
    status_ = Status::OK;
    value_ = value;
  }
}

template<typename T>
inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
    : status_(other.status_), value_(other.value_) {
}

template<typename T>
inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
  status_ = other.status_;
  value_ = other.value_;
  return *this;
}

template<typename T>
template<typename U>
inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
    : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
}

template<typename T>
template<typename U>
inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
  status_ = other.status_;
  if (status_.ok()) value_ = other.value_;
  return *this;
}

template<typename T>
inline const Status& StatusOr<T>::status() const {
  return status_;
}

template<typename T>
inline bool StatusOr<T>::ok() const {
  return status().ok();
}

template<typename T>
inline const T& StatusOr<T>::ValueOrDie() const {
  if (!status_.ok()) {
    internal::StatusOrHelper::Crash(status_);
  }
  return value_;
}
}  // namespace util
}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_


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
//
// This code is compiled directly on many platforms, including client
// platforms like Windows, Mac, and embedded systems.  Before making
// any changes here, make sure that you're not breaking any platforms.
//
// Define a small subset of tr1 type traits. The traits we define are:
//   enable_if
//   is_integral
//   is_floating_point
//   is_pointer
//   is_enum
//   is_reference
//   is_pod
//   has_trivial_constructor
//   has_trivial_copy
//   has_trivial_assign
//   has_trivial_destructor
//   remove_const
//   remove_volatile
//   remove_cv
//   remove_reference
//   add_reference
//   remove_pointer
//   is_same
//   is_convertible
// We can add more type traits as required.

#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_

#include <cstddef>                  // for NULL
#include <utility>                  // For pair

#include <google/protobuf/stubs/template_util.h>  // For true_type and false_type

namespace google {
namespace protobuf {
namespace internal {

template<typename B, typename D>
struct is_base_of {
  typedef char (&yes)[1];
  typedef char (&no)[2];

  // BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac.
  #undef check
  // END GOOGLE LOCAL MODIFICATION

  static yes check(const B*);
  static no check(const void*);

  enum {
    value = sizeof(check(static_cast<const D*>(NULL))) == sizeof(yes),
  };
};

template <bool cond, class T = void> struct enable_if;
template <class T> struct is_integral;
template <class T> struct is_floating_point;
template <class T> struct is_pointer;
// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
// is_enum uses is_convertible, which is not available on MSVC.
template <class T> struct is_enum;
#endif
template <class T> struct is_reference;
template <class T> struct is_pod;
template <class T> struct has_trivial_constructor;
template <class T> struct has_trivial_copy;
template <class T> struct has_trivial_assign;
template <class T> struct has_trivial_destructor;
template <class T> struct remove_const;
template <class T> struct remove_volatile;
template <class T> struct remove_cv;
template <class T> struct remove_reference;
template <class T> struct add_reference;
template <class T> struct remove_pointer;
template <class T, class U> struct is_same;
#if !(defined(__GNUC__) && __GNUC__ <= 3)
template <class From, class To> struct is_convertible;
#endif

// enable_if, equivalent semantics to c++11 std::enable_if, specifically:
//   "If B is true, the member typedef type shall equal T; otherwise, there
//    shall be no member typedef type."
// Specified by 20.9.7.6 [Other transformations]

template<bool cond, class T> struct enable_if { typedef T type; };
template<class T> struct enable_if<false, T> {};
// is_integral is false except for the built-in integer types. A
// cv-qualified type is integral if and only if the underlying type is.
template <class T> struct is_integral : false_type { };
template<> struct is_integral<bool> : true_type { };
template<> struct is_integral<char> : true_type { };
template<> struct is_integral<unsigned char> : true_type { };
template<> struct is_integral<signed char> : true_type { };
#if defined(_MSC_VER)
// wchar_t is not by default a distinct type from unsigned short in
// Microsoft C.
// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
template<> struct is_integral<__wchar_t> : true_type { };
#else
template<> struct is_integral<wchar_t> : true_type { };
#endif
template<> struct is_integral<short> : true_type { };
template<> struct is_integral<unsigned short> : true_type { };
template<> struct is_integral<int> : true_type { };
template<> struct is_integral<unsigned int> : true_type { };
template<> struct is_integral<long> : true_type { };
template<> struct is_integral<unsigned long> : true_type { };
#if defined(HAVE_LONG_LONG) || defined(_MSC_VER)
template<> struct is_integral<long long> : true_type { };
template<> struct is_integral<unsigned long long> : true_type { };
#endif
template <class T> struct is_integral<const T> : is_integral<T> { };
template <class T> struct is_integral<volatile T> : is_integral<T> { };
template <class T> struct is_integral<const volatile T> : is_integral<T> { };

// is_floating_point is false except for the built-in floating-point types.
// A cv-qualified type is integral if and only if the underlying type is.
template <class T> struct is_floating_point : false_type { };
template<> struct is_floating_point<float> : true_type { };
template<> struct is_floating_point<double> : true_type { };
template<> struct is_floating_point<long double> : true_type { };
template <class T> struct is_floating_point<const T>
    : is_floating_point<T> { };
template <class T> struct is_floating_point<volatile T>
    : is_floating_point<T> { };
template <class T> struct is_floating_point<const volatile T>
    : is_floating_point<T> { };

// is_pointer is false except for pointer types. A cv-qualified type (e.g.
// "int* const", as opposed to "int const*") is cv-qualified if and only if
// the underlying type is.
template <class T> struct is_pointer : false_type { };
template <class T> struct is_pointer<T*> : true_type { };
template <class T> struct is_pointer<const T> : is_pointer<T> { };
template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };

#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)

namespace type_traits_internal {

template <class T> struct is_class_or_union {
  template <class U> static small_ tester(void (U::*)());
  template <class U> static big_ tester(...);
  static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
};

// is_convertible chokes if the first argument is an array. That's why
// we use add_reference here.
template <bool NotUnum, class T> struct is_enum_impl
    : is_convertible<typename add_reference<T>::type, int> { };

template <class T> struct is_enum_impl<true, T> : false_type { };

}  // namespace type_traits_internal

// Specified by TR1 [4.5.1] primary type categories.

// Implementation note:
//
// Each type is either void, integral, floating point, array, pointer,
// reference, member object pointer, member function pointer, enum,
// union or class. Out of these, only integral, floating point, reference,
// class and enum types are potentially convertible to int. Therefore,
// if a type is not a reference, integral, floating point or class and
// is convertible to int, it's a enum. Adding cv-qualification to a type
// does not change whether it's an enum.
//
// Is-convertible-to-int check is done only if all other checks pass,
// because it can't be used with some types (e.g. void or classes with
// inaccessible conversion operators).
template <class T> struct is_enum
    : type_traits_internal::is_enum_impl<
          is_same<T, void>::value ||
              is_integral<T>::value ||
              is_floating_point<T>::value ||
              is_reference<T>::value ||
              type_traits_internal::is_class_or_union<T>::value,
          T> { };

template <class T> struct is_enum<const T> : is_enum<T> { };
template <class T> struct is_enum<volatile T> : is_enum<T> { };
template <class T> struct is_enum<const volatile T> : is_enum<T> { };

#endif

// is_reference is false except for reference types.
template<typename T> struct is_reference : false_type {};
template<typename T> struct is_reference<T&> : true_type {};

// We can't get is_pod right without compiler help, so fail conservatively.
// We will assume it's false except for arithmetic types, enumerations,
// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
// is not a POD even if T and U are PODs.
template <class T> struct is_pod
 : integral_constant<bool, (is_integral<T>::value ||
                            is_floating_point<T>::value ||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
                            // is_enum is not available on MSVC.
                            is_enum<T>::value ||
#endif
                            is_pointer<T>::value)> { };
template <class T> struct is_pod<const T> : is_pod<T> { };
template <class T> struct is_pod<volatile T> : is_pod<T> { };
template <class T> struct is_pod<const volatile T> : is_pod<T> { };

// We can't get has_trivial_constructor right without compiler help, so
// fail conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial
// constructors. (3) array of a type with a trivial constructor.
// (4) const versions thereof.
template <class T> struct has_trivial_constructor : is_pod<T> { };
template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
  : integral_constant<bool,
                      (has_trivial_constructor<T>::value &&
                       has_trivial_constructor<U>::value)> { };
template <class A, int N> struct has_trivial_constructor<A[N]>
  : has_trivial_constructor<A> { };
template <class T> struct has_trivial_constructor<const T>
  : has_trivial_constructor<T> { };

// We can't get has_trivial_copy right without compiler help, so fail
// conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial copy
// constructors. (3) array of a type with a trivial copy constructor.
// (4) const versions thereof.
template <class T> struct has_trivial_copy : is_pod<T> { };
template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
  : integral_constant<bool,
                      (has_trivial_copy<T>::value &&
                       has_trivial_copy<U>::value)> { };
template <class A, int N> struct has_trivial_copy<A[N]>
  : has_trivial_copy<A> { };
template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };

// We can't get has_trivial_assign right without compiler help, so fail
// conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial copy
// constructors. (3) array of a type with a trivial assign constructor.
template <class T> struct has_trivial_assign : is_pod<T> { };
template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
  : integral_constant<bool,
                      (has_trivial_assign<T>::value &&
                       has_trivial_assign<U>::value)> { };
template <class A, int N> struct has_trivial_assign<A[N]>
  : has_trivial_assign<A> { };

// We can't get has_trivial_destructor right without compiler help, so
// fail conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial
// destructors. (3) array of a type with a trivial destructor.
// (4) const versions thereof.
template <class T> struct has_trivial_destructor : is_pod<T> { };
template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
  : integral_constant<bool,
                      (has_trivial_destructor<T>::value &&
                       has_trivial_destructor<U>::value)> { };
template <class A, int N> struct has_trivial_destructor<A[N]>
  : has_trivial_destructor<A> { };
template <class T> struct has_trivial_destructor<const T>
  : has_trivial_destructor<T> { };

// Specified by TR1 [4.7.1]
template<typename T> struct remove_const { typedef T type; };
template<typename T> struct remove_const<T const> { typedef T type; };
template<typename T> struct remove_volatile { typedef T type; };
template<typename T> struct remove_volatile<T volatile> { typedef T type; };
template<typename T> struct remove_cv {
  typedef typename remove_const<typename remove_volatile<T>::type>::type type;
};

// Specified by TR1 [4.7.2] Reference modifications.
template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };

template <typename T> struct add_reference { typedef T& type; };
template <typename T> struct add_reference<T&> { typedef T& type; };

// Specified by TR1 [4.7.4] Pointer modifications.
template<typename T> struct remove_pointer { typedef T type; };
template<typename T> struct remove_pointer<T*> { typedef T type; };
template<typename T> struct remove_pointer<T* const> { typedef T type; };
template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
template<typename T> struct remove_pointer<T* const volatile> {
  typedef T type; };

// Specified by TR1 [4.6] Relationships between types
template<typename T, typename U> struct is_same : public false_type { };
template<typename T> struct is_same<T, T> : public true_type { };

// Specified by TR1 [4.6] Relationships between types
#if !(defined(__GNUC__) && __GNUC__ <= 3)
namespace type_traits_internal {

// This class is an implementation detail for is_convertible, and you
// don't need to know how it works to use is_convertible. For those
// who care: we declare two different functions, one whose argument is
// of type To and one with a variadic argument list. We give them
// return types of different size, so we can use sizeof to trick the
// compiler into telling us which function it would have chosen if we
// had called it with an argument of type From.  See Alexandrescu's
// _Modern C++ Design_ for more details on this sort of trick.

template <typename From, typename To>
struct ConvertHelper {
  static small_ Test(To);
  static big_ Test(...);
  static From Create();
  enum {
    value = sizeof(Test(Create())) == sizeof(small_)
  };
};
}  // namespace type_traits_internal

// Inherits from true_type if From is convertible to To, false_type otherwise.
template <typename From, typename To>
struct is_convertible
    : integral_constant<bool,
                        type_traits_internal::ConvertHelper<From, To>::value> {
};
#endif

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

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

// From: util/task/contrib/status_macros/status_macros.h

#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_

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

namespace google {
namespace protobuf {
namespace util {

// Run a command that returns a util::Status.  If the called code returns an
// error status, return that status up out of this method too.
//
// Example:
//   RETURN_IF_ERROR(DoThings(4));
#define RETURN_IF_ERROR(expr) \
  do { \
    /* Using _status below to avoid capture problems if expr is "status". */ \
    const ::google::protobuf::util::Status _status = (expr); \
    if (GOOGLE_PREDICT_FALSE(!_status.ok())) return _status; \
  } while (0)

// Internal helper for concatenating macro values.
#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y
#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y)

template<typename T>
Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
  if (result.ok()) {
    lhs = result.ValueOrDie();
  }
  return result.status();
}

#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \
  Status status = DoAssignOrReturn(lhs, (rexpr)); \
  if (GOOGLE_PREDICT_FALSE(!status.ok())) return status;

// Executes an expression that returns a util::StatusOr, extracting its value
// into the variable defined by lhs (or returning on error).
//
// Example: Assigning to an existing value
//   ValueType value;
//   ASSIGN_OR_RETURN(value, MaybeGetValue(arg));
//
// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used
//  in a single statement (e.g. as the body of an if statement without {})!
#define ASSIGN_OR_RETURN(lhs, rexpr) \
  ASSIGN_OR_RETURN_IMPL( \
      STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr);

}  // namespace util
}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_STATUS_H_


text:
optional_int32: 101
optional_int64: 102
optional_uint32: 103
optional_uint64: 104
optional_sint32: 105
optional_sint64: 106
optional_fixed32: 107
optional_fixed64: 108
optional_sfixed32: 109
optional_sfixed64: 110
optional_float: 111
optional_double: 112
optional_bool: true
optional_string: "115"
optional_bytes: "116"
OptionalGroup {
  a: 117
}
optional_nested_message {
  bb: 118
}
optional_foreign_message {
  c: 119
}
optional_import_message {
  d: 120
}
optional_nested_enum: BAZ
optional_foreign_enum: FOREIGN_BAZ
optional_import_enum: IMPORT_BAZ
optional_string_piece: "124"
optional_cord: "125"
optional_public_import_message {
  e: 126
}
optional_lazy_message {
  bb: 127
}
repeated_int32: 201
repeated_int32: 301
repeated_int64: 202
repeated_int64: 302
repeated_uint32: 203
repeated_uint32: 303
repeated_uint64: 204
repeated_uint64: 304
repeated_sint32: 205
repeated_sint32: 305
repeated_sint64: 206
repeated_sint64: 306
repeated_fixed32: 207
repeated_fixed32: 307
repeated_fixed64: 208
repeated_fixed64: 308
repeated_sfixed32: 209
repeated_sfixed32: 309
repeated_sfixed64: 210
repeated_sfixed64: 310
repeated_float: 211
repeated_float: 311
repeated_double: 212
repeated_double: 312
repeated_bool: true
repeated_bool: false
repeated_string: "215"
repeated_string: "315"
repeated_bytes: "216"
repeated_bytes: "316"
RepeatedGroup {
  a: 217
}
RepeatedGroup {
  a: 317
}
repeated_nested_message {
  bb: 218
}
repeated_nested_message {
  bb: 318
}
repeated_foreign_message {
  c: 219
}
repeated_foreign_message {
  c: 319
}
repeated_import_message {
  d: 220
}
repeated_import_message {
  d: 320
}
repeated_nested_enum: BAR
repeated_nested_enum: BAZ
repeated_foreign_enum: FOREIGN_BAR
repeated_foreign_enum: FOREIGN_BAZ
repeated_import_enum: IMPORT_BAR
repeated_import_enum: IMPORT_BAZ
repeated_string_piece: "224"
repeated_string_piece: "324"
repeated_cord: "225"
repeated_cord: "325"
repeated_lazy_message {
  bb: 227
}
repeated_lazy_message {
  bb: 327
}
default_int32: 401
default_int64: 402
default_uint32: 403
default_uint64: 404
default_sint32: 405
default_sint64: 406
default_fixed32: 407
default_fixed64: 408
default_sfixed32: 409
default_sfixed64: 410
default_float: 411
default_double: 412
default_bool: false
default_string: "415"
default_bytes: "416"
default_nested_enum: FOO
default_foreign_enum: FOREIGN_FOO
default_import_enum: IMPORT_FOO
default_string_piece: "424"
default_cord: "425"
oneof_uint32: 601
oneof_nested_message {
  bb: 602
}
oneof_string: "603"
oneof_bytes: "604"


text:
optional_int32: 101
optional_int64: 102
optional_uint32: 103
optional_uint64: 104
optional_sint32: 105
optional_sint64: 106
optional_fixed32: 107
optional_fixed64: 108
optional_sfixed32: 109
optional_sfixed64: 110
optional_float: 111
optional_double: 112
optional_bool: true
optional_string: "115"
optional_bytes: "116"
OptionalGroup {
  a: 117
}
optional_nested_message {
  bb: 118
}
optional_foreign_message {
  c: 119
}
optional_import_message {
  d: 120
}
optional_nested_enum: BAZ
optional_foreign_enum: FOREIGN_BAZ
optional_import_enum: IMPORT_BAZ
optional_string_piece: "124"
optional_cord: "125"
optional_public_import_message {
  e: 126
}
optional_lazy_message {
  bb: 127
}
repeated_int32: 201
repeated_int32: 301
repeated_int64: 202
repeated_int64: 302
repeated_uint32: 203
repeated_uint32: 303
repeated_uint64: 204
repeated_uint64: 304
repeated_sint32: 205
repeated_sint32: 305
repeated_sint64: 206
repeated_sint64: 306
repeated_fixed32: 207
repeated_fixed32: 307
repeated_fixed64: 208
repeated_fixed64: 308
repeated_sfixed32: 209
repeated_sfixed32: 309
repeated_sfixed64: 210
repeated_sfixed64: 310
repeated_float: 211
repeated_float: 311
repeated_double: 212
repeated_double: 312
repeated_bool: true
repeated_bool: false
repeated_string: "215"
repeated_string: "315"
repeated_bytes: "216"
repeated_bytes: "316"
RepeatedGroup {
  a: 217
}
RepeatedGroup {
  a: 317
}
repeated_nested_message {
  bb: 218
}
repeated_nested_message {
  bb: 318
}
repeated_foreign_message {
  c: 219
}
repeated_foreign_message {
  c: 319
}
repeated_import_message {
  d: 220
}
repeated_import_message {
  d: 320
}
repeated_nested_enum: BAR
repeated_nested_enum: BAZ
repeated_foreign_enum: FOREIGN_BAR
repeated_foreign_enum: FOREIGN_BAZ
repeated_import_enum: IMPORT_BAR
repeated_import_enum: IMPORT_BAZ
repeated_string_piece: "224"
repeated_string_piece: "324"
repeated_cord: "225"
repeated_cord: "325"
repeated_lazy_message {
  bb: 227
}
repeated_lazy_message {
  bb: 327
}
default_int32: 401
default_int64: 402
default_uint32: 403
default_uint64: 404
default_sint32: 405
default_sint64: 406
default_fixed32: 407
default_fixed64: 408
default_sfixed32: 409
default_sfixed64: 410
default_float: 411
default_double: 412
default_bool: false
default_string: "415"
default_bytes: "416"
default_nested_enum: FOO
default_foreign_enum: FOREIGN_FOO
default_import_enum: IMPORT_FOO
default_string_piece: "424"
default_cord: "425"
oneof_bytes: "604"


text:
[protobuf_unittest.optional_int32_extension]: 101
[protobuf_unittest.optional_int64_extension]: 102
[protobuf_unittest.optional_uint32_extension]: 103
[protobuf_unittest.optional_uint64_extension]: 104
[protobuf_unittest.optional_sint32_extension]: 105
[protobuf_unittest.optional_sint64_extension]: 106
[protobuf_unittest.optional_fixed32_extension]: 107
[protobuf_unittest.optional_fixed64_extension]: 108
[protobuf_unittest.optional_sfixed32_extension]: 109
[protobuf_unittest.optional_sfixed64_extension]: 110
[protobuf_unittest.optional_float_extension]: 111
[protobuf_unittest.optional_double_extension]: 112
[protobuf_unittest.optional_bool_extension]: true
[protobuf_unittest.optional_string_extension]: "115"
[protobuf_unittest.optional_bytes_extension]: "116"
[protobuf_unittest.optionalgroup_extension] <
  a: 117
>
[protobuf_unittest.optional_nested_message_extension] <
  bb: 118
>
[protobuf_unittest.optional_foreign_message_extension] <
  c: 119
>
[protobuf_unittest.optional_import_message_extension] <
  d: 120
>
[protobuf_unittest.optional_nested_enum_extension]: BAZ
[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ
[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ
[protobuf_unittest.optional_string_piece_extension]: "124"
[protobuf_unittest.optional_cord_extension]: "125"
[protobuf_unittest.optional_public_import_message_extension] <
  e: 126
>
[protobuf_unittest.optional_lazy_message_extension] <
  bb: 127
>
[protobuf_unittest.repeated_int32_extension]: 201
[protobuf_unittest.repeated_int32_extension]: 301
[protobuf_unittest.repeated_int64_extension]: 202
[protobuf_unittest.repeated_int64_extension]: 302
[protobuf_unittest.repeated_uint32_extension]: 203
[protobuf_unittest.repeated_uint32_extension]: 303
[protobuf_unittest.repeated_uint64_extension]: 204
[protobuf_unittest.repeated_uint64_extension]: 304
[protobuf_unittest.repeated_sint32_extension]: 205
[protobuf_unittest.repeated_sint32_extension]: 305
[protobuf_unittest.repeated_sint64_extension]: 206
[protobuf_unittest.repeated_sint64_extension]: 306
[protobuf_unittest.repeated_fixed32_extension]: 207
[protobuf_unittest.repeated_fixed32_extension]: 307
[protobuf_unittest.repeated_fixed64_extension]: 208
[protobuf_unittest.repeated_fixed64_extension]: 308
[protobuf_unittest.repeated_sfixed32_extension]: 209
[protobuf_unittest.repeated_sfixed32_extension]: 309
[protobuf_unittest.repeated_sfixed64_extension]: 210
[protobuf_unittest.repeated_sfixed64_extension]: 310
[protobuf_unittest.repeated_float_extension]: 211
[protobuf_unittest.repeated_float_extension]: 311
[protobuf_unittest.repeated_double_extension]: 212
[protobuf_unittest.repeated_double_extension]: 312
[protobuf_unittest.repeated_bool_extension]: true
[protobuf_unittest.repeated_bool_extension]: false
[protobuf_unittest.repeated_string_extension]: "215"
[protobuf_unittest.repeated_string_extension]: "315"
[protobuf_unittest.repeated_bytes_extension]: "216"
[protobuf_unittest.repeated_bytes_extension]: "316"
[protobuf_unittest.repeatedgroup_extension] <
  a: 217
>
[protobuf_unittest.repeatedgroup_extension] <
  a: 317
>
[protobuf_unittest.repeated_nested_message_extension] <
  bb: 218
>
[protobuf_unittest.repeated_nested_message_extension] <
  bb: 318
>
[protobuf_unittest.repeated_foreign_message_extension] <
  c: 219
>
[protobuf_unittest.repeated_foreign_message_extension] <
  c: 319
>
[protobuf_unittest.repeated_import_message_extension] <
  d: 220
>
[protobuf_unittest.repeated_import_message_extension] <
  d: 320
>
[protobuf_unittest.repeated_nested_enum_extension]: BAR
[protobuf_unittest.repeated_nested_enum_extension]: BAZ
[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR
[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ
[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR
[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ
[protobuf_unittest.repeated_string_piece_extension]: "224"
[protobuf_unittest.repeated_string_piece_extension]: "324"
[protobuf_unittest.repeated_cord_extension]: "225"
[protobuf_unittest.repeated_cord_extension]: "325"
[protobuf_unittest.repeated_lazy_message_extension] <
  bb: 227
>
[protobuf_unittest.repeated_lazy_message_extension] <
  bb: 327
>
[protobuf_unittest.default_int32_extension]: 401
[protobuf_unittest.default_int64_extension]: 402
[protobuf_unittest.default_uint32_extension]: 403
[protobuf_unittest.default_uint64_extension]: 404
[protobuf_unittest.default_sint32_extension]: 405
[protobuf_unittest.default_sint64_extension]: 406
[protobuf_unittest.default_fixed32_extension]: 407
[protobuf_unittest.default_fixed64_extension]: 408
[protobuf_unittest.default_sfixed32_extension]: 409
[protobuf_unittest.default_sfixed64_extension]: 410
[protobuf_unittest.default_float_extension]: 411
[protobuf_unittest.default_double_extension]: 412
[protobuf_unittest.default_bool_extension]: false
[protobuf_unittest.default_string_extension]: "415"
[protobuf_unittest.default_bytes_extension]: "416"
[protobuf_unittest.default_nested_enum_extension]: FOO
[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO
[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO
[protobuf_unittest.default_string_piece_extension]: "424"
[protobuf_unittest.default_cord_extension]: "425"
[protobuf_unittest.oneof_uint32_extension]: 601
[protobuf_unittest.oneof_nested_message_extension] <
  bb: 602
>
[protobuf_unittest.oneof_string_extension]: "603"
[protobuf_unittest.oneof_bytes_extension]: "604"


text:
[protobuf_unittest.optional_int32_extension]: 101
[protobuf_unittest.optional_int64_extension]: 102
[protobuf_unittest.optional_uint32_extension]: 103
[protobuf_unittest.optional_uint64_extension]: 104
[protobuf_unittest.optional_sint32_extension]: 105
[protobuf_unittest.optional_sint64_extension]: 106
[protobuf_unittest.optional_fixed32_extension]: 107
[protobuf_unittest.optional_fixed64_extension]: 108
[protobuf_unittest.optional_sfixed32_extension]: 109
[protobuf_unittest.optional_sfixed64_extension]: 110
[protobuf_unittest.optional_float_extension]: 111
[protobuf_unittest.optional_double_extension]: 112
[protobuf_unittest.optional_bool_extension]: true
[protobuf_unittest.optional_string_extension]: "115"
[protobuf_unittest.optional_bytes_extension]: "116"
[protobuf_unittest.optionalgroup_extension] {
  a: 117
}
[protobuf_unittest.optional_nested_message_extension] {
  bb: 118
}
[protobuf_unittest.optional_foreign_message_extension] {
  c: 119
}
[protobuf_unittest.optional_import_message_extension] {
  d: 120
}
[protobuf_unittest.optional_nested_enum_extension]: BAZ
[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ
[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ
[protobuf_unittest.optional_string_piece_extension]: "124"
[protobuf_unittest.optional_cord_extension]: "125"
[protobuf_unittest.optional_public_import_message_extension] {
  e: 126
}
[protobuf_unittest.optional_lazy_message_extension] {
  bb: 127
}
[protobuf_unittest.repeated_int32_extension]: 201
[protobuf_unittest.repeated_int32_extension]: 301
[protobuf_unittest.repeated_int64_extension]: 202
[protobuf_unittest.repeated_int64_extension]: 302
[protobuf_unittest.repeated_uint32_extension]: 203
[protobuf_unittest.repeated_uint32_extension]: 303
[protobuf_unittest.repeated_uint64_extension]: 204
[protobuf_unittest.repeated_uint64_extension]: 304
[protobuf_unittest.repeated_sint32_extension]: 205
[protobuf_unittest.repeated_sint32_extension]: 305
[protobuf_unittest.repeated_sint64_extension]: 206
[protobuf_unittest.repeated_sint64_extension]: 306
[protobuf_unittest.repeated_fixed32_extension]: 207
[protobuf_unittest.repeated_fixed32_extension]: 307
[protobuf_unittest.repeated_fixed64_extension]: 208
[protobuf_unittest.repeated_fixed64_extension]: 308
[protobuf_unittest.repeated_sfixed32_extension]: 209
[protobuf_unittest.repeated_sfixed32_extension]: 309
[protobuf_unittest.repeated_sfixed64_extension]: 210
[protobuf_unittest.repeated_sfixed64_extension]: 310
[protobuf_unittest.repeated_float_extension]: 211
[protobuf_unittest.repeated_float_extension]: 311
[protobuf_unittest.repeated_double_extension]: 212
[protobuf_unittest.repeated_double_extension]: 312
[protobuf_unittest.repeated_bool_extension]: true
[protobuf_unittest.repeated_bool_extension]: false
[protobuf_unittest.repeated_string_extension]: "215"
[protobuf_unittest.repeated_string_extension]: "315"
[protobuf_unittest.repeated_bytes_extension]: "216"
[protobuf_unittest.repeated_bytes_extension]: "316"
[protobuf_unittest.repeatedgroup_extension] {
  a: 217
}
[protobuf_unittest.repeatedgroup_extension] {
  a: 317
}
[protobuf_unittest.repeated_nested_message_extension] {
  bb: 218
}
[protobuf_unittest.repeated_nested_message_extension] {
  bb: 318
}
[protobuf_unittest.repeated_foreign_message_extension] {
  c: 219
}
[protobuf_unittest.repeated_foreign_message_extension] {
  c: 319
}
[protobuf_unittest.repeated_import_message_extension] {
  d: 220
}
[protobuf_unittest.repeated_import_message_extension] {
  d: 320
}
[protobuf_unittest.repeated_nested_enum_extension]: BAR
[protobuf_unittest.repeated_nested_enum_extension]: BAZ
[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR
[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ
[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR
[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ
[protobuf_unittest.repeated_string_piece_extension]: "224"
[protobuf_unittest.repeated_string_piece_extension]: "324"
[protobuf_unittest.repeated_cord_extension]: "225"
[protobuf_unittest.repeated_cord_extension]: "325"
[protobuf_unittest.repeated_lazy_message_extension] {
  bb: 227
}
[protobuf_unittest.repeated_lazy_message_extension] {
  bb: 327
}
[protobuf_unittest.default_int32_extension]: 401
[protobuf_unittest.default_int64_extension]: 402
[protobuf_unittest.default_uint32_extension]: 403
[protobuf_unittest.default_uint64_extension]: 404
[protobuf_unittest.default_sint32_extension]: 405
[protobuf_unittest.default_sint64_extension]: 406
[protobuf_unittest.default_fixed32_extension]: 407
[protobuf_unittest.default_fixed64_extension]: 408
[protobuf_unittest.default_sfixed32_extension]: 409
[protobuf_unittest.default_sfixed64_extension]: 410
[protobuf_unittest.default_float_extension]: 411
[protobuf_unittest.default_double_extension]: 412
[protobuf_unittest.default_bool_extension]: false
[protobuf_unittest.default_string_extension]: "415"
[protobuf_unittest.default_bytes_extension]: "416"
[protobuf_unittest.default_nested_enum_extension]: FOO
[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO
[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO
[protobuf_unittest.default_string_piece_extension]: "424"
[protobuf_unittest.default_cord_extension]: "425"
[protobuf_unittest.oneof_uint32_extension]: 601
[protobuf_unittest.oneof_nested_message_extension] {
  bb: 602
}
[protobuf_unittest.oneof_string_extension]: "603"
[protobuf_unittest.oneof_bytes_extension]: "604"


text:
map_int32_int32 {
  key: 0
  value: 0
}
map_int32_int32 {
  key: 1
  value: 1
}
map_int64_int64 {
  key: 0
  value: 0
}
map_int64_int64 {
  key: 1
  value: 1
}
map_uint32_uint32 {
  key: 0
  value: 0
}
map_uint32_uint32 {
  key: 1
  value: 1
}
map_uint64_uint64 {
  key: 0
  value: 0
}
map_uint64_uint64 {
  key: 1
  value: 1
}
map_sint32_sint32 {
  key: 0
  value: 0
}
map_sint32_sint32 {
  key: 1
  value: 1
}
map_sint64_sint64 {
  key: 0
  value: 0
}
map_sint64_sint64 {
  key: 1
  value: 1
}
map_fixed32_fixed32 {
  key: 0
  value: 0
}
map_fixed32_fixed32 {
  key: 1
  value: 1
}
map_fixed64_fixed64 {
  key: 0
  value: 0
}
map_fixed64_fixed64 {
  key: 1
  value: 1
}
map_sfixed32_sfixed32 {
  key: 0
  value: 0
}
map_sfixed32_sfixed32 {
  key: 1
  value: 1
}
map_sfixed64_sfixed64 {
  key: 0
  value: 0
}
map_sfixed64_sfixed64 {
  key: 1
  value: 1
}
map_int32_float {
  key: 0
  value: 0
}
map_int32_float {
  key: 1
  value: 1
}
map_int32_double {
  key: 0
  value: 0
}
map_int32_double {
  key: 1
  value: 1
}
map_bool_bool {
  key: false
  value: false
}
map_bool_bool {
  key: true
  value: true
}
map_string_string {
  key: "0"
  value: "0"
}
map_string_string {
  key: "1"
  value: "1"
}
map_int32_bytes {
  key: 0
  value: "0"
}
map_int32_bytes {
  key: 1
  value: "1"
}
map_int32_enum {
  key: 0
  value: MAP_ENUM_BAR
}
map_int32_enum {
  key: 1
  value: MAP_ENUM_BAZ
}
map_int32_foreign_message {
  key: 0
  value {
    c: 0
  }
}
map_int32_foreign_message {
  key: 1
  value {
    c: 1
  }
}


text:
optional_int32: 101
optional_int64: 102
optional_uint32: 103
optional_uint64: 104
optional_sint32: 105
optional_sint64: 106
optional_fixed32: 107
optional_fixed64: 108
optional_sfixed32: 109
optional_sfixed64: 110
optional_float: 111
optional_double: 112
optional_bool: true
optional_string: "115"
optional_bytes: "116"
OptionalGroup <
  a: 117
>
optional_nested_message <
  bb: 118
>
optional_foreign_message <
  c: 119
>
optional_import_message <
  d: 120
>
optional_nested_enum: BAZ
optional_foreign_enum: FOREIGN_BAZ
optional_import_enum: IMPORT_BAZ
optional_string_piece: "124"
optional_cord: "125"
optional_public_import_message <
  e: 126
>
optional_lazy_message <
  bb: 127
>
repeated_int32: 201
repeated_int32: 301
repeated_int64: 202
repeated_int64: 302
repeated_uint32: 203
repeated_uint32: 303
repeated_uint64: 204
repeated_uint64: 304
repeated_sint32: 205
repeated_sint32: 305
repeated_sint64: 206
repeated_sint64: 306
repeated_fixed32: 207
repeated_fixed32: 307
repeated_fixed64: 208
repeated_fixed64: 308
repeated_sfixed32: 209
repeated_sfixed32: 309
repeated_sfixed64: 210
repeated_sfixed64: 310
repeated_float: 211
repeated_float: 311
repeated_double: 212
repeated_double: 312
repeated_bool: true
repeated_bool: false
repeated_string: "215"
repeated_string: "315"
repeated_bytes: "216"
repeated_bytes: "316"
RepeatedGroup <
  a: 217
>
RepeatedGroup <
  a: 317
>
repeated_nested_message <
  bb: 218
>
repeated_nested_message <
  bb: 318
>
repeated_foreign_message <
  c: 219
>
repeated_foreign_message <
  c: 319
>
repeated_import_message <
  d: 220
>
repeated_import_message <
  d: 320
>
repeated_nested_enum: BAR
repeated_nested_enum: BAZ
repeated_foreign_enum: FOREIGN_BAR
repeated_foreign_enum: FOREIGN_BAZ
repeated_import_enum: IMPORT_BAR
repeated_import_enum: IMPORT_BAZ
repeated_string_piece: "224"
repeated_string_piece: "324"
repeated_cord: "225"
repeated_cord: "325"
repeated_lazy_message <
  bb: 227
>
repeated_lazy_message <
  bb: 327
>
default_int32: 401
default_int64: 402
default_uint32: 403
default_uint64: 404
default_sint32: 405
default_sint64: 406
default_fixed32: 407
default_fixed64: 408
default_sfixed32: 409
default_sfixed64: 410
default_float: 411
default_double: 412
default_bool: false
default_string: "415"
default_bytes: "416"
default_nested_enum: FOO
default_foreign_enum: FOREIGN_FOO
default_import_enum: IMPORT_FOO
default_string_piece: "424"
default_cord: "425"
oneof_uint32: 601
oneof_nested_message <
  bb: 602
>
oneof_string: "603"
oneof_bytes: "604"


text:
optional_int32: 101
optional_int64: 102
optional_uint32: 103
optional_uint64: 104
optional_sint32: 105
optional_sint64: 106
optional_fixed32: 107
optional_fixed64: 108
optional_sfixed32: 109
optional_sfixed64: 110
optional_float: 111
optional_double: 112
optional_bool: true
optional_string: "115"
optional_bytes: "116"
OptionalGroup <
  a: 117
>
optional_nested_message <
  bb: 118
>
optional_foreign_message <
  c: 119
>
optional_import_message <
  d: 120
>
optional_nested_enum: BAZ
optional_foreign_enum: FOREIGN_BAZ
optional_import_enum: IMPORT_BAZ
optional_string_piece: "124"
optional_cord: "125"
optional_public_import_message <
  e: 126
>
optional_lazy_message <
  bb: 127
>
repeated_int32: 201
repeated_int32: 301
repeated_int64: 202
repeated_int64: 302
repeated_uint32: 203
repeated_uint32: 303
repeated_uint64: 204
repeated_uint64: 304
repeated_sint32: 205
repeated_sint32: 305
repeated_sint64: 206
repeated_sint64: 306
repeated_fixed32: 207
repeated_fixed32: 307
repeated_fixed64: 208
repeated_fixed64: 308
repeated_sfixed32: 209
repeated_sfixed32: 309
repeated_sfixed64: 210
repeated_sfixed64: 310
repeated_float: 211
repeated_float: 311
repeated_double: 212
repeated_double: 312
repeated_bool: true
repeated_bool: false
repeated_string: "215"
repeated_string: "315"
repeated_bytes: "216"
repeated_bytes: "316"
RepeatedGroup <
  a: 217
>
RepeatedGroup <
  a: 317
>
repeated_nested_message <
  bb: 218
>
repeated_nested_message <
  bb: 318
>
repeated_foreign_message <
  c: 219
>
repeated_foreign_message <
  c: 319
>
repeated_import_message <
  d: 220
>
repeated_import_message <
  d: 320
>
repeated_nested_enum: BAR
repeated_nested_enum: BAZ
repeated_foreign_enum: FOREIGN_BAR
repeated_foreign_enum: FOREIGN_BAZ
repeated_import_enum: IMPORT_BAR
repeated_import_enum: IMPORT_BAZ
repeated_string_piece: "224"
repeated_string_piece: "324"
repeated_cord: "225"
repeated_cord: "325"
repeated_lazy_message <
  bb: 227
>
repeated_lazy_message <
  bb: 327
>
default_int32: 401
default_int64: 402
default_uint32: 403
default_uint64: 404
default_sint32: 405
default_sint64: 406
default_fixed32: 407
default_fixed64: 408
default_sfixed32: 409
default_sfixed64: 410
default_float: 411
default_double: 412
default_bool: false
default_string: "415"
default_bytes: "416"
default_nested_enum: FOO
default_foreign_enum: FOREIGN_FOO
default_import_enum: IMPORT_FOO
default_string_piece: "424"
default_cord: "425"
oneof_bytes: "604"


text:
# libstdc++.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.4a-GCC3.0 (1.641.2.256 2001/05/28 20:09:07 with GCC-local changes)
#
# Please DO NOT delete this file!
# It is necessary for linking the library.

# ---
# NOTE: This file lives in /usr/sfw/lib on Solaris 10.  Unfortunately,
# due to an apparent bug in the Solaris 10 6/06 release,
# /usr/sfw/lib/libstdc++.la is empty.  Below is the correct content,
# according to
#    http://forum.java.sun.com/thread.jspa?threadID=5073150
# By passing LDFLAGS='-Lsrc/solaris' to configure, make will pick up
# this copy of the file rather than the empty copy in /usr/sfw/lib.
#
# Also see
#   http://www.technicalarticles.org/index.php/Compiling_MySQL_5.0_on_Solaris_10
#
# Note: this is for 32-bit systems.  If you have a 64-bit system,
# uncomment the appropriate dependency_libs line below.
# ----

# The name that we can dlopen(3).
dlname='libstdc++.so.6'

# Names of this library.
library_names='libstdc++.so.6.0.3 libstdc++.so.6 libstdc++.so'

# The name of the static archive.
old_library='libstdc++.a'

# Libraries that this one depends upon.
# 32-bit version:
dependency_libs='-lc -lm -L/usr/sfw/lib -lgcc_s'
# 64-bit version:
#dependency_libs='-L/lib/64 -lc -lm -L/usr/sfw/lib/64 -lgcc_s'

# Version information for libstdc++.
current=6
age=0
revision=3

# Is this an already installed library?
installed=yes

# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''

# Directory that this library needs to be installed in:
libdir='/usr/sfw/lib'


text:
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "uv.h"

#define UV_STRINGIFY(v) UV_STRINGIFY_HELPER(v)
#define UV_STRINGIFY_HELPER(v) #v

#define UV_VERSION_STRING_BASE  UV_STRINGIFY(UV_VERSION_MAJOR) "." \
                                UV_STRINGIFY(UV_VERSION_MINOR) "." \
                                UV_STRINGIFY(UV_VERSION_PATCH)

#if UV_VERSION_IS_RELEASE
# define UV_VERSION_STRING  UV_VERSION_STRING_BASE
#else
# define UV_VERSION_STRING  UV_VERSION_STRING_BASE "-" UV_VERSION_SUFFIX
#endif

unsigned int uv_version(void) {
  return UV_VERSION_HEX;
}

const char* uv_version_string(void) {
  return UV_VERSION_STRING;
}


text:
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef UV_SRC_HEAP_H_
#define UV_SRC_HEAP_H_

#include <stddef.h>  /* NULL */

#if defined(__GNUC__)
# define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration
#else
# define HEAP_EXPORT(declaration) static declaration
#endif

struct heap_node {
  struct heap_node* left;
  struct heap_node* right;
  struct heap_node* parent;
};

/* A binary min heap.  The usual properties hold: the root is the lowest
 * element in the set, the height of the tree is at most log2(nodes) and
 * it's always a complete binary tree.
 *
 * The heap function try hard to detect corrupted tree nodes at the cost
 * of a minor reduction in performance.  Compile with -DNDEBUG to disable.
 */
struct heap {
  struct heap_node* min;
  unsigned int nelts;
};

/* Return non-zero if a < b. */
typedef int (*heap_compare_fn)(const struct heap_node* a,
                               const struct heap_node* b);

/* Public functions. */
HEAP_EXPORT(void heap_init(struct heap* heap));
HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap));
HEAP_EXPORT(void heap_insert(struct heap* heap,
                             struct heap_node* newnode,
                             heap_compare_fn less_than));
HEAP_EXPORT(void heap_remove(struct heap* heap,
                             struct heap_node* node,
                             heap_compare_fn less_than));
HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than));

/* Implementation follows. */

HEAP_EXPORT(void heap_init(struct heap* heap)) {
  heap->min = NULL;
  heap->nelts = 0;
}

HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) {
  return heap->min;
}

/* Swap parent with child. Child moves closer to the root, parent moves away. */
static void heap_node_swap(struct heap* heap,
                           struct heap_node* parent,
                           struct heap_node* child) {
  struct heap_node* sibling;
  struct heap_node t;

  t = *parent;
  *parent = *child;
  *child = t;

  parent->parent = child;
  if (child->left == child) {
    child->left = parent;
    sibling = child->right;
  } else {
    child->right = parent;
    sibling = child->left;
  }
  if (sibling != NULL)
    sibling->parent = child;

  if (parent->left != NULL)
    parent->left->parent = parent;
  if (parent->right != NULL)
    parent->right->parent = parent;

  if (child->parent == NULL)
    heap->min = child;
  else if (child->parent->left == parent)
    child->parent->left = child;
  else
    child->parent->right = child;
}

HEAP_EXPORT(void heap_insert(struct heap* heap,
                             struct heap_node* newnode,
                             heap_compare_fn less_than)) {
  struct heap_node** parent;
  struct heap_node** child;
  unsigned int path;
  unsigned int n;
  unsigned int k;

  newnode->left = NULL;
  newnode->right = NULL;
  newnode->parent = NULL;

  /* Calculate the path from the root to the insertion point.  This is a min
   * heap so we always insert at the left-most free node of the bottom row.
   */
  path = 0;
  for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2)
    path = (path << 1) | (n & 1);

  /* Now traverse the heap using the path we calculated in the previous step. */
  parent = child = &heap->min;
  while (k > 0) {
    parent = child;
    if (path & 1)
      child = &(*child)->right;
    else
      child = &(*child)->left;
    path >>= 1;
    k -= 1;
  }

  /* Insert the new node. */
  newnode->parent = *parent;
  *child = newnode;
  heap->nelts += 1;

  /* Walk up the tree and check at each node if the heap property holds.
   * It's a min heap so parent < child must be true.
   */
  while (newnode->parent != NULL && less_than(newnode, newnode->parent))
    heap_node_swap(heap, newnode->parent, newnode);
}

HEAP_EXPORT(void heap_remove(struct heap* heap,
                             struct heap_node* node,
                             heap_compare_fn less_than)) {
  struct heap_node* smallest;
  struct heap_node** max;
  struct heap_node* child;
  unsigned int path;
  unsigned int k;
  unsigned int n;

  if (heap->nelts == 0)
    return;

  /* Calculate the path from the min (the root) to the max, the left-most node
   * of the bottom row.
   */
  path = 0;
  for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2)
    path = (path << 1) | (n & 1);

  /* Now traverse the heap using the path we calculated in the previous step. */
  max = &heap->min;
  while (k > 0) {
    if (path & 1)
      max = &(*max)->right;
    else
      max = &(*max)->left;
    path >>= 1;
    k -= 1;
  }

  heap->nelts -= 1;

  /* Unlink the max node. */
  child = *max;
  *max = NULL;

  if (child == node) {
    /* We're removing either the max or the last node in the tree. */
    if (child == heap->min) {
      heap->min = NULL;
    }
    return;
  }

  /* Replace the to be deleted node with the max node. */
  child->left = node->left;
  child->right = node->right;
  child->parent = node->parent;

  if (child->left != NULL) {
    child->left->parent = child;
  }

  if (child->right != NULL) {
    child->right->parent = child;
  }

  if (node->parent == NULL) {
    heap->min = child;
  } else if (node->parent->left == node) {
    node->parent->left = child;
  } else {
    node->parent->right = child;
  }

  /* Walk down the subtree and check at each node if the heap property holds.
   * It's a min heap so parent < child must be true.  If the parent is bigger,
   * swap it with the smallest child.
   */
  for (;;) {
    smallest = child;
    if (child->left != NULL && less_than(child->left, smallest))
      smallest = child->left;
    if (child->right != NULL && less_than(child->right, smallest))
      smallest = child->right;
    if (smallest == child)
      break;
    heap_node_swap(heap, child, smallest);
  }

  /* Walk up the subtree and check that each parent is less than the node
   * this is required, because `max` node is not guaranteed to be the
   * actual maximum in tree
   */
  while (child->parent != NULL && less_than(child, child->parent))
    heap_node_swap(heap, child->parent, child);
}

HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) {
  heap_remove(heap, heap->min, less_than);
}

#undef HEAP_EXPORT

#endif  /* UV_SRC_HEAP_H_ */


text:
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/*
 * This file is private to libuv. It provides common functionality to both
 * Windows and Unix backends.
 */

#ifndef UV_COMMON_H_
#define UV_COMMON_H_

#include <assert.h>
#include <stdarg.h>
#include <stddef.h>

#if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h"
#else
# include <stdint.h>
#endif

#include "uv.h"
#include "tree.h"
#include "queue.h"

#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
extern int snprintf(char*, size_t, const char*, ...);
#endif

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

#define container_of(ptr, type, member) \
  ((type *) ((char *) (ptr) - offsetof(type, member)))

#define STATIC_ASSERT(expr)                                                   \
  void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])

#ifndef _WIN32
enum {
  UV__HANDLE_INTERNAL = 0x8000,
  UV__HANDLE_ACTIVE   = 0x4000,
  UV__HANDLE_REF      = 0x2000,
  UV__HANDLE_CLOSING  = 0 /* no-op on unix */
};
#else
# define UV__HANDLE_INTERNAL  0x80
# define UV__HANDLE_ACTIVE    0x40
# define UV__HANDLE_REF       0x20
# define UV__HANDLE_CLOSING   0x01
#endif

int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);

void uv__loop_close(uv_loop_t* loop);

int uv__tcp_bind(uv_tcp_t* tcp,
                 const struct sockaddr* addr,
                 unsigned int addrlen,
                 unsigned int flags);

int uv__tcp_connect(uv_connect_t* req,
                   uv_tcp_t* handle,
                   const struct sockaddr* addr,
                   unsigned int addrlen,
                   uv_connect_cb cb);

int uv__udp_bind(uv_udp_t* handle,
                 const struct sockaddr* addr,
                 unsigned int  addrlen,
                 unsigned int flags);

int uv__udp_send(uv_udp_send_t* req,
                 uv_udp_t* handle,
                 const uv_buf_t bufs[],
                 unsigned int nbufs,
                 const struct sockaddr* addr,
                 unsigned int addrlen,
                 uv_udp_send_cb send_cb);

int uv__udp_try_send(uv_udp_t* handle,
                     const uv_buf_t bufs[],
                     unsigned int nbufs,
                     const struct sockaddr* addr,
                     unsigned int addrlen);

int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloccb,
                       uv_udp_recv_cb recv_cb);

int uv__udp_recv_stop(uv_udp_t* handle);

void uv__fs_poll_close(uv_fs_poll_t* handle);

int uv__getaddrinfo_translate_error(int sys_err);    /* EAI_* error. */

void uv__work_submit(uv_loop_t* loop,
                     struct uv__work *w,
                     void (*work)(struct uv__work *w),
                     void (*done)(struct uv__work *w, int status));

void uv__work_done(uv_async_t* handle);

size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);

int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);

void uv__fs_scandir_cleanup(uv_fs_t* req);

#define uv__has_active_reqs(loop)                                             \
  (QUEUE_EMPTY(&(loop)->active_reqs) == 0)

#define uv__req_register(loop, req)                                           \
  do {                                                                        \
    QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue);            \
  }                                                                           \
  while (0)

#define uv__req_unregister(loop, req)                                         \
  do {                                                                        \
    assert(uv__has_active_reqs(loop));                                        \
    QUEUE_REMOVE(&(req)->active_queue);                                       \
  }                                                                           \
  while (0)

#define uv__has_active_handles(loop)                                          \
  ((loop)->active_handles > 0)

#define uv__active_handle_add(h)                                              \
  do {                                                                        \
    (h)->loop->active_handles++;                                              \
  }                                                                           \
  while (0)

#define uv__active_handle_rm(h)                                               \
  do {                                                                        \
    (h)->loop->active_handles--;                                              \
  }                                                                           \
  while (0)

#define uv__is_active(h)                                                      \
  (((h)->flags & UV__HANDLE_ACTIVE) != 0)

#define uv__is_closing(h)                                                     \
  (((h)->flags & (UV_CLOSING |  UV_CLOSED)) != 0)

#define uv__handle_start(h)                                                   \
  do {                                                                        \
    assert(((h)->flags & UV__HANDLE_CLOSING) == 0);                           \
    if (((h)->flags & UV__HANDLE_ACTIVE) != 0) break;                         \
    (h)->flags |= UV__HANDLE_ACTIVE;                                          \
    if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(h);         \
  }                                                                           \
  while (0)

#define uv__handle_stop(h)                                                    \
  do {                                                                        \
    assert(((h)->flags & UV__HANDLE_CLOSING) == 0);                           \
    if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break;                         \
    (h)->flags &= ~UV__HANDLE_ACTIVE;                                         \
    if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h);          \
  }                                                                           \
  while (0)

#define uv__handle_ref(h)                                                     \
  do {                                                                        \
    if (((h)->flags & UV__HANDLE_REF) != 0) break;                            \
    (h)->flags |= UV__HANDLE_REF;                                             \
    if (((h)->flags & UV__HANDLE_CLOSING) != 0) break;                        \
    if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_add(h);      \
  }                                                                           \
  while (0)

#define uv__handle_unref(h)                                                   \
  do {                                                                        \
    if (((h)->flags & UV__HANDLE_REF) == 0) break;                            \
    (h)->flags &= ~UV__HANDLE_REF;                                            \
    if (((h)->flags & UV__HANDLE_CLOSING) != 0) break;                        \
    if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_rm(h);       \
  }                                                                           \
  while (0)

#define uv__has_ref(h)                                                        \
  (((h)->flags & UV__HANDLE_REF) != 0)

#if defined(_WIN32)
# define uv__handle_platform_init(h) ((h)->u.fd = -1)
#else
# define uv__handle_platform_init(h) ((h)->next_closing = NULL)
#endif

#define uv__handle_init(loop_, h, type_)                                      \
  do {                                                                        \
    (h)->loop = (loop_);                                                      \
    (h)->type = (type_);                                                      \
    (h)->flags = UV__HANDLE_REF;  /* Ref the loop when active. */             \
    QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue);            \
    uv__handle_platform_init(h);                                              \
  }                                                                           \
  while (0)

/* Allocator prototypes */
void *uv__calloc(size_t count, size_t size);
char *uv__strdup(const char* s);
char *uv__strndup(const char* s, size_t n);
void* uv__malloc(size_t size);
void uv__free(void* ptr);
void* uv__realloc(void* ptr, size_t size);

#endif /* UV_COMMON_H_ */


text:
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "uv.h"
#include "uv-common.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>

struct poll_ctx {
  uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */
  int busy_polling;
  unsigned int interval;
  uint64_t start_time;
  uv_loop_t* loop;
  uv_fs_poll_cb poll_cb;
  uv_timer_t timer_handle;
  uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
  uv_stat_t statbuf;
  char path[1]; /* variable length */
};

static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b);
static void poll_cb(uv_fs_t* req);
static void timer_cb(uv_timer_t* timer);
static void timer_close_cb(uv_handle_t* handle);

static uv_stat_t zero_statbuf;

int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
  return 0;
}

int uv_fs_poll_start(uv_fs_poll_t* handle,
                     uv_fs_poll_cb cb,
                     const char* path,
                     unsigned int interval) {
  struct poll_ctx* ctx;
  uv_loop_t* loop;
  size_t len;
  int err;

  if (uv__is_active(handle))
    return 0;

  loop = handle->loop;
  len = strlen(path);
  ctx = uv__calloc(1, sizeof(*ctx) + len);

  if (ctx == NULL)
    return UV_ENOMEM;

  ctx->loop = loop;
  ctx->poll_cb = cb;
  ctx->interval = interval ? interval : 1;
  ctx->start_time = uv_now(loop);
  ctx->parent_handle = handle;
  memcpy(ctx->path, path, len + 1);

  err = uv_timer_init(loop, &ctx->timer_handle);
  if (err < 0)
    goto error;

  ctx->timer_handle.flags |= UV__HANDLE_INTERNAL;
  uv__handle_unref(&ctx->timer_handle);

  err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb);
  if (err < 0)
    goto error;

  handle->poll_ctx = ctx;
  uv__handle_start(handle);

  return 0;

error:
  uv__free(ctx);
  return err;
}

int uv_fs_poll_stop(uv_fs_poll_t* handle) {
  struct poll_ctx* ctx;

  if (!uv__is_active(handle))
    return 0;

  ctx = handle->poll_ctx;
  assert(ctx != NULL);
  assert(ctx->parent_handle != NULL);
  ctx->parent_handle = NULL;
  handle->poll_ctx = NULL;

  /* Close the timer if it's active. If it's inactive, there's a stat request
   * in progress and poll_cb will take care of the cleanup.
   */
  if (uv__is_active(&ctx->timer_handle))
    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);

  uv__handle_stop(handle);

  return 0;
}

int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
  struct poll_ctx* ctx;
  size_t required_len;

  if (!uv__is_active(handle)) {
    *size = 0;
    return UV_EINVAL;
  }

  ctx = handle->poll_ctx;
  assert(ctx != NULL);

  required_len = strlen(ctx->path);
  if (required_len >= *size) {
    *size = required_len + 1;
    return UV_ENOBUFS;
  }

  memcpy(buffer, ctx->path, required_len);
  *size = required_len;
  buffer[required_len] = '\0';

  return 0;
}

void uv__fs_poll_close(uv_fs_poll_t* handle) {
  uv_fs_poll_stop(handle);
}

static void timer_cb(uv_timer_t* timer) {
  struct poll_ctx* ctx;

  ctx = container_of(timer, struct poll_ctx, timer_handle);
  assert(ctx->parent_handle != NULL);
  assert(ctx->parent_handle->poll_ctx == ctx);
  ctx->start_time = uv_now(ctx->loop);

  if (uv_fs_stat(ctx->loop, &ctx->fs_req, ctx->path, poll_cb))
    abort();
}

static void poll_cb(uv_fs_t* req) {
  uv_stat_t* statbuf;
  struct poll_ctx* ctx;
  uint64_t interval;

  ctx = container_of(req, struct poll_ctx, fs_req);

  if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */
    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
    uv_fs_req_cleanup(req);
    return;
  }

  if (req->result != 0) {
    if (ctx->busy_polling != req->result) {
      ctx->poll_cb(ctx->parent_handle,
                   req->result,
                   &ctx->statbuf,
                   &zero_statbuf);
      ctx->busy_polling = req->result;
    }
    goto out;
  }

  statbuf = &req->statbuf;

  if (ctx->busy_polling != 0)
    if (ctx->busy_polling < 0 || !statbuf_eq(&ctx->statbuf, statbuf))
      ctx->poll_cb(ctx->parent_handle, 0, &ctx->statbuf, statbuf);

  ctx->statbuf = *statbuf;
  ctx->busy_polling = 1;

out:
  uv_fs_req_cleanup(req);

  if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */
    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
    return;
  }

  /* Reschedule timer, subtract the delay from doing the stat(). */
  interval = ctx->interval;
  interval -= (uv_now(ctx->loop) - ctx->start_time) % interval;

  if (uv_timer_start(&ctx->timer_handle, timer_cb, interval, 0))
    abort();
}

static void timer_close_cb(uv_handle_t* handle) {
  uv__free(container_of(handle, struct poll_ctx, timer_handle));
}

static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) {
  return a->st_ctim.tv_nsec == b->st_ctim.tv_nsec
      && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec
      && a->st_birthtim.tv_nsec == b->st_birthtim.tv_nsec
      && a->st_ctim.tv_sec == b->st_ctim.tv_sec
      && a->st_mtim.tv_sec == b->st_mtim.tv_sec
      && a->st_birthtim.tv_sec == b->st_birthtim.tv_sec
      && a->st_size == b->st_size
      && a->st_mode == b->st_mode
      && a->st_uid == b->st_uid
      && a->st_gid == b->st_gid
      && a->st_ino == b->st_ino
      && a->st_dev == b->st_dev
      && a->st_flags == b->st_flags
      && a->st_gen == b->st_gen;
}

#if defined(_WIN32)

#include "win/internal.h"
#include "win/handle-inl.h"

void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {
  assert(handle->flags & UV__HANDLE_CLOSING);
  assert(!(handle->flags & UV_HANDLE_CLOSED));
  uv__handle_close(handle);
}

#endif /* _WIN32 */


text:
/*
 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
 * Copyright (c) 1996-1999 by Internet Software Consortium.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>
#include <string.h>

#if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h"
#else
# include <stdint.h>
#endif

#include "uv.h"
#include "uv-common.h"

#define UV__INET_ADDRSTRLEN         16
#define UV__INET6_ADDRSTRLEN        46

static int inet_ntop4(const unsigned char *src, char *dst, size_t size);
static int inet_ntop6(const unsigned char *src, char *dst, size_t size);
static int inet_pton4(const char *src, unsigned char *dst);
static int inet_pton6(const char *src, unsigned char *dst);

int uv_inet_ntop(int af, const void* src, char* dst, size_t size) {
  switch (af) {
  case AF_INET:
    return (inet_ntop4(src, dst, size));
  case AF_INET6:
    return (inet_ntop6(src, dst, size));
  default:
    return UV_EAFNOSUPPORT;
  }
  /* NOTREACHED */
}

static int inet_ntop4(const unsigned char *src, char *dst, size_t size) {
  static const char fmt[] = "%u.%u.%u.%u";
  char tmp[UV__INET_ADDRSTRLEN];
  int l;

  l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
  if (l <= 0 || (size_t) l >= size) {
    return UV_ENOSPC;
  }
  strncpy(dst, tmp, size);
  dst[size - 1] = '\0';
  return 0;
}

static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
  /*
   * Note that int32_t and int16_t need only be "at least" large enough
   * to contain a value of the specified size.  On some systems, like
   * Crays, there is no such thing as an integer variable with 16 bits.
   * Keep this in mind if you think this function should have been coded
   * to use pointer overlays.  All the world's not a VAX.
   */
  char tmp[UV__INET6_ADDRSTRLEN], *tp;
  struct { int base, len; } best, cur;
  unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)];
  int i;

  /*
   * Preprocess:
   *  Copy the input (bytewise) array into a wordwise array.
   *  Find the longest run of 0x00's in src[] for :: shorthanding.
   */
  memset(words, '\0', sizeof words);
  for (i = 0; i < (int) sizeof(struct in6_addr); i++)
    words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
  best.base = -1;
  best.len = 0;
  cur.base = -1;
  cur.len = 0;
  for (i = 0; i < (int) ARRAY_SIZE(words); i++) {
    if (words[i] == 0) {
      if (cur.base == -1)
        cur.base = i, cur.len = 1;
      else
        cur.len++;
    } else {
      if (cur.base != -1) {
        if (best.base == -1 || cur.len > best.len)
          best = cur;
        cur.base = -1;
      }
    }
  }
  if (cur.base != -1) {
    if (best.base == -1 || cur.len > best.len)
      best = cur;
  }
  if (best.base != -1 && best.len < 2)
    best.base = -1;

  /*
   * Format the result.
   */
  tp = tmp;
  for (i = 0; i < (int) ARRAY_SIZE(words); i++) {
    /* Are we inside the best run of 0x00's? */
    if (best.base != -1 && i >= best.base &&
        i < (best.base + best.len)) {
      if (i == best.base)
        *tp++ = ':';
      continue;
    }
    /* Are we following an initial run of 0x00s or any real hex? */
    if (i != 0)
      *tp++ = ':';
    /* Is this address an encapsulated IPv4? */
    if (i == 6 && best.base == 0 && (best.len == 6 ||
        (best.len == 7 && words[7] != 0x0001) ||
        (best.len == 5 && words[5] == 0xffff))) {
      int err = inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp));
      if (err)
        return err;
      tp += strlen(tp);
      break;
    }
    tp += sprintf(tp, "%x", words[i]);
  }
  /* Was it a trailing run of 0x00's? */
  if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
    *tp++ = ':';
  *tp++ = '\0';

  /*
   * Check for overflow, copy, and we're done.
   */
  if ((size_t)(tp - tmp) > size) {
    return UV_ENOSPC;
  }
  strcpy(dst, tmp);
  return 0;
}

int uv_inet_pton(int af, const char* src, void* dst) {
  if (src == NULL || dst == NULL)
    return UV_EINVAL;

  switch (af) {
  case AF_INET:
    return (inet_pton4(src, dst));
  case AF_INET6: {
    int len;
    char tmp[UV__INET6_ADDRSTRLEN], *s, *p;
    s = (char*) src;
    p = strchr(src, '%');
    if (p != NULL) {
      s = tmp;
      len = p - src;
      if (len > UV__INET6_ADDRSTRLEN-1)
        return UV_EINVAL;
      memcpy(s, src, len);
      s[len] = '\0';
    }
    return inet_pton6(s, dst);
  }
  default:
    return UV_EAFNOSUPPORT;
  }
  /* NOTREACHED */
}

static int inet_pton4(const char *src, unsigned char *dst) {
  static const char digits[] = "0123456789";
  int saw_digit, octets, ch;
  unsigned char tmp[sizeof(struct in_addr)], *tp;

  saw_digit = 0;
  octets = 0;
  *(tp = tmp) = 0;
  while ((ch = *src++) != '\0') {
    const char *pch;

    if ((pch = strchr(digits, ch)) != NULL) {
      unsigned int nw = *tp * 10 + (pch - digits);

      if (saw_digit && *tp == 0)
        return UV_EINVAL;
      if (nw > 255)
        return UV_EINVAL;
      *tp = nw;
      if (!saw_digit) {
        if (++octets > 4)
          return UV_EINVAL;
        saw_digit = 1;
      }
    } else if (ch == '.' && saw_digit) {
      if (octets == 4)
        return UV_EINVAL;
      *++tp = 0;
      saw_digit = 0;
    } else
      return UV_EINVAL;
  }
  if (octets < 4)
    return UV_EINVAL;
  memcpy(dst, tmp, sizeof(struct in_addr));
  return 0;
}

static int inet_pton6(const char *src, unsigned char *dst) {
  static const char xdigits_l[] = "0123456789abcdef",
                    xdigits_u[] = "0123456789ABCDEF";
  unsigned char tmp[sizeof(struct in6_addr)], *tp, *endp, *colonp;
  const char *xdigits, *curtok;
  int ch, seen_xdigits;
  unsigned int val;

  memset((tp = tmp), '\0', sizeof tmp);
  endp = tp + sizeof tmp;
  colonp = NULL;
  /* Leading :: requires some special handling. */
  if (*src == ':')
    if (*++src != ':')
      return UV_EINVAL;
  curtok = src;
  seen_xdigits = 0;
  val = 0;
  while ((ch = *src++) != '\0') {
    const char *pch;

    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
      pch = strchr((xdigits = xdigits_u), ch);
    if (pch != NULL) {
      val <<= 4;
      val |= (pch - xdigits);
      if (++seen_xdigits > 4)
        return UV_EINVAL;
      continue;
    }
    if (ch == ':') {
      curtok = src;
      if (!seen_xdigits) {
        if (colonp)
          return UV_EINVAL;
        colonp = tp;
        continue;
      } else if (*src == '\0') {
        return UV_EINVAL;
      }
      if (tp + sizeof(uint16_t) > endp)
        return UV_EINVAL;
      *tp++ = (unsigned char) (val >> 8) & 0xff;
      *tp++ = (unsigned char) val & 0xff;
      seen_xdigits = 0;
      val = 0;
      continue;
    }
    if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) {
      int err = inet_pton4(curtok, tp);
      if (err == 0) {
        tp += sizeof(struct in_addr);
        seen_xdigits = 0;
        break;  /*%< '\\0' was seen by inet_pton4(). */
      }
    }
    return UV_EINVAL;
  }
  if (seen_xdigits) {
    if (tp + sizeof(uint16_t) > endp)
      return UV_EINVAL;
    *tp++ = (unsigned char) (val >> 8) & 0xff;
    *tp++ = (unsigned char) val & 0xff;
  }
  if (colonp != NULL) {
    /*
     * Since some memmove()'s erroneously fail to handle
     * overlapping regions, we'll do the shift by hand.
     */
    const int n = tp - colonp;
    int i;

    if (tp == endp)
      return UV_EINVAL;
    for (i = 1; i <= n; i++) {
      endp[- i] = colonp[n - i];
      colonp[n - i] = 0;
    }
    tp = endp;
  }
  if (tp != endp)
    return UV_EINVAL;
  memcpy(dst, tmp, sizeof tmp);
  return 0;
}


text:
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "uv-common.h"

#if !defined(_WIN32)
# include "unix/internal.h"
#else
# include "win/req-inl.h"
/* TODO(saghul): unify internal req functions */
static void uv__req_init(uv_loop_t* loop,
                         uv_req_t* req,
                         uv_req_type type) {
  uv_req_init(loop, req);
  req->type = type;
  uv__req_register(loop, req);
}
# define uv__req_init(loop, req, type) \
    uv__req_init((loop), (uv_req_t*)(req), (type))
#endif

#include <stdlib.h>

#define MAX_THREADPOOL_SIZE 128

static uv_once_t once = UV_ONCE_INIT;
static uv_cond_t cond;
static uv_mutex_t mutex;
static unsigned int idle_threads;
static unsigned int nthreads;
static uv_thread_t* threads;
static uv_thread_t default_threads[4];
static QUEUE exit_message;
static QUEUE wq;
static volatile int initialized;

static void uv__cancelled(struct uv__work* w) {
  abort();
}

/* To avoid deadlock with uv_cancel() it's crucial that the worker
 * never holds the global mutex and the loop-local mutex at the same time.
 */
static void worker(void* arg) {
  struct uv__work* w;
  QUEUE* q;

  (void) arg;

  for (;;) {
    uv_mutex_lock(&mutex);

    while (QUEUE_EMPTY(&wq)) {
      idle_threads += 1;
      uv_cond_wait(&cond, &mutex);
      idle_threads -= 1;
    }

    q = QUEUE_HEAD(&wq);

    if (q == &exit_message)
      uv_cond_signal(&cond);
    else {
      QUEUE_REMOVE(q);
      QUEUE_INIT(q);  /* Signal uv_cancel() that the work req is
                             executing. */
    }

    uv_mutex_unlock(&mutex);

    if (q == &exit_message)
      break;

    w = QUEUE_DATA(q, struct uv__work, wq);
    w->work(w);

    uv_mutex_lock(&w->loop->wq_mutex);
    w->work = NULL;  /* Signal uv_cancel() that the work req is done
                        executing. */
    QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
    uv_async_send(&w->loop->wq_async);
    uv_mutex_unlock(&w->loop->wq_mutex);
  }
}

static void post(QUEUE* q) {
  uv_mutex_lock(&mutex);
  QUEUE_INSERT_TAIL(&wq, q);
  if (idle_threads > 0)
    uv_cond_signal(&cond);
  uv_mutex_unlock(&mutex);
}

#ifndef _WIN32
UV_DESTRUCTOR(static void cleanup(void)) {
  unsigned int i;

  if (initialized == 0)
    return;

  post(&exit_message);

  for (i = 0; i < nthreads; i++)
    if (uv_thread_join(threads + i))
      abort();

  if (threads != default_threads)
    uv__free(threads);

  uv_mutex_destroy(&mutex);
  uv_cond_destroy(&cond);

  threads = NULL;
  nthreads = 0;
  initialized = 0;
}
#endif

static void init_once(void) {
  unsigned int i;
  const char* val;

  nthreads = ARRAY_SIZE(default_threads);
  val = getenv("UV_THREADPOOL_SIZE");
  if (val != NULL)
    nthreads = atoi(val);
  if (nthreads == 0)
    nthreads = 1;
  if (nthreads > MAX_THREADPOOL_SIZE)
    nthreads = MAX_THREADPOOL_SIZE;

  threads = default_threads;
  if (nthreads > ARRAY_SIZE(default_threads)) {
    threads = uv__malloc(nthreads * sizeof(threads[0]));
    if (threads == NULL) {
      nthreads = ARRAY_SIZE(default_threads);
      threads = default_threads;
    }
  }

  if (uv_cond_init(&cond))
    abort();

  if (uv_mutex_init(&mutex))
    abort();

  QUEUE_INIT(&wq);

  for (i = 0; i < nthreads; i++)
    if (uv_thread_create(threads + i, worker, NULL))
      abort();

  initialized = 1;
}

void uv__work_submit(uv_loop_t* loop,
                     struct uv__work* w,
                     void (*work)(struct uv__work* w),
                     void (*done)(struct uv__work* w, int status)) {
  uv_once(&once, init_once);
  w->loop = loop;
  w->work = work;
  w->done = done;
  post(&w->wq);
}

static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
  int cancelled;

  uv_mutex_lock(&mutex);
  uv_mutex_lock(&w->loop->wq_mutex);

  cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL;
  if (cancelled)
    QUEUE_REMOVE(&w->wq);

  uv_mutex_unlock(&w->loop->wq_mutex);
  uv_mutex_unlock(&mutex);

  if (!cancelled)
    return UV_EBUSY;

  w->work = uv__cancelled;
  uv_mutex_lock(&loop->wq_mutex);
  QUEUE_INSERT_TAIL(&loop->wq, &w->wq);
  uv_async_send(&loop->wq_async);
  uv_mutex_unlock(&loop->wq_mutex);

  return 0;
}

void uv__work_done(uv_async_t* handle) {
  struct uv__work* w;
  uv_loop_t* loop;
  QUEUE* q;
  QUEUE wq;
  int err;

  loop = container_of(handle, uv_loop_t, wq_async);
  uv_mutex_lock(&loop->wq_mutex);
  QUEUE_MOVE(&loop->wq, &wq);
  uv_mutex_unlock(&loop->wq_mutex);

  while (!QUEUE_EMPTY(&wq)) {
    q = QUEUE_HEAD(&wq);
    QUEUE_REMOVE(q);

    w = container_of(q, struct uv__work, wq);
    err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
    w->done(w, err);
  }
}

static void uv__queue_work(struct uv__work* w) {
  uv_work_t* req = container_of(w, uv_work_t, work_req);

  req->work_cb(req);
}

static void uv__queue_done(struct uv__work* w, int err) {
  uv_work_t* req;

  req = container_of(w, uv_work_t, work_req);
  uv__req_unregister(req->loop, req);

  if (req->after_work_cb == NULL)
    return;

  req->after_work_cb(req, err);
}

int uv_queue_work(uv_loop_t* loop,
                  uv_work_t* req,
                  uv_work_cb work_cb,
                  uv_after_work_cb after_work_cb) {
  if (work_cb == NULL)
    return UV_EINVAL;

  uv__req_init(loop, req, UV_WORK);
  req->loop = loop;
  req->work_cb = work_cb;
  req->after_work_cb = after_work_cb;
  uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done);
  return 0;
}

int uv_cancel(uv_req_t* req) {
  struct uv__work* wreq;
  uv_loop_t* loop;

  switch (req->type) {
  case UV_FS:
    loop =  ((uv_fs_t*) req)->loop;
    wreq = &((uv_fs_t*) req)->work_req;
    break;
  case UV_GETADDRINFO:
    loop =  ((uv_getaddrinfo_t*) req)->loop;
    wreq = &((uv_getaddrinfo_t*) req)->work_req;
    break;
  case UV_GETNAMEINFO:
    loop = ((uv_getnameinfo_t*) req)->loop;
    wreq = &((uv_getnameinfo_t*) req)->work_req;
    break;
  case UV_WORK:
    loop =  ((uv_work_t*) req)->loop;
    wreq = &((uv_work_t*) req)->work_req;
    break;
  default:
    return UV_EINVAL;
  }

  return uv__work_cancel(loop, req, wreq);
}