1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 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/java/java_field.h> 36 37#include <memory> 38#ifndef _SHARED_PTR_H 39#include <google/protobuf/stubs/shared_ptr.h> 40#endif 41 42#include <google/protobuf/stubs/logging.h> 43#include <google/protobuf/stubs/common.h> 44#include <google/protobuf/compiler/java/java_context.h> 45#include <google/protobuf/compiler/java/java_enum_field.h> 46#include <google/protobuf/compiler/java/java_enum_field_lite.h> 47#include <google/protobuf/compiler/java/java_helpers.h> 48#include <google/protobuf/compiler/java/java_lazy_message_field.h> 49#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h> 50#include <google/protobuf/compiler/java/java_map_field.h> 51#include <google/protobuf/compiler/java/java_map_field_lite.h> 52#include <google/protobuf/compiler/java/java_message_field.h> 53#include <google/protobuf/compiler/java/java_message_field_lite.h> 54#include <google/protobuf/compiler/java/java_primitive_field.h> 55#include <google/protobuf/compiler/java/java_primitive_field_lite.h> 56#include <google/protobuf/compiler/java/java_string_field.h> 57#include <google/protobuf/compiler/java/java_string_field_lite.h> 58#include <google/protobuf/io/printer.h> 59#include <google/protobuf/stubs/strutil.h> 60#include <google/protobuf/stubs/substitute.h> 61 62 63namespace google { 64namespace protobuf { 65namespace compiler { 66namespace java { 67 68namespace { 69 70ImmutableFieldGenerator* MakeImmutableGenerator( 71 const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, 72 Context* context) { 73 if (field->is_repeated()) { 74 switch (GetJavaType(field)) { 75 case JAVATYPE_MESSAGE: 76 if (IsMapEntry(field->message_type())) { 77 return new ImmutableMapFieldGenerator( 78 field, messageBitIndex, builderBitIndex, context); 79 } else { 80 if (IsLazy(field, context->EnforceLite())) { 81 return new RepeatedImmutableLazyMessageFieldGenerator( 82 field, messageBitIndex, builderBitIndex, context); 83 } else { 84 return new RepeatedImmutableMessageFieldGenerator( 85 field, messageBitIndex, builderBitIndex, context); 86 } 87 } 88 case JAVATYPE_ENUM: 89 return new RepeatedImmutableEnumFieldGenerator( 90 field, messageBitIndex, builderBitIndex, context); 91 case JAVATYPE_STRING: 92 return new RepeatedImmutableStringFieldGenerator( 93 field, messageBitIndex, builderBitIndex, context); 94 default: 95 return new RepeatedImmutablePrimitiveFieldGenerator( 96 field, messageBitIndex, builderBitIndex, context); 97 } 98 } else { 99 if (field->containing_oneof()) { 100 switch (GetJavaType(field)) { 101 case JAVATYPE_MESSAGE: 102 if (IsLazy(field, context->EnforceLite())) { 103 return new ImmutableLazyMessageOneofFieldGenerator( 104 field, messageBitIndex, builderBitIndex, context); 105 } else { 106 return new ImmutableMessageOneofFieldGenerator( 107 field, messageBitIndex, builderBitIndex, context); 108 } 109 case JAVATYPE_ENUM: 110 return new ImmutableEnumOneofFieldGenerator( 111 field, messageBitIndex, builderBitIndex, context); 112 case JAVATYPE_STRING: 113 return new ImmutableStringOneofFieldGenerator( 114 field, messageBitIndex, builderBitIndex, context); 115 default: 116 return new ImmutablePrimitiveOneofFieldGenerator( 117 field, messageBitIndex, builderBitIndex, context); 118 } 119 } else { 120 switch (GetJavaType(field)) { 121 case JAVATYPE_MESSAGE: 122 if (IsLazy(field, context->EnforceLite())) { 123 return new ImmutableLazyMessageFieldGenerator( 124 field, messageBitIndex, builderBitIndex, context); 125 } else { 126 return new ImmutableMessageFieldGenerator( 127 field, messageBitIndex, builderBitIndex, context); 128 } 129 case JAVATYPE_ENUM: 130 return new ImmutableEnumFieldGenerator( 131 field, messageBitIndex, builderBitIndex, context); 132 case JAVATYPE_STRING: 133 return new ImmutableStringFieldGenerator( 134 field, messageBitIndex, builderBitIndex, context); 135 default: 136 return new ImmutablePrimitiveFieldGenerator( 137 field, messageBitIndex, builderBitIndex, context); 138 } 139 } 140 } 141} 142 143ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator( 144 const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, 145 Context* context) { 146 if (field->is_repeated()) { 147 switch (GetJavaType(field)) { 148 case JAVATYPE_MESSAGE: 149 if (IsMapEntry(field->message_type())) { 150 return new ImmutableMapFieldLiteGenerator( 151 field, messageBitIndex, builderBitIndex, context); 152 } else { 153 if (IsLazy(field, context->EnforceLite())) { 154 return new RepeatedImmutableLazyMessageFieldLiteGenerator( 155 field, messageBitIndex, builderBitIndex, context); 156 } else { 157 return new RepeatedImmutableMessageFieldLiteGenerator( 158 field, messageBitIndex, builderBitIndex, context); 159 } 160 } 161 case JAVATYPE_ENUM: 162 return new RepeatedImmutableEnumFieldLiteGenerator( 163 field, messageBitIndex, builderBitIndex, context); 164 case JAVATYPE_STRING: 165 return new RepeatedImmutableStringFieldLiteGenerator( 166 field, messageBitIndex, builderBitIndex, context); 167 default: 168 return new RepeatedImmutablePrimitiveFieldLiteGenerator( 169 field, messageBitIndex, builderBitIndex, context); 170 } 171 } else { 172 if (field->containing_oneof()) { 173 switch (GetJavaType(field)) { 174 case JAVATYPE_MESSAGE: 175 if (IsLazy(field, context->EnforceLite())) { 176 return new ImmutableLazyMessageOneofFieldLiteGenerator( 177 field, messageBitIndex, builderBitIndex, context); 178 } else { 179 return new ImmutableMessageOneofFieldLiteGenerator( 180 field, messageBitIndex, builderBitIndex, context); 181 } 182 case JAVATYPE_ENUM: 183 return new ImmutableEnumOneofFieldLiteGenerator( 184 field, messageBitIndex, builderBitIndex, context); 185 case JAVATYPE_STRING: 186 return new ImmutableStringOneofFieldLiteGenerator( 187 field, messageBitIndex, builderBitIndex, context); 188 default: 189 return new ImmutablePrimitiveOneofFieldLiteGenerator( 190 field, messageBitIndex, builderBitIndex, context); 191 } 192 } else { 193 switch (GetJavaType(field)) { 194 case JAVATYPE_MESSAGE: 195 if (IsLazy(field, context->EnforceLite())) { 196 return new ImmutableLazyMessageFieldLiteGenerator( 197 field, messageBitIndex, builderBitIndex, context); 198 } else { 199 return new ImmutableMessageFieldLiteGenerator( 200 field, messageBitIndex, builderBitIndex, context); 201 } 202 case JAVATYPE_ENUM: 203 return new ImmutableEnumFieldLiteGenerator( 204 field, messageBitIndex, builderBitIndex, context); 205 case JAVATYPE_STRING: 206 return new ImmutableStringFieldLiteGenerator( 207 field, messageBitIndex, builderBitIndex, context); 208 default: 209 return new ImmutablePrimitiveFieldLiteGenerator( 210 field, messageBitIndex, builderBitIndex, context); 211 } 212 } 213 } 214} 215 216 217static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { 218 // Reaching here indicates a bug. Cases are: 219 // - This FieldGenerator should support packing, 220 // but this method should be overridden. 221 // - This FieldGenerator doesn't support packing, and this method 222 // should never have been called. 223 GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " 224 << "called on field generator that does not support packing."; 225} 226 227} // namespace 228 229ImmutableFieldGenerator::~ImmutableFieldGenerator() {} 230 231void ImmutableFieldGenerator:: 232GenerateParsingCodeFromPacked(io::Printer* printer) const { 233 ReportUnexpectedPackedFieldsCall(printer); 234} 235 236ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {} 237 238void ImmutableFieldLiteGenerator:: 239GenerateParsingCodeFromPacked(io::Printer* printer) const { 240 ReportUnexpectedPackedFieldsCall(printer); 241} 242 243// =================================================================== 244 245template <> 246FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap( 247 const Descriptor* descriptor, Context* context) 248 : descriptor_(descriptor), 249 field_generators_(new google::protobuf::scoped_ptr< 250 ImmutableFieldGenerator>[descriptor->field_count()]) { 251 252 // Construct all the FieldGenerators and assign them bit indices for their 253 // bit fields. 254 int messageBitIndex = 0; 255 int builderBitIndex = 0; 256 for (int i = 0; i < descriptor->field_count(); i++) { 257 ImmutableFieldGenerator* generator = MakeImmutableGenerator( 258 descriptor->field(i), messageBitIndex, builderBitIndex, context); 259 field_generators_[i].reset(generator); 260 messageBitIndex += generator->GetNumBitsForMessage(); 261 builderBitIndex += generator->GetNumBitsForBuilder(); 262 } 263} 264 265template<> 266FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {} 267 268template <> 269FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap( 270 const Descriptor* descriptor, Context* context) 271 : descriptor_(descriptor), 272 field_generators_(new google::protobuf::scoped_ptr< 273 ImmutableFieldLiteGenerator>[descriptor->field_count()]) { 274 // Construct all the FieldGenerators and assign them bit indices for their 275 // bit fields. 276 int messageBitIndex = 0; 277 int builderBitIndex = 0; 278 for (int i = 0; i < descriptor->field_count(); i++) { 279 ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator( 280 descriptor->field(i), messageBitIndex, builderBitIndex, context); 281 field_generators_[i].reset(generator); 282 messageBitIndex += generator->GetNumBitsForMessage(); 283 builderBitIndex += generator->GetNumBitsForBuilder(); 284 } 285} 286 287template<> 288FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {} 289 290 291void SetCommonFieldVariables(const FieldDescriptor* descriptor, 292 const FieldGeneratorInfo* info, 293 map<string, string>* variables) { 294 (*variables)["field_name"] = descriptor->name(); 295 (*variables)["name"] = info->name; 296 (*variables)["capitalized_name"] = info->capitalized_name; 297 (*variables)["disambiguated_reason"] = info->disambiguated_reason; 298 (*variables)["constant_name"] = FieldConstantName(descriptor); 299 (*variables)["number"] = SimpleItoa(descriptor->number()); 300} 301 302void SetCommonOneofVariables(const FieldDescriptor* descriptor, 303 const OneofGeneratorInfo* info, 304 map<string, string>* variables) { 305 (*variables)["oneof_name"] = info->name; 306 (*variables)["oneof_capitalized_name"] = info->capitalized_name; 307 (*variables)["oneof_index"] = 308 SimpleItoa(descriptor->containing_oneof()->index()); 309 (*variables)["set_oneof_case_message"] = info->name + 310 "Case_ = " + SimpleItoa(descriptor->number()); 311 (*variables)["clear_oneof_case_message"] = info->name + 312 "Case_ = 0"; 313 (*variables)["has_oneof_case_message"] = info->name + 314 "Case_ == " + SimpleItoa(descriptor->number()); 315} 316 317void PrintExtraFieldInfo(const map<string, string>& variables, 318 io::Printer* printer) { 319 const map<string, string>::const_iterator it = 320 variables.find("disambiguated_reason"); 321 if (it != variables.end() && !it->second.empty()) { 322 printer->Print( 323 variables, 324 "// An alternative name is used for field \"$field_name$\" because:\n" 325 "// $disambiguated_reason$\n"); 326 } 327} 328 329} // namespace java 330} // namespace compiler 331} // namespace protobuf 332} // namespace google 333