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