1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <google/protobuf/compiler/javanano/javanano_field.h> 36#include <google/protobuf/compiler/javanano/javanano_helpers.h> 37#include <google/protobuf/compiler/javanano/javanano_primitive_field.h> 38#include <google/protobuf/compiler/javanano/javanano_enum_field.h> 39#include <google/protobuf/compiler/javanano/javanano_map_field.h> 40#include <google/protobuf/compiler/javanano/javanano_message_field.h> 41#include <google/protobuf/stubs/common.h> 42 43namespace google { 44namespace protobuf { 45namespace compiler { 46namespace javanano { 47 48FieldGenerator::~FieldGenerator() {} 49 50bool FieldGenerator::SavedDefaultNeeded() const { 51 // No saved default for this field by default. 52 // Subclasses whose instances may need saved defaults will override this 53 // and return the appropriate value. 54 return false; 55} 56 57void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const { 58 // No saved default for this field by default. 59 // Subclasses whose instances may need saved defaults will override this 60 // and generate the appropriate init code to the printer. 61} 62 63void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const { 64 // Reaching here indicates a bug. Cases are: 65 // - This FieldGenerator should support packing, but this method should be 66 // overridden. 67 // - This FieldGenerator doesn't support packing, and this method should 68 // never have been called. 69 GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " 70 << "called on field generator that does not support packing."; 71} 72 73// ============================================= 74 75FieldGeneratorMap::FieldGeneratorMap( 76 const Descriptor* descriptor, const Params ¶ms) 77 : descriptor_(descriptor), 78 field_generators_( 79 new scoped_ptr<FieldGenerator>[descriptor->field_count()]) { 80 81 int next_has_bit_index = 0; 82 bool saved_defaults_needed = false; 83 // Construct all the FieldGenerators. 84 for (int i = 0; i < descriptor->field_count(); i++) { 85 FieldGenerator* field_generator = MakeGenerator( 86 descriptor->field(i), params, &next_has_bit_index); 87 saved_defaults_needed = saved_defaults_needed 88 || field_generator->SavedDefaultNeeded(); 89 field_generators_[i].reset(field_generator); 90 } 91 total_bits_ = next_has_bit_index; 92 saved_defaults_needed_ = saved_defaults_needed; 93} 94 95FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, 96 const Params ¶ms, int* next_has_bit_index) { 97 JavaType java_type = GetJavaType(field); 98 if (field->is_repeated()) { 99 switch (java_type) { 100 case JAVATYPE_MESSAGE: 101 if (IsMapEntry(field->message_type())) { 102 return new MapFieldGenerator(field, params); 103 } else { 104 return new RepeatedMessageFieldGenerator(field, params); 105 } 106 case JAVATYPE_ENUM: 107 return new RepeatedEnumFieldGenerator(field, params); 108 default: 109 return new RepeatedPrimitiveFieldGenerator(field, params); 110 } 111 } else if (field->containing_oneof()) { 112 switch (java_type) { 113 case JAVATYPE_MESSAGE: 114 return new MessageOneofFieldGenerator(field, params); 115 case JAVATYPE_ENUM: 116 default: 117 return new PrimitiveOneofFieldGenerator(field, params); 118 } 119 } else if (params.optional_field_accessors() && field->is_optional() 120 && java_type != JAVATYPE_MESSAGE) { 121 // We need a has-bit for each primitive/enum field because their default 122 // values could be same as explicitly set values. But we don't need it 123 // for a message field because they have no defaults and Nano uses 'null' 124 // for unset messages, which cannot be set explicitly. 125 switch (java_type) { 126 case JAVATYPE_ENUM: 127 return new AccessorEnumFieldGenerator( 128 field, params, (*next_has_bit_index)++); 129 default: 130 return new AccessorPrimitiveFieldGenerator( 131 field, params, (*next_has_bit_index)++); 132 } 133 } else { 134 switch (java_type) { 135 case JAVATYPE_MESSAGE: 136 return new MessageFieldGenerator(field, params); 137 case JAVATYPE_ENUM: 138 return new EnumFieldGenerator(field, params); 139 default: 140 return new PrimitiveFieldGenerator(field, params); 141 } 142 } 143} 144 145FieldGeneratorMap::~FieldGeneratorMap() {} 146 147const FieldGenerator& FieldGeneratorMap::get( 148 const FieldDescriptor* field) const { 149 GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); 150 return *field_generators_[field->index()]; 151} 152 153void SetCommonOneofVariables(const FieldDescriptor* descriptor, 154 map<string, string>* variables) { 155 (*variables)["oneof_name"] = 156 UnderscoresToCamelCase(descriptor->containing_oneof()); 157 (*variables)["oneof_capitalized_name"] = 158 UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof()); 159 (*variables)["oneof_index"] = 160 SimpleItoa(descriptor->containing_oneof()->index()); 161 (*variables)["set_oneof_case"] = 162 "this." + (*variables)["oneof_name"] + 163 "Case_ = " + SimpleItoa(descriptor->number()); 164 (*variables)["clear_oneof_case"] = 165 "this." + (*variables)["oneof_name"] + "Case_ = 0"; 166 (*variables)["has_oneof_case"] = 167 "this." + (*variables)["oneof_name"] + "Case_ == " + 168 SimpleItoa(descriptor->number()); 169} 170 171void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, 172 const map<string, string>& variables, 173 io::Printer* printer) { 174 if (GetJavaType(descriptor) == JAVATYPE_BYTES) { 175 printer->Print(variables, 176 "if (this.has$capitalized_name$()) {\n" 177 " if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n" 178 " (byte[]) other.$oneof_name$_)) {\n" 179 " return false;\n" 180 " }\n" 181 "}\n"); 182 } else { 183 printer->Print(variables, 184 "if (this.has$capitalized_name$()) {\n" 185 " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" 186 " return false;\n" 187 " }\n" 188 "}\n"); 189 } 190} 191 192void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor, 193 const map<string, string>& variables, 194 io::Printer* printer) { 195 if (GetJavaType(descriptor) == JAVATYPE_BYTES) { 196 printer->Print(variables, 197 "result = 31 * result + ($has_oneof_case$\n" 198 " ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n"); 199 } else { 200 printer->Print(variables, 201 "result = 31 * result +\n" 202 " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n"); 203 } 204} 205 206} // namespace javanano 207} // namespace compiler 208} // namespace protobuf 209} // namespace google 210