text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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 <limits>
#include <vector>

#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

const char kThickSeparator[] =
  "// ===================================================================\n";
const char kThinSeparator[] =
  "// -------------------------------------------------------------------\n";

class RenameKeywords {
 private:
  hash_set<string> java_keywords_set_;

 public:
  RenameKeywords() {
    static const char* kJavaKeywordsList[] = {
      // Reserved Java Keywords
      "abstract", "assert", "boolean", "break", "byte", "case", "catch",
      "char", "class", "const", "continue", "default", "do", "double", "else",
      "enum", "extends", "final", "finally", "float", "for", "goto", "if",
      "implements", "import", "instanceof", "int", "interface", "long",
      "native", "new", "package", "private", "protected", "public", "return",
      "short", "static", "strictfp", "super", "switch", "synchronized",
      "this", "throw", "throws", "transient", "try", "void", "volatile", "while",

      // Reserved Keywords for Literals
      "false", "null", "true"
    };

    for (int i = 0; i < GOOGLE_ARRAYSIZE(kJavaKeywordsList); i++) {
      java_keywords_set_.insert(kJavaKeywordsList[i]);
    }
  }

  // Used to rename the a field name if it's a java keyword.  Specifically
  // this is used to rename the ["name"] or ["capitalized_name"] field params.
  // (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html)
  string RenameJavaKeywordsImpl(const string& input) {
    string result = input;

    if (java_keywords_set_.find(result) != java_keywords_set_.end()) {
      result += "_";
    }

    return result;
  }

};

static RenameKeywords sRenameKeywords;

namespace {

const char* kDefaultPackage = "";

const string& FieldName(const FieldDescriptor* field) {
  // Groups are hacky:  The name of the field is just the lower-cased name
  // of the group type.  In Java, though, we would like to retain the original
  // capitalization of the type name.
  if (field->type() == FieldDescriptor::TYPE_GROUP) {
    return field->message_type()->name();
  } else {
    return field->name();
  }
}

string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
  string result;
  // Note:  I distrust ctype.h due to locales.
  for (int i = 0; i < input.size(); i++) {
    if ('a' <= input[i] && input[i] <= 'z') {
      if (cap_next_letter) {
        result += input[i] + ('A' - 'a');
      } else {
        result += input[i];
      }
      cap_next_letter = false;
    } else if ('A' <= input[i] && input[i] <= 'Z') {
      if (i == 0 && !cap_next_letter) {
        // Force first letter to lower-case unless explicitly told to
        // capitalize it.
        result += input[i] + ('a' - 'A');
      } else {
        // Capital letters after the first are left as-is.
        result += input[i];
      }
      cap_next_letter = false;
    } else if ('0' <= input[i] && input[i] <= '9') {
      result += input[i];
      cap_next_letter = true;
    } else {
      cap_next_letter = true;
    }
  }
  return result;
}

}  // namespace

string UnderscoresToCamelCase(const FieldDescriptor* field) {
  return UnderscoresToCamelCaseImpl(FieldName(field), false);
}

string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
  return UnderscoresToCamelCaseImpl(FieldName(field), true);
}

string UnderscoresToCamelCase(const MethodDescriptor* method) {
  return UnderscoresToCamelCaseImpl(method->name(), false);
}

string UnderscoresToCamelCase(const OneofDescriptor* oneof) {
  return UnderscoresToCamelCaseImpl(oneof->name(), false);
}

string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) {
  return UnderscoresToCamelCaseImpl(oneof->name(), true);
}

string RenameJavaKeywords(const string& input) {
  return sRenameKeywords.RenameJavaKeywordsImpl(input);
}

string StripProto(const string& filename) {
  if (HasSuffixString(filename, ".protodevel")) {
    return StripSuffixString(filename, ".protodevel");
  } else {
    return StripSuffixString(filename, ".proto");
  }
}

string FileClassName(const Params& params, const FileDescriptor* file) {
  if (params.has_java_outer_classname(file->name())) {
    return params.java_outer_classname(file->name());
  } else {
    // Use the filename itself with underscores removed
    // and a CamelCase style name.
    string basename;
    string::size_type last_slash = file->name().find_last_of('/');
    if (last_slash == string::npos) {
      basename = file->name();
    } else {
      basename = file->name().substr(last_slash + 1);
    }
    return UnderscoresToCamelCaseImpl(StripProto(basename), true);
  }
}

string FileJavaPackage(const Params& params, const FileDescriptor* file) {
  if (params.has_java_package(file->name())) {
    return params.java_package(file->name());
  } else {
    string result = kDefaultPackage;
    if (!file->package().empty()) {
      if (!result.empty()) result += '.';
      result += file->package();
    }

    if (!result.empty()) {
      result += ".";
    }
    result += "nano";

    return result;
  }
}

bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
  // If java_multiple_files is false, the outer class is always needed.
  if (!params.java_multiple_files(file->name())) {
    return true;
  }

  // File-scope extensions need the outer class as the scope.
  if (file->extension_count() != 0) {
    return true;
  }

  // If container interfaces are not generated, file-scope enums need the
  // outer class as the scope.
  if (file->enum_type_count() != 0 && !params.java_enum_style()) {
    return true;
  }

  return false;
}

string ToJavaName(const Params& params, const string& name, bool is_class,
    const Descriptor* parent, const FileDescriptor* file) {
  string result;
  if (parent != NULL) {
    result.append(ClassName(params, parent));
  } else if (is_class && params.java_multiple_files(file->name())) {
    result.append(FileJavaPackage(params, file));
  } else {
    result.append(ClassName(params, file));
  }
  if (!result.empty()) result.append(1, '.');
  result.append(RenameJavaKeywords(name));
  return result;
}

string ClassName(const Params& params, const FileDescriptor* descriptor) {
  string result = FileJavaPackage(params, descriptor);
  if (!result.empty()) result += '.';
  result += FileClassName(params, descriptor);
  return result;
}

string ClassName(const Params& params, const EnumDescriptor* descriptor) {
  const Descriptor* parent = descriptor->containing_type();
  // When using Java enum style, an enum's class name contains the enum name.
  // Use the standard ToJavaName translation.
  if (params.java_enum_style()) {
    return ToJavaName(params, descriptor->name(), true, parent,
                      descriptor->file());
  }
  // Otherwise the enum members are accessed from the enclosing class.
  if (parent != NULL) {
    return ClassName(params, parent);
  } else {
    return ClassName(params, descriptor->file());
  }
}

string FieldConstantName(const FieldDescriptor *field) {
  string name = field->name() + "_FIELD_NUMBER";
  UpperString(&name);
  return name;
}

string FieldDefaultConstantName(const FieldDescriptor *field) {
  return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
}

void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
  // We don't want to print group bodies so we cut off after the first line
  // (the second line for extensions).
  string def = field->DebugString();
  string::size_type first_line_end = def.find_first_of('\n');
  printer->Print("// $def$\n",
    "def", def.substr(0, first_line_end));
  if (field->is_extension()) {
    string::size_type second_line_start = first_line_end + 1;
    string::size_type second_line_length =
        def.find('\n', second_line_start) - second_line_start;
    printer->Print("// $def$\n",
      "def", def.substr(second_line_start, second_line_length));
  }
}

JavaType GetJavaType(FieldDescriptor::Type field_type) {
  switch (field_type) {
    case FieldDescriptor::TYPE_INT32:
    case FieldDescriptor::TYPE_UINT32:
    case FieldDescriptor::TYPE_SINT32:
    case FieldDescriptor::TYPE_FIXED32:
    case FieldDescriptor::TYPE_SFIXED32:
      return JAVATYPE_INT;

    case FieldDescriptor::TYPE_INT64:
    case FieldDescriptor::TYPE_UINT64:
    case FieldDescriptor::TYPE_SINT64:
    case FieldDescriptor::TYPE_FIXED64:
    case FieldDescriptor::TYPE_SFIXED64:
      return JAVATYPE_LONG;

    case FieldDescriptor::TYPE_FLOAT:
      return JAVATYPE_FLOAT;

    case FieldDescriptor::TYPE_DOUBLE:
      return JAVATYPE_DOUBLE;

    case FieldDescriptor::TYPE_BOOL:
      return JAVATYPE_BOOLEAN;

    case FieldDescriptor::TYPE_STRING:
      return JAVATYPE_STRING;

    case FieldDescriptor::TYPE_BYTES:
      return JAVATYPE_BYTES;

    case FieldDescriptor::TYPE_ENUM:
      return JAVATYPE_ENUM;

    case FieldDescriptor::TYPE_GROUP:
    case FieldDescriptor::TYPE_MESSAGE:
      return JAVATYPE_MESSAGE;

    // No default because we want the compiler to complain if any new
    // types are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return JAVATYPE_INT;
}

string PrimitiveTypeName(JavaType type) {
  switch (type) {
    case JAVATYPE_INT    : return "int";
    case JAVATYPE_LONG   : return "long";
    case JAVATYPE_FLOAT  : return "float";
    case JAVATYPE_DOUBLE : return "double";
    case JAVATYPE_BOOLEAN: return "boolean";
    case JAVATYPE_STRING : return "java.lang.String";
    case JAVATYPE_BYTES  : return "byte[]";
    case JAVATYPE_ENUM   : return "int";
    case JAVATYPE_MESSAGE: return "";

    // No default because we want the compiler to complain if any new
    // JavaTypes are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return "";
}

string BoxedPrimitiveTypeName(JavaType type) {
  switch (type) {
    case JAVATYPE_INT    : return "java.lang.Integer";
    case JAVATYPE_LONG   : return "java.lang.Long";
    case JAVATYPE_FLOAT  : return "java.lang.Float";
    case JAVATYPE_DOUBLE : return "java.lang.Double";
    case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
    case JAVATYPE_STRING : return "java.lang.String";
    case JAVATYPE_BYTES  : return "byte[]";
    case JAVATYPE_ENUM   : return "java.lang.Integer";
    case JAVATYPE_MESSAGE: return "";

    // No default because we want the compiler to complain if any new
    // JavaTypes are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return "";
}

string EmptyArrayName(const Params& params, const FieldDescriptor* field) {
  switch (GetJavaType(field)) {
    case JAVATYPE_INT    : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
    case JAVATYPE_LONG   : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY";
    case JAVATYPE_FLOAT  : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY";
    case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY";
    case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY";
    case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY";
    case JAVATYPE_BYTES  : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY";
    case JAVATYPE_ENUM   : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
    case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY";

    // No default because we want the compiler to complain if any new
    // JavaTypes are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return "";
}

string DefaultValue(const Params& params, const FieldDescriptor* field) {
  if (field->label() == FieldDescriptor::LABEL_REPEATED) {
    return EmptyArrayName(params, field);
  }

  if (params.use_reference_types_for_primitives()) {
    if (params.reftypes_primitive_enums()
          && field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
      return "Integer.MIN_VALUE";
    }
    return "null";
  }

  // Switch on cpp_type since we need to know which default_value_* method
  // of FieldDescriptor to call.
  switch (field->cpp_type()) {
    case FieldDescriptor::CPPTYPE_INT32:
      return SimpleItoa(field->default_value_int32());
    case FieldDescriptor::CPPTYPE_UINT32:
      // Need to print as a signed int since Java has no unsigned.
      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
    case FieldDescriptor::CPPTYPE_INT64:
      return SimpleItoa(field->default_value_int64()) + "L";
    case FieldDescriptor::CPPTYPE_UINT64:
      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
             "L";
    case FieldDescriptor::CPPTYPE_DOUBLE: {
      double value = field->default_value_double();
      if (value == std::numeric_limits<double>::infinity()) {
        return "Double.POSITIVE_INFINITY";
      } else if (value == -std::numeric_limits<double>::infinity()) {
        return "Double.NEGATIVE_INFINITY";
      } else if (value != value) {
        return "Double.NaN";
      } else {
        return SimpleDtoa(value) + "D";
      }
    }
    case FieldDescriptor::CPPTYPE_FLOAT: {
      float value = field->default_value_float();
      if (value == std::numeric_limits<float>::infinity()) {
        return "Float.POSITIVE_INFINITY";
      } else if (value == -std::numeric_limits<float>::infinity()) {
        return "Float.NEGATIVE_INFINITY";
      } else if (value != value) {
        return "Float.NaN";
      } else {
        return SimpleFtoa(value) + "F";
      }
    }
    case FieldDescriptor::CPPTYPE_BOOL:
      return field->default_value_bool() ? "true" : "false";
    case FieldDescriptor::CPPTYPE_STRING:
      if (!field->default_value_string().empty()) {
        // Point it to the static final in the generated code.
        return FieldDefaultConstantName(field);
      } else {
        if (field->type() == FieldDescriptor::TYPE_BYTES) {
          return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES";
        } else {
          return "\"\"";
        }
      }

    case FieldDescriptor::CPPTYPE_ENUM:
      return ClassName(params, field->enum_type()) + "." +
             RenameJavaKeywords(field->default_value_enum()->name());

    case FieldDescriptor::CPPTYPE_MESSAGE:
      return "null";

    // No default because we want the compiler to complain if any new
    // types are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return "";
}

static const char* kBitMasks[] = {
  "0x00000001",
  "0x00000002",
  "0x00000004",
  "0x00000008",
  "0x00000010",
  "0x00000020",
  "0x00000040",
  "0x00000080",

  "0x00000100",
  "0x00000200",
  "0x00000400",
  "0x00000800",
  "0x00001000",
  "0x00002000",
  "0x00004000",
  "0x00008000",

  "0x00010000",
  "0x00020000",
  "0x00040000",
  "0x00080000",
  "0x00100000",
  "0x00200000",
  "0x00400000",
  "0x00800000",

  "0x01000000",
  "0x02000000",
  "0x04000000",
  "0x08000000",
  "0x10000000",
  "0x20000000",
  "0x40000000",
  "0x80000000",
};

string GetBitFieldName(int index) {
  string var_name = "bitField";
  var_name += SimpleItoa(index);
  var_name += "_";
  return var_name;
}

string GetBitFieldNameForBit(int bit_index) {
  return GetBitFieldName(bit_index / 32);
}

string GenerateGetBit(int bit_index) {
  string var_name = GetBitFieldNameForBit(bit_index);
  int bit_in_var_index = bit_index % 32;

  string mask = kBitMasks[bit_in_var_index];
  string result = "((" + var_name + " & " + mask + ") != 0)";
  return result;
}

string GenerateSetBit(int bit_index) {
  string var_name = GetBitFieldNameForBit(bit_index);
  int bit_in_var_index = bit_index % 32;

  string mask = kBitMasks[bit_in_var_index];
  string result = var_name + " |= " + mask;
  return result;
}

string GenerateClearBit(int bit_index) {
  string var_name = GetBitFieldNameForBit(bit_index);
  int bit_in_var_index = bit_index % 32;

  string mask = kBitMasks[bit_in_var_index];
  string result = var_name + " = (" + var_name + " & ~" + mask + ")";
  return result;
}

string GenerateDifferentBit(int bit_index) {
  string var_name = GetBitFieldNameForBit(bit_index);
  int bit_in_var_index = bit_index % 32;

  string mask = kBitMasks[bit_in_var_index];
  string result = "((" + var_name + " & " + mask
      + ") != (other." + var_name + " & " + mask + "))";
  return result;
}

void SetBitOperationVariables(const string name,
    int bitIndex, std::map<string, string>* variables) {
  (*variables)["get_" + name] = GenerateGetBit(bitIndex);
  (*variables)["set_" + name] = GenerateSetBit(bitIndex);
  (*variables)["clear_" + name] = GenerateClearBit(bitIndex);
  (*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
}

bool HasMapField(const Descriptor* descriptor) {
  for (int i = 0; i < descriptor->field_count(); ++i) {
    const FieldDescriptor* field = descriptor->field(i);
    if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
        IsMapEntry(field->message_type())) {
      return true;
    }
  }
  return false;
}

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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/compiler/javanano/javanano_field.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
#include <google/protobuf/compiler/javanano/javanano_map_field.h>
#include <google/protobuf/compiler/javanano/javanano_message_field.h>
#include <google/protobuf/stubs/common.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

FieldGenerator::~FieldGenerator() {}

bool FieldGenerator::SavedDefaultNeeded() const {
  // No saved default for this field by default.
  // Subclasses whose instances may need saved defaults will override this
  // and return the appropriate value.
  return false;
}

void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
  // No saved default for this field by default.
  // Subclasses whose instances may need saved defaults will override this
  // and generate the appropriate init code to the printer.
}

void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
  // Reaching here indicates a bug. Cases are:
  //   - This FieldGenerator should support packing, but this method should be
  //     overridden.
  //   - This FieldGenerator doesn't support packing, and this method should
  //     never have been called.
  GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
             << "called on field generator that does not support packing.";
}

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

FieldGeneratorMap::FieldGeneratorMap(
    const Descriptor* descriptor, const Params &params)
  : descriptor_(descriptor),
    field_generators_(
      new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {

  int next_has_bit_index = 0;
  bool saved_defaults_needed = false;
  // Construct all the FieldGenerators.
  for (int i = 0; i < descriptor->field_count(); i++) {
    FieldGenerator* field_generator = MakeGenerator(
        descriptor->field(i), params, &next_has_bit_index);
    saved_defaults_needed = saved_defaults_needed
        || field_generator->SavedDefaultNeeded();
    field_generators_[i].reset(field_generator);
  }
  total_bits_ = next_has_bit_index;
  saved_defaults_needed_ = saved_defaults_needed;
}

FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
    const Params &params, int* next_has_bit_index) {
  JavaType java_type = GetJavaType(field);
  if (field->is_repeated()) {
    switch (java_type) {
      case JAVATYPE_MESSAGE:
        if (IsMapEntry(field->message_type())) {
          return new MapFieldGenerator(field, params);
        } else {
          return new RepeatedMessageFieldGenerator(field, params);
        }
      case JAVATYPE_ENUM:
        return new RepeatedEnumFieldGenerator(field, params);
      default:
        return new RepeatedPrimitiveFieldGenerator(field, params);
    }
  } else if (field->containing_oneof()) {
    switch (java_type) {
      case JAVATYPE_MESSAGE:
        return new MessageOneofFieldGenerator(field, params);
      case JAVATYPE_ENUM:
      default:
        return new PrimitiveOneofFieldGenerator(field, params);
    }
  } else if (params.optional_field_accessors() && field->is_optional()
      && java_type != JAVATYPE_MESSAGE) {
    // We need a has-bit for each primitive/enum field because their default
    // values could be same as explicitly set values. But we don't need it
    // for a message field because they have no defaults and Nano uses 'null'
    // for unset messages, which cannot be set explicitly.
    switch (java_type) {
      case JAVATYPE_ENUM:
        return new AccessorEnumFieldGenerator(
            field, params, (*next_has_bit_index)++);
      default:
        return new AccessorPrimitiveFieldGenerator(
            field, params, (*next_has_bit_index)++);
    }
  } else {
    switch (java_type) {
      case JAVATYPE_MESSAGE:
        return new MessageFieldGenerator(field, params);
      case JAVATYPE_ENUM:
        return new EnumFieldGenerator(field, params);
      default:
        return new PrimitiveFieldGenerator(field, params);
    }
  }
}

FieldGeneratorMap::~FieldGeneratorMap() {}

const FieldGenerator& FieldGeneratorMap::get(
    const FieldDescriptor* field) const {
  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
  return *field_generators_[field->index()];
}

void SetCommonOneofVariables(const FieldDescriptor* descriptor,
                             std::map<string, string>* variables) {
  (*variables)["oneof_name"] =
      UnderscoresToCamelCase(descriptor->containing_oneof());
  (*variables)["oneof_capitalized_name"] =
      UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
  (*variables)["oneof_index"] =
      SimpleItoa(descriptor->containing_oneof()->index());
  (*variables)["set_oneof_case"] =
      "this." + (*variables)["oneof_name"] +
      "Case_ = " + SimpleItoa(descriptor->number());
  (*variables)["clear_oneof_case"] =
      "this." + (*variables)["oneof_name"] + "Case_ = 0";
  (*variables)["has_oneof_case"] =
      "this." + (*variables)["oneof_name"] + "Case_ == " +
      SimpleItoa(descriptor->number());
}

void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
                              const std::map<string, string>& variables,
                              io::Printer* printer) {
  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
    printer->Print(variables,
      "if (this.has$capitalized_name$()) {\n"
      "  if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
      "                               (byte[]) other.$oneof_name$_)) {\n"
      "    return false;\n"
      "  }\n"
      "}\n");
  } else {
    printer->Print(variables,
      "if (this.has$capitalized_name$()) {\n"
      "  if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
      "    return false;\n"
      "  }\n"
      "}\n");
  }
}

void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
                                const std::map<string, string>& variables,
                                io::Printer* printer) {
  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
    printer->Print(variables,
      "result = 31 * result + ($has_oneof_case$\n"
      "   ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
  } else {
    printer->Print(variables,
      "result = 31 * result +\n"
      "  ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
  }
}

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google

mime_type: text/plain


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__

#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>

namespace google {
namespace protobuf {
  class FileDescriptor;        // descriptor.h
  namespace io {
    class Printer;             // printer.h
  }
  namespace compiler {
    class GeneratorContext;     // code_generator.h
  }
}

namespace protobuf {
namespace compiler {
namespace javanano {

class FileGenerator {
 public:
  explicit FileGenerator(const FileDescriptor* file, const Params& params);
  ~FileGenerator();

  // Checks for problems that would otherwise lead to cryptic compile errors.
  // Returns true if there are no problems, or writes an error description to
  // the given string and returns false otherwise.
  bool Validate(string* error);

  void Generate(io::Printer* printer);

  // If we aren't putting everything into one file, this will write all the
  // files other than the outer file (i.e. one for each message, enum, and
  // service type).
  void GenerateSiblings(const string& package_dir,
                        GeneratorContext* output_directory,
                        vector<string>* file_list);

  const string& java_package() { return java_package_; }
  const string& classname()    { return classname_;    }

 private:
  const FileDescriptor* file_;
  const Params& params_;
  string java_package_;
  string classname_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__

#include <string>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_field.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/stubs/common.h>

namespace google {
namespace protobuf {
  namespace io {
    class Printer;             // printer.h
  }
}

namespace protobuf {
namespace compiler {
namespace javanano {

class MessageGenerator {
 public:
  explicit MessageGenerator(const Descriptor* descriptor, const Params& params);
  ~MessageGenerator();

  // All static variables have to be declared at the top-level of the file
  // so that we can control initialization order, which is important for
  // DescriptorProto bootstrapping to work.
  void GenerateStaticVariables(io::Printer* printer);

  // Output code which initializes the static variables generated by
  // GenerateStaticVariables().
  void GenerateStaticVariableInitializers(io::Printer* printer);

  // Generate the class itself.
  void Generate(io::Printer* printer);

 private:
  void GenerateMessageSerializationMethods(io::Printer* printer);
  void GenerateMergeFromMethods(io::Printer* printer);
  void GenerateParseFromMethods(io::Printer* printer);
  void GenerateSerializeOneField(io::Printer* printer,
                                 const FieldDescriptor* field);

  void GenerateClear(io::Printer* printer);
  void GenerateFieldInitializers(io::Printer* printer);
  void GenerateEquals(io::Printer* printer);
  void GenerateHashCode(io::Printer* printer);
  void GenerateClone(io::Printer* printer);

  const Params& params_;
  const Descriptor* descriptor_;
  FieldGeneratorMap field_generators_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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 <map>
#include <math.h>
#include <string>

#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

using internal::WireFormat;
using internal::WireFormatLite;

namespace {

bool IsReferenceType(JavaType type) {
  switch (type) {
    case JAVATYPE_INT    : return false;
    case JAVATYPE_LONG   : return false;
    case JAVATYPE_FLOAT  : return false;
    case JAVATYPE_DOUBLE : return false;
    case JAVATYPE_BOOLEAN: return false;
    case JAVATYPE_STRING : return true;
    case JAVATYPE_BYTES  : return true;
    case JAVATYPE_ENUM   : return false;
    case JAVATYPE_MESSAGE: return true;

    // No default because we want the compiler to complain if any new
    // JavaTypes are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return false;
}

bool IsArrayType(JavaType type) {
  switch (type) {
    case JAVATYPE_INT    : return false;
    case JAVATYPE_LONG   : return false;
    case JAVATYPE_FLOAT  : return false;
    case JAVATYPE_DOUBLE : return false;
    case JAVATYPE_BOOLEAN: return false;
    case JAVATYPE_STRING : return false;
    case JAVATYPE_BYTES  : return true;
    case JAVATYPE_ENUM   : return false;
    case JAVATYPE_MESSAGE: return false;

    // No default because we want the compiler to complain if any new
    // JavaTypes are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return false;
}

const char* GetCapitalizedType(const FieldDescriptor* field) {
  switch (field->type()) {
    case FieldDescriptor::TYPE_INT32   : return "Int32"   ;
    case FieldDescriptor::TYPE_UINT32  : return "UInt32"  ;
    case FieldDescriptor::TYPE_SINT32  : return "SInt32"  ;
    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
    case FieldDescriptor::TYPE_INT64   : return "Int64"   ;
    case FieldDescriptor::TYPE_UINT64  : return "UInt64"  ;
    case FieldDescriptor::TYPE_SINT64  : return "SInt64"  ;
    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
    case FieldDescriptor::TYPE_FLOAT   : return "Float"   ;
    case FieldDescriptor::TYPE_DOUBLE  : return "Double"  ;
    case FieldDescriptor::TYPE_BOOL    : return "Bool"    ;
    case FieldDescriptor::TYPE_STRING  : return "String"  ;
    case FieldDescriptor::TYPE_BYTES   : return "Bytes"   ;
    case FieldDescriptor::TYPE_ENUM    : return "Enum"    ;
    case FieldDescriptor::TYPE_GROUP   : return "Group"   ;
    case FieldDescriptor::TYPE_MESSAGE : return "Message" ;

    // No default because we want the compiler to complain if any new
    // types are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return NULL;
}

// For encodings with fixed sizes, returns that size in bytes.  Otherwise
// returns -1.
int FixedSize(FieldDescriptor::Type type) {
  switch (type) {
    case FieldDescriptor::TYPE_INT32   : return -1;
    case FieldDescriptor::TYPE_INT64   : return -1;
    case FieldDescriptor::TYPE_UINT32  : return -1;
    case FieldDescriptor::TYPE_UINT64  : return -1;
    case FieldDescriptor::TYPE_SINT32  : return -1;
    case FieldDescriptor::TYPE_SINT64  : return -1;
    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;

    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
    case FieldDescriptor::TYPE_ENUM    : return -1;

    case FieldDescriptor::TYPE_STRING  : return -1;
    case FieldDescriptor::TYPE_BYTES   : return -1;
    case FieldDescriptor::TYPE_GROUP   : return -1;
    case FieldDescriptor::TYPE_MESSAGE : return -1;

    // No default because we want the compiler to complain if any new
    // types are added.
  }
  GOOGLE_LOG(FATAL) << "Can't get here.";
  return -1;
}

bool AllAscii(const string& text) {
  for (int i = 0; i < text.size(); i++) {
    if ((text[i] & 0x80) != 0) {
      return false;
    }
  }
  return true;
}

void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
                           std::map<string, string>* variables) {
  (*variables)["name"] =
    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
  (*variables)["capitalized_name"] =
    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
  (*variables)["number"] = SimpleItoa(descriptor->number());
  if (params.use_reference_types_for_primitives()
      && !descriptor->is_repeated()) {
    (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
  } else {
    (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
  }
  // Deals with defaults. For C++-string types (string and bytes),
  // we might need to have the generated code do the unicode decoding
  // (see comments in InternalNano.java for gory details.). We would
  // like to do this once into a static field and re-use that from
  // then on.
  if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
      !descriptor->default_value_string().empty() &&
      !params.use_reference_types_for_primitives()) {
    if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
      (*variables)["default"] = DefaultValue(params, descriptor);
      (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
      (*variables)["default_constant_value"] = strings::Substitute(
          "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
          CEscape(descriptor->default_value_string()));
      (*variables)["default_copy_if_needed"] =
          (*variables)["default"] + ".clone()";
    } else if (AllAscii(descriptor->default_value_string())) {
      // All chars are ASCII.  In this case directly referencing a
      // CEscape()'d string literal works fine.
      (*variables)["default"] =
          "\"" + CEscape(descriptor->default_value_string()) + "\"";
      (*variables)["default_copy_if_needed"] = (*variables)["default"];
    } else {
      // Strings where some chars are non-ASCII. We need to save the
      // default value.
      (*variables)["default"] = DefaultValue(params, descriptor);
      (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
      (*variables)["default_constant_value"] = strings::Substitute(
          "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
          CEscape(descriptor->default_value_string()));
      (*variables)["default_copy_if_needed"] = (*variables)["default"];
    }
  } else {
    // Non-string, non-bytes field. Defaults are literals.
    (*variables)["default"] = DefaultValue(params, descriptor);
    (*variables)["default_copy_if_needed"] = (*variables)["default"];
  }
  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
  (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
  (*variables)["tag_size"] = SimpleItoa(
      WireFormat::TagSize(descriptor->number(), descriptor->type()));
  (*variables)["non_packed_tag"] = SimpleItoa(
      internal::WireFormatLite::MakeTag(descriptor->number(),
          internal::WireFormat::WireTypeForFieldType(descriptor->type())));
  int fixed_size = FixedSize(descriptor->type());
  if (fixed_size != -1) {
    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
  }
  (*variables)["message_name"] = descriptor->containing_type()->name();
  (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
}
}  // namespace

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

PrimitiveFieldGenerator::
PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
  : FieldGenerator(params), descriptor_(descriptor) {
  SetPrimitiveVariables(descriptor, params, &variables_);
}

PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}

bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
  return variables_.find("default_constant") != variables_.end();
}

void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
  if (variables_.find("default_constant") != variables_.end()) {
    printer->Print(variables_,
      "$default_constant$ = $default_constant_value$;\n");
  }
}

void PrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer, bool lazy_init) const {
  if (variables_.find("default_constant") != variables_.end()) {
    // Those primitive types that need a saved default.
    if (lazy_init) {
      printer->Print(variables_,
        "private static $type$ $default_constant$;\n");
    } else {
      printer->Print(variables_,
        "private static final $type$ $default_constant$ =\n"
        "    $default_constant_value$;\n");
    }
  }

  printer->Print(variables_,
    "public $type$ $name$;\n");

  if (params_.generate_has()) {
    printer->Print(variables_,
      "public boolean has$capitalized_name$;\n");
  }
}

void PrimitiveFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$ = $default_copy_if_needed$;\n");

  if (params_.generate_has()) {
    printer->Print(variables_,
      "has$capitalized_name$ = false;\n");
  }
}

void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "this.$name$ = input.read$capitalized_type$();\n");

  if (params_.generate_has()) {
    printer->Print(variables_,
      "has$capitalized_name$ = true;\n");
  }
}

void PrimitiveFieldGenerator::
GenerateSerializationConditional(io::Printer* printer) const {
  if (params_.use_reference_types_for_primitives()) {
    // For reference type mode, serialize based on equality
    // to null.
    printer->Print(variables_,
      "if (this.$name$ != null) {\n");
    return;
  }
  if (params_.generate_has()) {
    printer->Print(variables_,
      "if (has$capitalized_name$ || ");
  } else {
    printer->Print(variables_,
      "if (");
  }
  JavaType java_type = GetJavaType(descriptor_);
  if (IsArrayType(java_type)) {
    printer->Print(variables_,
      "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
  } else if (IsReferenceType(java_type)) {
    printer->Print(variables_,
      "!this.$name$.equals($default$)) {\n");
  } else if (java_type == JAVATYPE_FLOAT) {
    printer->Print(variables_,
      "java.lang.Float.floatToIntBits(this.$name$)\n"
      "    != java.lang.Float.floatToIntBits($default$)) {\n");
  } else if (java_type == JAVATYPE_DOUBLE) {
    printer->Print(variables_,
      "java.lang.Double.doubleToLongBits(this.$name$)\n"
      "    != java.lang.Double.doubleToLongBits($default$)) {\n");
  } else {
    printer->Print(variables_,
      "this.$name$ != $default$) {\n");
  }
}

void PrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  if (descriptor_->is_required() && !params_.generate_has()) {
    // Always serialize a required field if we don't have the 'has' signal.
    printer->Print(variables_,
      "output.write$capitalized_type$($number$, this.$name$);\n");
  } else {
    GenerateSerializationConditional(printer);
    printer->Print(variables_,
      "  output.write$capitalized_type$($number$, this.$name$);\n"
      "}\n");
  }
}

void PrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  if (descriptor_->is_required() && !params_.generate_has()) {
    printer->Print(variables_,
      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
      "    .compute$capitalized_type$Size($number$, this.$name$);\n");
  } else {
    GenerateSerializationConditional(printer);
    printer->Print(variables_,
      "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
      "      .compute$capitalized_type$Size($number$, this.$name$);\n"
      "}\n");
  }
}

void RepeatedPrimitiveFieldGenerator::
GenerateFixClonedCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null && this.$name$.length > 0) {\n"
    "  cloned.$name$ = this.$name$.clone();\n"
    "}\n");
}

void PrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  // We define equality as serialized form equality. If generate_has(),
  // then if the field value equals the default value in both messages,
  // but one's 'has' field is set and the other's is not, the serialized
  // forms are different and we should return false.
  JavaType java_type = GetJavaType(descriptor_);
  if (java_type == JAVATYPE_BYTES) {
    printer->Print(variables_,
      "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
    if (params_.generate_has()) {
      printer->Print(variables_,
        "\n"
        "    || (java.util.Arrays.equals(this.$name$, $default$)\n"
        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
    }
    printer->Print(") {\n"
      "  return false;\n"
      "}\n");
  } else if (java_type == JAVATYPE_STRING
      || params_.use_reference_types_for_primitives()) {
    printer->Print(variables_,
      "if (this.$name$ == null) {\n"
      "  if (other.$name$ != null) {\n"
      "    return false;\n"
      "  }\n"
      "} else if (!this.$name$.equals(other.$name$)");
    if (params_.generate_has()) {
      printer->Print(variables_,
        "\n"
        "    || (this.$name$.equals($default$)\n"
        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
    }
    printer->Print(") {\n"
      "  return false;\n"
      "}\n");
  } else if (java_type == JAVATYPE_FLOAT) {
    printer->Print(variables_,
      "{\n"
      "  int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
      "  if (bits != java.lang.Float.floatToIntBits(other.$name$)");
    if (params_.generate_has()) {
      printer->Print(variables_,
        "\n"
        "      || (bits == java.lang.Float.floatToIntBits($default$)\n"
        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
    }
    printer->Print(") {\n"
      "    return false;\n"
      "  }\n"
      "}\n");
  } else if (java_type == JAVATYPE_DOUBLE) {
    printer->Print(variables_,
      "{\n"
      "  long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
      "  if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
    if (params_.generate_has()) {
      printer->Print(variables_,
        "\n"
        "      || (bits == java.lang.Double.doubleToLongBits($default$)\n"
        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
    }
    printer->Print(") {\n"
      "    return false;\n"
      "  }\n"
      "}\n");
  } else {
    printer->Print(variables_,
      "if (this.$name$ != other.$name$");
    if (params_.generate_has()) {
      printer->Print(variables_,
        "\n"
        "    || (this.$name$ == $default$\n"
        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
    }
    printer->Print(") {\n"
      "  return false;\n"
      "}\n");
  }
}

void PrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
  JavaType java_type = GetJavaType(descriptor_);
  if (java_type == JAVATYPE_BYTES) {
    printer->Print(variables_,
      "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
  } else if (java_type == JAVATYPE_STRING
      || params_.use_reference_types_for_primitives()) {
    printer->Print(variables_,
      "result = 31 * result\n"
      "    + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
  } else {
    switch (java_type) {
      // For all Java primitive types below, the hash codes match the
      // results of BoxedType.valueOf(primitiveValue).hashCode().
      case JAVATYPE_INT:
        printer->Print(variables_,
          "result = 31 * result + this.$name$;\n");
        break;
      case JAVATYPE_LONG:
        printer->Print(variables_,
          "result = 31 * result\n"
          "    + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
        break;
      case JAVATYPE_FLOAT:
        printer->Print(variables_,
          "result = 31 * result\n"
          "    + java.lang.Float.floatToIntBits(this.$name$);\n");
        break;
      case JAVATYPE_DOUBLE:
        printer->Print(variables_,
          "{\n"
          "  long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
          "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
          "}\n");
        break;
      case JAVATYPE_BOOLEAN:
        printer->Print(variables_,
          "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
        break;
      default:
        GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
        break;
    }
  }
}

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

AccessorPrimitiveFieldGenerator::
AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
     const Params& params, int has_bit_index)
  : FieldGenerator(params), descriptor_(descriptor) {
  SetPrimitiveVariables(descriptor, params, &variables_);
  SetBitOperationVariables("has", has_bit_index, &variables_);
}

AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}

bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
  return variables_.find("default_constant") != variables_.end();
}

void AccessorPrimitiveFieldGenerator::
GenerateInitSavedDefaultCode(io::Printer* printer) const {
  if (variables_.find("default_constant") != variables_.end()) {
    printer->Print(variables_,
      "$default_constant$ = $default_constant_value$;\n");
  }
}

void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer, bool lazy_init) const {
  if (variables_.find("default_constant") != variables_.end()) {
    // Those primitive types that need a saved default.
    if (lazy_init) {
      printer->Print(variables_,
        "private static $type$ $default_constant$;\n");
    } else {
      printer->Print(variables_,
        "private static final $type$ $default_constant$ =\n"
        "    $default_constant_value$;\n");
    }
  }
  printer->Print(variables_,
    "private $type$ $name$_;\n"
    "public $type$ get$capitalized_name$() {\n"
    "  return $name$_;\n"
    "}\n"
    "public $message_name$ set$capitalized_name$($type$ value) {\n");
  if (IsReferenceType(GetJavaType(descriptor_))) {
    printer->Print(variables_,
      "  if (value == null) {\n"
      "    throw new java.lang.NullPointerException();\n"
      "  }\n");
  }
  printer->Print(variables_,
    "  $name$_ = value;\n"
    "  $set_has$;\n"
    "  return this;\n"
    "}\n"
    "public boolean has$capitalized_name$() {\n"
    "  return $get_has$;\n"
    "}\n"
    "public $message_name$ clear$capitalized_name$() {\n"
    "  $name$_ = $default_copy_if_needed$;\n"
    "  $clear_has$;\n"
    "  return this;\n"
    "}\n");
}

void AccessorPrimitiveFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$_ = $default_copy_if_needed$;\n");
}

void AccessorPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$_ = input.read$capitalized_type$();\n"
    "$set_has$;\n");
}

void AccessorPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if ($get_has$) {\n"
    "  output.write$capitalized_type$($number$, $name$_);\n"
    "}\n");
}

void AccessorPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if ($get_has$) {\n"
    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    "      .compute$capitalized_type$Size($number$, $name$_);\n"
    "}\n");
}

void AccessorPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  switch (GetJavaType(descriptor_)) {
    // For all Java primitive types below, the equality checks match the
    // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
    case JAVATYPE_FLOAT:
      printer->Print(variables_,
        "if ($different_has$\n"
        "    || java.lang.Float.floatToIntBits($name$_)\n"
        "        != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
        "  return false;\n"
        "}\n");
      break;
    case JAVATYPE_DOUBLE:
      printer->Print(variables_,
        "if ($different_has$\n"
        "    || java.lang.Double.doubleToLongBits($name$_)\n"
        "        != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
        "  return false;\n"
        "}\n");
      break;
    case JAVATYPE_INT:
    case JAVATYPE_LONG:
    case JAVATYPE_BOOLEAN:
      printer->Print(variables_,
        "if ($different_has$\n"
        "    || $name$_ != other.$name$_) {\n"
        "  return false;\n"
        "}\n");
      break;
    case JAVATYPE_STRING:
      // Accessor style would guarantee $name$_ non-null
      printer->Print(variables_,
        "if ($different_has$\n"
        "    || !$name$_.equals(other.$name$_)) {\n"
        "  return false;\n"
        "}\n");
      break;
    case JAVATYPE_BYTES:
      // Accessor style would guarantee $name$_ non-null
      printer->Print(variables_,
        "if ($different_has$\n"
        "    || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
        "  return false;\n"
        "}\n");
      break;
    default:
      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
      break;
  }
}

void AccessorPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
  switch (GetJavaType(descriptor_)) {
    // For all Java primitive types below, the hash codes match the
    // results of BoxedType.valueOf(primitiveValue).hashCode().
    case JAVATYPE_INT:
      printer->Print(variables_,
        "result = 31 * result + $name$_;\n");
      break;
    case JAVATYPE_LONG:
      printer->Print(variables_,
        "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
      break;
    case JAVATYPE_FLOAT:
      printer->Print(variables_,
        "result = 31 * result +\n"
        "    java.lang.Float.floatToIntBits($name$_);\n");
      break;
    case JAVATYPE_DOUBLE:
      printer->Print(variables_,
        "{\n"
        "  long v = java.lang.Double.doubleToLongBits($name$_);\n"
        "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
        "}\n");
      break;
    case JAVATYPE_BOOLEAN:
      printer->Print(variables_,
        "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
      break;
    case JAVATYPE_STRING:
      // Accessor style would guarantee $name$_ non-null
      printer->Print(variables_,
        "result = 31 * result + $name$_.hashCode();\n");
      break;
    case JAVATYPE_BYTES:
      // Accessor style would guarantee $name$_ non-null
      printer->Print(variables_,
        "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
      break;
    default:
      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
      break;
  }
}

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

PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
    const FieldDescriptor* descriptor, const Params& params)
  : FieldGenerator(params), descriptor_(descriptor) {
    SetPrimitiveVariables(descriptor, params, &variables_);
    SetCommonOneofVariables(descriptor, &variables_);
}

PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}

void PrimitiveOneofFieldGenerator::GenerateMembers(
    io::Printer* printer, bool /*unused lazy_init*/) const {
  printer->Print(variables_,
    "public boolean has$capitalized_name$() {\n"
    "  return $has_oneof_case$;\n"
    "}\n"
    "public $type$ get$capitalized_name$() {\n"
    "  if ($has_oneof_case$) {\n"
    "    return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
    "  }\n"
    "  return $default$;\n"
    "}\n"
    "public $message_name$ set$capitalized_name$($type$ value) {\n"
    "  $set_oneof_case$;\n"
    "  this.$oneof_name$_ = value;\n"
    "  return this;\n"
    "}\n");
}

void PrimitiveOneofFieldGenerator::GenerateClearCode(
    io::Printer* printer) const {
  // No clear method for oneof fields.
}

void PrimitiveOneofFieldGenerator::GenerateMergingCode(
    io::Printer* printer) const {
  printer->Print(variables_,
    "this.$oneof_name$_ = input.read$capitalized_type$();\n"
    "$set_oneof_case$;\n");
}

void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
    io::Printer* printer) const {
  printer->Print(variables_,
    "if ($has_oneof_case$) {\n"
    "  output.write$capitalized_type$(\n"
    "      $number$, ($boxed_type$) this.$oneof_name$_);\n"
    "}\n");
}

void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
    io::Printer* printer) const {
  printer->Print(variables_,
    "if ($has_oneof_case$) {\n"
    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    "      .compute$capitalized_type$Size(\n"
    "          $number$, ($boxed_type$) this.$oneof_name$_);\n"
    "}\n");
}

void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
    io::Printer* printer) const {
  GenerateOneofFieldEquals(descriptor_, variables_, printer);
}

void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
    io::Printer* printer) const {
  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
}

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

RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
    const FieldDescriptor* descriptor, const Params& params)
  : FieldGenerator(params), descriptor_(descriptor) {
  SetPrimitiveVariables(descriptor, params, &variables_);
}

RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}

void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
  printer->Print(variables_,
    "public $type$[] $name$;\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$ = $default$;\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  // First, figure out the length of the array, then parse.
  printer->Print(variables_,
    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
    "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
    "int i = this.$name$ == null ? 0 : this.$name$.length;\n");

  if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
    printer->Print(variables_,
      "byte[][] newArray = new byte[i + arrayLength][];\n");
  } else {
    printer->Print(variables_,
      "$type$[] newArray = new $type$[i + arrayLength];\n");
  }
  printer->Print(variables_,
    "if (i != 0) {\n"
    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
    "}\n"
    "for (; i < newArray.length - 1; i++) {\n"
    "  newArray[i] = input.read$capitalized_type$();\n"
    "  input.readTag();\n"
    "}\n"
    "// Last one without readTag.\n"
    "newArray[i] = input.read$capitalized_type$();\n"
    "this.$name$ = newArray;\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateMergingCodeFromPacked(io::Printer* printer) const {
  printer->Print(
    "int length = input.readRawVarint32();\n"
    "int limit = input.pushLimit(length);\n");

  // If we know the elements will all be of the same size, the arrayLength
  // can be calculated much more easily. However, FixedSize() returns 1 for
  // repeated bool fields, which are guaranteed to have the fixed size of
  // 1 byte per value only if we control the output. On the wire they can
  // legally appear as variable-size integers, so we need to use the slow
  // way for repeated bool fields.
  if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
      || FixedSize(descriptor_->type()) == -1) {
    printer->Print(variables_,
      "// First pass to compute array length.\n"
      "int arrayLength = 0;\n"
      "int startPos = input.getPosition();\n"
      "while (input.getBytesUntilLimit() > 0) {\n"
      "  input.read$capitalized_type$();\n"
      "  arrayLength++;\n"
      "}\n"
      "input.rewindToPosition(startPos);\n");
  } else {
    printer->Print(variables_,
      "int arrayLength = length / $fixed_size$;\n");
  }

  printer->Print(variables_,
    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
    "$type$[] newArray = new $type$[i + arrayLength];\n"
    "if (i != 0) {\n"
    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
    "}\n"
    "for (; i < newArray.length; i++) {\n"
    "  newArray[i] = input.read$capitalized_type$();\n"
    "}\n"
    "this.$name$ = newArray;\n"
    "input.popLimit(limit);\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer* printer) const {
  // Creates a variable dataSize and puts the serialized size in there.
  // If the element type is a Java reference type, also generates
  // dataCount which stores the number of non-null elements in the field.
  if (IsReferenceType(GetJavaType(descriptor_))) {
    printer->Print(variables_,
      "int dataCount = 0;\n"
      "int dataSize = 0;\n"
      "for (int i = 0; i < this.$name$.length; i++) {\n"
      "  $type$ element = this.$name$[i];\n"
      "  if (element != null) {\n"
      "    dataCount++;\n"
      "    dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
      "        .compute$capitalized_type$SizeNoTag(element);\n"
      "  }\n"
      "}\n");
  } else if (FixedSize(descriptor_->type()) == -1) {
    printer->Print(variables_,
      "int dataSize = 0;\n"
      "for (int i = 0; i < this.$name$.length; i++) {\n"
      "  $type$ element = this.$name$[i];\n"
      "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
      "      .compute$capitalized_type$SizeNoTag(element);\n"
      "}\n");
  } else {
    printer->Print(variables_,
      "int dataSize = $fixed_size$ * this.$name$.length;\n");
  }
}

void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null && this.$name$.length > 0) {\n");
  printer->Indent();

  if (descriptor_->is_packable() && descriptor_->options().packed()) {
    GenerateRepeatedDataSizeCode(printer);
    printer->Print(variables_,
      "output.writeRawVarint32($tag$);\n"
      "output.writeRawVarint32(dataSize);\n"
      "for (int i = 0; i < this.$name$.length; i++) {\n"
      "  output.write$capitalized_type$NoTag(this.$name$[i]);\n"
      "}\n");
  } else if (IsReferenceType(GetJavaType(descriptor_))) {
    printer->Print(variables_,
      "for (int i = 0; i < this.$name$.length; i++) {\n"
      "  $type$ element = this.$name$[i];\n"
      "  if (element != null) {\n"
      "    output.write$capitalized_type$($number$, element);\n"
      "  }\n"
      "}\n");
  } else {
    printer->Print(variables_,
      "for (int i = 0; i < this.$name$.length; i++) {\n"
      "  output.write$capitalized_type$($number$, this.$name$[i]);\n"
      "}\n");
  }

  printer->Outdent();
  printer->Print("}\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null && this.$name$.length > 0) {\n");
  printer->Indent();

  GenerateRepeatedDataSizeCode(printer);

  printer->Print(
    "size += dataSize;\n");
  if (descriptor_->is_packable() && descriptor_->options().packed()) {
    printer->Print(variables_,
      "size += $tag_size$;\n"
      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
      "    .computeRawVarint32Size(dataSize);\n");
  } else if (IsReferenceType(GetJavaType(descriptor_))) {
    printer->Print(variables_,
      "size += $tag_size$ * dataCount;\n");
  } else {
    printer->Print(variables_,
      "size += $tag_size$ * this.$name$.length;\n");
  }

  printer->Outdent();

  printer->Print(
    "}\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
    "    this.$name$, other.$name$)) {\n"
    "  return false;\n"
    "}\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "result = 31 * result\n"
    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
}

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__

#include <map>
#include <string>
#include <google/protobuf/compiler/javanano/javanano_field.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

class PrimitiveFieldGenerator : public FieldGenerator {
 public:
  explicit PrimitiveFieldGenerator(
      const FieldDescriptor* descriptor, const Params& params);
  ~PrimitiveFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  bool SavedDefaultNeeded() const;
  void GenerateInitSavedDefaultCode(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
  void GenerateClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCodeCode(io::Printer* printer) const;

 private:
  void GenerateSerializationConditional(io::Printer* printer) const;

  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
};

class AccessorPrimitiveFieldGenerator : public FieldGenerator {
 public:
  explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
      const Params &params, int has_bit_index);
  ~AccessorPrimitiveFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  bool SavedDefaultNeeded() const;
  void GenerateInitSavedDefaultCode(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
  void GenerateClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCodeCode(io::Printer* printer) const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
};

class PrimitiveOneofFieldGenerator : public FieldGenerator {
 public:
  explicit PrimitiveOneofFieldGenerator(
      const FieldDescriptor* descriptor, const Params& params);
  ~PrimitiveOneofFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
  void GenerateClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCodeCode(io::Printer* printer) const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
};

class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
 public:
  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
                                           const Params& params);
  ~RepeatedPrimitiveFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
  void GenerateClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateMergingCodeFromPacked(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCodeCode(io::Printer* printer) const;
  void GenerateFixClonedCode(io::Printer* printer) const;

 private:
  void GenerateRepeatedDataSizeCode(io::Printer* printer) const;

  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__

#include <string>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/printer.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

// Commonly-used separator comments.  Thick is a line of '=', thin is a line
// of '-'.
extern const char kThickSeparator[];
extern const char kThinSeparator[];

// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
// "fooBarBaz" or "FooBarBaz", respectively.
string UnderscoresToCamelCase(const FieldDescriptor* field);
string UnderscoresToCamelCase(const OneofDescriptor* oneof);
string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof);

// Appends an "_" to the end of a field where the name is a reserved java
// keyword.  For example int32 public = 1 will generate int public_.
string RenameJavaKeywords(const string& input);

// Similar, but for method names.  (Typically, this merely has the effect
// of lower-casing the first letter of the name.)
string UnderscoresToCamelCase(const MethodDescriptor* method);

// Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename);

// Gets the unqualified class name for the file.  Each .proto file becomes a
// single Java class, with all its contents nested in that class.
string FileClassName(const Params& params, const FileDescriptor* file);

// Returns the file's Java package name.
string FileJavaPackage(const Params& params, const FileDescriptor* file);

// Returns whether the Java outer class is needed, i.e. whether the option
// java_multiple_files is false, or the proto file contains any file-scope
// enums/extensions.
bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file);

// Converts the given simple name of a proto entity to its fully-qualified name
// in the Java namespace, given that it is in the given file enclosed in the
// given parent message (or NULL for file-scope entities). Whether the file's
// outer class name should be included in the return value depends on factors
// inferrable from the given arguments, including is_class which indicates
// whether the entity translates to a Java class.
string ToJavaName(const Params& params, const string& name, bool is_class,
    const Descriptor* parent, const FileDescriptor* file);

// These return the fully-qualified class name corresponding to the given
// descriptor.
inline string ClassName(const Params& params, const Descriptor* descriptor) {
  return ToJavaName(params, descriptor->name(), true,
                    descriptor->containing_type(), descriptor->file());
}
string ClassName(const Params& params, const EnumDescriptor* descriptor);
inline string ClassName(const Params& params,
    const ServiceDescriptor* descriptor) {
  return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file());
}
inline string ExtensionIdentifierName(const Params& params,
    const FieldDescriptor* descriptor) {
  return ToJavaName(params, descriptor->name(), false,
                    descriptor->extension_scope(), descriptor->file());
}
string ClassName(const Params& params, const FileDescriptor* descriptor);

// Get the unqualified name that should be used for a field's field
// number constant.
string FieldConstantName(const FieldDescriptor *field);

string FieldDefaultConstantName(const FieldDescriptor *field);

// Print the field's proto-syntax definition as a comment.
void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field);

enum JavaType {
  JAVATYPE_INT,
  JAVATYPE_LONG,
  JAVATYPE_FLOAT,
  JAVATYPE_DOUBLE,
  JAVATYPE_BOOLEAN,
  JAVATYPE_STRING,
  JAVATYPE_BYTES,
  JAVATYPE_ENUM,
  JAVATYPE_MESSAGE
};

JavaType GetJavaType(FieldDescriptor::Type field_type);

inline JavaType GetJavaType(const FieldDescriptor* field) {
  return GetJavaType(field->type());
}

string PrimitiveTypeName(JavaType type);

// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT.  Returns NULL for enum and message
// types.
string BoxedPrimitiveTypeName(JavaType type);

string EmptyArrayName(const Params& params, const FieldDescriptor* field);

string DefaultValue(const Params& params, const FieldDescriptor* field);

// Methods for shared bitfields.

// Gets the name of the shared bitfield for the given field index.
string GetBitFieldName(int index);

// Gets the name of the shared bitfield for the given bit index.
// Effectively, GetBitFieldName(bit_index / 32)
string GetBitFieldNameForBit(int bit_index);

// Generates the java code for the expression that returns whether the bit at
// the given bit index is set.
// Example: "((bitField1_ & 0x04000000) != 0)"
string GenerateGetBit(int bit_index);

// Generates the java code for the expression that sets the bit at the given
// bit index.
// Example: "bitField1_ |= 0x04000000"
string GenerateSetBit(int bit_index);

// Generates the java code for the expression that clears the bit at the given
// bit index.
// Example: "bitField1_ = (bitField1_ & ~0x04000000)"
string GenerateClearBit(int bit_index);

// Generates the java code for the expression that returns whether the bit at
// the given bit index contains different values in the current object and
// another object accessible via the variable 'other'.
// Example: "((bitField1_ & 0x04000000) != (other.bitField1_ & 0x04000000))"
string GenerateDifferentBit(int bit_index);

// Sets the 'get_*', 'set_*', 'clear_*' and 'different_*' variables, where * is
// the given name of the bit, to the appropriate Java expressions for the given
// bit index.
void SetBitOperationVariables(const string name,
    int bitIndex, std::map<string, string>* variables);

inline bool IsMapEntry(const Descriptor* descriptor) {
  // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
  return descriptor->options().map_entry() &&
      descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
}

bool HasMapField(const Descriptor* descriptor);

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__