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

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

#include <iomanip>
#include <ostream>  // NOLINT(readability/streams)
#include <sstream>

namespace google {
namespace protobuf {

const uint128_pod kuint128max = {
    static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)),
    static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF))
};

// Returns the 0-based position of the last set bit (i.e., most significant bit)
// in the given uint64. The argument may not be 0.
//
// For example:
//   Given: 5 (decimal) == 101 (binary)
//   Returns: 2
#define STEP(T, n, pos, sh)                   \
  do {                                        \
    if ((n) >= (static_cast<T>(1) << (sh))) { \
      (n) = (n) >> (sh);                      \
      (pos) |= (sh);                          \
    }                                         \
  } while (0)
static inline int Fls64(uint64 n) {
  GOOGLE_DCHECK_NE(0, n);
  int pos = 0;
  STEP(uint64, n, pos, 0x20);
  uint32 n32 = n;
  STEP(uint32, n32, pos, 0x10);
  STEP(uint32, n32, pos, 0x08);
  STEP(uint32, n32, pos, 0x04);
  return pos + ((GOOGLE_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3);
}
#undef STEP

// Like Fls64() above, but returns the 0-based position of the last set bit
// (i.e., most significant bit) in the given uint128. The argument may not be 0.
static inline int Fls128(uint128 n) {
  if (uint64 hi = Uint128High64(n)) {
    return Fls64(hi) + 64;
  }
  return Fls64(Uint128Low64(n));
}

// Long division/modulo for uint128 implemented using the shift-subtract
// division algorithm adapted from:
// http://stackoverflow.com/questions/5386377/division-without-using
void uint128::DivModImpl(uint128 dividend, uint128 divisor,
                         uint128* quotient_ret, uint128* remainder_ret) {
  if (divisor == 0) {
    GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_
                      << ", lo=" << dividend.lo_;
  }

  if (divisor > dividend) {
    *quotient_ret = 0;
    *remainder_ret = dividend;
    return;
  }

  if (divisor == dividend) {
    *quotient_ret = 1;
    *remainder_ret = 0;
    return;
  }

  uint128 denominator = divisor;
  uint128 position = 1;
  uint128 quotient = 0;

  // Left aligns the MSB of the denominator and the dividend.
  int shift = Fls128(dividend) - Fls128(denominator);
  denominator <<= shift;
  position <<= shift;

  // Uses shift-subtract algorithm to divide dividend by denominator. The
  // remainder will be left in dividend.
  while (position > 0) {
    if (dividend >= denominator) {
      dividend -= denominator;
      quotient |= position;
    }
    position >>= 1;
    denominator >>= 1;
  }

  *quotient_ret = quotient;
  *remainder_ret = dividend;
}

uint128& uint128::operator/=(const uint128& divisor) {
  uint128 quotient = 0;
  uint128 remainder = 0;
  DivModImpl(*this, divisor, &quotient, &remainder);
  *this = quotient;
  return *this;
}
uint128& uint128::operator%=(const uint128& divisor) {
  uint128 quotient = 0;
  uint128 remainder = 0;
  DivModImpl(*this, divisor, &quotient, &remainder);
  *this = remainder;
  return *this;
}

std::ostream& operator<<(std::ostream& o, const uint128& b) {
  std::ios_base::fmtflags flags = o.flags();

  // Select a divisor which is the largest power of the base < 2^64.
  uint128 div;
  std::streamsize div_base_log;
  switch (flags & std::ios::basefield) {
    case std::ios::hex:
      div = static_cast<uint64>(GOOGLE_ULONGLONG(0x1000000000000000));  // 16^15
      div_base_log = 15;
      break;
    case std::ios::oct:
      div = static_cast<uint64>(GOOGLE_ULONGLONG(01000000000000000000000));  // 8^21
      div_base_log = 21;
      break;
    default:  // std::ios::dec
      div = static_cast<uint64>(GOOGLE_ULONGLONG(10000000000000000000));  // 10^19
      div_base_log = 19;
      break;
  }

  // Now piece together the uint128 representation from three chunks of
  // the original value, each less than "div" and therefore representable
  // as a uint64.
  std::ostringstream os;
  std::ios_base::fmtflags copy_mask =
      std::ios::basefield | std::ios::showbase | std::ios::uppercase;
  os.setf(flags & copy_mask, copy_mask);
  uint128 high = b;
  uint128 low;
  uint128::DivModImpl(high, div, &high, &low);
  uint128 mid;
  uint128::DivModImpl(high, div, &high, &mid);
  if (high.lo_ != 0) {
    os << high.lo_;
    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
    os << mid.lo_;
    os << std::setw(div_base_log);
  } else if (mid.lo_ != 0) {
    os << mid.lo_;
    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
  }
  os << low.lo_;
  std::string rep = os.str();

  // Add the requisite padding.
  std::streamsize width = o.width(0);
  if (width > rep.size()) {
    if ((flags & std::ios::adjustfield) == std::ios::left) {
      rep.append(width - rep.size(), o.fill());
    } else {
      rep.insert(static_cast<std::string::size_type>(0),
                 width - rep.size(), o.fill());
    }
  }

  // Stream the final representation in a single "<<" call.
  return o << rep;
}

}  // 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.

// from google3/strings/strutil.h

#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__

#include <stdlib.h>
#include <vector>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringpiece.h>

namespace google {
namespace protobuf {

#ifdef _MSC_VER
#define strtoll  _strtoi64
#define strtoull _strtoui64
#elif defined(__DECCXX) && defined(__osf__)
// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit.
#define strtoll strtol
#define strtoull strtoul
#endif

// ----------------------------------------------------------------------
// ascii_isalnum()
//    Check if an ASCII character is alphanumeric.  We can't use ctype's
//    isalnum() because it is affected by locale.  This function is applied
//    to identifiers in the protocol buffer language, not to natural-language
//    strings, so locale should not be taken into account.
// ascii_isdigit()
//    Like above, but only accepts digits.
// ascii_isspace()
//    Check if the character is a space character.
// ----------------------------------------------------------------------

inline bool ascii_isalnum(char c) {
  return ('a' <= c && c <= 'z') ||
         ('A' <= c && c <= 'Z') ||
         ('0' <= c && c <= '9');
}

inline bool ascii_isdigit(char c) {
  return ('0' <= c && c <= '9');
}

inline bool ascii_isspace(char c) {
  return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' ||
      c == '\r';
}

inline bool ascii_isupper(char c) {
  return c >= 'A' && c <= 'Z';
}

inline bool ascii_islower(char c) {
  return c >= 'a' && c <= 'z';
}

inline char ascii_toupper(char c) {
  return ascii_islower(c) ? c - ('a' - 'A') : c;
}

inline char ascii_tolower(char c) {
  return ascii_isupper(c) ? c + ('a' - 'A') : c;
}

inline int hex_digit_to_int(char c) {
  /* Assume ASCII. */
  int x = static_cast<unsigned char>(c);
  if (x > '9') {
    x += 9;
  }
  return x & 0xf;
}

// ----------------------------------------------------------------------
// HasPrefixString()
//    Check if a string begins with a given prefix.
// StripPrefixString()
//    Given a string and a putative prefix, returns the string minus the
//    prefix string if the prefix matches, otherwise the original
//    string.
// ----------------------------------------------------------------------
inline bool HasPrefixString(const string& str,
                            const string& prefix) {
  return str.size() >= prefix.size() &&
         str.compare(0, prefix.size(), prefix) == 0;
}

inline string StripPrefixString(const string& str, const string& prefix) {
  if (HasPrefixString(str, prefix)) {
    return str.substr(prefix.size());
  } else {
    return str;
  }
}

// ----------------------------------------------------------------------
// HasSuffixString()
//    Return true if str ends in suffix.
// StripSuffixString()
//    Given a string and a putative suffix, returns the string minus the
//    suffix string if the suffix matches, otherwise the original
//    string.
// ----------------------------------------------------------------------
inline bool HasSuffixString(const string& str,
                            const string& suffix) {
  return str.size() >= suffix.size() &&
         str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}

inline string StripSuffixString(const string& str, const string& suffix) {
  if (HasSuffixString(str, suffix)) {
    return str.substr(0, str.size() - suffix.size());
  } else {
    return str;
  }
}

// ----------------------------------------------------------------------
// ReplaceCharacters
//    Replaces any occurrence of the character 'remove' (or the characters
//    in 'remove') with the character 'replacewith'.
//    Good for keeping html characters or protocol characters (\t) out
//    of places where they might cause a problem.
// StripWhitespace
//    Removes whitespaces from both ends of the given string.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void ReplaceCharacters(string* s, const char* remove,
                                          char replacewith);
LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove,
                                    char replacewith);

LIBPROTOBUF_EXPORT void StripWhitespace(string* s);

// ----------------------------------------------------------------------
// LowerString()
// UpperString()
// ToUpper()
//    Convert the characters in "s" to lowercase or uppercase.  ASCII-only:
//    these functions intentionally ignore locale because they are applied to
//    identifiers used in the Protocol Buffer language, not to natural-language
//    strings.
// ----------------------------------------------------------------------

inline void LowerString(string * s) {
  string::iterator end = s->end();
  for (string::iterator i = s->begin(); i != end; ++i) {
    // tolower() changes based on locale.  We don't want this!
    if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
  }
}

inline void UpperString(string * s) {
  string::iterator end = s->end();
  for (string::iterator i = s->begin(); i != end; ++i) {
    // toupper() changes based on locale.  We don't want this!
    if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
  }
}

inline string ToUpper(const string& s) {
  string out = s;
  UpperString(&out);
  return out;
}

// ----------------------------------------------------------------------
// StringReplace()
//    Give me a string and two patterns "old" and "new", and I replace
//    the first instance of "old" in the string with "new", if it
//    exists.  RETURN a new string, regardless of whether the replacement
//    happened or not.
// ----------------------------------------------------------------------

LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub,
                                        const string& newsub, bool replace_all);

// ----------------------------------------------------------------------
// SplitStringUsing()
//    Split a string using a character delimiter. Append the components
//    to 'result'.  If there are consecutive delimiters, this function skips
//    over all of them.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
                                         vector<string>* res);

// Split a string using one or more byte delimiters, presented
// as a nul-terminated c string. Append the components to 'result'.
// If there are consecutive delimiters, this function will return
// corresponding empty strings.  If you want to drop the empty
// strings, try SplitStringUsing().
//
// If "full" is the empty string, yields an empty string as the only value.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
                                              const char* delim,
                                              vector<string>* result);

// ----------------------------------------------------------------------
// Split()
//    Split a string using a character delimiter.
// ----------------------------------------------------------------------
inline vector<string> Split(
    const string& full, const char* delim, bool skip_empty = true) {
  vector<string> result;
  if (skip_empty) {
    SplitStringUsing(full, delim, &result);
  } else {
    SplitStringAllowEmpty(full, delim, &result);
  }
  return result;
}

// ----------------------------------------------------------------------
// JoinStrings()
//    These methods concatenate a vector of strings into a C++ string, using
//    the C-string "delim" as a separator between components. There are two
//    flavors of the function, one flavor returns the concatenated string,
//    another takes a pointer to the target string. In the latter case the
//    target string is cleared and overwritten.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void JoinStrings(const vector<string>& components,
                                    const char* delim, string* result);

inline string JoinStrings(const vector<string>& components,
                          const char* delim) {
  string result;
  JoinStrings(components, delim, &result);
  return result;
}

// ----------------------------------------------------------------------
// UnescapeCEscapeSequences()
//    Copies "source" to "dest", rewriting C-style escape sequences
//    -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII
//    equivalents.  "dest" must be sufficiently large to hold all
//    the characters in the rewritten string (i.e. at least as large
//    as strlen(source) + 1 should be safe, since the replacements
//    are always shorter than the original escaped sequences).  It's
//    safe for source and dest to be the same.  RETURNS the length
//    of dest.
//
//    It allows hex sequences \xhh, or generally \xhhhhh with an
//    arbitrary number of hex digits, but all of them together must
//    specify a value of a single byte (e.g. \x0045 is equivalent
//    to \x45, and \x1234 is erroneous).
//
//    It also allows escape sequences of the form \uhhhh (exactly four
//    hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight
//    hex digits, upper or lower case) to specify a Unicode code
//    point. The dest array will contain the UTF8-encoded version of
//    that code-point (e.g., if source contains \u2019, then dest will
//    contain the three bytes 0xE2, 0x80, and 0x99).
//
//    Errors: In the first form of the call, errors are reported with
//    LOG(ERROR). The same is true for the second form of the call if
//    the pointer to the string vector is NULL; otherwise, error
//    messages are stored in the vector. In either case, the effect on
//    the dest array is not defined, but rest of the source will be
//    processed.
//    ----------------------------------------------------------------------

LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
                                                vector<string> *errors);

// ----------------------------------------------------------------------
// UnescapeCEscapeString()
//    This does the same thing as UnescapeCEscapeSequences, but creates
//    a new string. The caller does not need to worry about allocating
//    a dest buffer. This should be used for non performance critical
//    tasks such as printing debug messages. It is safe for src and dest
//    to be the same.
//
//    The second call stores its errors in a supplied string vector.
//    If the string vector pointer is NULL, it reports the errors with LOG().
//
//    In the first and second calls, the length of dest is returned. In the
//    the third call, the new string is returned.
// ----------------------------------------------------------------------

LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest);
LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest,
                                             vector<string> *errors);
LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src);

// ----------------------------------------------------------------------
// CEscape()
//    Escapes 'src' using C-style escape sequences and returns the resulting
//    string.
//
//    Escaped chars: \n, \r, \t, ", ', \, and !isprint().
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string CEscape(const string& src);

// ----------------------------------------------------------------------
// CEscapeAndAppend()
//    Escapes 'src' using C-style escape sequences, and appends the escaped
//    string to 'dest'.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, string* dest);

namespace strings {
// Like CEscape() but does not escape bytes with the upper bit set.
LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src);

// Like CEscape() but uses hex (\x) escapes instead of octals.
LIBPROTOBUF_EXPORT string CHexEscape(const string& src);
}  // namespace strings

// ----------------------------------------------------------------------
// strto32()
// strtou32()
// strto64()
// strtou64()
//    Architecture-neutral plug compatible replacements for strtol() and
//    strtoul().  Long's have different lengths on ILP-32 and LP-64
//    platforms, so using these is safer, from the point of view of
//    overflow behavior, than using the standard libc functions.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int32 strto32_adaptor(const char *nptr, char **endptr,
                                         int base);
LIBPROTOBUF_EXPORT uint32 strtou32_adaptor(const char *nptr, char **endptr,
                                           int base);

inline int32 strto32(const char *nptr, char **endptr, int base) {
  if (sizeof(int32) == sizeof(long))
    return strtol(nptr, endptr, base);
  else
    return strto32_adaptor(nptr, endptr, base);
}

inline uint32 strtou32(const char *nptr, char **endptr, int base) {
  if (sizeof(uint32) == sizeof(unsigned long))
    return strtoul(nptr, endptr, base);
  else
    return strtou32_adaptor(nptr, endptr, base);
}

// For now, long long is 64-bit on all the platforms we care about, so these
// functions can simply pass the call to strto[u]ll.
inline int64 strto64(const char *nptr, char **endptr, int base) {
  GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
                        sizeof_int64_is_not_sizeof_long_long);
  return strtoll(nptr, endptr, base);
}

inline uint64 strtou64(const char *nptr, char **endptr, int base) {
  GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
                        sizeof_uint64_is_not_sizeof_long_long);
  return strtoull(nptr, endptr, base);
}

// ----------------------------------------------------------------------
// safe_strtob()
// safe_strto32()
// safe_strtou32()
// safe_strto64()
// safe_strtou64()
// safe_strtof()
// safe_strtod()
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);

LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value);
LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value);
inline bool safe_strto32(const char* str, int32* value) {
  return safe_strto32(string(str), value);
}
inline bool safe_strto32(StringPiece str, int32* value) {
  return safe_strto32(str.ToString(), value);
}
inline bool safe_strtou32(const char* str, uint32* value) {
  return safe_strtou32(string(str), value);
}
inline bool safe_strtou32(StringPiece str, uint32* value) {
  return safe_strtou32(str.ToString(), value);
}

LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value);
LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value);
inline bool safe_strto64(const char* str, int64* value) {
  return safe_strto64(string(str), value);
}
inline bool safe_strto64(StringPiece str, int64* value) {
  return safe_strto64(str.ToString(), value);
}
inline bool safe_strtou64(const char* str, uint64* value) {
  return safe_strtou64(string(str), value);
}
inline bool safe_strtou64(StringPiece str, uint64* value) {
  return safe_strtou64(str.ToString(), value);
}

LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value);
LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value);
inline bool safe_strtof(const string& str, float* value) {
  return safe_strtof(str.c_str(), value);
}
inline bool safe_strtod(const string& str, double* value) {
  return safe_strtod(str.c_str(), value);
}
inline bool safe_strtof(StringPiece str, float* value) {
  return safe_strtof(str.ToString(), value);
}
inline bool safe_strtod(StringPiece str, double* value) {
  return safe_strtod(str.ToString(), value);
}

// ----------------------------------------------------------------------
// FastIntToBuffer()
// FastHexToBuffer()
// FastHex64ToBuffer()
// FastHex32ToBuffer()
// FastTimeToBuffer()
//    These are intended for speed.  FastIntToBuffer() assumes the
//    integer is non-negative.  FastHexToBuffer() puts output in
//    hex rather than decimal.  FastTimeToBuffer() puts the output
//    into RFC822 format.
//
//    FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format,
//    padded to exactly 16 bytes (plus one byte for '\0')
//
//    FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format,
//    padded to exactly 8 bytes (plus one byte for '\0')
//
//       All functions take the output buffer as an arg.
//    They all return a pointer to the beginning of the output,
//    which may not be the beginning of the input buffer.
// ----------------------------------------------------------------------

// Suggested buffer size for FastToBuffer functions.  Also works with
// DoubleToBuffer() and FloatToBuffer().
static const int kFastToBufferSize = 32;

LIBPROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer);
char* FastUInt32ToBuffer(uint32 i, char* buffer);  // inline below
char* FastUInt64ToBuffer(uint64 i, char* buffer);  // inline below
LIBPROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer);
LIBPROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer);

// at least 22 bytes long
inline char* FastIntToBuffer(int i, char* buffer) {
  return (sizeof(i) == 4 ?
          FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
}
inline char* FastUIntToBuffer(unsigned int i, char* buffer) {
  return (sizeof(i) == 4 ?
          FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
}
inline char* FastLongToBuffer(long i, char* buffer) {
  return (sizeof(i) == 4 ?
          FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
}
inline char* FastULongToBuffer(unsigned long i, char* buffer) {
  return (sizeof(i) == 4 ?
          FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
}

// ----------------------------------------------------------------------
// FastInt32ToBufferLeft()
// FastUInt32ToBufferLeft()
// FastInt64ToBufferLeft()
// FastUInt64ToBufferLeft()
//
// Like the Fast*ToBuffer() functions above, these are intended for speed.
// Unlike the Fast*ToBuffer() functions, however, these functions write
// their output to the beginning of the buffer (hence the name, as the
// output is left-aligned).  The caller is responsible for ensuring that
// the buffer has enough space to hold the output.
//
// Returns a pointer to the end of the string (i.e. the null character
// terminating the string).
// ----------------------------------------------------------------------

LIBPROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer);

// Just define these in terms of the above.
inline char* FastUInt32ToBuffer(uint32 i, char* buffer) {
  FastUInt32ToBufferLeft(i, buffer);
  return buffer;
}
inline char* FastUInt64ToBuffer(uint64 i, char* buffer) {
  FastUInt64ToBufferLeft(i, buffer);
  return buffer;
}

inline string SimpleBtoa(bool value) {
  return value ? "true" : "false";
}

// ----------------------------------------------------------------------
// SimpleItoa()
//    Description: converts an integer to a string.
//
//    Return value: string
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string SimpleItoa(int i);
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned int i);
LIBPROTOBUF_EXPORT string SimpleItoa(long i);
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long i);
LIBPROTOBUF_EXPORT string SimpleItoa(long long i);
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i);

// ----------------------------------------------------------------------
// SimpleDtoa()
// SimpleFtoa()
// DoubleToBuffer()
// FloatToBuffer()
//    Description: converts a double or float to a string which, if
//    passed to NoLocaleStrtod(), will produce the exact same original double
//    (except in case of NaN; all NaNs are considered the same value).
//    We try to keep the string short but it's not guaranteed to be as
//    short as possible.
//
//    DoubleToBuffer() and FloatToBuffer() write the text to the given
//    buffer and return it.  The buffer must be at least
//    kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
//    bytes for floats.  kFastToBufferSize is also guaranteed to be large
//    enough to hold either.
//
//    Return value: string
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string SimpleDtoa(double value);
LIBPROTOBUF_EXPORT string SimpleFtoa(float value);

LIBPROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer);
LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);

// In practice, doubles should never need more than 24 bytes and floats
// should never need more than 14 (including null terminators), but we
// overestimate to be safe.
static const int kDoubleToBufferSize = 32;
static const int kFloatToBufferSize = 24;

namespace strings {

enum PadSpec {
  NO_PAD = 1,
  ZERO_PAD_2,
  ZERO_PAD_3,
  ZERO_PAD_4,
  ZERO_PAD_5,
  ZERO_PAD_6,
  ZERO_PAD_7,
  ZERO_PAD_8,
  ZERO_PAD_9,
  ZERO_PAD_10,
  ZERO_PAD_11,
  ZERO_PAD_12,
  ZERO_PAD_13,
  ZERO_PAD_14,
  ZERO_PAD_15,
  ZERO_PAD_16,
};

struct Hex {
  uint64 value;
  enum PadSpec spec;
  template <class Int>
  explicit Hex(Int v, PadSpec s = NO_PAD)
      : spec(s) {
    // Prevent sign-extension by casting integers to
    // their unsigned counterparts.
#ifdef LANG_CXX11
    static_assert(
        sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
        "Unknown integer type");
#endif
    value = sizeof(v) == 1 ? static_cast<uint8>(v)
          : sizeof(v) == 2 ? static_cast<uint16>(v)
          : sizeof(v) == 4 ? static_cast<uint32>(v)
          : static_cast<uint64>(v);
  }
};

struct LIBPROTOBUF_EXPORT AlphaNum {
  const char *piece_data_;  // move these to string_ref eventually
  size_t piece_size_;       // move these to string_ref eventually

  char digits[kFastToBufferSize];

  // No bool ctor -- bools convert to an integral type.
  // A bool ctor would also convert incoming pointers (bletch).

  AlphaNum(int32 i32)
      : piece_data_(digits),
        piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
  AlphaNum(uint32 u32)
      : piece_data_(digits),
        piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
  AlphaNum(int64 i64)
      : piece_data_(digits),
        piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
  AlphaNum(uint64 u64)
      : piece_data_(digits),
        piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}

  AlphaNum(float f)
    : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
  AlphaNum(double f)
    : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}

  AlphaNum(Hex hex);

  AlphaNum(const char* c_str)
      : piece_data_(c_str), piece_size_(strlen(c_str)) {}
  // TODO: Add a string_ref constructor, eventually
  // AlphaNum(const StringPiece &pc) : piece(pc) {}

  AlphaNum(const string& str)
      : piece_data_(str.data()), piece_size_(str.size()) {}

  AlphaNum(StringPiece str)
      : piece_data_(str.data()), piece_size_(str.size()) {}

  AlphaNum(internal::StringPiecePod str)
      : piece_data_(str.data()), piece_size_(str.size()) {}

  size_t size() const { return piece_size_; }
  const char *data() const { return piece_data_; }

 private:
  // Use ":" not ':'
  AlphaNum(char c);  // NOLINT(runtime/explicit)

  // Disallow copy and assign.
  AlphaNum(const AlphaNum&);
  void operator=(const AlphaNum&);
};

}  // namespace strings

using strings::AlphaNum;

// ----------------------------------------------------------------------
// StrCat()
//    This merges the given strings or numbers, with no delimiter.  This
//    is designed to be the fastest possible way to construct a string out
//    of a mix of raw C strings, strings, bool values,
//    and numeric values.
//
//    Don't use this for user-visible strings.  The localization process
//    works poorly on strings built up out of fragments.
//
//    For clarity and performance, don't use StrCat when appending to a
//    string.  In particular, avoid using any of these (anti-)patterns:
//      str.append(StrCat(...)
//      str += StrCat(...)
//      str = StrCat(str, ...)
//    where the last is the worse, with the potential to change a loop
//    from a linear time operation with O(1) dynamic allocations into a
//    quadratic time operation with O(n) dynamic allocations.  StrAppend
//    is a better choice than any of the above, subject to the restriction
//    of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
//    be a reference into str.
// ----------------------------------------------------------------------

LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b);
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
                                 const AlphaNum& c);
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
                                 const AlphaNum& c, const AlphaNum& d);
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
                                 const AlphaNum& c, const AlphaNum& d,
                                 const AlphaNum& e);
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
                                 const AlphaNum& c, const AlphaNum& d,
                                 const AlphaNum& e, const AlphaNum& f);
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
                                 const AlphaNum& c, const AlphaNum& d,
                                 const AlphaNum& e, const AlphaNum& f,
                                 const AlphaNum& g);
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
                                 const AlphaNum& c, const AlphaNum& d,
                                 const AlphaNum& e, const AlphaNum& f,
                                 const AlphaNum& g, const AlphaNum& h);
LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
                                 const AlphaNum& c, const AlphaNum& d,
                                 const AlphaNum& e, const AlphaNum& f,
                                 const AlphaNum& g, const AlphaNum& h,
                                 const AlphaNum& i);

inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); }

// ----------------------------------------------------------------------
// StrAppend()
//    Same as above, but adds the output to the given string.
//    WARNING: For speed, StrAppend does not try to check each of its input
//    arguments to be sure that they are not a subset of the string being
//    appended to.  That is, while this will work:
//
//    string s = "foo";
//    s += s;
//
//    This will not (necessarily) work:
//
//    string s = "foo";
//    StrAppend(&s, s);
//
//    Note: while StrCat supports appending up to 9 arguments, StrAppend
//    is currently limited to 4.  That's rarely an issue except when
//    automatically transforming StrCat to StrAppend, and can easily be
//    worked around as consecutive calls to StrAppend are quite efficient.
// ----------------------------------------------------------------------

LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a);
LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
                                  const AlphaNum& b);
LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
                                  const AlphaNum& b, const AlphaNum& c);
LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
                                  const AlphaNum& b, const AlphaNum& c,
                                  const AlphaNum& d);

// ----------------------------------------------------------------------
// Join()
//    These methods concatenate a range of components into a C++ string, using
//    the C-string "delim" as a separator between components.
// ----------------------------------------------------------------------
template <typename Iterator>
void Join(Iterator start, Iterator end,
          const char* delim, string* result) {
  for (Iterator it = start; it != end; ++it) {
    if (it != start) {
      result->append(delim);
    }
    StrAppend(result, *it);
  }
}

template <typename Range>
string Join(const Range& components,
            const char* delim) {
  string result;
  Join(components.begin(), components.end(), delim, &result);
  return result;
}

// ----------------------------------------------------------------------
// ToHex()
//    Return a lower-case hex string representation of the given integer.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string ToHex(uint64 num);

// ----------------------------------------------------------------------
// GlobalReplaceSubstring()
//    Replaces all instances of a substring in a string.  Does nothing
//    if 'substring' is empty.  Returns the number of replacements.
//
//    NOTE: The string pieces must not overlap s.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring,
                                              const string& replacement,
                                              string* s);

// ----------------------------------------------------------------------
// Base64Unescape()
//    Converts "src" which is encoded in Base64 to its binary equivalent and
//    writes it to "dest". If src contains invalid characters, dest is cleared
//    and the function returns false. Returns true on success.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest);

// ----------------------------------------------------------------------
// WebSafeBase64Unescape()
//    This is a variation of Base64Unescape which uses '-' instead of '+', and
//    '_' instead of '/'. src is not null terminated, instead specify len. I
//    recommend that slen<szdest, but we honor szdest anyway.
//    RETURNS the length of dest, or -1 if src contains invalid chars.

//    The variation that stores into a string clears the string first, and
//    returns false (with dest empty) if src contains invalid chars; for
//    this version src and dest must be different strings.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen,
                                             char* dest, int szdest);
LIBPROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest);

// Return the length to use for the output buffer given to the base64 escape
// routines. Make sure to use the same value for do_padding in both.
// This function may return incorrect results if given input_len values that
// are extremely high, which should happen rarely.
LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len,
                                                 bool do_padding);
// Use this version when calling Base64Escape without a do_padding arg.
LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len);

// ----------------------------------------------------------------------
// Base64Escape()
// WebSafeBase64Escape()
//    Encode "src" to "dest" using base64 encoding.
//    src is not null terminated, instead specify len.
//    'dest' should have at least CalculateBase64EscapedLen() length.
//    RETURNS the length of dest.
//    The WebSafe variation use '-' instead of '+' and '_' instead of '/'
//    so that we can place the out in the URL or cookies without having
//    to escape them.  It also has an extra parameter "do_padding",
//    which when set to false will prevent padding with "=".
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen,
                                    char* dest, int szdest);
LIBPROTOBUF_EXPORT int WebSafeBase64Escape(
    const unsigned char* src, int slen, char* dest,
    int szdest, bool do_padding);
// Encode src into dest with padding.
LIBPROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest);
// Encode src into dest web-safely without padding.
LIBPROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest);
// Encode src into dest web-safely with padding.
LIBPROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
                                                       string* dest);

LIBPROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
                                     string* dest, bool do_padding);
LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
                                            string* dest, bool do_padding);

inline bool IsValidCodePoint(uint32 code_point) {
  return code_point < 0xD800 ||
         (code_point >= 0xE000 && code_point <= 0x10FFFF);
}

static const int UTFmax = 4;
// ----------------------------------------------------------------------
// EncodeAsUTF8Char()
//  Helper to append a Unicode code point to a string as UTF8, without bringing
//  in any external dependencies. The output buffer must be as least 4 bytes
//  large.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int EncodeAsUTF8Char(uint32 code_point, char* output);

// ----------------------------------------------------------------------
// UTF8FirstLetterNumBytes()
//   Length of the first UTF-8 character.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len);

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_STRUTIL_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: laszlocsomor@google.com (Laszlo Csomor)
//
// Implementation for long-path-aware open/mkdir/access/etc. on Windows, as well
// as for the supporting utility functions.
//
// These functions convert the input path to an absolute Windows path
// with "\\?\" prefix, then pass that to _wopen/_wmkdir/_waccess/etc.
// (declared in <io.h>) respectively. This allows working with files/directories
// whose paths are longer than MAX_PATH (260 chars).
//
// This file is only used on Windows, it's empty on other platforms.

#if defined(_WIN32)

// Comment this out to fall back to using the ANSI versions (open, mkdir, ...)
// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to
// debug failing tests if that's caused by the long path support.
#define SUPPORT_LONGPATHS

#include <ctype.h>
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <wctype.h>
#include <windows.h>

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

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

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

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

template <typename char_type>
struct CharTraits {
  static bool is_alpha(char_type ch);
};

template <>
struct CharTraits<char> {
  static bool is_alpha(char ch) { return isalpha(ch); }
};

template <>
struct CharTraits<wchar_t> {
  static bool is_alpha(wchar_t ch) { return iswalpha(ch); }
};

template <typename char_type>
bool null_or_empty(const char_type* s) {
  return s == nullptr || *s == 0;
}

// Returns true if the path starts with a drive letter, e.g. "c:".
// Note that this won't check for the "\" after the drive letter, so this also
// returns true for "c:foo" (which is "c:\${PWD}\foo").
// This check requires that a path not have a longpath prefix ("\\?\").
template <typename char_type>
bool has_drive_letter(const char_type* ch) {
  return CharTraits<char_type>::is_alpha(ch[0]) && ch[1] == ':';
}

// Returns true if the path starts with a longpath prefix ("\\?\").
template <typename char_type>
bool has_longpath_prefix(const char_type* path) {
  return path[0] == '\\' && path[1] == '\\' && path[2] == '?' &&
         path[3] == '\\';
}

template <typename char_type>
bool is_separator(char_type c) {
  return c == '/' || c == '\\';
}

// Returns true if the path starts with a drive specifier (e.g. "c:\").
template <typename char_type>
bool is_path_absolute(const char_type* path) {
  return has_drive_letter(path) && is_separator(path[2]);
}

template <typename char_type>
bool is_drive_relative(const char_type* path) {
  return has_drive_letter(path) && (path[2] == 0 || !is_separator(path[2]));
}

wstring join_paths(const wstring& path1, const wstring& path2) {
  if (path1.empty() || is_path_absolute(path2.c_str()) ||
      has_longpath_prefix(path2.c_str())) {
    return path2;
  }
  if (path2.empty()) {
    return path1;
  }

  if (is_separator(path1[path1.size() - 1])) {
    return is_separator(path2[0]) ? (path1 + path2.substr(1))
                                       : (path1 + path2);
  } else {
    return is_separator(path2[0]) ? (path1 + path2)
                                       : (path1 + L'\\' + path2);
  }
}

wstring normalize(wstring path) {
  if (has_longpath_prefix(path.c_str())) {
    path = path.substr(4);
  }

  static const wstring dot(L".");
  static const wstring dotdot(L"..");

  std::vector<wstring> segments;
  int segment_start = -1;
  // Find the path segments in `path` (separated by "/").
  for (int i = 0;; ++i) {
    if (!is_separator(path[i]) && path[i] != L'\0') {
      // The current character does not end a segment, so start one unless it's
      // already started.
      if (segment_start < 0) {
        segment_start = i;
      }
    } else if (segment_start >= 0 && i > segment_start) {
      // The current character is "/" or "\0", so this ends a segment.
      // Add that to `segments` if there's anything to add; handle "." and "..".
      wstring segment(path, segment_start, i - segment_start);
      segment_start = -1;
      if (segment == dotdot) {
        if (!segments.empty() &&
            (!has_drive_letter(segments[0].c_str()) || segments.size() > 1)) {
          segments.pop_back();
        }
      } else if (segment != dot && !segment.empty()) {
        segments.push_back(segment);
      }
    }
    if (path[i] == L'\0') {
      break;
    }
  }

  // Handle the case when `path` is just a drive specifier (or some degenerate
  // form of it, e.g. "c:\..").
  if (segments.size() == 1 && segments[0].size() == 2 &&
      has_drive_letter(segments[0].c_str())) {
    return segments[0] + L'\\';
  }

  // Join all segments.
  bool first = true;
  std::wstringstream result;
  for (int i = 0; i < segments.size(); ++i) {
    if (!first) {
      result << L'\\';
    }
    first = false;
    result << segments[i];
  }
  // Preserve trailing separator if the input contained it.
  if (!path.empty() && is_separator(path[path.size() - 1])) {
    result << L'\\';
  }
  return result.str();
}

bool as_windows_path(const char* path, wstring* result) {
  if (null_or_empty(path)) {
    result->clear();
    return true;
  }
  wstring wpath;
  if (!strings::utf8_to_wcs(path, &wpath)) {
    return false;
  }
  if (has_longpath_prefix(wpath.c_str())) {
    *result = wpath;
    return true;
  }
  if (is_separator(path[0]) || is_drive_relative(path)) {
    return false;
  }

  if (!is_path_absolute(wpath.c_str())) {
    int size = ::GetCurrentDirectoryW(0, NULL);
    if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
      return false;
    }
    scoped_array<WCHAR> wcwd(new WCHAR[size]);
    ::GetCurrentDirectoryW(size, wcwd.get());
    wpath = join_paths(wcwd.get(), wpath);
  }
  wpath = normalize(wpath);
  if (!has_longpath_prefix(wpath.c_str())) {
    // Add the "\\?\" prefix unconditionally. This way we prevent the Win32 API
    // from processing the path and "helpfully" removing trailing dots from the
    // path, for example.
    // See https://github.com/bazelbuild/bazel/issues/2935
    wpath = wstring(L"\\\\?\\") + wpath;
  }
  *result = wpath;
  return true;
}

}  // namespace

int open(const char* path, int flags, int mode) {
#ifdef SUPPORT_LONGPATHS
  wstring wpath;
  if (!as_windows_path(path, &wpath)) {
    errno = ENOENT;
    return -1;
  }
  return ::_wopen(wpath.c_str(), flags, mode);
#else
  return ::_open(path, flags, mode);
#endif
}

int mkdir(const char* path, int _mode) {
#ifdef SUPPORT_LONGPATHS
  wstring wpath;
  if (!as_windows_path(path, &wpath)) {
    errno = ENOENT;
    return -1;
  }
  return ::_wmkdir(wpath.c_str());
#else   // not SUPPORT_LONGPATHS
  return ::_mkdir(path);
#endif  // not SUPPORT_LONGPATHS
}

int access(const char* path, int mode) {
#ifdef SUPPORT_LONGPATHS
  wstring wpath;
  if (!as_windows_path(path, &wpath)) {
    errno = ENOENT;
    return -1;
  }
  return ::_waccess(wpath.c_str(), mode);
#else
  return ::_access(path, mode);
#endif
}

int chdir(const char* path) {
#ifdef SUPPORT_LONGPATHS
  wstring wpath;
  if (!as_windows_path(path, &wpath)) {
    errno = ENOENT;
    return -1;
  }
  return ::_wchdir(wpath.c_str());
#else
  return ::_chdir(path);
#endif
}

int stat(const char* path, struct _stat* buffer) {
#ifdef SUPPORT_LONGPATHS
  wstring wpath;
  if (!as_windows_path(path, &wpath)) {
    errno = ENOENT;
    return -1;
  }
  return ::_wstat(wpath.c_str(), buffer);
#else   // not SUPPORT_LONGPATHS
  return ::_stat(path, buffer);
#endif  // not SUPPORT_LONGPATHS
}

FILE* fopen(const char* path, const char* mode) {
#ifdef SUPPORT_LONGPATHS
  if (null_or_empty(path)) {
    errno = EINVAL;
    return NULL;
  }
  wstring wpath;
  if (!as_windows_path(path, &wpath)) {
    errno = ENOENT;
    return NULL;
  }
  wstring wmode;
  if (!strings::utf8_to_wcs(mode, &wmode)) {
    errno = EINVAL;
    return NULL;
  }
  return ::_wfopen(wpath.c_str(), wmode.c_str());
#else
  return ::fopen(path, mode);
#endif
}

int close(int fd) { return ::close(fd); }

int dup(int fd) { return ::_dup(fd); }

int dup2(int fd1, int fd2) { return ::_dup2(fd1, fd2); }

int read(int fd, void* buffer, size_t size) {
  return ::_read(fd, buffer, size);
}

int setmode(int fd, int mode) { return ::_setmode(fd, mode); }

int write(int fd, const void* buffer, size_t size) {
  return ::_write(fd, buffer, size);
}

wstring testonly_utf8_to_winpath(const char* path) {
  wstring wpath;
  return as_windows_path(path, &wpath) ? wpath : wstring();
}

namespace strings {

bool wcs_to_mbs(const WCHAR* s, string* out, bool outUtf8) {
  if (null_or_empty(s)) {
    out->clear();
    return true;
  }
  BOOL usedDefaultChar = FALSE;
  SetLastError(0);
  int size = WideCharToMultiByte(
      outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0, NULL,
      outUtf8 ? NULL : &usedDefaultChar);
  if ((size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
      || usedDefaultChar) {
    return false;
  }
  scoped_array<CHAR> astr(new CHAR[size]);
  WideCharToMultiByte(
      outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, astr.get(), size, NULL, NULL);
  out->assign(astr.get());
  return true;
}

bool mbs_to_wcs(const char* s, wstring* out, bool inUtf8) {
  if (null_or_empty(s)) {
    out->clear();
    return true;
  }

  SetLastError(0);
  int size =
      MultiByteToWideChar(inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0);
  if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
    return false;
  }
  scoped_array<WCHAR> wstr(new WCHAR[size]);
  MultiByteToWideChar(
      inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, wstr.get(), size + 1);
  out->assign(wstr.get());
  return true;
}

bool utf8_to_wcs(const char* input, wstring* out) {
  return mbs_to_wcs(input, out, true);
}

bool wcs_to_utf8(const wchar_t* input, string* out) {
  return wcs_to_mbs(input, out, true);
}

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

#endif  // defined(_WIN32)


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)
//
// emulates google3/base/once.h
//
// This header is intended to be included only by internal .cc files and
// generated .pb.cc files.  Users should not use this directly.

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

#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY

#ifdef _WIN32
#include <windows.h>
#else
#include <sched.h>
#endif

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

namespace google {
namespace protobuf {

namespace {

void SchedYield() {
#ifdef _WIN32
  Sleep(0);
#else  // POSIX
  sched_yield();
#endif
}

}  // namespace

void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) {
  internal::AtomicWord state = internal::Acquire_Load(once);
  // Fast path. The provided closure was already executed.
  if (state == ONCE_STATE_DONE) {
    return;
  }
  // The closure execution did not complete yet. The once object can be in one
  // of the two following states:
  //   - UNINITIALIZED: We are the first thread calling this function.
  //   - EXECUTING_CLOSURE: Another thread is already executing the closure.
  //
  // First, try to change the state from UNINITIALIZED to EXECUTING_CLOSURE
  // atomically.
  state = internal::Acquire_CompareAndSwap(
      once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_CLOSURE);
  if (state == ONCE_STATE_UNINITIALIZED) {
    // We are the first thread to call this function, so we have to call the
    // closure.
    closure->Run();
    internal::Release_Store(once, ONCE_STATE_DONE);
  } else {
    // Another thread has already started executing the closure. We need to
    // wait until it completes the initialization.
    while (state == ONCE_STATE_EXECUTING_CLOSURE) {
      // Note that futex() could be used here on Linux as an improvement.
      SchedYield();
      state = internal::Acquire_Load(once);
    }
  }
}

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_NO_THREAD_SAFETY


text:
// Copyright 2005 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: lar@google.com (Laramie Leavitt)
//
// Template metaprogramming utility functions.
//
// 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.
//
//
// The names chosen here reflect those used in tr1 and the boost::mpl
// library, there are similar operations used in the Loki library as
// well.  I prefer the boost names for 2 reasons:
// 1.  I think that portions of the Boost libraries are more likely to
// be included in the c++ standard.
// 2.  It is not impossible that some of the boost libraries will be
// included in our own build in the future.
// Both of these outcomes means that we may be able to directly replace
// some of these with boost equivalents.
//
#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_

namespace google {
namespace protobuf {
namespace internal {

// Types small_ and big_ are guaranteed such that sizeof(small_) <
// sizeof(big_)
typedef char small_;

struct big_ {
  char dummy[2];
};

// Identity metafunction.
template <class T>
struct identity_ {
  typedef T type;
};

// integral_constant, defined in tr1, is a wrapper for an integer
// value. We don't really need this generality; we could get away
// with hardcoding the integer type to bool. We use the fully
// general integer_constant for compatibility with tr1.

template<class T, T v>
struct integral_constant {
  static const T value = v;
  typedef T value_type;
  typedef integral_constant<T, v> type;
};

template <class T, T v> const T integral_constant<T, v>::value;

// Abbreviations: true_type and false_type are structs that represent boolean
// true and false values. Also define the boost::mpl versions of those names,
// true_ and false_.
typedef integral_constant<bool, true>  true_type;
typedef integral_constant<bool, false> false_type;
typedef true_type  true_;
typedef false_type false_;

// if_ is a templatized conditional statement.
// if_<cond, A, B> is a compile time evaluation of cond.
// if_<>::type contains A if cond is true, B otherwise.
template<bool cond, typename A, typename B>
struct if_{
  typedef A type;
};

template<typename A, typename B>
struct if_<false, A, B> {
  typedef B type;
};

// type_equals_ is a template type comparator, similar to Loki IsSameType.
// type_equals_<A, B>::value is true iff "A" is the same type as "B".
//
// New code should prefer base::is_same, defined in base/type_traits.h.
// It is functionally identical, but is_same is the standard spelling.
template<typename A, typename B>
struct type_equals_ : public false_ {
};

template<typename A>
struct type_equals_<A, A> : public true_ {
};

// and_ is a template && operator.
// and_<A, B>::value evaluates "A::value && B::value".
template<typename A, typename B>
struct and_ : public integral_constant<bool, (A::value && B::value)> {
};

// or_ is a template || operator.
// or_<A, B>::value evaluates "A::value || B::value".
template<typename A, typename B>
struct or_ : public integral_constant<bool, (A::value || B::value)> {
};

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

#endif  // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2015 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: ogabbay@advaoptical.com (Oded Gabbay)
// Cleaned up by: bsilver16384@gmail.com (Brian Silverman)
//
// This file is an internal atomic implementation, use atomicops.h instead.

#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_

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

namespace google {
namespace protobuf {
namespace internal {

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

  __asm__ __volatile__(
      "0:                                  \n\t"
      "lwarx %[prev],0,%[ptr]              \n\t"
      "cmpw 0,%[prev],%[old_value]         \n\t"
      "bne- 1f                             \n\t"
      "stwcx. %[new_value],0,%[ptr]        \n\t"
      "bne- 0b                             \n\t"
      "1:                                  \n\t"
      : [prev] "=&r"(prev), "+m"(*ptr)
      : [ptr] "r"(ptr), [old_value] "r"(old_value), [new_value] "r"(new_value)
      : "cc", "memory");

  return prev;
}

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

  __asm__ __volatile__(
      "0:                                  \n\t"
      "lwarx %[old],0,%[ptr]               \n\t"
      "stwcx. %[new_value],0,%[ptr]        \n\t"
      "bne- 0b                             \n\t"
      : [old] "=&r"(old), "+m"(*ptr)
      : [ptr] "r"(ptr), [new_value] "r"(new_value)
      : "cc", "memory");

  return old;
}

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

  __asm__ __volatile__(
      "0:                                  \n\t"
      "lwarx %[temp],0,%[ptr]              \n\t"
      "add %[temp],%[increment],%[temp]    \n\t"
      "stwcx. %[temp],0,%[ptr]             \n\t"
      "bne- 0b                             \n\t"
      : [temp] "=&r"(temp)
      : [increment] "r"(increment), [ptr] "r"(ptr)
      : "cc", "memory");

  return temp;
}

inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
                                        Atomic32 increment) {
  MemoryBarrierInternal();
  Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
  MemoryBarrierInternal();
  return res;
}

inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
                                       Atomic32 old_value, Atomic32 new_value) {
  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
  MemoryBarrierInternal();
  return res;
}

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

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

inline void MemoryBarrierInternal() { __asm__ __volatile__("sync" : : : "memory"); }

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

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

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

inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
  Atomic32 value = *ptr;
  MemoryBarrierInternal();
  return value;
}

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

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

#undef ATOMICOPS_COMPILER_BARRIER

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

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

#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_

// For _smp_cmpxchg()
#include <pthread.h>

namespace google {
namespace protobuf {
namespace internal {

inline Atomic32 QNXCmpxchg(Atomic32 old_value,
                           Atomic32 new_value,
                           volatile Atomic32* ptr) {
  return static_cast<Atomic32>(
      _smp_cmpxchg((volatile unsigned *)ptr,
                   (unsigned)old_value,
                   (unsigned)new_value));
}

inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
                                         Atomic32 old_value,
                                         Atomic32 new_value) {
  Atomic32 prev_value = *ptr;
  do {
    if (!QNXCmpxchg(old_value, new_value,
                    const_cast<Atomic32*>(ptr))) {
      return old_value;
    }
    prev_value = *ptr;
  } while (prev_value == old_value);
  return prev_value;
}

inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
                                         Atomic32 new_value) {
  Atomic32 old_value;
  do {
    old_value = *ptr;
  } while (QNXCmpxchg(old_value, new_value,
                      const_cast<Atomic32*>(ptr)));
  return old_value;
}

inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
                                          Atomic32 increment) {
  return Barrier_AtomicIncrement(ptr, increment);
}

inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
                                        Atomic32 increment) {
  for (;;) {
    // Atomic exchange the old value with an incremented one.
    Atomic32 old_value = *ptr;
    Atomic32 new_value = old_value + increment;
    if (QNXCmpxchg(old_value, new_value,
                   const_cast<Atomic32*>(ptr)) == 0) {
      // The exchange took place as expected.
      return new_value;
    }
    // Otherwise, *ptr changed mid-loop and we need to retry.
  }
}

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

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

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

inline void MemoryBarrierInternal() {
  __sync_synchronize();
}

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

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

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

inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
  Atomic32 value = *ptr;
  MemoryBarrierInternal();
  return value;
}

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

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

#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_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_SCOPED_PTR_H_
#define GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_

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

namespace google {
namespace protobuf {

// ===================================================================
// from google3/base/scoped_ptr.h

namespace internal {

//  This is an implementation designed to match the anticipated future TR2
//  implementation of the scoped_ptr class, and its closely-related brethren,
//  scoped_array, scoped_ptr_malloc, and make_scoped_ptr.

template <class C> class scoped_ptr;
template <class C> class scoped_array;

// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
// automatically deletes the pointer it holds (if any).
// That is, scoped_ptr<T> owns the T object that it points to.
// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
//
// The size of a scoped_ptr is small:
// sizeof(scoped_ptr<C>) == sizeof(C*)
template <class C>
class scoped_ptr {
 public:

  // The element type
  typedef C element_type;

  // Constructor.  Defaults to initializing with NULL.
  // There is no way to create an uninitialized scoped_ptr.
  // The input parameter must be allocated with new.
  explicit scoped_ptr(C* p = NULL) : ptr_(p) { }

  // Destructor.  If there is a C object, delete it.
  // We don't need to test ptr_ == NULL because C++ does that for us.
  ~scoped_ptr() {
    enum { type_must_be_complete = sizeof(C) };
    delete ptr_;
  }

  // Reset.  Deletes the current owned object, if any.
  // Then takes ownership of a new object, if given.
  // this->reset(this->get()) works.
  void reset(C* p = NULL) {
    if (p != ptr_) {
      enum { type_must_be_complete = sizeof(C) };
      delete ptr_;
      ptr_ = p;
    }
  }

  // Accessors to get the owned object.
  // operator* and operator-> will assert() if there is no current object.
  C& operator*() const {
    assert(ptr_ != NULL);
    return *ptr_;
  }
  C* operator->() const  {
    assert(ptr_ != NULL);
    return ptr_;
  }
  C* get() const { return ptr_; }

  // Comparison operators.
  // These return whether two scoped_ptr refer to the same object, not just to
  // two different but equal objects.
  bool operator==(C* p) const { return ptr_ == p; }
  bool operator!=(C* p) const { return ptr_ != p; }

  // Swap two scoped pointers.
  void swap(scoped_ptr& p2) {
    C* tmp = ptr_;
    ptr_ = p2.ptr_;
    p2.ptr_ = tmp;
  }

  // Release a pointer.
  // The return value is the current pointer held by this object.
  // If this object holds a NULL pointer, the return value is NULL.
  // After this operation, this object will hold a NULL pointer,
  // and will not own the object any more.
  C* release() {
    C* retVal = ptr_;
    ptr_ = NULL;
    return retVal;
  }

 private:
  C* ptr_;

  // Forbid comparison of scoped_ptr types.  If C2 != C, it totally doesn't
  // make sense, and if C2 == C, it still doesn't make sense because you should
  // never have the same object owned by two different scoped_ptrs.
  template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
  template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;

  // Disallow evil constructors
  scoped_ptr(const scoped_ptr&);
  void operator=(const scoped_ptr&);
};

// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
// with new [] and the destructor deletes objects with delete [].
//
// As with scoped_ptr<C>, a scoped_array<C> either points to an object
// or is NULL.  A scoped_array<C> owns the object that it points to.
//
// Size: sizeof(scoped_array<C>) == sizeof(C*)
template <class C>
class scoped_array {
 public:

  // The element type
  typedef C element_type;

  // Constructor.  Defaults to initializing with NULL.
  // There is no way to create an uninitialized scoped_array.
  // The input parameter must be allocated with new [].
  explicit scoped_array(C* p = NULL) : array_(p) { }

  // Destructor.  If there is a C object, delete it.
  // We don't need to test ptr_ == NULL because C++ does that for us.
  ~scoped_array() {
    enum { type_must_be_complete = sizeof(C) };
    delete[] array_;
  }

  // Reset.  Deletes the current owned object, if any.
  // Then takes ownership of a new object, if given.
  // this->reset(this->get()) works.
  void reset(C* p = NULL) {
    if (p != array_) {
      enum { type_must_be_complete = sizeof(C) };
      delete[] array_;
      array_ = p;
    }
  }

  // Get one element of the current object.
  // Will assert() if there is no current object, or index i is negative.
  C& operator[](std::ptrdiff_t i) const {
    assert(i >= 0);
    assert(array_ != NULL);
    return array_[i];
  }

  // Get a pointer to the zeroth element of the current object.
  // If there is no current object, return NULL.
  C* get() const {
    return array_;
  }

  // Comparison operators.
  // These return whether two scoped_array refer to the same object, not just to
  // two different but equal objects.
  bool operator==(C* p) const { return array_ == p; }
  bool operator!=(C* p) const { return array_ != p; }

  // Swap two scoped arrays.
  void swap(scoped_array& p2) {
    C* tmp = array_;
    array_ = p2.array_;
    p2.array_ = tmp;
  }

  // Release an array.
  // The return value is the current pointer held by this object.
  // If this object holds a NULL pointer, the return value is NULL.
  // After this operation, this object will hold a NULL pointer,
  // and will not own the object any more.
  C* release() {
    C* retVal = array_;
    array_ = NULL;
    return retVal;
  }

 private:
  C* array_;

  // Forbid comparison of different scoped_array types.
  template <class C2> bool operator==(scoped_array<C2> const& p2) const;
  template <class C2> bool operator!=(scoped_array<C2> const& p2) const;

  // Disallow evil constructors
  scoped_array(const scoped_array&);
  void operator=(const scoped_array&);
};

}  // namespace internal

// We made these internal so that they would show up as such in the docs,
// but we don't want to stick "internal::" in front of them everywhere.
using internal::scoped_ptr;
using internal::scoped_array;

}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_


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

// All Rights Reserved.
//
// Author: Maxim Lifantsev
//
// Useful integer and floating point limits and type traits.
//
// This partially replaces/duplictes numeric_limits<> from <limits>.
// We get a Google-style class that we have a greater control over
// and thus can add new features to it or fix whatever happens to be broken in
// numeric_limits for the compilers we use.
//

#ifndef UTIL_MATH_MATHLIMITS_H__
#define UTIL_MATH_MATHLIMITS_H__

// Note that for Windows we do something different because it does not support
// the plain isinf and isnan.
#if __cplusplus >= 201103L
// GCC 4.9 has a bug that makes isinf and isnan ambigious when both <math.h>
// and <cmath> get pulled into the same translation unit. We use the ones in
// std:: namespace explicitly for C++11
#include <cmath>
#define GOOGLE_PROTOBUF_USE_STD_CMATH
#elif _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
// libstdc++ <cmath> header undefines the global macros and put functions in
// std:: namespace even before C++11. Use the ones in std:: instead too.
#include <cmath>
#define GOOGLE_PROTOBUF_USE_STD_CMATH
#else
#include <math.h>
#endif

#include <string.h>

#include <cfloat>

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

// ========================================================================= //

// Useful integer and floating point limits and type traits.
// This is just for the documentation;
// real members are defined in our specializations below.
namespace google {
namespace protobuf {
template<typename T> struct MathLimits {
  // Type name.
  typedef T Type;
  // Unsigned version of the Type with the same byte size.
  // Same as Type for floating point and unsigned types.
  typedef T UnsignedType;
  // If the type supports negative values.
  static const bool kIsSigned;
  // If the type supports only integer values.
  static const bool kIsInteger;
  // Magnitude-wise smallest representable positive value.
  static const Type kPosMin;
  // Magnitude-wise largest representable positive value.
  static const Type kPosMax;
  // Smallest representable value.
  static const Type kMin;
  // Largest representable value.
  static const Type kMax;
  // Magnitude-wise smallest representable negative value.
  // Present only if kIsSigned.
  static const Type kNegMin;
  // Magnitude-wise largest representable negative value.
  // Present only if kIsSigned.
  static const Type kNegMax;
  // Smallest integer x such that 10^x is representable.
  static const int kMin10Exp;
  // Largest integer x such that 10^x is representable.
  static const int kMax10Exp;
  // Smallest positive value such that Type(1) + kEpsilon != Type(1)
  static const Type kEpsilon;
  // Typical rounding error that is enough to cover
  // a few simple floating-point operations.
  // Slightly larger than kEpsilon to account for a few rounding errors.
  // Is zero if kIsInteger.
  static const Type kStdError;
  // Number of decimal digits of mantissa precision.
  // Present only if !kIsInteger.
  static const int kPrecisionDigits;
  // Not a number, i.e. result of 0/0.
  // Present only if !kIsInteger.
  static const Type kNaN;
  // Positive infinity, i.e. result of 1/0.
  // Present only if !kIsInteger.
  static const Type kPosInf;
  // Negative infinity, i.e. result of -1/0.
  // Present only if !kIsInteger.
  static const Type kNegInf;

  // NOTE: Special floating point values behave
  // in a special (but mathematically-logical) way
  // in terms of (in)equalty comparison and mathematical operations
  // -- see out unittest for examples.

  // Special floating point value testers.
  // Present in integer types for convenience.
  static bool IsFinite(const Type x);
  static bool IsNaN(const Type x);
  static bool IsInf(const Type x);
  static bool IsPosInf(const Type x);
  static bool IsNegInf(const Type x);
};

// ========================================================================= //

// All #define-s below are simply to refactor the declarations of
// MathLimits template specializations.
// They are all #undef-ined below.

// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not
// get an overflow while computing the constants.

#define SIGNED_INT_MAX(Type) \
  (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2)))

#define SIGNED_INT_MIN(Type) \
  (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2)))

#define UNSIGNED_INT_MAX(Type) \
  (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1)))

// Compile-time selected log10-related constants for integer types.
#define SIGNED_MAX_10_EXP(Type) \
  (sizeof(Type) == 1 ? 2 : ( \
    sizeof(Type) == 2 ? 4 : ( \
      sizeof(Type) == 4 ? 9 : ( \
        sizeof(Type) == 8 ? 18 : -1))))

#define UNSIGNED_MAX_10_EXP(Type) \
  (sizeof(Type) == 1 ? 2 : ( \
    sizeof(Type) == 2 ? 4 : ( \
      sizeof(Type) == 4 ? 9 : ( \
        sizeof(Type) == 8 ? 19 : -1))))

#define DECL_INT_LIMIT_FUNCS \
  static bool IsFinite(const Type /*x*/) { return true; } \
  static bool IsNaN(const Type /*x*/) { return false; } \
  static bool IsInf(const Type /*x*/) { return false; } \
  static bool IsPosInf(const Type /*x*/) { return false; } \
  static bool IsNegInf(const Type /*x*/) { return false; }

#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \
template<> \
struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
  typedef IntType Type; \
  typedef UnsignedIntType UnsignedType; \
  static const bool kIsSigned = true; \
  static const bool kIsInteger = true; \
  static const Type kPosMin = 1; \
  static const Type kPosMax = SIGNED_INT_MAX(Type); \
  static const Type kMin = SIGNED_INT_MIN(Type); \
  static const Type kMax = kPosMax; \
  static const Type kNegMin = -1; \
  static const Type kNegMax = kMin; \
  static const int kMin10Exp = 0; \
  static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \
  static const Type kEpsilon = 1; \
  static const Type kStdError = 0; \
  DECL_INT_LIMIT_FUNCS \
};

#define DECL_UNSIGNED_INT_LIMITS(IntType) \
template<> \
struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
  typedef IntType Type; \
  typedef IntType UnsignedType; \
  static const bool kIsSigned = false; \
  static const bool kIsInteger = true; \
  static const Type kPosMin = 1; \
  static const Type kPosMax = UNSIGNED_INT_MAX(Type); \
  static const Type kMin = 0; \
  static const Type kMax = kPosMax; \
  static const int kMin10Exp = 0; \
  static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \
  static const Type kEpsilon = 1; \
  static const Type kStdError = 0; \
  DECL_INT_LIMIT_FUNCS \
};

DECL_SIGNED_INT_LIMITS(signed char, unsigned char)
DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int)
DECL_SIGNED_INT_LIMITS(signed int, unsigned int)
DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int)
DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int)
DECL_UNSIGNED_INT_LIMITS(unsigned char)
DECL_UNSIGNED_INT_LIMITS(unsigned short int)
DECL_UNSIGNED_INT_LIMITS(unsigned int)
DECL_UNSIGNED_INT_LIMITS(unsigned long int)
DECL_UNSIGNED_INT_LIMITS(unsigned long long int)

#undef DECL_SIGNED_INT_LIMITS
#undef DECL_UNSIGNED_INT_LIMITS
#undef SIGNED_INT_MAX
#undef SIGNED_INT_MIN
#undef UNSIGNED_INT_MAX
#undef SIGNED_MAX_10_EXP
#undef UNSIGNED_MAX_10_EXP
#undef DECL_INT_LIMIT_FUNCS

// For non-Windows builds we use the std:: versions of isinf and isnan if they
// are available; see the comment about <cmath> at the top of this file for the
// details on why we need to do this.
#ifdef GOOGLE_PROTOBUF_USE_STD_CMATH
#define ISINF std::isinf
#define ISNAN std::isnan
#else
#define ISINF isinf
#define ISNAN isnan
#endif

// ========================================================================= //
#ifdef WIN32  // Lacks built-in isnan() and isinf()
#define DECL_FP_LIMIT_FUNCS \
  static bool IsFinite(const Type x) { return _finite(x); } \
  static bool IsNaN(const Type x) { return _isnan(x); } \
  static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \
  static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \
  static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; }
#else
#define DECL_FP_LIMIT_FUNCS \
  static bool IsFinite(const Type x) { return !ISINF(x) && !ISNAN(x); } \
  static bool IsNaN(const Type x) { return ISNAN(x); } \
  static bool IsInf(const Type x) { return ISINF(x); } \
  static bool IsPosInf(const Type x) { return ISINF(x) && x > 0; } \
  static bool IsNegInf(const Type x) { return ISINF(x) && x < 0; }
#endif

// We can't put floating-point constant values in the header here because
// such constants are not considered to be primitive-type constants by gcc.
// CAVEAT: Hence, they are going to be initialized only during
// the global objects construction time.
#define DECL_FP_LIMITS(FP_Type, PREFIX) \
template<> \
struct LIBPROTOBUF_EXPORT MathLimits<FP_Type> { \
  typedef FP_Type Type; \
  typedef FP_Type UnsignedType; \
  static const bool kIsSigned = true; \
  static const bool kIsInteger = false; \
  static const Type kPosMin; \
  static const Type kPosMax; \
  static const Type kMin; \
  static const Type kMax; \
  static const Type kNegMin; \
  static const Type kNegMax; \
  static const int kMin10Exp = PREFIX##_MIN_10_EXP; \
  static const int kMax10Exp = PREFIX##_MAX_10_EXP; \
  static const Type kEpsilon; \
  static const Type kStdError; \
  static const int kPrecisionDigits = PREFIX##_DIG; \
  static const Type kNaN; \
  static const Type kPosInf; \
  static const Type kNegInf; \
  DECL_FP_LIMIT_FUNCS \
};

DECL_FP_LIMITS(float, FLT)
DECL_FP_LIMITS(double, DBL)
DECL_FP_LIMITS(long double, LDBL)

#undef ISINF
#undef ISNAN
#undef DECL_FP_LIMITS
#undef DECL_FP_LIMIT_FUNCS

// ========================================================================= //
}  // namespace protobuf
}  // namespace google

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

// All Rights Reserved.
//
// Author: Maxim Lifantsev
//

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

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

namespace google {
namespace protobuf {

// MSVC++ 2005 and older compilers think the header declaration was a
// definition, and erroneously flag these as a duplicate definition.
#if defined(COMPILER_MSVC) || __cpluscplus < 201103L

#define DEF_COMMON_LIMITS(Type)
#define DEF_UNSIGNED_INT_LIMITS(Type)
#define DEF_SIGNED_INT_LIMITS(Type)
#define DEF_PRECISION_LIMITS(Type)

#else

#define DEF_COMMON_LIMITS(Type) \
const bool MathLimits<Type>::kIsSigned; \
const bool MathLimits<Type>::kIsInteger; \
const int MathLimits<Type>::kMin10Exp; \
const int MathLimits<Type>::kMax10Exp;

#define DEF_UNSIGNED_INT_LIMITS(Type) \
DEF_COMMON_LIMITS(Type) \
const Type MathLimits<Type>::kPosMin; \
const Type MathLimits<Type>::kPosMax; \
const Type MathLimits<Type>::kMin; \
const Type MathLimits<Type>::kMax; \
const Type MathLimits<Type>::kEpsilon; \
const Type MathLimits<Type>::kStdError;

#define DEF_SIGNED_INT_LIMITS(Type) \
DEF_UNSIGNED_INT_LIMITS(Type) \
const Type MathLimits<Type>::kNegMin; \
const Type MathLimits<Type>::kNegMax;

#define DEF_PRECISION_LIMITS(Type) \
const int MathLimits<Type>::kPrecisionDigits;

#endif  // not COMPILER_MSVC

// http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format#Double-double_arithmetic
// With some compilers (gcc 4.6.x) on some platforms (powerpc64),
// "long double" is implemented as a pair of double: "double double" format.
// This causes a problem with epsilon (eps).
// eps is the smallest positive number such that 1.0 + eps > 1.0
//
// Normal format:  1.0 + e = 1.0...01      // N-1 zeros for N fraction bits
// D-D format:     1.0 + e = 1.000...0001  // epsilon can be very small
//
// In the normal format, 1.0 + e has to fit in one stretch of bits.
// The maximum rounding error is half of eps.
//
// In the double-double format, 1.0 + e splits across two doubles:
// 1.0 in the high double, e in the low double, and they do not have to
// be contiguous.  The maximum rounding error on a value close to 1.0 is
// much larger than eps.
//
// Some code checks for errors by comparing a computed value to a golden
// value +/- some multiple of the maximum rounding error.  The maximum
// rounding error is not available so we use eps as an approximation
// instead.  That fails when long double is in the double-double format.
// Therefore, we define kStdError as a multiple of
// max(DBL_EPSILON * DBL_EPSILON, kEpsilon) rather than a multiple of kEpsilon.

#define DEF_FP_LIMITS(Type, PREFIX) \
DEF_COMMON_LIMITS(Type) \
const Type MathLimits<Type>::kPosMin = PREFIX##_MIN; \
const Type MathLimits<Type>::kPosMax = PREFIX##_MAX; \
const Type MathLimits<Type>::kMin = -MathLimits<Type>::kPosMax; \
const Type MathLimits<Type>::kMax = MathLimits<Type>::kPosMax; \
const Type MathLimits<Type>::kNegMin = -MathLimits<Type>::kPosMin; \
const Type MathLimits<Type>::kNegMax = -MathLimits<Type>::kPosMax; \
const Type MathLimits<Type>::kEpsilon = PREFIX##_EPSILON; \
/* 32 is 5 bits of mantissa error; should be adequate for common errors */ \
const Type MathLimits<Type>::kStdError = \
  32 * (DBL_EPSILON * DBL_EPSILON > MathLimits<Type>::kEpsilon \
      ? DBL_EPSILON * DBL_EPSILON : MathLimits<Type>::kEpsilon); \
DEF_PRECISION_LIMITS(Type) \
const Type MathLimits<Type>::kNaN = HUGE_VAL - HUGE_VAL; \
const Type MathLimits<Type>::kPosInf = HUGE_VAL; \
const Type MathLimits<Type>::kNegInf = -HUGE_VAL;

// The following are *not* casts!
DEF_SIGNED_INT_LIMITS(int8)
DEF_SIGNED_INT_LIMITS(int16)  // NOLINT(readability/casting)
DEF_SIGNED_INT_LIMITS(int32)  // NOLINT(readability/casting)
DEF_SIGNED_INT_LIMITS(int64)  // NOLINT(readability/casting)
DEF_UNSIGNED_INT_LIMITS(uint8)
DEF_UNSIGNED_INT_LIMITS(uint16)  // NOLINT(readability/casting)
DEF_UNSIGNED_INT_LIMITS(uint32)  // NOLINT(readability/casting)
DEF_UNSIGNED_INT_LIMITS(uint64)  // NOLINT(readability/casting)

DEF_SIGNED_INT_LIMITS(long int)
DEF_UNSIGNED_INT_LIMITS(unsigned long int)

DEF_FP_LIMITS(float, FLT)
DEF_FP_LIMITS(double, DBL)
DEF_FP_LIMITS(long double, LDBL);

#undef DEF_COMMON_LIMITS
#undef DEF_SIGNED_INT_LIMITS
#undef DEF_UNSIGNED_INT_LIMITS
#undef DEF_FP_LIMITS
#undef DEF_PRECISION_LIMITS
}  // namespace protobuf
}  // namespace google