Line data Source code
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 <map>
36 : #include <math.h>
37 : #include <string>
38 :
39 : #include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
40 : #include <google/protobuf/stubs/common.h>
41 : #include <google/protobuf/compiler/javanano/javanano_helpers.h>
42 : #include <google/protobuf/io/printer.h>
43 : #include <google/protobuf/wire_format.h>
44 : #include <google/protobuf/stubs/strutil.h>
45 : #include <google/protobuf/stubs/substitute.h>
46 :
47 : namespace google {
48 : namespace protobuf {
49 : namespace compiler {
50 : namespace javanano {
51 :
52 : using internal::WireFormat;
53 : using internal::WireFormatLite;
54 :
55 : namespace {
56 :
57 0 : bool IsReferenceType(JavaType type) {
58 0 : switch (type) {
59 : case JAVATYPE_INT : return false;
60 : case JAVATYPE_LONG : return false;
61 : case JAVATYPE_FLOAT : return false;
62 : case JAVATYPE_DOUBLE : return false;
63 : case JAVATYPE_BOOLEAN: return false;
64 0 : case JAVATYPE_STRING : return true;
65 0 : case JAVATYPE_BYTES : return true;
66 : case JAVATYPE_ENUM : return false;
67 0 : case JAVATYPE_MESSAGE: return true;
68 :
69 : // No default because we want the compiler to complain if any new
70 : // JavaTypes are added.
71 : }
72 :
73 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
74 0 : return false;
75 : }
76 :
77 0 : bool IsArrayType(JavaType type) {
78 0 : switch (type) {
79 : case JAVATYPE_INT : return false;
80 : case JAVATYPE_LONG : return false;
81 : case JAVATYPE_FLOAT : return false;
82 : case JAVATYPE_DOUBLE : return false;
83 : case JAVATYPE_BOOLEAN: return false;
84 : case JAVATYPE_STRING : return false;
85 : case JAVATYPE_BYTES : return true;
86 : case JAVATYPE_ENUM : return false;
87 : case JAVATYPE_MESSAGE: return false;
88 :
89 : // No default because we want the compiler to complain if any new
90 : // JavaTypes are added.
91 : }
92 :
93 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
94 0 : return false;
95 : }
96 :
97 0 : const char* GetCapitalizedType(const FieldDescriptor* field) {
98 0 : switch (field->type()) {
99 : case FieldDescriptor::TYPE_INT32 : return "Int32" ;
100 0 : case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
101 0 : case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
102 0 : case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
103 0 : case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
104 0 : case FieldDescriptor::TYPE_INT64 : return "Int64" ;
105 0 : case FieldDescriptor::TYPE_UINT64 : return "UInt64" ;
106 0 : case FieldDescriptor::TYPE_SINT64 : return "SInt64" ;
107 0 : case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
108 0 : case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
109 0 : case FieldDescriptor::TYPE_FLOAT : return "Float" ;
110 0 : case FieldDescriptor::TYPE_DOUBLE : return "Double" ;
111 0 : case FieldDescriptor::TYPE_BOOL : return "Bool" ;
112 0 : case FieldDescriptor::TYPE_STRING : return "String" ;
113 0 : case FieldDescriptor::TYPE_BYTES : return "Bytes" ;
114 0 : case FieldDescriptor::TYPE_ENUM : return "Enum" ;
115 0 : case FieldDescriptor::TYPE_GROUP : return "Group" ;
116 0 : case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
117 :
118 : // No default because we want the compiler to complain if any new
119 : // types are added.
120 : }
121 :
122 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
123 0 : return NULL;
124 : }
125 :
126 : // For encodings with fixed sizes, returns that size in bytes. Otherwise
127 : // returns -1.
128 0 : int FixedSize(FieldDescriptor::Type type) {
129 0 : switch (type) {
130 : case FieldDescriptor::TYPE_INT32 : return -1;
131 : case FieldDescriptor::TYPE_INT64 : return -1;
132 : case FieldDescriptor::TYPE_UINT32 : return -1;
133 : case FieldDescriptor::TYPE_UINT64 : return -1;
134 : case FieldDescriptor::TYPE_SINT32 : return -1;
135 : case FieldDescriptor::TYPE_SINT64 : return -1;
136 0 : case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
137 0 : case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
138 0 : case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
139 0 : case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
140 0 : case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
141 0 : case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
142 :
143 0 : case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
144 : case FieldDescriptor::TYPE_ENUM : return -1;
145 :
146 : case FieldDescriptor::TYPE_STRING : return -1;
147 : case FieldDescriptor::TYPE_BYTES : return -1;
148 : case FieldDescriptor::TYPE_GROUP : return -1;
149 : case FieldDescriptor::TYPE_MESSAGE : return -1;
150 :
151 : // No default because we want the compiler to complain if any new
152 : // types are added.
153 : }
154 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
155 0 : return -1;
156 : }
157 :
158 : bool AllAscii(const string& text) {
159 0 : for (int i = 0; i < text.size(); i++) {
160 0 : if ((text[i] & 0x80) != 0) {
161 : return false;
162 : }
163 : }
164 : return true;
165 : }
166 :
167 :
168 0 : void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
169 : map<string, string>* variables) {
170 0 : (*variables)["name"] =
171 : RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
172 0 : (*variables)["capitalized_name"] =
173 : RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
174 0 : (*variables)["number"] = SimpleItoa(descriptor->number());
175 0 : if (params.use_reference_types_for_primitives()
176 0 : && !descriptor->is_repeated()) {
177 0 : (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
178 : } else {
179 0 : (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
180 : }
181 : // Deals with defaults. For C++-string types (string and bytes),
182 : // we might need to have the generated code do the unicode decoding
183 : // (see comments in InternalNano.java for gory details.). We would
184 : // like to do this once into a static field and re-use that from
185 : // then on.
186 0 : if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
187 0 : !descriptor->default_value_string().empty() &&
188 0 : !params.use_reference_types_for_primitives()) {
189 0 : if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
190 0 : (*variables)["default"] = DefaultValue(params, descriptor);
191 0 : (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
192 0 : (*variables)["default_constant_value"] = strings::Substitute(
193 : "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
194 0 : CEscape(descriptor->default_value_string()));
195 0 : (*variables)["default_copy_if_needed"] =
196 0 : (*variables)["default"] + ".clone()";
197 0 : } else if (AllAscii(descriptor->default_value_string())) {
198 : // All chars are ASCII. In this case directly referencing a
199 : // CEscape()'d string literal works fine.
200 0 : (*variables)["default"] =
201 0 : "\"" + CEscape(descriptor->default_value_string()) + "\"";
202 0 : (*variables)["default_copy_if_needed"] = (*variables)["default"];
203 : } else {
204 : // Strings where some chars are non-ASCII. We need to save the
205 : // default value.
206 0 : (*variables)["default"] = DefaultValue(params, descriptor);
207 0 : (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
208 0 : (*variables)["default_constant_value"] = strings::Substitute(
209 : "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
210 0 : CEscape(descriptor->default_value_string()));
211 0 : (*variables)["default_copy_if_needed"] = (*variables)["default"];
212 : }
213 : } else {
214 : // Non-string, non-bytes field. Defaults are literals.
215 0 : (*variables)["default"] = DefaultValue(params, descriptor);
216 0 : (*variables)["default_copy_if_needed"] = (*variables)["default"];
217 : }
218 0 : (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
219 0 : (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
220 0 : (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
221 0 : (*variables)["tag_size"] = SimpleItoa(
222 : WireFormat::TagSize(descriptor->number(), descriptor->type()));
223 0 : (*variables)["non_packed_tag"] = SimpleItoa(
224 : internal::WireFormatLite::MakeTag(descriptor->number(),
225 : internal::WireFormat::WireTypeForFieldType(descriptor->type())));
226 0 : int fixed_size = FixedSize(descriptor->type());
227 0 : if (fixed_size != -1) {
228 0 : (*variables)["fixed_size"] = SimpleItoa(fixed_size);
229 : }
230 0 : (*variables)["message_name"] = descriptor->containing_type()->name();
231 0 : (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
232 0 : }
233 : } // namespace
234 :
235 : // ===================================================================
236 :
237 0 : PrimitiveFieldGenerator::
238 : PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
239 0 : : FieldGenerator(params), descriptor_(descriptor) {
240 0 : SetPrimitiveVariables(descriptor, params, &variables_);
241 0 : }
242 :
243 0 : PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
244 :
245 0 : bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
246 0 : return variables_.find("default_constant") != variables_.end();
247 : }
248 :
249 0 : void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
250 0 : if (variables_.find("default_constant") != variables_.end()) {
251 : printer->Print(variables_,
252 0 : "$default_constant$ = $default_constant_value$;\n");
253 : }
254 0 : }
255 :
256 0 : void PrimitiveFieldGenerator::
257 : GenerateMembers(io::Printer* printer, bool lazy_init) const {
258 0 : if (variables_.find("default_constant") != variables_.end()) {
259 : // Those primitive types that need a saved default.
260 0 : if (lazy_init) {
261 : printer->Print(variables_,
262 0 : "private static $type$ $default_constant$;\n");
263 : } else {
264 : printer->Print(variables_,
265 : "private static final $type$ $default_constant$ =\n"
266 0 : " $default_constant_value$;\n");
267 : }
268 : }
269 :
270 : printer->Print(variables_,
271 0 : "public $type$ $name$;\n");
272 :
273 0 : if (params_.generate_has()) {
274 : printer->Print(variables_,
275 0 : "public boolean has$capitalized_name$;\n");
276 : }
277 0 : }
278 :
279 0 : void PrimitiveFieldGenerator::
280 : GenerateClearCode(io::Printer* printer) const {
281 : printer->Print(variables_,
282 0 : "$name$ = $default_copy_if_needed$;\n");
283 :
284 0 : if (params_.generate_has()) {
285 : printer->Print(variables_,
286 0 : "has$capitalized_name$ = false;\n");
287 : }
288 0 : }
289 :
290 0 : void PrimitiveFieldGenerator::
291 : GenerateMergingCode(io::Printer* printer) const {
292 : printer->Print(variables_,
293 0 : "this.$name$ = input.read$capitalized_type$();\n");
294 :
295 0 : if (params_.generate_has()) {
296 : printer->Print(variables_,
297 0 : "has$capitalized_name$ = true;\n");
298 : }
299 0 : }
300 :
301 0 : void PrimitiveFieldGenerator::
302 : GenerateSerializationConditional(io::Printer* printer) const {
303 0 : if (params_.use_reference_types_for_primitives()) {
304 : // For reference type mode, serialize based on equality
305 : // to null.
306 : printer->Print(variables_,
307 0 : "if (this.$name$ != null) {\n");
308 0 : return;
309 : }
310 0 : if (params_.generate_has()) {
311 : printer->Print(variables_,
312 0 : "if (has$capitalized_name$ || ");
313 : } else {
314 : printer->Print(variables_,
315 0 : "if (");
316 : }
317 0 : JavaType java_type = GetJavaType(descriptor_);
318 0 : if (IsArrayType(java_type)) {
319 : printer->Print(variables_,
320 0 : "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
321 0 : } else if (IsReferenceType(java_type)) {
322 : printer->Print(variables_,
323 0 : "!this.$name$.equals($default$)) {\n");
324 0 : } else if (java_type == JAVATYPE_FLOAT) {
325 : printer->Print(variables_,
326 : "java.lang.Float.floatToIntBits(this.$name$)\n"
327 0 : " != java.lang.Float.floatToIntBits($default$)) {\n");
328 0 : } else if (java_type == JAVATYPE_DOUBLE) {
329 : printer->Print(variables_,
330 : "java.lang.Double.doubleToLongBits(this.$name$)\n"
331 0 : " != java.lang.Double.doubleToLongBits($default$)) {\n");
332 : } else {
333 : printer->Print(variables_,
334 0 : "this.$name$ != $default$) {\n");
335 : }
336 : }
337 :
338 0 : void PrimitiveFieldGenerator::
339 : GenerateSerializationCode(io::Printer* printer) const {
340 0 : if (descriptor_->is_required() && !params_.generate_has()) {
341 : // Always serialize a required field if we don't have the 'has' signal.
342 : printer->Print(variables_,
343 0 : "output.write$capitalized_type$($number$, this.$name$);\n");
344 : } else {
345 0 : GenerateSerializationConditional(printer);
346 : printer->Print(variables_,
347 : " output.write$capitalized_type$($number$, this.$name$);\n"
348 0 : "}\n");
349 : }
350 0 : }
351 :
352 0 : void PrimitiveFieldGenerator::
353 : GenerateSerializedSizeCode(io::Printer* printer) const {
354 0 : if (descriptor_->is_required() && !params_.generate_has()) {
355 : printer->Print(variables_,
356 : "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
357 0 : " .compute$capitalized_type$Size($number$, this.$name$);\n");
358 : } else {
359 0 : GenerateSerializationConditional(printer);
360 : printer->Print(variables_,
361 : " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
362 : " .compute$capitalized_type$Size($number$, this.$name$);\n"
363 0 : "}\n");
364 : }
365 0 : }
366 :
367 0 : void RepeatedPrimitiveFieldGenerator::
368 : GenerateFixClonedCode(io::Printer* printer) const {
369 : printer->Print(variables_,
370 : "if (this.$name$ != null && this.$name$.length > 0) {\n"
371 : " cloned.$name$ = this.$name$.clone();\n"
372 0 : "}\n");
373 0 : }
374 :
375 0 : void PrimitiveFieldGenerator::
376 : GenerateEqualsCode(io::Printer* printer) const {
377 : // We define equality as serialized form equality. If generate_has(),
378 : // then if the field value equals the default value in both messages,
379 : // but one's 'has' field is set and the other's is not, the serialized
380 : // forms are different and we should return false.
381 0 : JavaType java_type = GetJavaType(descriptor_);
382 0 : if (java_type == JAVATYPE_BYTES) {
383 : printer->Print(variables_,
384 0 : "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
385 0 : if (params_.generate_has()) {
386 : printer->Print(variables_,
387 : "\n"
388 : " || (java.util.Arrays.equals(this.$name$, $default$)\n"
389 0 : " && this.has$capitalized_name$ != other.has$capitalized_name$)");
390 : }
391 : printer->Print(") {\n"
392 : " return false;\n"
393 0 : "}\n");
394 0 : } else if (java_type == JAVATYPE_STRING
395 0 : || params_.use_reference_types_for_primitives()) {
396 : printer->Print(variables_,
397 : "if (this.$name$ == null) {\n"
398 : " if (other.$name$ != null) {\n"
399 : " return false;\n"
400 : " }\n"
401 0 : "} else if (!this.$name$.equals(other.$name$)");
402 0 : if (params_.generate_has()) {
403 : printer->Print(variables_,
404 : "\n"
405 : " || (this.$name$.equals($default$)\n"
406 0 : " && this.has$capitalized_name$ != other.has$capitalized_name$)");
407 : }
408 : printer->Print(") {\n"
409 : " return false;\n"
410 0 : "}\n");
411 0 : } else if (java_type == JAVATYPE_FLOAT) {
412 : printer->Print(variables_,
413 : "{\n"
414 : " int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
415 0 : " if (bits != java.lang.Float.floatToIntBits(other.$name$)");
416 0 : if (params_.generate_has()) {
417 : printer->Print(variables_,
418 : "\n"
419 : " || (bits == java.lang.Float.floatToIntBits($default$)\n"
420 0 : " && this.has$capitalized_name$ != other.has$capitalized_name$)");
421 : }
422 : printer->Print(") {\n"
423 : " return false;\n"
424 : " }\n"
425 0 : "}\n");
426 0 : } else if (java_type == JAVATYPE_DOUBLE) {
427 : printer->Print(variables_,
428 : "{\n"
429 : " long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
430 0 : " if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
431 0 : if (params_.generate_has()) {
432 : printer->Print(variables_,
433 : "\n"
434 : " || (bits == java.lang.Double.doubleToLongBits($default$)\n"
435 0 : " && this.has$capitalized_name$ != other.has$capitalized_name$)");
436 : }
437 : printer->Print(") {\n"
438 : " return false;\n"
439 : " }\n"
440 0 : "}\n");
441 : } else {
442 : printer->Print(variables_,
443 0 : "if (this.$name$ != other.$name$");
444 0 : if (params_.generate_has()) {
445 : printer->Print(variables_,
446 : "\n"
447 : " || (this.$name$ == $default$\n"
448 0 : " && this.has$capitalized_name$ != other.has$capitalized_name$)");
449 : }
450 : printer->Print(") {\n"
451 : " return false;\n"
452 0 : "}\n");
453 : }
454 0 : }
455 :
456 0 : void PrimitiveFieldGenerator::
457 : GenerateHashCodeCode(io::Printer* printer) const {
458 0 : JavaType java_type = GetJavaType(descriptor_);
459 0 : if (java_type == JAVATYPE_BYTES) {
460 : printer->Print(variables_,
461 0 : "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
462 0 : } else if (java_type == JAVATYPE_STRING
463 0 : || params_.use_reference_types_for_primitives()) {
464 : printer->Print(variables_,
465 : "result = 31 * result\n"
466 0 : " + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
467 : } else {
468 0 : switch (java_type) {
469 : // For all Java primitive types below, the hash codes match the
470 : // results of BoxedType.valueOf(primitiveValue).hashCode().
471 : case JAVATYPE_INT:
472 : printer->Print(variables_,
473 0 : "result = 31 * result + this.$name$;\n");
474 0 : break;
475 : case JAVATYPE_LONG:
476 : printer->Print(variables_,
477 : "result = 31 * result\n"
478 0 : " + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
479 0 : break;
480 : case JAVATYPE_FLOAT:
481 : printer->Print(variables_,
482 : "result = 31 * result\n"
483 0 : " + java.lang.Float.floatToIntBits(this.$name$);\n");
484 0 : break;
485 : case JAVATYPE_DOUBLE:
486 : printer->Print(variables_,
487 : "{\n"
488 : " long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
489 : " result = 31 * result + (int) (v ^ (v >>> 32));\n"
490 0 : "}\n");
491 0 : break;
492 : case JAVATYPE_BOOLEAN:
493 : printer->Print(variables_,
494 0 : "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
495 0 : break;
496 : default:
497 0 : GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
498 0 : break;
499 : }
500 : }
501 0 : }
502 :
503 : // ===================================================================
504 :
505 0 : AccessorPrimitiveFieldGenerator::
506 : AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
507 : const Params& params, int has_bit_index)
508 0 : : FieldGenerator(params), descriptor_(descriptor) {
509 0 : SetPrimitiveVariables(descriptor, params, &variables_);
510 0 : SetBitOperationVariables("has", has_bit_index, &variables_);
511 0 : }
512 :
513 0 : AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
514 :
515 0 : bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
516 0 : return variables_.find("default_constant") != variables_.end();
517 : }
518 :
519 0 : void AccessorPrimitiveFieldGenerator::
520 : GenerateInitSavedDefaultCode(io::Printer* printer) const {
521 0 : if (variables_.find("default_constant") != variables_.end()) {
522 : printer->Print(variables_,
523 0 : "$default_constant$ = $default_constant_value$;\n");
524 : }
525 0 : }
526 :
527 0 : void AccessorPrimitiveFieldGenerator::
528 : GenerateMembers(io::Printer* printer, bool lazy_init) const {
529 0 : if (variables_.find("default_constant") != variables_.end()) {
530 : // Those primitive types that need a saved default.
531 0 : if (lazy_init) {
532 : printer->Print(variables_,
533 0 : "private static $type$ $default_constant$;\n");
534 : } else {
535 : printer->Print(variables_,
536 : "private static final $type$ $default_constant$ =\n"
537 0 : " $default_constant_value$;\n");
538 : }
539 : }
540 : printer->Print(variables_,
541 : "private $type$ $name$_;\n"
542 : "public $type$ get$capitalized_name$() {\n"
543 : " return $name$_;\n"
544 : "}\n"
545 0 : "public $message_name$ set$capitalized_name$($type$ value) {\n");
546 0 : if (IsReferenceType(GetJavaType(descriptor_))) {
547 : printer->Print(variables_,
548 : " if (value == null) {\n"
549 : " throw new java.lang.NullPointerException();\n"
550 0 : " }\n");
551 : }
552 : printer->Print(variables_,
553 : " $name$_ = value;\n"
554 : " $set_has$;\n"
555 : " return this;\n"
556 : "}\n"
557 : "public boolean has$capitalized_name$() {\n"
558 : " return $get_has$;\n"
559 : "}\n"
560 : "public $message_name$ clear$capitalized_name$() {\n"
561 : " $name$_ = $default_copy_if_needed$;\n"
562 : " $clear_has$;\n"
563 : " return this;\n"
564 0 : "}\n");
565 0 : }
566 :
567 0 : void AccessorPrimitiveFieldGenerator::
568 : GenerateClearCode(io::Printer* printer) const {
569 : printer->Print(variables_,
570 0 : "$name$_ = $default_copy_if_needed$;\n");
571 0 : }
572 :
573 0 : void AccessorPrimitiveFieldGenerator::
574 : GenerateMergingCode(io::Printer* printer) const {
575 : printer->Print(variables_,
576 : "$name$_ = input.read$capitalized_type$();\n"
577 0 : "$set_has$;\n");
578 0 : }
579 :
580 0 : void AccessorPrimitiveFieldGenerator::
581 : GenerateSerializationCode(io::Printer* printer) const {
582 : printer->Print(variables_,
583 : "if ($get_has$) {\n"
584 : " output.write$capitalized_type$($number$, $name$_);\n"
585 0 : "}\n");
586 0 : }
587 :
588 0 : void AccessorPrimitiveFieldGenerator::
589 : GenerateSerializedSizeCode(io::Printer* printer) const {
590 : printer->Print(variables_,
591 : "if ($get_has$) {\n"
592 : " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
593 : " .compute$capitalized_type$Size($number$, $name$_);\n"
594 0 : "}\n");
595 0 : }
596 :
597 0 : void AccessorPrimitiveFieldGenerator::
598 : GenerateEqualsCode(io::Printer* printer) const {
599 0 : switch (GetJavaType(descriptor_)) {
600 : // For all Java primitive types below, the equality checks match the
601 : // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
602 : case JAVATYPE_FLOAT:
603 : printer->Print(variables_,
604 : "if ($different_has$\n"
605 : " || java.lang.Float.floatToIntBits($name$_)\n"
606 : " != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
607 : " return false;\n"
608 0 : "}\n");
609 0 : break;
610 : case JAVATYPE_DOUBLE:
611 : printer->Print(variables_,
612 : "if ($different_has$\n"
613 : " || java.lang.Double.doubleToLongBits($name$_)\n"
614 : " != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
615 : " return false;\n"
616 0 : "}\n");
617 0 : break;
618 : case JAVATYPE_INT:
619 : case JAVATYPE_LONG:
620 : case JAVATYPE_BOOLEAN:
621 : printer->Print(variables_,
622 : "if ($different_has$\n"
623 : " || $name$_ != other.$name$_) {\n"
624 : " return false;\n"
625 0 : "}\n");
626 0 : break;
627 : case JAVATYPE_STRING:
628 : // Accessor style would guarantee $name$_ non-null
629 : printer->Print(variables_,
630 : "if ($different_has$\n"
631 : " || !$name$_.equals(other.$name$_)) {\n"
632 : " return false;\n"
633 0 : "}\n");
634 0 : break;
635 : case JAVATYPE_BYTES:
636 : // Accessor style would guarantee $name$_ non-null
637 : printer->Print(variables_,
638 : "if ($different_has$\n"
639 : " || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
640 : " return false;\n"
641 0 : "}\n");
642 0 : break;
643 : default:
644 0 : GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
645 0 : break;
646 : }
647 0 : }
648 :
649 0 : void AccessorPrimitiveFieldGenerator::
650 : GenerateHashCodeCode(io::Printer* printer) const {
651 0 : switch (GetJavaType(descriptor_)) {
652 : // For all Java primitive types below, the hash codes match the
653 : // results of BoxedType.valueOf(primitiveValue).hashCode().
654 : case JAVATYPE_INT:
655 : printer->Print(variables_,
656 0 : "result = 31 * result + $name$_;\n");
657 0 : break;
658 : case JAVATYPE_LONG:
659 : printer->Print(variables_,
660 0 : "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
661 0 : break;
662 : case JAVATYPE_FLOAT:
663 : printer->Print(variables_,
664 : "result = 31 * result +\n"
665 0 : " java.lang.Float.floatToIntBits($name$_);\n");
666 0 : break;
667 : case JAVATYPE_DOUBLE:
668 : printer->Print(variables_,
669 : "{\n"
670 : " long v = java.lang.Double.doubleToLongBits($name$_);\n"
671 : " result = 31 * result + (int) (v ^ (v >>> 32));\n"
672 0 : "}\n");
673 0 : break;
674 : case JAVATYPE_BOOLEAN:
675 : printer->Print(variables_,
676 0 : "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
677 0 : break;
678 : case JAVATYPE_STRING:
679 : // Accessor style would guarantee $name$_ non-null
680 : printer->Print(variables_,
681 0 : "result = 31 * result + $name$_.hashCode();\n");
682 0 : break;
683 : case JAVATYPE_BYTES:
684 : // Accessor style would guarantee $name$_ non-null
685 : printer->Print(variables_,
686 0 : "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
687 0 : break;
688 : default:
689 0 : GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
690 0 : break;
691 : }
692 0 : }
693 :
694 : // ===================================================================
695 :
696 0 : PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
697 : const FieldDescriptor* descriptor, const Params& params)
698 0 : : FieldGenerator(params), descriptor_(descriptor) {
699 0 : SetPrimitiveVariables(descriptor, params, &variables_);
700 0 : SetCommonOneofVariables(descriptor, &variables_);
701 0 : }
702 :
703 0 : PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
704 :
705 0 : void PrimitiveOneofFieldGenerator::GenerateMembers(
706 : io::Printer* printer, bool /*unused lazy_init*/) const {
707 : printer->Print(variables_,
708 : "public boolean has$capitalized_name$() {\n"
709 : " return $has_oneof_case$;\n"
710 : "}\n"
711 : "public $type$ get$capitalized_name$() {\n"
712 : " if ($has_oneof_case$) {\n"
713 : " return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
714 : " }\n"
715 : " return $default$;\n"
716 : "}\n"
717 : "public $message_name$ set$capitalized_name$($type$ value) {\n"
718 : " $set_oneof_case$;\n"
719 : " this.$oneof_name$_ = value;\n"
720 : " return this;\n"
721 0 : "}\n");
722 0 : }
723 :
724 0 : void PrimitiveOneofFieldGenerator::GenerateClearCode(
725 : io::Printer* printer) const {
726 : // No clear method for oneof fields.
727 0 : }
728 :
729 0 : void PrimitiveOneofFieldGenerator::GenerateMergingCode(
730 : io::Printer* printer) const {
731 : printer->Print(variables_,
732 : "this.$oneof_name$_ = input.read$capitalized_type$();\n"
733 0 : "$set_oneof_case$;\n");
734 0 : }
735 :
736 0 : void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
737 : io::Printer* printer) const {
738 : printer->Print(variables_,
739 : "if ($has_oneof_case$) {\n"
740 : " output.write$capitalized_type$(\n"
741 : " $number$, ($boxed_type$) this.$oneof_name$_);\n"
742 0 : "}\n");
743 0 : }
744 :
745 0 : void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
746 : io::Printer* printer) const {
747 : printer->Print(variables_,
748 : "if ($has_oneof_case$) {\n"
749 : " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
750 : " .compute$capitalized_type$Size(\n"
751 : " $number$, ($boxed_type$) this.$oneof_name$_);\n"
752 0 : "}\n");
753 0 : }
754 :
755 0 : void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
756 : io::Printer* printer) const {
757 0 : GenerateOneofFieldEquals(descriptor_, variables_, printer);
758 0 : }
759 :
760 0 : void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
761 : io::Printer* printer) const {
762 0 : GenerateOneofFieldHashCode(descriptor_, variables_, printer);
763 0 : }
764 :
765 : // ===================================================================
766 :
767 0 : RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
768 : const FieldDescriptor* descriptor, const Params& params)
769 0 : : FieldGenerator(params), descriptor_(descriptor) {
770 0 : SetPrimitiveVariables(descriptor, params, &variables_);
771 0 : }
772 :
773 0 : RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
774 :
775 0 : void RepeatedPrimitiveFieldGenerator::
776 : GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
777 : printer->Print(variables_,
778 0 : "public $type$[] $name$;\n");
779 0 : }
780 :
781 0 : void RepeatedPrimitiveFieldGenerator::
782 : GenerateClearCode(io::Printer* printer) const {
783 : printer->Print(variables_,
784 0 : "$name$ = $default$;\n");
785 0 : }
786 :
787 0 : void RepeatedPrimitiveFieldGenerator::
788 : GenerateMergingCode(io::Printer* printer) const {
789 : // First, figure out the length of the array, then parse.
790 : printer->Print(variables_,
791 : "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
792 : " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
793 0 : "int i = this.$name$ == null ? 0 : this.$name$.length;\n");
794 :
795 0 : if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
796 : printer->Print(variables_,
797 0 : "byte[][] newArray = new byte[i + arrayLength][];\n");
798 : } else {
799 : printer->Print(variables_,
800 0 : "$type$[] newArray = new $type$[i + arrayLength];\n");
801 : }
802 : printer->Print(variables_,
803 : "if (i != 0) {\n"
804 : " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
805 : "}\n"
806 : "for (; i < newArray.length - 1; i++) {\n"
807 : " newArray[i] = input.read$capitalized_type$();\n"
808 : " input.readTag();\n"
809 : "}\n"
810 : "// Last one without readTag.\n"
811 : "newArray[i] = input.read$capitalized_type$();\n"
812 0 : "this.$name$ = newArray;\n");
813 0 : }
814 :
815 0 : void RepeatedPrimitiveFieldGenerator::
816 : GenerateMergingCodeFromPacked(io::Printer* printer) const {
817 : printer->Print(
818 : "int length = input.readRawVarint32();\n"
819 0 : "int limit = input.pushLimit(length);\n");
820 :
821 : // If we know the elements will all be of the same size, the arrayLength
822 : // can be calculated much more easily. However, FixedSize() returns 1 for
823 : // repeated bool fields, which are guaranteed to have the fixed size of
824 : // 1 byte per value only if we control the output. On the wire they can
825 : // legally appear as variable-size integers, so we need to use the slow
826 : // way for repeated bool fields.
827 0 : if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
828 0 : || FixedSize(descriptor_->type()) == -1) {
829 : printer->Print(variables_,
830 : "// First pass to compute array length.\n"
831 : "int arrayLength = 0;\n"
832 : "int startPos = input.getPosition();\n"
833 : "while (input.getBytesUntilLimit() > 0) {\n"
834 : " input.read$capitalized_type$();\n"
835 : " arrayLength++;\n"
836 : "}\n"
837 0 : "input.rewindToPosition(startPos);\n");
838 : } else {
839 : printer->Print(variables_,
840 0 : "int arrayLength = length / $fixed_size$;\n");
841 : }
842 :
843 : printer->Print(variables_,
844 : "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
845 : "$type$[] newArray = new $type$[i + arrayLength];\n"
846 : "if (i != 0) {\n"
847 : " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
848 : "}\n"
849 : "for (; i < newArray.length; i++) {\n"
850 : " newArray[i] = input.read$capitalized_type$();\n"
851 : "}\n"
852 : "this.$name$ = newArray;\n"
853 0 : "input.popLimit(limit);\n");
854 0 : }
855 :
856 0 : void RepeatedPrimitiveFieldGenerator::
857 : GenerateRepeatedDataSizeCode(io::Printer* printer) const {
858 : // Creates a variable dataSize and puts the serialized size in there.
859 : // If the element type is a Java reference type, also generates
860 : // dataCount which stores the number of non-null elements in the field.
861 0 : if (IsReferenceType(GetJavaType(descriptor_))) {
862 : printer->Print(variables_,
863 : "int dataCount = 0;\n"
864 : "int dataSize = 0;\n"
865 : "for (int i = 0; i < this.$name$.length; i++) {\n"
866 : " $type$ element = this.$name$[i];\n"
867 : " if (element != null) {\n"
868 : " dataCount++;\n"
869 : " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
870 : " .compute$capitalized_type$SizeNoTag(element);\n"
871 : " }\n"
872 0 : "}\n");
873 0 : } else if (FixedSize(descriptor_->type()) == -1) {
874 : printer->Print(variables_,
875 : "int dataSize = 0;\n"
876 : "for (int i = 0; i < this.$name$.length; i++) {\n"
877 : " $type$ element = this.$name$[i];\n"
878 : " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
879 : " .compute$capitalized_type$SizeNoTag(element);\n"
880 0 : "}\n");
881 : } else {
882 : printer->Print(variables_,
883 0 : "int dataSize = $fixed_size$ * this.$name$.length;\n");
884 : }
885 0 : }
886 :
887 0 : void RepeatedPrimitiveFieldGenerator::
888 : GenerateSerializationCode(io::Printer* printer) const {
889 : printer->Print(variables_,
890 0 : "if (this.$name$ != null && this.$name$.length > 0) {\n");
891 0 : printer->Indent();
892 :
893 0 : if (descriptor_->is_packable() && descriptor_->options().packed()) {
894 0 : GenerateRepeatedDataSizeCode(printer);
895 : printer->Print(variables_,
896 : "output.writeRawVarint32($tag$);\n"
897 : "output.writeRawVarint32(dataSize);\n"
898 : "for (int i = 0; i < this.$name$.length; i++) {\n"
899 : " output.write$capitalized_type$NoTag(this.$name$[i]);\n"
900 0 : "}\n");
901 0 : } else if (IsReferenceType(GetJavaType(descriptor_))) {
902 : printer->Print(variables_,
903 : "for (int i = 0; i < this.$name$.length; i++) {\n"
904 : " $type$ element = this.$name$[i];\n"
905 : " if (element != null) {\n"
906 : " output.write$capitalized_type$($number$, element);\n"
907 : " }\n"
908 0 : "}\n");
909 : } else {
910 : printer->Print(variables_,
911 : "for (int i = 0; i < this.$name$.length; i++) {\n"
912 : " output.write$capitalized_type$($number$, this.$name$[i]);\n"
913 0 : "}\n");
914 : }
915 :
916 0 : printer->Outdent();
917 0 : printer->Print("}\n");
918 0 : }
919 :
920 0 : void RepeatedPrimitiveFieldGenerator::
921 : GenerateSerializedSizeCode(io::Printer* printer) const {
922 : printer->Print(variables_,
923 0 : "if (this.$name$ != null && this.$name$.length > 0) {\n");
924 0 : printer->Indent();
925 :
926 0 : GenerateRepeatedDataSizeCode(printer);
927 :
928 : printer->Print(
929 0 : "size += dataSize;\n");
930 0 : if (descriptor_->is_packable() && descriptor_->options().packed()) {
931 : printer->Print(variables_,
932 : "size += $tag_size$;\n"
933 : "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
934 0 : " .computeRawVarint32Size(dataSize);\n");
935 0 : } else if (IsReferenceType(GetJavaType(descriptor_))) {
936 : printer->Print(variables_,
937 0 : "size += $tag_size$ * dataCount;\n");
938 : } else {
939 : printer->Print(variables_,
940 0 : "size += $tag_size$ * this.$name$.length;\n");
941 : }
942 :
943 0 : printer->Outdent();
944 :
945 : printer->Print(
946 0 : "}\n");
947 0 : }
948 :
949 0 : void RepeatedPrimitiveFieldGenerator::
950 : GenerateEqualsCode(io::Printer* printer) const {
951 : printer->Print(variables_,
952 : "if (!com.google.protobuf.nano.InternalNano.equals(\n"
953 : " this.$name$, other.$name$)) {\n"
954 : " return false;\n"
955 0 : "}\n");
956 0 : }
957 :
958 0 : void RepeatedPrimitiveFieldGenerator::
959 : GenerateHashCodeCode(io::Printer* printer) const {
960 : printer->Print(variables_,
961 : "result = 31 * result\n"
962 0 : " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
963 0 : }
964 :
965 : } // namespace javanano
966 : } // namespace compiler
967 : } // namespace protobuf
968 : } // namespace google
|