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 (at) 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 63 namespace google { 64 namespace protobuf { 65 namespace compiler { 66 namespace java { 67 68 namespace { 69 70 ImmutableFieldGenerator* 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 143 ImmutableFieldLiteGenerator* 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 217 static 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 229 ImmutableFieldGenerator::~ImmutableFieldGenerator() {} 230 231 void ImmutableFieldGenerator:: 232 GenerateParsingCodeFromPacked(io::Printer* printer) const { 233 ReportUnexpectedPackedFieldsCall(printer); 234 } 235 236 ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {} 237 238 void ImmutableFieldLiteGenerator:: 239 GenerateParsingCodeFromPacked(io::Printer* printer) const { 240 ReportUnexpectedPackedFieldsCall(printer); 241 } 242 243 // =================================================================== 244 245 template <> 246 FieldGeneratorMap<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 265 template<> 266 FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {} 267 268 template <> 269 FieldGeneratorMap<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 287 template<> 288 FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {} 289 290 291 void 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 302 void 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 317 void 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