1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
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/javanano/javanano_field.h>
36 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
37 #include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
38 #include <google/protobuf/compiler/javanano/javanano_enum_field.h>
39 #include <google/protobuf/compiler/javanano/javanano_map_field.h>
40 #include <google/protobuf/compiler/javanano/javanano_message_field.h>
41 #include <google/protobuf/stubs/common.h>
42
43 namespace google {
44 namespace protobuf {
45 namespace compiler {
46 namespace javanano {
47
~FieldGenerator()48 FieldGenerator::~FieldGenerator() {}
49
SavedDefaultNeeded() const50 bool FieldGenerator::SavedDefaultNeeded() const {
51 // No saved default for this field by default.
52 // Subclasses whose instances may need saved defaults will override this
53 // and return the appropriate value.
54 return false;
55 }
56
GenerateInitSavedDefaultCode(io::Printer * printer) const57 void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
58 // No saved default for this field by default.
59 // Subclasses whose instances may need saved defaults will override this
60 // and generate the appropriate init code to the printer.
61 }
62
GenerateMergingCodeFromPacked(io::Printer * printer) const63 void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
64 // Reaching here indicates a bug. Cases are:
65 // - This FieldGenerator should support packing, but this method should be
66 // overridden.
67 // - This FieldGenerator doesn't support packing, and this method should
68 // never have been called.
69 GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
70 << "called on field generator that does not support packing.";
71 }
72
73 // =============================================
74
FieldGeneratorMap(const Descriptor * descriptor,const Params & params)75 FieldGeneratorMap::FieldGeneratorMap(
76 const Descriptor* descriptor, const Params ¶ms)
77 : descriptor_(descriptor),
78 field_generators_(
79 new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
80
81 int next_has_bit_index = 0;
82 bool saved_defaults_needed = false;
83 // Construct all the FieldGenerators.
84 for (int i = 0; i < descriptor->field_count(); i++) {
85 FieldGenerator* field_generator = MakeGenerator(
86 descriptor->field(i), params, &next_has_bit_index);
87 saved_defaults_needed = saved_defaults_needed
88 || field_generator->SavedDefaultNeeded();
89 field_generators_[i].reset(field_generator);
90 }
91 total_bits_ = next_has_bit_index;
92 saved_defaults_needed_ = saved_defaults_needed;
93 }
94
MakeGenerator(const FieldDescriptor * field,const Params & params,int * next_has_bit_index)95 FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
96 const Params ¶ms, int* next_has_bit_index) {
97 JavaType java_type = GetJavaType(field);
98 if (field->is_repeated()) {
99 switch (java_type) {
100 case JAVATYPE_MESSAGE:
101 if (IsMapEntry(field->message_type())) {
102 return new MapFieldGenerator(field, params);
103 } else {
104 return new RepeatedMessageFieldGenerator(field, params);
105 }
106 case JAVATYPE_ENUM:
107 return new RepeatedEnumFieldGenerator(field, params);
108 default:
109 return new RepeatedPrimitiveFieldGenerator(field, params);
110 }
111 } else if (field->containing_oneof()) {
112 switch (java_type) {
113 case JAVATYPE_MESSAGE:
114 return new MessageOneofFieldGenerator(field, params);
115 case JAVATYPE_ENUM:
116 default:
117 return new PrimitiveOneofFieldGenerator(field, params);
118 }
119 } else if (params.optional_field_accessors() && field->is_optional()
120 && java_type != JAVATYPE_MESSAGE) {
121 // We need a has-bit for each primitive/enum field because their default
122 // values could be same as explicitly set values. But we don't need it
123 // for a message field because they have no defaults and Nano uses 'null'
124 // for unset messages, which cannot be set explicitly.
125 switch (java_type) {
126 case JAVATYPE_ENUM:
127 return new AccessorEnumFieldGenerator(
128 field, params, (*next_has_bit_index)++);
129 default:
130 return new AccessorPrimitiveFieldGenerator(
131 field, params, (*next_has_bit_index)++);
132 }
133 } else {
134 switch (java_type) {
135 case JAVATYPE_MESSAGE:
136 return new MessageFieldGenerator(field, params);
137 case JAVATYPE_ENUM:
138 return new EnumFieldGenerator(field, params);
139 default:
140 return new PrimitiveFieldGenerator(field, params);
141 }
142 }
143 }
144
~FieldGeneratorMap()145 FieldGeneratorMap::~FieldGeneratorMap() {}
146
get(const FieldDescriptor * field) const147 const FieldGenerator& FieldGeneratorMap::get(
148 const FieldDescriptor* field) const {
149 GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
150 return *field_generators_[field->index()];
151 }
152
SetCommonOneofVariables(const FieldDescriptor * descriptor,map<string,string> * variables)153 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
154 map<string, string>* variables) {
155 (*variables)["oneof_name"] =
156 UnderscoresToCamelCase(descriptor->containing_oneof());
157 (*variables)["oneof_capitalized_name"] =
158 UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
159 (*variables)["oneof_index"] =
160 SimpleItoa(descriptor->containing_oneof()->index());
161 (*variables)["set_oneof_case"] =
162 "this." + (*variables)["oneof_name"] +
163 "Case_ = " + SimpleItoa(descriptor->number());
164 (*variables)["clear_oneof_case"] =
165 "this." + (*variables)["oneof_name"] + "Case_ = 0";
166 (*variables)["has_oneof_case"] =
167 "this." + (*variables)["oneof_name"] + "Case_ == " +
168 SimpleItoa(descriptor->number());
169 }
170
GenerateOneofFieldEquals(const FieldDescriptor * descriptor,const map<string,string> & variables,io::Printer * printer)171 void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
172 const map<string, string>& variables,
173 io::Printer* printer) {
174 if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
175 printer->Print(variables,
176 "if (this.has$capitalized_name$()) {\n"
177 " if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
178 " (byte[]) other.$oneof_name$_)) {\n"
179 " return false;\n"
180 " }\n"
181 "}\n");
182 } else {
183 printer->Print(variables,
184 "if (this.has$capitalized_name$()) {\n"
185 " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
186 " return false;\n"
187 " }\n"
188 "}\n");
189 }
190 }
191
GenerateOneofFieldHashCode(const FieldDescriptor * descriptor,const map<string,string> & variables,io::Printer * printer)192 void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
193 const map<string, string>& variables,
194 io::Printer* printer) {
195 if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
196 printer->Print(variables,
197 "result = 31 * result + ($has_oneof_case$\n"
198 " ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
199 } else {
200 printer->Print(variables,
201 "result = 31 * result +\n"
202 " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
203 }
204 }
205
206 } // namespace javanano
207 } // namespace compiler
208 } // namespace protobuf
209 } // namespace google
210