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 
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 
MakeImmutableGenerator(const FieldDescriptor * field,int messageBitIndex,int builderBitIndex,Context * context)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 
ReportUnexpectedPackedFieldsCall(io::Printer * printer)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 
~ImmutableFieldGenerator()139 ImmutableFieldGenerator::~ImmutableFieldGenerator() {}
140 
141 void ImmutableFieldGenerator::
GenerateParsingCodeFromPacked(io::Printer * printer) const142 GenerateParsingCodeFromPacked(io::Printer* printer) const {
143   ReportUnexpectedPackedFieldsCall(printer);
144 }
145 
146 // ===================================================================
147 
148 template <>
FieldGeneratorMap(const Descriptor * descriptor,Context * context)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<>
~FieldGeneratorMap()169 FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {}
170 
171 
SetCommonFieldVariables(const FieldDescriptor * descriptor,const FieldGeneratorInfo * info,map<string,string> * variables)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 
SetCommonOneofVariables(const FieldDescriptor * descriptor,const OneofGeneratorInfo * info,map<string,string> * variables)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 
PrintExtraFieldInfo(const map<string,string> & variables,io::Printer * printer)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