| 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/field.h> | 
| 36 |  | 
| 37 | #include <memory> | 
| 38 |  | 
| 39 | #include <google/protobuf/stubs/logging.h> | 
| 40 | #include <google/protobuf/stubs/common.h> | 
| 41 | #include <google/protobuf/io/printer.h> | 
| 42 | #include <google/protobuf/stubs/strutil.h> | 
| 43 | #include <google/protobuf/stubs/substitute.h> | 
| 44 | #include <google/protobuf/compiler/java/context.h> | 
| 45 | #include <google/protobuf/compiler/java/enum_field.h> | 
| 46 | #include <google/protobuf/compiler/java/enum_field_lite.h> | 
| 47 | #include <google/protobuf/compiler/java/helpers.h> | 
| 48 | #include <google/protobuf/compiler/java/map_field.h> | 
| 49 | #include <google/protobuf/compiler/java/map_field_lite.h> | 
| 50 | #include <google/protobuf/compiler/java/message_field.h> | 
| 51 | #include <google/protobuf/compiler/java/message_field_lite.h> | 
| 52 | #include <google/protobuf/compiler/java/primitive_field.h> | 
| 53 | #include <google/protobuf/compiler/java/primitive_field_lite.h> | 
| 54 | #include <google/protobuf/compiler/java/string_field.h> | 
| 55 | #include <google/protobuf/compiler/java/string_field_lite.h> | 
| 56 |  | 
| 57 |  | 
| 58 | namespace google { | 
| 59 | namespace protobuf { | 
| 60 | namespace compiler { | 
| 61 | namespace java { | 
| 62 |  | 
| 63 | namespace { | 
| 64 |  | 
| 65 | ImmutableFieldGenerator* MakeImmutableGenerator(const FieldDescriptor* field, | 
| 66 |                                                 int messageBitIndex, | 
| 67 |                                                 int builderBitIndex, | 
| 68 |                                                 Context* context) { | 
| 69 |   if (field->is_repeated()) { | 
| 70 |     switch (GetJavaType(field)) { | 
| 71 |       case JAVATYPE_MESSAGE: | 
| 72 |         if (IsMapEntry(descriptor: field->message_type())) { | 
| 73 |           return new ImmutableMapFieldGenerator(field, messageBitIndex, | 
| 74 |                                                 builderBitIndex, context); | 
| 75 |         } else { | 
| 76 |           return new RepeatedImmutableMessageFieldGenerator( | 
| 77 |               field, messageBitIndex, builderBitIndex, context); | 
| 78 |         } | 
| 79 |       case JAVATYPE_ENUM: | 
| 80 |         return new RepeatedImmutableEnumFieldGenerator( | 
| 81 |             field, messageBitIndex, builderBitIndex, context); | 
| 82 |       case JAVATYPE_STRING: | 
| 83 |         return new RepeatedImmutableStringFieldGenerator( | 
| 84 |             field, messageBitIndex, builderBitIndex, context); | 
| 85 |       default: | 
| 86 |         return new RepeatedImmutablePrimitiveFieldGenerator( | 
| 87 |             field, messageBitIndex, builderBitIndex, context); | 
| 88 |     } | 
| 89 |   } else { | 
| 90 |     if (IsRealOneof(descriptor: field)) { | 
| 91 |       switch (GetJavaType(field)) { | 
| 92 |         case JAVATYPE_MESSAGE: | 
| 93 |           return new ImmutableMessageOneofFieldGenerator( | 
| 94 |               field, messageBitIndex, builderBitIndex, context); | 
| 95 |         case JAVATYPE_ENUM: | 
| 96 |           return new ImmutableEnumOneofFieldGenerator(field, messageBitIndex, | 
| 97 |                                                       builderBitIndex, context); | 
| 98 |         case JAVATYPE_STRING: | 
| 99 |           return new ImmutableStringOneofFieldGenerator( | 
| 100 |               field, messageBitIndex, builderBitIndex, context); | 
| 101 |         default: | 
| 102 |           return new ImmutablePrimitiveOneofFieldGenerator( | 
| 103 |               field, messageBitIndex, builderBitIndex, context); | 
| 104 |       } | 
| 105 |     } else { | 
| 106 |       switch (GetJavaType(field)) { | 
| 107 |         case JAVATYPE_MESSAGE: | 
| 108 |           return new ImmutableMessageFieldGenerator(field, messageBitIndex, | 
| 109 |                                                     builderBitIndex, context); | 
| 110 |         case JAVATYPE_ENUM: | 
| 111 |           return new ImmutableEnumFieldGenerator(field, messageBitIndex, | 
| 112 |                                                  builderBitIndex, context); | 
| 113 |         case JAVATYPE_STRING: | 
| 114 |           return new ImmutableStringFieldGenerator(field, messageBitIndex, | 
| 115 |                                                    builderBitIndex, context); | 
| 116 |         default: | 
| 117 |           return new ImmutablePrimitiveFieldGenerator(field, messageBitIndex, | 
| 118 |                                                       builderBitIndex, context); | 
| 119 |       } | 
| 120 |     } | 
| 121 |   } | 
| 122 | } | 
| 123 |  | 
| 124 | ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator( | 
| 125 |     const FieldDescriptor* field, int messageBitIndex, Context* context) { | 
| 126 |   if (field->is_repeated()) { | 
| 127 |     switch (GetJavaType(field)) { | 
| 128 |       case JAVATYPE_MESSAGE: | 
| 129 |         if (IsMapEntry(descriptor: field->message_type())) { | 
| 130 |           return new ImmutableMapFieldLiteGenerator(field, messageBitIndex, | 
| 131 |                                                     context); | 
| 132 |         } else { | 
| 133 |           return new RepeatedImmutableMessageFieldLiteGenerator( | 
| 134 |               field, messageBitIndex, context); | 
| 135 |         } | 
| 136 |       case JAVATYPE_ENUM: | 
| 137 |         return new RepeatedImmutableEnumFieldLiteGenerator( | 
| 138 |             field, messageBitIndex, context); | 
| 139 |       case JAVATYPE_STRING: | 
| 140 |         return new RepeatedImmutableStringFieldLiteGenerator( | 
| 141 |             field, messageBitIndex, context); | 
| 142 |       default: | 
| 143 |         return new RepeatedImmutablePrimitiveFieldLiteGenerator( | 
| 144 |             field, messageBitIndex, context); | 
| 145 |     } | 
| 146 |   } else { | 
| 147 |     if (IsRealOneof(descriptor: field)) { | 
| 148 |       switch (GetJavaType(field)) { | 
| 149 |         case JAVATYPE_MESSAGE: | 
| 150 |           return new ImmutableMessageOneofFieldLiteGenerator( | 
| 151 |               field, messageBitIndex, context); | 
| 152 |         case JAVATYPE_ENUM: | 
| 153 |           return new ImmutableEnumOneofFieldLiteGenerator( | 
| 154 |               field, messageBitIndex, context); | 
| 155 |         case JAVATYPE_STRING: | 
| 156 |           return new ImmutableStringOneofFieldLiteGenerator( | 
| 157 |               field, messageBitIndex, context); | 
| 158 |         default: | 
| 159 |           return new ImmutablePrimitiveOneofFieldLiteGenerator( | 
| 160 |               field, messageBitIndex, context); | 
| 161 |       } | 
| 162 |     } else { | 
| 163 |       switch (GetJavaType(field)) { | 
| 164 |         case JAVATYPE_MESSAGE: | 
| 165 |           return new ImmutableMessageFieldLiteGenerator(field, messageBitIndex, | 
| 166 |                                                         context); | 
| 167 |         case JAVATYPE_ENUM: | 
| 168 |           return new ImmutableEnumFieldLiteGenerator(field, messageBitIndex, | 
| 169 |                                                      context); | 
| 170 |         case JAVATYPE_STRING: | 
| 171 |           return new ImmutableStringFieldLiteGenerator(field, messageBitIndex, | 
| 172 |                                                        context); | 
| 173 |         default: | 
| 174 |           return new ImmutablePrimitiveFieldLiteGenerator( | 
| 175 |               field, messageBitIndex, context); | 
| 176 |       } | 
| 177 |     } | 
| 178 |   } | 
| 179 | } | 
| 180 |  | 
| 181 |  | 
| 182 | static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { | 
| 183 |   // Reaching here indicates a bug. Cases are: | 
| 184 |   //   - This FieldGenerator should support packing, | 
| 185 |   //     but this method should be overridden. | 
| 186 |   //   - This FieldGenerator doesn't support packing, and this method | 
| 187 |   //     should never have been called. | 
| 188 |   GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "  | 
| 189 |              << "called on field generator that does not support packing." ; | 
| 190 | } | 
| 191 |  | 
| 192 | }  // namespace | 
| 193 |  | 
| 194 | ImmutableFieldGenerator::~ImmutableFieldGenerator() {} | 
| 195 |  | 
| 196 | void ImmutableFieldGenerator::GenerateParsingCodeFromPacked( | 
| 197 |     io::Printer* printer) const { | 
| 198 |   ReportUnexpectedPackedFieldsCall(printer); | 
| 199 | } | 
| 200 |  | 
| 201 | ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {} | 
| 202 |  | 
| 203 | // =================================================================== | 
| 204 |  | 
| 205 | template <> | 
| 206 | FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap( | 
| 207 |     const Descriptor* descriptor, Context* context) | 
| 208 |     : descriptor_(descriptor), field_generators_(descriptor->field_count()) { | 
| 209 |   // Construct all the FieldGenerators and assign them bit indices for their | 
| 210 |   // bit fields. | 
| 211 |   int messageBitIndex = 0; | 
| 212 |   int builderBitIndex = 0; | 
| 213 |   for (int i = 0; i < descriptor->field_count(); i++) { | 
| 214 |     ImmutableFieldGenerator* generator = MakeImmutableGenerator( | 
| 215 |         field: descriptor->field(index: i), messageBitIndex, builderBitIndex, context); | 
| 216 |     field_generators_[i].reset(p: generator); | 
| 217 |     messageBitIndex += generator->GetNumBitsForMessage(); | 
| 218 |     builderBitIndex += generator->GetNumBitsForBuilder(); | 
| 219 |   } | 
| 220 | } | 
| 221 |  | 
| 222 | template <> | 
| 223 | FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {} | 
| 224 |  | 
| 225 | template <> | 
| 226 | FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap( | 
| 227 |     const Descriptor* descriptor, Context* context) | 
| 228 |     : descriptor_(descriptor), field_generators_(descriptor->field_count()) { | 
| 229 |   // Construct all the FieldGenerators and assign them bit indices for their | 
| 230 |   // bit fields. | 
| 231 |   int messageBitIndex = 0; | 
| 232 |   for (int i = 0; i < descriptor->field_count(); i++) { | 
| 233 |     ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator( | 
| 234 |         field: descriptor->field(index: i), messageBitIndex, context); | 
| 235 |     field_generators_[i].reset(p: generator); | 
| 236 |     messageBitIndex += generator->GetNumBitsForMessage(); | 
| 237 |   } | 
| 238 | } | 
| 239 |  | 
| 240 | template <> | 
| 241 | FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {} | 
| 242 |  | 
| 243 |  | 
| 244 | void SetCommonFieldVariables(const FieldDescriptor* descriptor, | 
| 245 |                              const FieldGeneratorInfo* info, | 
| 246 |                              std::map<std::string, std::string>* variables) { | 
| 247 |   (*variables)["field_name" ] = descriptor->name(); | 
| 248 |   (*variables)["name" ] = info->name; | 
| 249 |   (*variables)["classname" ] = descriptor->containing_type()->name(); | 
| 250 |   (*variables)["capitalized_name" ] = info->capitalized_name; | 
| 251 |   (*variables)["disambiguated_reason" ] = info->disambiguated_reason; | 
| 252 |   (*variables)["constant_name" ] = FieldConstantName(field: descriptor); | 
| 253 |   (*variables)["number" ] = StrCat(a: descriptor->number()); | 
| 254 |   (*variables)["kt_dsl_builder" ] = "_builder" ; | 
| 255 |   // These variables are placeholders to pick out the beginning and ends of | 
| 256 |   // identifiers for annotations (when doing so with existing variables would | 
| 257 |   // be ambiguous or impossible). They should never be set to anything but the | 
| 258 |   // empty string. | 
| 259 |   (*variables)["{" ] = "" ; | 
| 260 |   (*variables)["}" ] = "" ; | 
| 261 |   (*variables)["kt_name" ] = | 
| 262 |       IsForbiddenKotlin(field_name: info->name) ? info->name + "_"  : info->name; | 
| 263 |   (*variables)["kt_capitalized_name" ] = IsForbiddenKotlin(field_name: info->name) | 
| 264 |                                             ? info->capitalized_name + "_"  | 
| 265 |                                             : info->capitalized_name; | 
| 266 |   if (!descriptor->is_repeated()) { | 
| 267 |     (*variables)["annotation_field_type" ] = FieldTypeName(field_type: descriptor->type()); | 
| 268 |   } else if (GetJavaType(field: descriptor) == JAVATYPE_MESSAGE && | 
| 269 |              IsMapEntry(descriptor: descriptor->message_type())) { | 
| 270 |     (*variables)["annotation_field_type" ] = | 
| 271 |         std::string(FieldTypeName(field_type: descriptor->type())) + "MAP" ; | 
| 272 |   } else { | 
| 273 |     (*variables)["annotation_field_type" ] = | 
| 274 |         std::string(FieldTypeName(field_type: descriptor->type())) + "_LIST" ; | 
| 275 |     if (descriptor->is_packed()) { | 
| 276 |       (*variables)["annotation_field_type" ] = | 
| 277 |           (*variables)["annotation_field_type" ] + "_PACKED" ; | 
| 278 |     } | 
| 279 |   } | 
| 280 | } | 
| 281 |  | 
| 282 | void SetCommonOneofVariables(const FieldDescriptor* descriptor, | 
| 283 |                              const OneofGeneratorInfo* info, | 
| 284 |                              std::map<std::string, std::string>* variables) { | 
| 285 |   (*variables)["oneof_name" ] = info->name; | 
| 286 |   (*variables)["oneof_capitalized_name" ] = info->capitalized_name; | 
| 287 |   (*variables)["oneof_index" ] = | 
| 288 |       StrCat(a: descriptor->containing_oneof()->index()); | 
| 289 |   (*variables)["oneof_stored_type" ] = GetOneofStoredType(field: descriptor); | 
| 290 |   (*variables)["set_oneof_case_message" ] = | 
| 291 |       info->name + "Case_ = "  + StrCat(a: descriptor->number()); | 
| 292 |   (*variables)["clear_oneof_case_message" ] = info->name + "Case_ = 0" ; | 
| 293 |   (*variables)["has_oneof_case_message" ] = | 
| 294 |       info->name + "Case_ == "  + StrCat(a: descriptor->number()); | 
| 295 | } | 
| 296 |  | 
| 297 | void (const std::map<std::string, std::string>& variables, | 
| 298 |                          io::Printer* printer) { | 
| 299 |   const std::map<std::string, std::string>::const_iterator it = | 
| 300 |       variables.find(x: "disambiguated_reason" ); | 
| 301 |   if (it != variables.end() && !it->second.empty()) { | 
| 302 |     printer->Print( | 
| 303 |         variables, | 
| 304 |         text: "// An alternative name is used for field \"$field_name$\" because:\n"  | 
| 305 |         "//     $disambiguated_reason$\n" ); | 
| 306 |   } | 
| 307 | } | 
| 308 |  | 
| 309 | }  // namespace java | 
| 310 | }  // namespace compiler | 
| 311 | }  // namespace protobuf | 
| 312 | }  // namespace google | 
| 313 |  |