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