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 39 #include <google/protobuf/stubs/common.h> 40 #include <google/protobuf/compiler/java/java_context.h> 41 #include <google/protobuf/compiler/java/java_enum_field.h> 42 #include <google/protobuf/compiler/java/java_helpers.h> 43 #include <google/protobuf/compiler/java/java_lazy_message_field.h> 44 #include <google/protobuf/compiler/java/java_message_field.h> 45 #include <google/protobuf/compiler/java/java_primitive_field.h> 46 #include <google/protobuf/compiler/java/java_string_field.h> 47 #include <google/protobuf/io/printer.h> 48 #include <google/protobuf/stubs/strutil.h> 49 #include <google/protobuf/stubs/substitute.h> 50 51 namespace google { 52 namespace protobuf { 53 namespace compiler { 54 namespace java { 55 56 namespace { 57 58 ImmutableFieldGenerator* MakeImmutableGenerator( 59 const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, 60 Context* context) { 61 if (field->is_repeated()) { 62 switch (GetJavaType(field)) { 63 case JAVATYPE_MESSAGE: 64 if (IsLazy(field)) { 65 return new RepeatedImmutableLazyMessageFieldGenerator( 66 field, messageBitIndex, builderBitIndex, context); 67 } else { 68 return new RepeatedImmutableMessageFieldGenerator( 69 field, messageBitIndex, builderBitIndex, context); 70 } 71 case JAVATYPE_ENUM: 72 return new RepeatedImmutableEnumFieldGenerator( 73 field, messageBitIndex, builderBitIndex, context); 74 case JAVATYPE_STRING: 75 return new RepeatedImmutableStringFieldGenerator( 76 field, messageBitIndex, builderBitIndex, context); 77 default: 78 return new RepeatedImmutablePrimitiveFieldGenerator( 79 field, messageBitIndex, builderBitIndex, context); 80 } 81 } else { 82 if (field->containing_oneof()) { 83 switch (GetJavaType(field)) { 84 case JAVATYPE_MESSAGE: 85 if (IsLazy(field)) { 86 return new ImmutableLazyMessageOneofFieldGenerator( 87 field, messageBitIndex, builderBitIndex, context); 88 } else { 89 return new ImmutableMessageOneofFieldGenerator( 90 field, messageBitIndex, builderBitIndex, context); 91 } 92 case JAVATYPE_ENUM: 93 return new ImmutableEnumOneofFieldGenerator( 94 field, messageBitIndex, builderBitIndex, context); 95 case JAVATYPE_STRING: 96 return new ImmutableStringOneofFieldGenerator( 97 field, messageBitIndex, builderBitIndex, context); 98 default: 99 return new ImmutablePrimitiveOneofFieldGenerator( 100 field, messageBitIndex, builderBitIndex, context); 101 } 102 } else { 103 switch (GetJavaType(field)) { 104 case JAVATYPE_MESSAGE: 105 if (IsLazy(field)) { 106 return new ImmutableLazyMessageFieldGenerator( 107 field, messageBitIndex, builderBitIndex, context); 108 } else { 109 return new ImmutableMessageFieldGenerator( 110 field, messageBitIndex, builderBitIndex, context); 111 } 112 case JAVATYPE_ENUM: 113 return new ImmutableEnumFieldGenerator( 114 field, messageBitIndex, builderBitIndex, context); 115 case JAVATYPE_STRING: 116 return new ImmutableStringFieldGenerator( 117 field, messageBitIndex, builderBitIndex, context); 118 default: 119 return new ImmutablePrimitiveFieldGenerator( 120 field, messageBitIndex, builderBitIndex, context); 121 } 122 } 123 } 124 } 125 126 127 static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { 128 // Reaching here indicates a bug. Cases are: 129 // - This FieldGenerator should support packing, 130 // but this method should be overridden. 131 // - This FieldGenerator doesn't support packing, and this method 132 // should never have been called. 133 GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " 134 << "called on field generator that does not support packing."; 135 } 136 137 } // namespace 138 139 ImmutableFieldGenerator::~ImmutableFieldGenerator() {} 140 141 void ImmutableFieldGenerator:: 142 GenerateParsingCodeFromPacked(io::Printer* printer) const { 143 ReportUnexpectedPackedFieldsCall(printer); 144 } 145 146 // =================================================================== 147 148 template <> 149 FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap( 150 const Descriptor* descriptor, Context* context) 151 : descriptor_(descriptor), 152 field_generators_(new scoped_ptr< 153 ImmutableFieldGenerator>[descriptor->field_count()]) { 154 155 // Construct all the FieldGenerators and assign them bit indices for their 156 // bit fields. 157 int messageBitIndex = 0; 158 int builderBitIndex = 0; 159 for (int i = 0; i < descriptor->field_count(); i++) { 160 ImmutableFieldGenerator* generator = MakeImmutableGenerator( 161 descriptor->field(i), messageBitIndex, builderBitIndex, context); 162 field_generators_[i].reset(generator); 163 messageBitIndex += generator->GetNumBitsForMessage(); 164 builderBitIndex += generator->GetNumBitsForBuilder(); 165 } 166 } 167 168 template<> 169 FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {} 170 171 172 void SetCommonFieldVariables(const FieldDescriptor* descriptor, 173 const FieldGeneratorInfo* info, 174 map<string, string>* variables) { 175 (*variables)["field_name"] = descriptor->name(); 176 (*variables)["name"] = info->name; 177 (*variables)["capitalized_name"] = info->capitalized_name; 178 (*variables)["disambiguated_reason"] = info->disambiguated_reason; 179 (*variables)["constant_name"] = FieldConstantName(descriptor); 180 (*variables)["number"] = SimpleItoa(descriptor->number()); 181 } 182 183 void SetCommonOneofVariables(const FieldDescriptor* descriptor, 184 const OneofGeneratorInfo* info, 185 map<string, string>* variables) { 186 (*variables)["oneof_name"] = info->name; 187 (*variables)["oneof_capitalized_name"] = info->capitalized_name; 188 (*variables)["oneof_index"] = 189 SimpleItoa(descriptor->containing_oneof()->index()); 190 (*variables)["set_oneof_case_message"] = info->name + 191 "Case_ = " + SimpleItoa(descriptor->number()); 192 (*variables)["clear_oneof_case_message"] = info->name + 193 "Case_ = 0"; 194 (*variables)["has_oneof_case_message"] = info->name + 195 "Case_ == " + SimpleItoa(descriptor->number()); 196 } 197 198 void PrintExtraFieldInfo(const map<string, string>& variables, 199 io::Printer* printer) { 200 const map<string, string>::const_iterator it = 201 variables.find("disambiguated_reason"); 202 if (it != variables.end() && !it->second.empty()) { 203 printer->Print( 204 variables, 205 "// An alternative name is used for field \"$field_name$\" because:\n" 206 "// $disambiguated_reason$\n"); 207 } 208 } 209 210 } // namespace java 211 } // namespace compiler 212 } // namespace protobuf 213 } // namespace google 214