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/util/internal/datapiece.h>

#include <google/protobuf/struct.pb.h>
#include <google/protobuf/type.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/mathlimits.h>
#include <google/protobuf/stubs/mathutil.h>

namespace google {
namespace protobuf {
namespace util {
namespace converter {

using google::protobuf::EnumDescriptor;
using google::protobuf::EnumValueDescriptor;
;
;
;
using util::error::Code;
using util::Status;
using util::StatusOr;

namespace {

inline Status InvalidArgument(StringPiece value_str) {
  return Status(util::error::INVALID_ARGUMENT, value_str);
}

template <typename To, typename From>
StatusOr<To> ValidateNumberConversion(To after, From before) {
  if (after == before &&
      MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
    return after;
  } else {
    return InvalidArgument(::google::protobuf::internal::is_integral<From>::value
                               ? ValueAsString(before)
                               : ::google::protobuf::internal::is_same<From, double>::value
                                     ? DoubleAsString(before)
                                     : FloatAsString(before));
  }
}

// For general conversion between
//     int32, int64, uint32, uint64, double and float
// except conversion between double and float.
template <typename To, typename From>
StatusOr<To> NumberConvertAndCheck(From before) {
  if (::google::protobuf::internal::is_same<From, To>::value) return before;

  To after = static_cast<To>(before);
  return ValidateNumberConversion(after, before);
}

// For conversion to integer types (int32, int64, uint32, uint64) from floating
// point types (double, float) only.
template <typename To, typename From>
StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
  if (::google::protobuf::internal::is_same<From, To>::value) return before;

  To after = static_cast<To>(before);
  return ValidateNumberConversion(after, before);
}

// For conversion between double and float only.
StatusOr<double> FloatToDouble(float before) {
  // Casting float to double should just work as double has more precision
  // than float.
  return static_cast<double>(before);
}

StatusOr<float> DoubleToFloat(double before) {
  if (MathLimits<double>::IsNaN(before)) {
    return std::numeric_limits<float>::quiet_NaN();
  } else if (!MathLimits<double>::IsFinite(before)) {
    // Converting a double +inf/-inf to float should just work.
    return static_cast<float>(before);
  } else if (before > std::numeric_limits<float>::max() ||
             before < -std::numeric_limits<float>::max()) {
    // Double value outside of the range of float.
    return InvalidArgument(DoubleAsString(before));
  } else {
    return static_cast<float>(before);
  }
}

}  // namespace

StatusOr<int32> DataPiece::ToInt32() const {
  if (type_ == TYPE_STRING) return StringToNumber<int32>(safe_strto32);

  if (type_ == TYPE_DOUBLE)
    return FloatingPointToIntConvertAndCheck<int32, double>(double_);

  if (type_ == TYPE_FLOAT)
    return FloatingPointToIntConvertAndCheck<int32, float>(float_);

  return GenericConvert<int32>();
}

StatusOr<uint32> DataPiece::ToUint32() const {
  if (type_ == TYPE_STRING) return StringToNumber<uint32>(safe_strtou32);

  if (type_ == TYPE_DOUBLE)
    return FloatingPointToIntConvertAndCheck<uint32, double>(double_);

  if (type_ == TYPE_FLOAT)
    return FloatingPointToIntConvertAndCheck<uint32, float>(float_);

  return GenericConvert<uint32>();
}

StatusOr<int64> DataPiece::ToInt64() const {
  if (type_ == TYPE_STRING) return StringToNumber<int64>(safe_strto64);

  if (type_ == TYPE_DOUBLE)
    return FloatingPointToIntConvertAndCheck<int64, double>(double_);

  if (type_ == TYPE_FLOAT)
    return FloatingPointToIntConvertAndCheck<int64, float>(float_);

  return GenericConvert<int64>();
}

StatusOr<uint64> DataPiece::ToUint64() const {
  if (type_ == TYPE_STRING) return StringToNumber<uint64>(safe_strtou64);

  if (type_ == TYPE_DOUBLE)
    return FloatingPointToIntConvertAndCheck<uint64, double>(double_);

  if (type_ == TYPE_FLOAT)
    return FloatingPointToIntConvertAndCheck<uint64, float>(float_);

  return GenericConvert<uint64>();
}

StatusOr<double> DataPiece::ToDouble() const {
  if (type_ == TYPE_FLOAT) {
    return FloatToDouble(float_);
  }
  if (type_ == TYPE_STRING) {
    if (str_ == "Infinity") return std::numeric_limits<double>::infinity();
    if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
    if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
    StatusOr<double> value = StringToNumber<double>(safe_strtod);
    if (value.ok() && !MathLimits<double>::IsFinite(value.ValueOrDie())) {
      // safe_strtod converts out-of-range values to +inf/-inf, but we want
      // to report them as errors.
      return InvalidArgument(StrCat("\"", str_, "\""));
    } else {
      return value;
    }
  }
  return GenericConvert<double>();
}

StatusOr<float> DataPiece::ToFloat() const {
  if (type_ == TYPE_DOUBLE) {
    return DoubleToFloat(double_);
  }
  if (type_ == TYPE_STRING) {
    if (str_ == "Infinity") return std::numeric_limits<float>::infinity();
    if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity();
    if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN();
    // SafeStrToFloat() is used instead of safe_strtof() because the later
    // does not fail on inputs like SimpleDtoa(DBL_MAX).
    return StringToNumber<float>(SafeStrToFloat);
  }
  return GenericConvert<float>();
}

StatusOr<bool> DataPiece::ToBool() const {
  switch (type_) {
    case TYPE_BOOL:
      return bool_;
    case TYPE_STRING:
      return StringToNumber<bool>(safe_strtob);
    default:
      return InvalidArgument(
          ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
  }
}

StatusOr<string> DataPiece::ToString() const {
  switch (type_) {
    case TYPE_STRING:
      return str_.ToString();
    case TYPE_BYTES: {
      string base64;
      Base64Escape(str_, &base64);
      return base64;
    }
    default:
      return InvalidArgument(
          ValueAsStringOrDefault("Cannot convert to string."));
  }
}

string DataPiece::ValueAsStringOrDefault(StringPiece default_string) const {
  switch (type_) {
    case TYPE_INT32:
      return SimpleItoa(i32_);
    case TYPE_INT64:
      return SimpleItoa(i64_);
    case TYPE_UINT32:
      return SimpleItoa(u32_);
    case TYPE_UINT64:
      return SimpleItoa(u64_);
    case TYPE_DOUBLE:
      return DoubleAsString(double_);
    case TYPE_FLOAT:
      return FloatAsString(float_);
    case TYPE_BOOL:
      return SimpleBtoa(bool_);
    case TYPE_STRING:
      return StrCat("\"", str_.ToString(), "\"");
    case TYPE_BYTES: {
      string base64;
      WebSafeBase64Escape(str_, &base64);
      return StrCat("\"", base64, "\"");
    }
    case TYPE_NULL:
      return "null";
    default:
      return default_string.ToString();
  }
}

StatusOr<string> DataPiece::ToBytes() const {
  if (type_ == TYPE_BYTES) return str_.ToString();
  if (type_ == TYPE_STRING) {
    string decoded;
    if (!DecodeBase64(str_, &decoded)) {
      return InvalidArgument(ValueAsStringOrDefault("Invalid data in input."));
    }
    return decoded;
  } else {
    return InvalidArgument(ValueAsStringOrDefault(
        "Wrong type. Only String or Bytes can be converted to Bytes."));
  }
}

StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
                                bool use_lower_camel_for_enums) const {
  if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;

  if (type_ == TYPE_STRING) {
    // First try the given value as a name.
    string enum_name = str_.ToString();
    const google::protobuf::EnumValue* value =
        FindEnumValueByNameOrNull(enum_type, enum_name);
    if (value != NULL) return value->number();

    // Check if int version of enum is sent as string.
    StatusOr<int32> int_value = ToInt32();
    if (int_value.ok()) {
      if (const google::protobuf::EnumValue* enum_value =
              FindEnumValueByNumberOrNull(enum_type, int_value.ValueOrDie())) {
        return enum_value->number();
      }
    }

    // Next try a normalized name.
    for (string::iterator it = enum_name.begin(); it != enum_name.end(); ++it) {
      *it = *it == '-' ? '_' : ascii_toupper(*it);
    }
    value = FindEnumValueByNameOrNull(enum_type, enum_name);
    if (value != NULL) return value->number();

    // If use_lower_camel_for_enums is true try with enum name without
    // underscore. This will also accept camel case names as the enum_name has
    // been normalized before.
    if (use_lower_camel_for_enums) {
      value = FindEnumValueByNameWithoutUnderscoreOrNull(enum_type, enum_name);
      if (value != NULL) return value->number();
    }
  } else {
    // We don't need to check whether the value is actually declared in the
    // enum because we preserve unknown enum values as well.
    return ToInt32();
  }
  return InvalidArgument(
      ValueAsStringOrDefault("Cannot find enum with given value."));
}

template <typename To>
StatusOr<To> DataPiece::GenericConvert() const {
  switch (type_) {
    case TYPE_INT32:
      return NumberConvertAndCheck<To, int32>(i32_);
    case TYPE_INT64:
      return NumberConvertAndCheck<To, int64>(i64_);
    case TYPE_UINT32:
      return NumberConvertAndCheck<To, uint32>(u32_);
    case TYPE_UINT64:
      return NumberConvertAndCheck<To, uint64>(u64_);
    case TYPE_DOUBLE:
      return NumberConvertAndCheck<To, double>(double_);
    case TYPE_FLOAT:
      return NumberConvertAndCheck<To, float>(float_);
    default:  // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL
      return InvalidArgument(ValueAsStringOrDefault(
          "Wrong type. Bool, Enum, String and Cord not supported in "
          "GenericConvert."));
  }
}

template <typename To>
StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const {
  if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
    return InvalidArgument(StrCat("\"", str_, "\""));
  }
  To result;
  if (func(str_, &result)) return result;
  return InvalidArgument(StrCat("\"", str_.ToString(), "\""));
}

bool DataPiece::DecodeBase64(StringPiece src, string* dest) const {
  // Try web-safe decode first, if it fails, try the non-web-safe decode.
  if (WebSafeBase64Unescape(src, dest)) {
    if (use_strict_base64_decoding_) {
      // In strict mode, check if the escaped version gives us the same value as
      // unescaped.
      string encoded;
      // WebSafeBase64Escape does no padding by default.
      WebSafeBase64Escape(*dest, &encoded);
      // Remove trailing padding '=' characters before comparison.
      StringPiece src_no_padding = StringPiece(src).substr(
          0, src.ends_with("=") ? src.find_last_not_of('=') + 1 : src.length());
      return encoded == src_no_padding;
    }
    return true;
  }

  if (Base64Unescape(src, dest)) {
    if (use_strict_base64_decoding_) {
      string encoded;
      Base64Escape(
          reinterpret_cast<const unsigned char*>(dest->data()), dest->length(),
          &encoded, false);
      StringPiece src_no_padding = StringPiece(src).substr(
          0, src.ends_with("=") ? src.find_last_not_of('=') + 1 : src.length());
      return encoded == src_no_padding;
    }
    return true;
  }

  return false;
}

void DataPiece::InternalCopy(const DataPiece& other) {
  type_ = other.type_;
  use_strict_base64_decoding_ = other.use_strict_base64_decoding_;
  switch (type_) {
    case TYPE_INT32:
    case TYPE_INT64:
    case TYPE_UINT32:
    case TYPE_UINT64:
    case TYPE_DOUBLE:
    case TYPE_FLOAT:
    case TYPE_BOOL:
    case TYPE_ENUM:
    case TYPE_NULL:
    case TYPE_BYTES:
    case TYPE_STRING: {
      str_ = other.str_;
      break;
    }
  }
}

}  // namespace converter
}  // namespace util
}  // 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.

syntax = "proto3";

package google.protobuf.testing;

message DefaultValueTest {
  double double_value = 1;
  repeated double repeated_double = 2;
  float float_value = 3;
  int64 int64_value = 5;
  uint64 uint64_value = 7;
  int32 int32_value = 9;
  uint32 uint32_value = 11;
  bool bool_value = 13;
  string string_value = 15;
  bytes bytes_value = 17 [ctype = CORD];

  enum EnumDefault {
    ENUM_FIRST = 0;
    ENUM_SECOND = 1;
    ENUM_THIRD = 2;
  }
  EnumDefault enum_value = 18;
}

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.

syntax = "proto3";

package google.protobuf.testing;

import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/wrappers.proto";

message DefaultValueTestCases {
  DoubleMessage empty_double = 1;
  DoubleMessage double_with_default_value = 2;
  DoubleMessage double_with_nondefault_value = 3;
  DoubleMessage repeated_double = 4;
  DoubleMessage nested_message = 5;
  DoubleMessage repeated_nested_message = 6;
  DoubleMessage double_message_with_oneof = 7;
  StructMessage empty_struct = 201;
  StructMessage empty_struct2 = 202;
  StructMessage struct_with_null_value = 203;
  StructMessage struct_with_values = 204;
  StructMessage struct_with_nested_struct = 205;
  StructMessage struct_with_nested_list = 206;
  StructMessage struct_with_list_of_nulls = 207;
  StructMessage struct_with_list_of_lists = 208;
  StructMessage struct_with_list_of_structs = 209;
  google.protobuf.Struct top_level_struct = 210;
  ValueMessage value_wrapper_simple = 212;
  ValueMessage value_wrapper_with_struct = 213;
  ValueMessage value_wrapper_with_list = 214;
  ListValueMessage list_value_wrapper = 215;
  google.protobuf.Value top_level_value_simple = 216;
  google.protobuf.Value top_level_value_with_struct = 217;
  google.protobuf.Value top_level_value_with_list = 218;
  google.protobuf.ListValue top_level_listvalue = 219;
  AnyMessage empty_any = 301;
  AnyMessage type_only_any = 302;
  AnyMessage recursive_any = 303;
  AnyMessage any_with_message_value = 304;
  AnyMessage any_with_nested_message = 305;
  AnyMessage any_with_message_containing_map = 306;
  AnyMessage any_with_message_containing_struct = 307;
  google.protobuf.Any top_level_any = 308;
  StringtoIntMap empty_map = 401;
  StringtoIntMap string_to_int = 402;
  IntToStringMap int_to_string = 403;
  MixedMap mixed1 = 404;
  MixedMap2 mixed2 = 405;
  MixedMap2 empty_mixed2 = 406;
  MessageMap map_of_objects = 407;
  MixedMap mixed_empty = 408;
  MessageMap message_map_empty = 409;
  DoubleValueMessage double_value = 501;
  DoubleValueMessage double_value_default = 502;
}

message DoubleMessage {
  double double_value = 1;
  repeated double repeated_double = 2;
  DoubleMessage nested_message = 3;
  repeated DoubleMessage repeated_nested_message = 4;
  google.protobuf.DoubleValue double_wrapper = 100;
  oneof value {
    string str_value = 112;
    int64 num_value = 113;
  }
}

message StructMessage {
  google.protobuf.Struct struct = 1;
}

message ValueMessage {
  google.protobuf.Value value = 1;
}

message ListValueMessage {
  google.protobuf.ListValue shopping_list = 1;
}
message RequestMessage {
  string content = 1;
}

// A test service.
service DefaultValueTestService {
  // A test method.
  rpc Call(RequestMessage) returns (DefaultValueTestCases);
}

message AnyMessage {
  google.protobuf.Any any = 1;
  AnyData data = 2;
}

message AnyData {
  int32 attr = 1;
  string str = 2;
  repeated string msgs = 3;
  AnyData nested_data = 4;
  map<string, string> map_data = 7;
  google.protobuf.Struct struct_data = 8;
  repeated AnyData repeated_data = 9;
}

message StringtoIntMap {
  map<string, int32> map = 1;
}

message IntToStringMap {
  map<int32, string> map = 1;
}

message MixedMap {
  string msg = 1;
  map<string, float> map = 2;
  int32 int_value = 3;
}

message MixedMap2 {
  enum E {
    E0 = 0;
    E1 = 1;
    E2 = 2;
    E3 = 3;
  }
  map<int32, bool> map = 1;
  E ee = 2;
  string msg = 4;
}

message MessageMap {
  message M {
    int32 inner_int = 1;
    string inner_text = 2;
  }
  map<string, M> map = 1;
}

message DoubleValueMessage {
  google.protobuf.DoubleValue double = 1;
}


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.

syntax = "proto3";

package google.protobuf.testing;

import "google/protobuf/wrappers.proto";

// Top-level test cases proto used by MarshallingTest. See description
// at the top of the class MarshallingTest for details on how to write
// test cases.
message WrappersTestCases {
  DoubleWrapper double_wrapper = 1;
  FloatWrapper float_wrapper = 2;
  Int64Wrapper int64_wrapper = 3;
  UInt64Wrapper uint64_wrapper = 4;
  Int32Wrapper int32_wrapper = 5;
  UInt32Wrapper uint32_wrapper = 6;
  BoolWrapper bool_wrapper = 7;
  StringWrapper string_wrapper = 8;
  BytesWrapper bytes_wrapper = 9;

  DoubleWrapper double_wrapper_default = 10;
  FloatWrapper float_wrapper_default = 11;
  Int64Wrapper int64_wrapper_default = 12;
  UInt64Wrapper uint64_wrapper_default = 13;
  Int32Wrapper int32_wrapper_default = 14;
  UInt32Wrapper uint32_wrapper_default = 15;
  BoolWrapper bool_wrapper_default = 16;
  StringWrapper string_wrapper_default = 17;
  BytesWrapper bytes_wrapper_default = 18;
}

message DoubleWrapper {
  google.protobuf.DoubleValue double = 1;
}

message FloatWrapper {
  google.protobuf.FloatValue float = 1;
}

message Int64Wrapper {
  google.protobuf.Int64Value int64 = 1;
}

message UInt64Wrapper {
  google.protobuf.UInt64Value uint64 = 1;
}

message Int32Wrapper {
  google.protobuf.Int32Value int32 = 1;
}

message UInt32Wrapper {
  google.protobuf.UInt32Value uint32 = 1;
}

message BoolWrapper {
  google.protobuf.BoolValue bool = 1;
}

message StringWrapper {
  google.protobuf.StringValue string = 1;
}

message BytesWrapper {
  google.protobuf.BytesValue bytes = 1;
}

service WrappersTestService {
  rpc Call(WrappersTestCases) returns (WrappersTestCases);
}


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.

syntax = "proto3";

package google.protobuf.testing;

import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

// Top-level test cases proto used by MarshallingTest. See description
// at the top of the class MarshallingTest for details on how to write
// test cases.
message AnyTestCases {
  AnyWrapper empty_any = 1;
  AnyWrapper type_only_any = 2;
  AnyWrapper wrapper_any = 3;
  AnyWrapper any_with_timestamp_value = 4;
  AnyWrapper any_with_duration_value = 5;
  AnyWrapper any_with_struct_value = 6;
  AnyWrapper recursive_any = 7;
  AnyWrapper any_with_message_value = 8;
  AnyWrapper any_with_nested_message = 9;
  AnyWrapper any_with_message_with_wrapper_type = 10;
  AnyWrapper any_with_message_with_timestamp = 11;
  AnyWrapper any_with_message_containing_map = 12;
  AnyWrapper any_with_message_containing_struct = 13;
  AnyWrapper any_with_message_containing_repeated_message = 14;
  AnyWrapper recursive_any_with_type_field_at_end = 15;

  google.protobuf.Any top_level_any = 50;
  google.protobuf.Any top_level_any_with_type_field_at_end = 51;
}

message AnyWrapper {
  google.protobuf.Any any = 1;
}

// Hack to make sure the types we put into the any are included in the types.
// Real solution is to add these types to the service config.
message Imports {
  google.protobuf.DoubleValue dbl = 1;
  google.protobuf.Struct struct = 2;
  google.protobuf.Timestamp timestamp = 3;
  google.protobuf.Duration duration = 4;
  google.protobuf.Int32Value i32 = 5;
  Data data = 100;
}

message Data {
  int32 attr = 1;
  string str = 2;
  repeated string msgs = 3;
  Data nested_data = 4;
  google.protobuf.Int32Value int_wrapper = 5;
  google.protobuf.Timestamp time = 6;
  map<string, string> map_data = 7;
  google.protobuf.Struct struct_data = 8;
  repeated Data repeated_data = 9;
}

service AnyTestService {
  rpc Call(AnyTestCases) returns (AnyTestCases);
  rpc Call1(Imports) returns (Imports);
}

message AnyIn {
  string something = 1;
  google.protobuf.Any any = 2;
}

message AnyOut {
  google.protobuf.Any any = 1;
}

message AnyM {
  string foo = 1;
}


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.

syntax = "proto3";

package google.protobuf.testing;

import "google/protobuf/field_mask.proto";

message NestedFieldMask {
  string data = 1;
  google.protobuf.FieldMask single_mask = 2;
  repeated google.protobuf.FieldMask repeated_mask = 3;
}

message FieldMaskTest {
  string id = 1;
  google.protobuf.FieldMask single_mask = 2;
  repeated google.protobuf.FieldMask repeated_mask = 3;
  repeated NestedFieldMask nested_mask = 4;
}

message FieldMaskTestCases {
  FieldMaskWrapper single_mask = 1;
  FieldMaskWrapper multiple_mask = 2;
  FieldMaskWrapper snake_camel = 3;
  FieldMaskWrapper empty_field = 4;
  FieldMaskWrapper apiary_format1 = 5;
  FieldMaskWrapper apiary_format2 = 6;
  FieldMaskWrapper apiary_format3 = 7;
  FieldMaskWrapper map_key1 = 8;
  FieldMaskWrapper map_key2 = 9;
  FieldMaskWrapper map_key3 = 10;
  FieldMaskWrapper map_key4 = 11;
  FieldMaskWrapper map_key5 = 12;
}

message FieldMaskWrapper {
  google.protobuf.FieldMask mask = 1;
}

service FieldMaskTestService {
  rpc Call(FieldMaskTestCases) returns (FieldMaskTestCases);
}


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.

syntax = "proto3";

package google.protobuf.testing;

// Top-level test cases proto used by MarshallingTest. See description
// at the top of the class MarshallingTest for details on how to write
// test cases.
message MapsTestCases {
  EmptyMap empty_map = 1;
  StringtoInt string_to_int = 2;
  IntToString int_to_string = 3;
  Mixed1 mixed1 = 4;
  Mixed2 mixed2 = 5;
  MapOfObjects map_of_objects = 6;

  // Empty key tests
  StringtoInt empty_key_string_to_int1 = 7;
  StringtoInt empty_key_string_to_int2 = 8;
  StringtoInt empty_key_string_to_int3 = 9;
  BoolToString empty_key_bool_to_string = 10;
  IntToString empty_key_int_to_string = 11;
  Mixed1 empty_key_mixed = 12;
  MapOfObjects empty_key_map_objects = 13;
}

message EmptyMap {
  map<int32, int32> map = 1;
}

message StringtoInt {
  map<string, int32> map = 1;
}

message IntToString {
  map<int32, string> map = 1;
}

message BoolToString {
  map<bool, string> map = 1;
}

message Mixed1 {
  string msg = 1;
  map<string, float> map = 2;
}

message Mixed2 {
  enum E {
    E0 = 0;
    E1 = 1;
    E2 = 2;
    E3 = 3;
  }
  map<int32, bool> map = 1;
  E ee = 2;
}

message MapOfObjects {
  message M {
    string inner_text = 1;
  }
  map<string, M> map = 1;
}

message DummyRequest {
}

service MapsTestService {
  rpc Call(DummyRequest) returns (MapsTestCases);
}

message MapIn {
  string other = 1;
  repeated string things = 2;
  map<string, string> map_input = 3;
}

message MapOut {
  map<string, MapM> map1 = 1;
  map<string, MapOut> map2 = 2;
  map<int32, string> map3 = 3;
  map<bool, string> map4 = 5;
  string bar = 4;
}

// A message with exactly the same wire representation as MapOut, but using
// repeated message fields instead of map fields. We use this message to test
// the wire-format compatibility of the JSON transcoder (e.g., whether it
// handles missing keys correctly).
message MapOutWireFormat {
  message Map1Entry {
    string key = 1;
    MapM value = 2;
  }
  repeated Map1Entry map1 = 1;
  message Map2Entry {
    string key = 1;
    MapOut value = 2;
  }
  repeated Map2Entry map2 = 2;
  message Map3Entry {
    int32 key = 1;
    string value = 2;
  }
  repeated Map3Entry map3 = 3;
  message Map4Entry {
    bool key = 1;
    string value = 2;
  }
  repeated Map4Entry map4 = 5;
  string bar = 4;
}

message MapM {
  string foo = 1;
}


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.

syntax = "proto3";

package google.protobuf.testing;

import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

message TimestampDurationTestCases {
  // Timestamp tests
  TimeStampType epoch = 1;
  TimeStampType epoch2 = 2;
  TimeStampType mintime = 3;
  TimeStampType maxtime = 4;
  TimeStampType timeval1 = 5;
  TimeStampType timeval2 = 6;
  TimeStampType timeval3 = 7;
  TimeStampType timeval4 = 8;
  TimeStampType timeval5 = 9;
  TimeStampType timeval6 = 10;
  TimeStampType timeval7 = 11;
  google.protobuf.Timestamp timeval8 = 12;

  // Duration tests
  DurationType zero_duration = 101;
  DurationType min_duration = 102;
  DurationType max_duration = 103;
  DurationType duration1 = 104;
  DurationType duration2 = 105;
  DurationType duration3 = 106;
  DurationType duration4 = 107;
  google.protobuf.Duration duration5 = 108;
}

message TimeStampType {
  google.protobuf.Timestamp timestamp = 1;
}

message DurationType {
  google.protobuf.Duration duration = 1;
}

service TimestampDurationTestService {
  rpc Call(TimestampDurationTestCases) returns (TimestampDurationTestCases);
}

message TimestampDuration {
  google.protobuf.Timestamp ts = 1;
  google.protobuf.Duration dur = 2;
  repeated google.protobuf.Timestamp rep_ts = 3;
}


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.

// Proto to test proto3 oneofs.
syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

package google.protobuf.testing.oneofs;

message OneOfsRequest {
  string value = 1;
  oneof data {
    string str_data = 2;
    int32 int_data = 3;
    // Simple message
    Data message_data = 4;
    MoreData more_data = 5;
    // Well known types
    google.protobuf.Struct struct_data = 6;
    google.protobuf.Value value_data = 7;
    google.protobuf.ListValue list_value_data = 8;
    google.protobuf.Timestamp ts_data = 9;
  }
  google.protobuf.Any any_data = 19;
}

message RequestWithSimpleOneof {
  string value = 1;
  oneof data {
    string str_data = 2;
    int32 int_data = 3;
    Data message_data = 4;
    MoreData more_data = 5;
  }
}

message Data {
  int32 data_value = 1;
}

message MoreData {
  string str_value = 1;
}

message Response {
  string value = 1;
}


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: sven@google.com (Sven Mawson)
//
// Sample protos for testing.

// Some of the older enums don't use CAPITALS_WITH_UNDERSCORES for testing.
// LINT: LEGACY_NAMES

syntax = "proto2";

package google.protobuf.testing;

// A book
message Book {
  optional string title = 1;
  optional Author author = 2;
  optional uint32 length = 3;
  optional int64 published = 4;
  optional bytes content = 5;

  optional group Data = 6 {
    optional uint32 year = 7;
    optional string copyright = 8;
  }

  message Label {
    optional string key = 1;
    optional string value = 2;
  }

  optional Publisher publisher = 9;
  repeated Label labels = 10;

  enum Type {
    FICTION = 1;
    KIDS = 2;
    ACTION_AND_ADVENTURE = 3;
    arts_and_photography = 4;
  }
  optional Type type = 11;

  extensions 200 to 499;
}

// A publisher of a book, tests required fields.
message Publisher {
  required string name = 1;
}

// An author of a book
message Author {
  optional uint64 id = 1 [json_name = "@id"];
  optional string name = 2;
  repeated string pseudonym = 3;
  optional bool alive = 4;
  repeated Author friend = 5;
}

// For testing resiliency of our protostream parser.
// Field numbers of Author are reused for something else.
message BadAuthor {
  optional string id = 1;  // non-length-delimited to length-delimited.
  repeated uint64 name = 2;  // string to repeated (both length-delimited).
  optional string pseudonym = 3;  // Repeated to optional.
  repeated bool alive = 4 [packed=true];  // Optional to repeated.
}

// All primitive types
message Primitive {
  // 32 bit numbers:
  optional fixed32 fix32 = 1;
  optional uint32 u32 = 2;
  optional int32 i32 = 3;
  optional sfixed32 sf32 = 4;
  optional sint32 s32 = 5;

  // 64 bit numbers:
  optional fixed64 fix64 = 6;
  optional uint64 u64 = 7;
  optional int64 i64 = 8;
  optional sfixed64 sf64 = 9;
  optional sint64 s64 = 10;

  // The other stuff.
  optional string str = 11;
  optional bytes bytes = 12;
  optional float float = 13;
  optional double double = 14;
  optional bool bool = 15;

  // repeated 32 bit numbers:
  repeated fixed32 rep_fix32 = 16;
  repeated uint32 rep_u32 = 17;
  repeated int32 rep_i32 = 18;
  repeated sfixed32 rep_sf32 = 19;
  repeated sint32 rep_s32 = 20;

  // repeated 64 bit numbers:
  repeated fixed64 rep_fix64 = 21;
  repeated uint64 rep_u64 = 22;
  repeated int64 rep_i64 = 23;
  repeated sfixed64 rep_sf64 = 24;
  repeated sint64 rep_s64 = 25;

  // repeated other stuff:
  repeated string rep_str = 26;
  repeated bytes rep_bytes = 27;
  repeated float rep_float = 28;
  repeated double rep_double = 29;
  repeated bool rep_bool = 30;
}

// Test packed versions of all repeated primitives.
// The field numbers should match their non-packed version in Primitive message.
message PackedPrimitive {
  // repeated 32 bit numbers:
  repeated fixed32 rep_fix32 = 16 [packed=true];
  repeated uint32 rep_u32 = 17 [packed=true];
  repeated int32 rep_i32 = 18 [packed=true];
  repeated sfixed32 rep_sf32 = 19 [packed=true];
  repeated sint32 rep_s32 = 20 [packed=true];

  // repeated 64 bit numbers:
  repeated fixed64 rep_fix64 = 21 [packed=true];
  repeated uint64 rep_u64 = 22 [packed=true];
  repeated int64 rep_i64 = 23 [packed=true];
  repeated sfixed64 rep_sf64 = 24 [packed=true];
  repeated sint64 rep_s64 = 25 [packed=true];

  // repeated other stuff:
  repeated float rep_float = 28 [packed=true];
  repeated double rep_double = 29 [packed=true];
  repeated bool rep_bool = 30 [packed=true];
}

// Test extensions.
extend Book {
  repeated Author more_author = 201;
}

// Test nested extensions.
message NestedBook {
  extend Book {
    optional NestedBook another_book = 301;
  }
  // Recurse
  optional Book book = 1;
}

// For testing resiliency of our protostream parser.
// Field number of NestedBook is reused for something else.
message BadNestedBook {
  repeated uint32 book = 1 [packed=true];  // Packed to optional message.
}

// A recursively defined message.
message Cyclic {
  optional int32 m_int = 1;
  optional string m_str = 2;
  optional Book m_book = 3;
  repeated Author m_author = 5;
  optional Cyclic m_cyclic = 4;
}

// Test that two messages can have different fields mapped to the same JSON
// name. See: https://github.com/google/protobuf/issues/1415
message TestJsonName1 {
  optional int32 one_value = 1 [json_name = "value"];
}
message TestJsonName2 {
  optional int32 another_value = 1 [json_name = "value"];
}


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.

syntax = "proto3";

package google.protobuf.testing;

import "google/protobuf/struct.proto";

message StructTestCases {
  StructWrapper empty_value = 1;
  StructWrapper empty_value2 = 2;
  StructWrapper null_value = 3;
  StructWrapper simple_struct = 4;
  StructWrapper longer_struct = 5;
  StructWrapper struct_with_nested_struct = 6;
  StructWrapper struct_with_nested_list = 7;
  StructWrapper struct_with_list_of_nulls = 8;
  StructWrapper struct_with_list_of_lists = 9;
  StructWrapper struct_with_list_of_structs = 10;
  StructWrapper struct_with_empty_list = 11;
  StructWrapper struct_with_list_with_empty_struct = 12;
  google.protobuf.Struct top_level_struct = 13;
  google.protobuf.Struct top_level_struct_with_empty_list = 14;
  google.protobuf.Struct top_level_struct_with_list_with_empty_struct = 15;
  ValueWrapper value_wrapper_simple = 16;
  ValueWrapper value_wrapper_with_struct = 17;
  ValueWrapper value_wrapper_with_list = 18;
  ValueWrapper value_wrapper_with_empty_list = 19;
  ValueWrapper value_wrapper_with_list_with_empty_struct = 20;
  ListValueWrapper list_value_wrapper = 21;
  ListValueWrapper list_value_wrapper_with_empty_list = 22;
  ListValueWrapper list_value_wrapper_with_list_with_empty_struct = 23;
  google.protobuf.Value top_level_value_simple = 24;
  google.protobuf.Value top_level_value_with_struct = 25;
  google.protobuf.Value top_level_value_with_list = 26;
  google.protobuf.Value top_level_value_with_empty_list = 27;
  google.protobuf.Value top_level_value_with_list_with_empty_struct = 28;
  google.protobuf.ListValue top_level_listvalue = 29;
  google.protobuf.ListValue top_level_empty_listvalue = 30;
  google.protobuf.ListValue top_level_listvalue_with_empty_struct = 31;
  RepeatedValueWrapper repeated_value = 32;
  RepeatedValueWrapper repeated_value_nested_list = 33;
  RepeatedValueWrapper repeated_value_nested_list2 = 34;
  RepeatedValueWrapper repeated_value_nested_list3 = 35;
  RepeatedListValueWrapper repeated_listvalue = 36;
  MapOfStruct map_of_struct = 37;
  MapOfStruct map_of_struct_value = 38;
  MapOfStruct map_of_listvalue = 39;
}

message StructWrapper {
  google.protobuf.Struct struct = 1;
}

message ValueWrapper {
  google.protobuf.Value value = 1;
}

message RepeatedValueWrapper {
  repeated google.protobuf.Value values = 1;
}

message ListValueWrapper {
  google.protobuf.ListValue shopping_list = 1;
}

message RepeatedListValueWrapper {
  repeated google.protobuf.ListValue dimensions = 1;
}

message MapOfStruct {
  map<string, google.protobuf.Struct> struct_map = 1;
  map<string, google.protobuf.Value> value_map = 2;
  map<string, google.protobuf.ListValue> listvalue_map = 3;
}

// Hack to test return types with Struct as top-level message. Struct typers
// cannot be directly used in API requests. Hence using Dummy as request type.
message Dummy {
  string text = 1;
}

service StructTestService {
  rpc Call(Dummy) returns (StructTestCases);
}

message StructType {
  google.protobuf.Struct object = 1;
}


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.

syntax = "proto3";

package google.protobuf.testing;

message Proto3Message {
  enum NestedEnum {
    FOO = 0;
    BAR = 1;
    BAZ = 2;
  }
  NestedEnum enum_value = 1;
}


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)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>

namespace google {
namespace protobuf {
namespace io {

Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
    : variable_delimiter_(variable_delimiter),
      output_(output),
      buffer_(NULL),
      buffer_size_(0),
      offset_(0),
      at_start_of_line_(true),
      failed_(false),
      annotation_collector_(NULL) {}

Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter,
                 AnnotationCollector* annotation_collector)
    : variable_delimiter_(variable_delimiter),
      output_(output),
      buffer_(NULL),
      buffer_size_(0),
      offset_(0),
      at_start_of_line_(true),
      failed_(false),
      annotation_collector_(annotation_collector) {}

Printer::~Printer() {
  // Only BackUp() if we have called Next() at least once and never failed.
  if (buffer_size_ > 0 && !failed_) {
    output_->BackUp(buffer_size_);
  }
}

bool Printer::GetSubstitutionRange(const char* varname,
                                   std::pair<size_t, size_t>* range) {
  std::map<string, std::pair<size_t, size_t> >::const_iterator iter =
      substitutions_.find(varname);
  if (iter == substitutions_.end()) {
    GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname;
    return false;
  }
  if (iter->second.first > iter->second.second) {
    GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: "
                << varname;
    return false;
  }
  *range = iter->second;
  return true;
}

void Printer::Annotate(const char* begin_varname, const char* end_varname,
                       const string& file_path, const std::vector<int>& path) {
  if (annotation_collector_ == NULL) {
    // Can't generate signatures with this Printer.
    return;
  }
  std::pair<size_t, size_t> begin, end;
  if (!GetSubstitutionRange(begin_varname, &begin) ||
      !GetSubstitutionRange(end_varname, &end)) {
    return;
  }
  if (begin.first > end.second) {
    GOOGLE_LOG(DFATAL) << "  Annotation has negative length from " << begin_varname
                << " to " << end_varname;
  } else {
    annotation_collector_->AddAnnotation(begin.first, end.second, file_path,
                                         path);
  }
}

void Printer::Print(const std::map<string, string>& variables,
                    const char* text) {
  int size = strlen(text);
  int pos = 0;  // The number of bytes we've written so far.
  substitutions_.clear();
  line_start_variables_.clear();

  for (int i = 0; i < size; i++) {
    if (text[i] == '\n') {
      // Saw newline.  If there is more text, we may need to insert an indent
      // here.  So, write what we have so far, including the '\n'.
      WriteRaw(text + pos, i - pos + 1);
      pos = i + 1;

      // Setting this true will cause the next WriteRaw() to insert an indent
      // first.
      at_start_of_line_ = true;
      line_start_variables_.clear();

    } else if (text[i] == variable_delimiter_) {
      // Saw the start of a variable name.

      // Write what we have so far.
      WriteRaw(text + pos, i - pos);
      pos = i + 1;

      // Find closing delimiter.
      const char* end = strchr(text + pos, variable_delimiter_);
      if (end == NULL) {
        GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
        end = text + pos;
      }
      int endpos = end - text;

      string varname(text + pos, endpos - pos);
      if (varname.empty()) {
        // Two delimiters in a row reduce to a literal delimiter character.
        WriteRaw(&variable_delimiter_, 1);
      } else {
        // Replace with the variable's value.
        std::map<string, string>::const_iterator iter = variables.find(varname);
        if (iter == variables.end()) {
          GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
        } else {
          if (at_start_of_line_ && iter->second.empty()) {
            line_start_variables_.push_back(varname);
          }
          WriteRaw(iter->second.data(), iter->second.size());
          std::pair<std::map<string, std::pair<size_t, size_t> >::iterator,
                    bool>
              inserted = substitutions_.insert(std::make_pair(
                  varname,
                  std::make_pair(offset_ - iter->second.size(), offset_)));
          if (!inserted.second) {
            // This variable was used multiple times.  Make its span have
            // negative length so we can detect it if it gets used in an
            // annotation.
            inserted.first->second = std::make_pair(1, 0);
          }
        }
      }

      // Advance past this variable.
      i = endpos;
      pos = endpos + 1;
    }
  }

  // Write the rest.
  WriteRaw(text + pos, size - pos);
}

void Printer::Print(const char* text) {
  static std::map<string, string> empty;
  Print(empty, text);
}

void Printer::Print(const char* text,
                    const char* variable, const string& value) {
  std::map<string, string> vars;
  vars[variable] = value;
  Print(vars, text);
}

void Printer::Print(const char* text,
                    const char* variable1, const string& value1,
                    const char* variable2, const string& value2) {
  std::map<string, string> vars;
  vars[variable1] = value1;
  vars[variable2] = value2;
  Print(vars, text);
}

void Printer::Print(const char* text,
                    const char* variable1, const string& value1,
                    const char* variable2, const string& value2,
                    const char* variable3, const string& value3) {
  std::map<string, string> vars;
  vars[variable1] = value1;
  vars[variable2] = value2;
  vars[variable3] = value3;
  Print(vars, text);
}

void Printer::Print(const char* text,
                    const char* variable1, const string& value1,
                    const char* variable2, const string& value2,
                    const char* variable3, const string& value3,
                    const char* variable4, const string& value4) {
  std::map<string, string> vars;
  vars[variable1] = value1;
  vars[variable2] = value2;
  vars[variable3] = value3;
  vars[variable4] = value4;
  Print(vars, text);
}

void Printer::Print(const char* text,
                    const char* variable1, const string& value1,
                    const char* variable2, const string& value2,
                    const char* variable3, const string& value3,
                    const char* variable4, const string& value4,
                    const char* variable5, const string& value5) {
  std::map<string, string> vars;
  vars[variable1] = value1;
  vars[variable2] = value2;
  vars[variable3] = value3;
  vars[variable4] = value4;
  vars[variable5] = value5;
  Print(vars, text);
}

void Printer::Print(const char* text,
                    const char* variable1, const string& value1,
                    const char* variable2, const string& value2,
                    const char* variable3, const string& value3,
                    const char* variable4, const string& value4,
                    const char* variable5, const string& value5,
                    const char* variable6, const string& value6) {
  std::map<string, string> vars;
  vars[variable1] = value1;
  vars[variable2] = value2;
  vars[variable3] = value3;
  vars[variable4] = value4;
  vars[variable5] = value5;
  vars[variable6] = value6;
  Print(vars, text);
}

void Printer::Print(const char* text,
                    const char* variable1, const string& value1,
                    const char* variable2, const string& value2,
                    const char* variable3, const string& value3,
                    const char* variable4, const string& value4,
                    const char* variable5, const string& value5,
                    const char* variable6, const string& value6,
                    const char* variable7, const string& value7) {
  std::map<string, string> vars;
  vars[variable1] = value1;
  vars[variable2] = value2;
  vars[variable3] = value3;
  vars[variable4] = value4;
  vars[variable5] = value5;
  vars[variable6] = value6;
  vars[variable7] = value7;
  Print(vars, text);
}

void Printer::Print(const char* text,
                    const char* variable1, const string& value1,
                    const char* variable2, const string& value2,
                    const char* variable3, const string& value3,
                    const char* variable4, const string& value4,
                    const char* variable5, const string& value5,
                    const char* variable6, const string& value6,
                    const char* variable7, const string& value7,
                    const char* variable8, const string& value8) {
  std::map<string, string> vars;
  vars[variable1] = value1;
  vars[variable2] = value2;
  vars[variable3] = value3;
  vars[variable4] = value4;
  vars[variable5] = value5;
  vars[variable6] = value6;
  vars[variable7] = value7;
  vars[variable8] = value8;
  Print(vars, text);
}

void Printer::Indent() {
  indent_ += "  ";
}

void Printer::Outdent() {
  if (indent_.empty()) {
    GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
    return;
  }

  indent_.resize(indent_.size() - 2);
}

void Printer::PrintRaw(const string& data) {
  WriteRaw(data.data(), data.size());
}

void Printer::PrintRaw(const char* data) {
  if (failed_) return;
  WriteRaw(data, strlen(data));
}

void Printer::WriteRaw(const char* data, int size) {
  if (failed_) return;
  if (size == 0) return;

  if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
    // Insert an indent.
    at_start_of_line_ = false;
    CopyToBuffer(indent_.data(), indent_.size());
    if (failed_) return;
    // Fix up empty variables (e.g., "{") that should be annotated as
    // coming after the indent.
    for (std::vector<string>::iterator i = line_start_variables_.begin();
         i != line_start_variables_.end(); ++i) {
      substitutions_[*i].first += indent_.size();
      substitutions_[*i].second += indent_.size();
    }
  }

  // If we're going to write any data, clear line_start_variables_, since
  // we've either updated them in the block above or they no longer refer to
  // the current line.
  line_start_variables_.clear();

  CopyToBuffer(data, size);
}

void Printer::CopyToBuffer(const char* data, int size) {
  if (failed_) return;
  if (size == 0) return;

  while (size > buffer_size_) {
    // Data exceeds space in the buffer.  Copy what we can and request a
    // new buffer.
    memcpy(buffer_, data, buffer_size_);
    offset_ += buffer_size_;
    data += buffer_size_;
    size -= buffer_size_;
    void* void_buffer;
    failed_ = !output_->Next(&void_buffer, &buffer_size_);
    if (failed_) return;
    buffer_ = reinterpret_cast<char*>(void_buffer);
  }

  // Buffer is big enough to receive the data; copy it.
  memcpy(buffer_, data, size);
  buffer_ += size;
  buffer_size_ -= size;
  offset_ += size;
}

}  // namespace io
}  // namespace protobuf
}  // namespace google


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

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/io/zero_copy_stream_impl_lite.h>

#include <algorithm>
#include <limits>

#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stl_util.h>

namespace google {
namespace protobuf {
namespace io {

namespace {

// Default block size for Copying{In,Out}putStreamAdaptor.
static const int kDefaultBlockSize = 8192;

}  // namespace

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

ArrayInputStream::ArrayInputStream(const void* data, int size,
                                   int block_size)
  : data_(reinterpret_cast<const uint8*>(data)),
    size_(size),
    block_size_(block_size > 0 ? block_size : size),
    position_(0),
    last_returned_size_(0) {
}

bool ArrayInputStream::Next(const void** data, int* size) {
  if (position_ < size_) {
    last_returned_size_ = std::min(block_size_, size_ - position_);
    *data = data_ + position_;
    *size = last_returned_size_;
    position_ += last_returned_size_;
    return true;
  } else {
    // We're at the end of the array.
    last_returned_size_ = 0;   // Don't let caller back up.
    return false;
  }
}

void ArrayInputStream::BackUp(int count) {
  GOOGLE_CHECK_GT(last_returned_size_, 0)
      << "BackUp() can only be called after a successful Next().";
  GOOGLE_CHECK_LE(count, last_returned_size_);
  GOOGLE_CHECK_GE(count, 0);
  position_ -= count;
  last_returned_size_ = 0;  // Don't let caller back up further.
}

bool ArrayInputStream::Skip(int count) {
  GOOGLE_CHECK_GE(count, 0);
  last_returned_size_ = 0;   // Don't let caller back up.
  if (count > size_ - position_) {
    position_ = size_;
    return false;
  } else {
    position_ += count;
    return true;
  }
}

int64 ArrayInputStream::ByteCount() const {
  return position_;
}

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

ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
  : data_(reinterpret_cast<uint8*>(data)),
    size_(size),
    block_size_(block_size > 0 ? block_size : size),
    position_(0),
    last_returned_size_(0) {
}

bool ArrayOutputStream::Next(void** data, int* size) {
  if (position_ < size_) {
    last_returned_size_ = std::min(block_size_, size_ - position_);
    *data = data_ + position_;
    *size = last_returned_size_;
    position_ += last_returned_size_;
    return true;
  } else {
    // We're at the end of the array.
    last_returned_size_ = 0;   // Don't let caller back up.
    return false;
  }
}

void ArrayOutputStream::BackUp(int count) {
  GOOGLE_CHECK_GT(last_returned_size_, 0)
      << "BackUp() can only be called after a successful Next().";
  GOOGLE_CHECK_LE(count, last_returned_size_);
  GOOGLE_CHECK_GE(count, 0);
  position_ -= count;
  last_returned_size_ = 0;  // Don't let caller back up further.
}

int64 ArrayOutputStream::ByteCount() const {
  return position_;
}

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

StringOutputStream::StringOutputStream(string* target)
  : target_(target) {
}

bool StringOutputStream::Next(void** data, int* size) {
  GOOGLE_CHECK(target_ != NULL);
  int old_size = target_->size();

  // Grow the string.
  if (old_size < target_->capacity()) {
    // Resize the string to match its capacity, since we can get away
    // without a memory allocation this way.
    STLStringResizeUninitialized(target_, target_->capacity());
  } else {
    // Size has reached capacity, try to double the size.
    if (old_size > std::numeric_limits<int>::max() / 2) {
      // Can not double the size otherwise it is going to cause integer
      // overflow in the expression below: old_size * 2 ";
      GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for "
                 << "StringOutputStream.";
      return false;
    }
    // Double the size, also make sure that the new size is at least
    // kMinimumSize.
    STLStringResizeUninitialized(
        target_,
        std::max(old_size * 2,
                 kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
  }

  *data = mutable_string_data(target_) + old_size;
  *size = target_->size() - old_size;
  return true;
}

void StringOutputStream::BackUp(int count) {
  GOOGLE_CHECK_GE(count, 0);
  GOOGLE_CHECK(target_ != NULL);
  GOOGLE_CHECK_LE(count, target_->size());
  target_->resize(target_->size() - count);
}

int64 StringOutputStream::ByteCount() const {
  GOOGLE_CHECK(target_ != NULL);
  return target_->size();
}

void StringOutputStream::SetString(string* target) {
  target_ = target;
}

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

int CopyingInputStream::Skip(int count) {
  char junk[4096];
  int skipped = 0;
  while (skipped < count) {
    int bytes =
        Read(junk, std::min(count - skipped, implicit_cast<int>(sizeof(junk))));
    if (bytes <= 0) {
      // EOF or read error.
      return skipped;
    }
    skipped += bytes;
  }
  return skipped;
}

CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
    CopyingInputStream* copying_stream, int block_size)
  : copying_stream_(copying_stream),
    owns_copying_stream_(false),
    failed_(false),
    position_(0),
    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
    buffer_used_(0),
    backup_bytes_(0) {
}

CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
  if (owns_copying_stream_) {
    delete copying_stream_;
  }
}

bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
  if (failed_) {
    // Already failed on a previous read.
    return false;
  }

  AllocateBufferIfNeeded();

  if (backup_bytes_ > 0) {
    // We have data left over from a previous BackUp(), so just return that.
    *data = buffer_.get() + buffer_used_ - backup_bytes_;
    *size = backup_bytes_;
    backup_bytes_ = 0;
    return true;
  }

  // Read new data into the buffer.
  buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
  if (buffer_used_ <= 0) {
    // EOF or read error.  We don't need the buffer anymore.
    if (buffer_used_ < 0) {
      // Read error (not EOF).
      failed_ = true;
    }
    FreeBuffer();
    return false;
  }
  position_ += buffer_used_;

  *size = buffer_used_;
  *data = buffer_.get();
  return true;
}

void CopyingInputStreamAdaptor::BackUp(int count) {
  GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
    << " BackUp() can only be called after Next().";
  GOOGLE_CHECK_LE(count, buffer_used_)
    << " Can't back up over more bytes than were returned by the last call"
       " to Next().";
  GOOGLE_CHECK_GE(count, 0)
    << " Parameter to BackUp() can't be negative.";

  backup_bytes_ = count;
}

bool CopyingInputStreamAdaptor::Skip(int count) {
  GOOGLE_CHECK_GE(count, 0);

  if (failed_) {
    // Already failed on a previous read.
    return false;
  }

  // First skip any bytes left over from a previous BackUp().
  if (backup_bytes_ >= count) {
    // We have more data left over than we're trying to skip.  Just chop it.
    backup_bytes_ -= count;
    return true;
  }

  count -= backup_bytes_;
  backup_bytes_ = 0;

  int skipped = copying_stream_->Skip(count);
  position_ += skipped;
  return skipped == count;
}

int64 CopyingInputStreamAdaptor::ByteCount() const {
  return position_ - backup_bytes_;
}

void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
  if (buffer_.get() == NULL) {
    buffer_.reset(new uint8[buffer_size_]);
  }
}

void CopyingInputStreamAdaptor::FreeBuffer() {
  GOOGLE_CHECK_EQ(backup_bytes_, 0);
  buffer_used_ = 0;
  buffer_.reset();
}

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

CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
    CopyingOutputStream* copying_stream, int block_size)
  : copying_stream_(copying_stream),
    owns_copying_stream_(false),
    failed_(false),
    position_(0),
    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
    buffer_used_(0) {
}

CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
  WriteBuffer();
  if (owns_copying_stream_) {
    delete copying_stream_;
  }
}

bool CopyingOutputStreamAdaptor::Flush() {
  return WriteBuffer();
}

bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
  if (buffer_used_ == buffer_size_) {
    if (!WriteBuffer()) return false;
  }

  AllocateBufferIfNeeded();

  *data = buffer_.get() + buffer_used_;
  *size = buffer_size_ - buffer_used_;
  buffer_used_ = buffer_size_;
  return true;
}

void CopyingOutputStreamAdaptor::BackUp(int count) {
  GOOGLE_CHECK_GE(count, 0);
  GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
    << " BackUp() can only be called after Next().";
  GOOGLE_CHECK_LE(count, buffer_used_)
    << " Can't back up over more bytes than were returned by the last call"
       " to Next().";

  buffer_used_ -= count;
}

int64 CopyingOutputStreamAdaptor::ByteCount() const {
  return position_ + buffer_used_;
}

bool CopyingOutputStreamAdaptor::WriteBuffer() {
  if (failed_) {
    // Already failed on a previous write.
    return false;
  }

  if (buffer_used_ == 0) return true;

  if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
    position_ += buffer_used_;
    buffer_used_ = 0;
    return true;
  } else {
    failed_ = true;
    FreeBuffer();
    return false;
  }
}

void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
  if (buffer_ == NULL) {
    buffer_.reset(new uint8[buffer_size_]);
  }
}

void CopyingOutputStreamAdaptor::FreeBuffer() {
  buffer_used_ = 0;
  buffer_.reset();
}

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

}  // namespace io
}  // namespace protobuf
}  // namespace google


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

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.
//
// This file contains common implementations of the interfaces defined in
// zero_copy_stream.h which are included in the "lite" protobuf library.
// These implementations cover I/O on raw arrays and strings, as well as
// adaptors which make it easy to implement streams based on traditional
// streams.  Of course, many users will probably want to write their own
// implementations of these interfaces specific to the particular I/O
// abstractions they prefer to use, but these should cover the most common
// cases.

#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__

#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <iosfwd>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stl_util.h>

namespace google {
namespace protobuf {
namespace io {

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

// A ZeroCopyInputStream backed by an in-memory array of bytes.
class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
 public:
  // Create an InputStream that returns the bytes pointed to by "data".
  // "data" remains the property of the caller but must remain valid until
  // the stream is destroyed.  If a block_size is given, calls to Next()
  // will return data blocks no larger than the given size.  Otherwise, the
  // first call to Next() returns the entire array.  block_size is mainly
  // useful for testing; in production you would probably never want to set
  // it.
  ArrayInputStream(const void* data, int size, int block_size = -1);

  // implements ZeroCopyInputStream ----------------------------------
  bool Next(const void** data, int* size);
  void BackUp(int count);
  bool Skip(int count);
  int64 ByteCount() const;

 private:
  const uint8* const data_;  // The byte array.
  const int size_;           // Total size of the array.
  const int block_size_;     // How many bytes to return at a time.

  int position_;
  int last_returned_size_;   // How many bytes we returned last time Next()
                             // was called (used for error checking only).

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
};

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

// A ZeroCopyOutputStream backed by an in-memory array of bytes.
class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
 public:
  // Create an OutputStream that writes to the bytes pointed to by "data".
  // "data" remains the property of the caller but must remain valid until
  // the stream is destroyed.  If a block_size is given, calls to Next()
  // will return data blocks no larger than the given size.  Otherwise, the
  // first call to Next() returns the entire array.  block_size is mainly
  // useful for testing; in production you would probably never want to set
  // it.
  ArrayOutputStream(void* data, int size, int block_size = -1);

  // implements ZeroCopyOutputStream ---------------------------------
  bool Next(void** data, int* size);
  void BackUp(int count);
  int64 ByteCount() const;

 private:
  uint8* const data_;        // The byte array.
  const int size_;           // Total size of the array.
  const int block_size_;     // How many bytes to return at a time.

  int position_;
  int last_returned_size_;   // How many bytes we returned last time Next()
                             // was called (used for error checking only).

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
};

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

// A ZeroCopyOutputStream which appends bytes to a string.
class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
 public:
  // Create a StringOutputStream which appends bytes to the given string.
  // The string remains property of the caller, but it is mutated in arbitrary
  // ways and MUST NOT be accessed in any way until you're done with the
  // stream. Either be sure there's no further usage, or (safest) destroy the
  // stream before using the contents.
  //
  // Hint:  If you call target->reserve(n) before creating the stream,
  //   the first call to Next() will return at least n bytes of buffer
  //   space.
  explicit StringOutputStream(string* target);

  // implements ZeroCopyOutputStream ---------------------------------
  bool Next(void** data, int* size);
  void BackUp(int count);
  int64 ByteCount() const;

 protected:
  void SetString(string* target);

 private:
  static const int kMinimumSize = 16;

  string* target_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
};

// Note:  There is no StringInputStream.  Instead, just create an
// ArrayInputStream as follows:
//   ArrayInputStream input(str.data(), str.size());

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

// A generic traditional input stream interface.
//
// Lots of traditional input streams (e.g. file descriptors, C stdio
// streams, and C++ iostreams) expose an interface where every read
// involves copying bytes into a buffer.  If you want to take such an
// interface and make a ZeroCopyInputStream based on it, simply implement
// CopyingInputStream and then use CopyingInputStreamAdaptor.
//
// CopyingInputStream implementations should avoid buffering if possible.
// CopyingInputStreamAdaptor does its own buffering and will read data
// in large blocks.
class LIBPROTOBUF_EXPORT CopyingInputStream {
 public:
  virtual ~CopyingInputStream() {}

  // Reads up to "size" bytes into the given buffer.  Returns the number of
  // bytes read.  Read() waits until at least one byte is available, or
  // returns zero if no bytes will ever become available (EOF), or -1 if a
  // permanent read error occurred.
  virtual int Read(void* buffer, int size) = 0;

  // Skips the next "count" bytes of input.  Returns the number of bytes
  // actually skipped.  This will always be exactly equal to "count" unless
  // EOF was reached or a permanent read error occurred.
  //
  // The default implementation just repeatedly calls Read() into a scratch
  // buffer.
  virtual int Skip(int count);
};

// A ZeroCopyInputStream which reads from a CopyingInputStream.  This is
// useful for implementing ZeroCopyInputStreams that read from traditional
// streams.  Note that this class is not really zero-copy.
//
// If you want to read from file descriptors or C++ istreams, this is
// already implemented for you:  use FileInputStream or IstreamInputStream
// respectively.
class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
 public:
  // Creates a stream that reads from the given CopyingInputStream.
  // If a block_size is given, it specifies the number of bytes that
  // should be read and returned with each call to Next().  Otherwise,
  // a reasonable default is used.  The caller retains ownership of
  // copying_stream unless SetOwnsCopyingStream(true) is called.
  explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
                                     int block_size = -1);
  ~CopyingInputStreamAdaptor();

  // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
  // delete the underlying CopyingInputStream when it is destroyed.
  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }

  // implements ZeroCopyInputStream ----------------------------------
  bool Next(const void** data, int* size);
  void BackUp(int count);
  bool Skip(int count);
  int64 ByteCount() const;

 private:
  // Insures that buffer_ is not NULL.
  void AllocateBufferIfNeeded();
  // Frees the buffer and resets buffer_used_.
  void FreeBuffer();

  // The underlying copying stream.
  CopyingInputStream* copying_stream_;
  bool owns_copying_stream_;

  // True if we have seen a permenant error from the underlying stream.
  bool failed_;

  // The current position of copying_stream_, relative to the point where
  // we started reading.
  int64 position_;

  // Data is read into this buffer.  It may be NULL if no buffer is currently
  // in use.  Otherwise, it points to an array of size buffer_size_.
  google::protobuf::scoped_array<uint8> buffer_;
  const int buffer_size_;

  // Number of valid bytes currently in the buffer (i.e. the size last
  // returned by Next()).  0 <= buffer_used_ <= buffer_size_.
  int buffer_used_;

  // Number of bytes in the buffer which were backed up over by a call to
  // BackUp().  These need to be returned again.
  // 0 <= backup_bytes_ <= buffer_used_
  int backup_bytes_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
};

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

// A generic traditional output stream interface.
//
// Lots of traditional output streams (e.g. file descriptors, C stdio
// streams, and C++ iostreams) expose an interface where every write
// involves copying bytes from a buffer.  If you want to take such an
// interface and make a ZeroCopyOutputStream based on it, simply implement
// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
//
// CopyingOutputStream implementations should avoid buffering if possible.
// CopyingOutputStreamAdaptor does its own buffering and will write data
// in large blocks.
class LIBPROTOBUF_EXPORT CopyingOutputStream {
 public:
  virtual ~CopyingOutputStream() {}

  // Writes "size" bytes from the given buffer to the output.  Returns true
  // if successful, false on a write error.
  virtual bool Write(const void* buffer, int size) = 0;
};

// A ZeroCopyOutputStream which writes to a CopyingOutputStream.  This is
// useful for implementing ZeroCopyOutputStreams that write to traditional
// streams.  Note that this class is not really zero-copy.
//
// If you want to write to file descriptors or C++ ostreams, this is
// already implemented for you:  use FileOutputStream or OstreamOutputStream
// respectively.
class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
 public:
  // Creates a stream that writes to the given Unix file descriptor.
  // If a block_size is given, it specifies the size of the buffers
  // that should be returned by Next().  Otherwise, a reasonable default
  // is used.
  explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
                                      int block_size = -1);
  ~CopyingOutputStreamAdaptor();

  // Writes all pending data to the underlying stream.  Returns false if a
  // write error occurred on the underlying stream.  (The underlying
  // stream itself is not necessarily flushed.)
  bool Flush();

  // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
  // delete the underlying CopyingOutputStream when it is destroyed.
  void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }

  // implements ZeroCopyOutputStream ---------------------------------
  bool Next(void** data, int* size);
  void BackUp(int count);
  int64 ByteCount() const;

 private:
  // Write the current buffer, if it is present.
  bool WriteBuffer();
  // Insures that buffer_ is not NULL.
  void AllocateBufferIfNeeded();
  // Frees the buffer.
  void FreeBuffer();

  // The underlying copying stream.
  CopyingOutputStream* copying_stream_;
  bool owns_copying_stream_;

  // True if we have seen a permenant error from the underlying stream.
  bool failed_;

  // The current position of copying_stream_, relative to the point where
  // we started writing.
  int64 position_;

  // Data is written from this buffer.  It may be NULL if no buffer is
  // currently in use.  Otherwise, it points to an array of size buffer_size_.
  google::protobuf::scoped_array<uint8> buffer_;
  const int buffer_size_;

  // Number of valid bytes currently in the buffer (i.e. the size last
  // returned by Next()).  When BackUp() is called, we just reduce this.
  // 0 <= buffer_used_ <= buffer_size_.
  int buffer_used_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
};

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

// mutable_string_data() and as_string_data() are workarounds to improve
// the performance of writing new data to an existing string.  Unfortunately
// the methods provided by the string class are suboptimal, and using memcpy()
// is mildly annoying because it requires its pointer args to be non-NULL even
// if we ask it to copy 0 bytes.  Furthermore, string_as_array() has the
// property that it always returns NULL if its arg is the empty string, exactly
// what we want to avoid if we're using it in conjunction with memcpy()!
// With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size),
// where s is a string*.  Without C++11, &(*s)[0] is not guaranteed to be safe,
// so we use string_as_array(), and live with the extra logic that tests whether
// *s is empty.

// Return a pointer to mutable characters underlying the given string.  The
// return value is valid until the next time the string is resized.  We
// trust the caller to treat the return value as an array of length s->size().
inline char* mutable_string_data(string* s) {
#ifdef LANG_CXX11
  // This should be simpler & faster than string_as_array() because the latter
  // is guaranteed to return NULL when *s is empty, so it has to check for that.
  return &(*s)[0];
#else
  return string_as_array(s);
#endif
}

// as_string_data(s) is equivalent to
//  ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); })
// Sometimes it's faster: in some scenarios p cannot be NULL, and then the
// code can avoid that check.
inline std::pair<char*, bool> as_string_data(string* s) {
  char *p = mutable_string_data(s);
#ifdef LANG_CXX11
  return std::make_pair(p, true);
#else
  return std::make_pair(p, p != NULL);
#endif
}

}  // namespace io
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_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.

#include <google/protobuf/io/strtod.h>

#include <cstdio>
#include <cstring>
#include <limits>
#include <string>

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

namespace google {
namespace protobuf {
namespace io {

// ----------------------------------------------------------------------
// NoLocaleStrtod()
//   This code will make you cry.
// ----------------------------------------------------------------------

namespace {

// Returns a string identical to *input except that the character pointed to
// by radix_pos (which should be '.') is replaced with the locale-specific
// radix character.
string LocalizeRadix(const char* input, const char* radix_pos) {
  // Determine the locale-specific radix character by calling sprintf() to
  // print the number 1.5, then stripping off the digits.  As far as I can
  // tell, this is the only portable, thread-safe way to get the C library
  // to divuldge the locale's radix character.  No, localeconv() is NOT
  // thread-safe.
  char temp[16];
  int size = sprintf(temp, "%.1f", 1.5);
  GOOGLE_CHECK_EQ(temp[0], '1');
  GOOGLE_CHECK_EQ(temp[size-1], '5');
  GOOGLE_CHECK_LE(size, 6);

  // Now replace the '.' in the input with it.
  string result;
  result.reserve(strlen(input) + size - 3);
  result.append(input, radix_pos);
  result.append(temp + 1, size - 2);
  result.append(radix_pos + 1);
  return result;
}

}  // namespace

double NoLocaleStrtod(const char* text, char** original_endptr) {
  // We cannot simply set the locale to "C" temporarily with setlocale()
  // as this is not thread-safe.  Instead, we try to parse in the current
  // locale first.  If parsing stops at a '.' character, then this is a
  // pretty good hint that we're actually in some other locale in which
  // '.' is not the radix character.

  char* temp_endptr;
  double result = strtod(text, &temp_endptr);
  if (original_endptr != NULL) *original_endptr = temp_endptr;
  if (*temp_endptr != '.') return result;

  // Parsing halted on a '.'.  Perhaps we're in a different locale?  Let's
  // try to replace the '.' with a locale-specific radix character and
  // try again.
  string localized = LocalizeRadix(text, temp_endptr);
  const char* localized_cstr = localized.c_str();
  char* localized_endptr;
  result = strtod(localized_cstr, &localized_endptr);
  if ((localized_endptr - localized_cstr) >
      (temp_endptr - text)) {
    // This attempt got further, so replacing the decimal must have helped.
    // Update original_endptr to point at the right location.
    if (original_endptr != NULL) {
      // size_diff is non-zero if the localized radix has multiple bytes.
      int size_diff = localized.size() - strlen(text);
      // const_cast is necessary to match the strtod() interface.
      *original_endptr = const_cast<char*>(
        text + (localized_endptr - localized_cstr - size_diff));
    }
  }

  return result;
}

float SafeDoubleToFloat(double value) {
  if (value > std::numeric_limits<float>::max()) {
    return std::numeric_limits<float>::infinity();
  } else if (value < -std::numeric_limits<float>::max()) {
    return -std::numeric_limits<float>::infinity();
  } else {
    return static_cast<float>(value);
  }
}

}  // namespace io
}  // namespace protobuf
}  // namespace google