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 <algorithm>
36 #include <google/protobuf/stubs/hash.h>
37 #include <limits>
38 #include <vector>
39
40 #include <google/protobuf/compiler/java/java_helpers.h>
41 #include <google/protobuf/compiler/java/java_name_resolver.h>
42 #include <google/protobuf/descriptor.pb.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 java {
51
52 using internal::WireFormat;
53 using internal::WireFormatLite;
54
55 const char kThickSeparator[] =
56 "// ===================================================================\n";
57 const char kThinSeparator[] =
58 "// -------------------------------------------------------------------\n";
59
60 namespace {
61
62 const char* kDefaultPackage = "";
63
64 // Names that should be avoided as field names.
65 // Using them will cause the compiler to generate accessors whose names are
66 // colliding with methods defined in base classes.
67 const char* kForbiddenWordList[] = {
68 // message base class:
69 "cached_size", "serialized_size",
70 // java.lang.Object:
71 "class",
72 };
73
IsForbidden(const string & field_name)74 bool IsForbidden(const string& field_name) {
75 for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
76 if (field_name == kForbiddenWordList[i]) {
77 return true;
78 }
79 }
80 return false;
81 }
82
FieldName(const FieldDescriptor * field)83 string FieldName(const FieldDescriptor* field) {
84 string field_name;
85 // Groups are hacky: The name of the field is just the lower-cased name
86 // of the group type. In Java, though, we would like to retain the original
87 // capitalization of the type name.
88 if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
89 field_name = field->message_type()->name();
90 } else {
91 field_name = field->name();
92 }
93 if (IsForbidden(field_name)) {
94 // Append a trailing "#" to indicate that the name should be decorated to
95 // avoid collision with other names.
96 field_name += "#";
97 }
98 return field_name;
99 }
100
101
102 } // namespace
103
PrintGeneratedAnnotation(io::Printer * printer,char delimiter,const string & annotation_file)104 void PrintGeneratedAnnotation(io::Printer* printer, char delimiter,
105 const string& annotation_file) {
106 if (annotation_file.empty()) {
107 return;
108 }
109 string ptemplate =
110 "@javax.annotation.Generated(value=\"protoc\", comments=\"annotations:";
111 ptemplate.push_back(delimiter);
112 ptemplate.append("annotation_file");
113 ptemplate.push_back(delimiter);
114 ptemplate.append("\")\n");
115 printer->Print(ptemplate.c_str(), "annotation_file", annotation_file);
116 }
117
UnderscoresToCamelCase(const string & input,bool cap_next_letter)118 string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
119 string result;
120 // Note: I distrust ctype.h due to locales.
121 for (int i = 0; i < input.size(); i++) {
122 if ('a' <= input[i] && input[i] <= 'z') {
123 if (cap_next_letter) {
124 result += input[i] + ('A' - 'a');
125 } else {
126 result += input[i];
127 }
128 cap_next_letter = false;
129 } else if ('A' <= input[i] && input[i] <= 'Z') {
130 if (i == 0 && !cap_next_letter) {
131 // Force first letter to lower-case unless explicitly told to
132 // capitalize it.
133 result += input[i] + ('a' - 'A');
134 } else {
135 // Capital letters after the first are left as-is.
136 result += input[i];
137 }
138 cap_next_letter = false;
139 } else if ('0' <= input[i] && input[i] <= '9') {
140 result += input[i];
141 cap_next_letter = true;
142 } else {
143 cap_next_letter = true;
144 }
145 }
146 // Add a trailing "_" if the name should be altered.
147 if (input[input.size() - 1] == '#') {
148 result += '_';
149 }
150 return result;
151 }
152
UnderscoresToCamelCase(const FieldDescriptor * field)153 string UnderscoresToCamelCase(const FieldDescriptor* field) {
154 return UnderscoresToCamelCase(FieldName(field), false);
155 }
156
UnderscoresToCapitalizedCamelCase(const FieldDescriptor * field)157 string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
158 return UnderscoresToCamelCase(FieldName(field), true);
159 }
160
UnderscoresToCamelCase(const MethodDescriptor * method)161 string UnderscoresToCamelCase(const MethodDescriptor* method) {
162 return UnderscoresToCamelCase(method->name(), false);
163 }
164
UniqueFileScopeIdentifier(const Descriptor * descriptor)165 string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
166 return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
167 }
168
StripProto(const string & filename)169 string StripProto(const string& filename) {
170 if (HasSuffixString(filename, ".protodevel")) {
171 return StripSuffixString(filename, ".protodevel");
172 } else {
173 return StripSuffixString(filename, ".proto");
174 }
175 }
176
FileClassName(const FileDescriptor * file,bool immutable)177 string FileClassName(const FileDescriptor* file, bool immutable) {
178 ClassNameResolver name_resolver;
179 return name_resolver.GetFileClassName(file, immutable);
180 }
181
FileJavaPackage(const FileDescriptor * file,bool immutable)182 string FileJavaPackage(const FileDescriptor* file, bool immutable) {
183 string result;
184
185 if (file->options().has_java_package()) {
186 result = file->options().java_package();
187 } else {
188 result = kDefaultPackage;
189 if (!file->package().empty()) {
190 if (!result.empty()) result += '.';
191 result += file->package();
192 }
193 }
194
195 return result;
196 }
197
JavaPackageToDir(string package_name)198 string JavaPackageToDir(string package_name) {
199 string package_dir =
200 StringReplace(package_name, ".", "/", true);
201 if (!package_dir.empty()) package_dir += "/";
202 return package_dir;
203 }
204
205 // TODO(xiaofeng): This function is only kept for it's publicly referenced.
206 // It should be removed after mutable API up-integration.
ToJavaName(const string & full_name,const FileDescriptor * file)207 string ToJavaName(const string& full_name,
208 const FileDescriptor* file) {
209 string result;
210 if (file->options().java_multiple_files()) {
211 result = FileJavaPackage(file);
212 } else {
213 result = ClassName(file);
214 }
215 if (!result.empty()) {
216 result += '.';
217 }
218 if (file->package().empty()) {
219 result += full_name;
220 } else {
221 // Strip the proto package from full_name since we've replaced it with
222 // the Java package.
223 result += full_name.substr(file->package().size() + 1);
224 }
225 return result;
226 }
227
ClassName(const Descriptor * descriptor)228 string ClassName(const Descriptor* descriptor) {
229 ClassNameResolver name_resolver;
230 return name_resolver.GetClassName(descriptor, true);
231 }
232
ClassName(const EnumDescriptor * descriptor)233 string ClassName(const EnumDescriptor* descriptor) {
234 ClassNameResolver name_resolver;
235 return name_resolver.GetClassName(descriptor, true);
236 }
237
ClassName(const ServiceDescriptor * descriptor)238 string ClassName(const ServiceDescriptor* descriptor) {
239 ClassNameResolver name_resolver;
240 return name_resolver.GetClassName(descriptor, true);
241 }
242
ClassName(const FileDescriptor * descriptor)243 string ClassName(const FileDescriptor* descriptor) {
244 ClassNameResolver name_resolver;
245 return name_resolver.GetClassName(descriptor, true);
246 }
247
ExtraMessageInterfaces(const Descriptor * descriptor)248 string ExtraMessageInterfaces(const Descriptor* descriptor) {
249 string interfaces = "// @@protoc_insertion_point(message_implements:"
250 + descriptor->full_name() + ")";
251 return interfaces;
252 }
253
254
ExtraBuilderInterfaces(const Descriptor * descriptor)255 string ExtraBuilderInterfaces(const Descriptor* descriptor) {
256 string interfaces = "// @@protoc_insertion_point(builder_implements:"
257 + descriptor->full_name() + ")";
258 return interfaces;
259 }
260
ExtraMessageOrBuilderInterfaces(const Descriptor * descriptor)261 string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
262 string interfaces = "// @@protoc_insertion_point(interface_extends:"
263 + descriptor->full_name() + ")";
264 return interfaces;
265 }
266
FieldConstantName(const FieldDescriptor * field)267 string FieldConstantName(const FieldDescriptor *field) {
268 string name = field->name() + "_FIELD_NUMBER";
269 UpperString(&name);
270 return name;
271 }
272
GetType(const FieldDescriptor * field)273 FieldDescriptor::Type GetType(const FieldDescriptor* field) {
274 return field->type();
275 }
276
GetJavaType(const FieldDescriptor * field)277 JavaType GetJavaType(const FieldDescriptor* field) {
278 switch (GetType(field)) {
279 case FieldDescriptor::TYPE_INT32:
280 case FieldDescriptor::TYPE_UINT32:
281 case FieldDescriptor::TYPE_SINT32:
282 case FieldDescriptor::TYPE_FIXED32:
283 case FieldDescriptor::TYPE_SFIXED32:
284 return JAVATYPE_INT;
285
286 case FieldDescriptor::TYPE_INT64:
287 case FieldDescriptor::TYPE_UINT64:
288 case FieldDescriptor::TYPE_SINT64:
289 case FieldDescriptor::TYPE_FIXED64:
290 case FieldDescriptor::TYPE_SFIXED64:
291 return JAVATYPE_LONG;
292
293 case FieldDescriptor::TYPE_FLOAT:
294 return JAVATYPE_FLOAT;
295
296 case FieldDescriptor::TYPE_DOUBLE:
297 return JAVATYPE_DOUBLE;
298
299 case FieldDescriptor::TYPE_BOOL:
300 return JAVATYPE_BOOLEAN;
301
302 case FieldDescriptor::TYPE_STRING:
303 return JAVATYPE_STRING;
304
305 case FieldDescriptor::TYPE_BYTES:
306 return JAVATYPE_BYTES;
307
308 case FieldDescriptor::TYPE_ENUM:
309 return JAVATYPE_ENUM;
310
311 case FieldDescriptor::TYPE_GROUP:
312 case FieldDescriptor::TYPE_MESSAGE:
313 return JAVATYPE_MESSAGE;
314
315 // No default because we want the compiler to complain if any new
316 // types are added.
317 }
318
319 GOOGLE_LOG(FATAL) << "Can't get here.";
320 return JAVATYPE_INT;
321 }
322
PrimitiveTypeName(JavaType type)323 const char* PrimitiveTypeName(JavaType type) {
324 switch (type) {
325 case JAVATYPE_INT : return "int";
326 case JAVATYPE_LONG : return "long";
327 case JAVATYPE_FLOAT : return "float";
328 case JAVATYPE_DOUBLE : return "double";
329 case JAVATYPE_BOOLEAN: return "boolean";
330 case JAVATYPE_STRING : return "java.lang.String";
331 case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
332 case JAVATYPE_ENUM : return NULL;
333 case JAVATYPE_MESSAGE: return NULL;
334
335 // No default because we want the compiler to complain if any new
336 // JavaTypes are added.
337 }
338
339 GOOGLE_LOG(FATAL) << "Can't get here.";
340 return NULL;
341 }
342
BoxedPrimitiveTypeName(JavaType type)343 const char* BoxedPrimitiveTypeName(JavaType type) {
344 switch (type) {
345 case JAVATYPE_INT : return "java.lang.Integer";
346 case JAVATYPE_LONG : return "java.lang.Long";
347 case JAVATYPE_FLOAT : return "java.lang.Float";
348 case JAVATYPE_DOUBLE : return "java.lang.Double";
349 case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
350 case JAVATYPE_STRING : return "java.lang.String";
351 case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
352 case JAVATYPE_ENUM : return NULL;
353 case JAVATYPE_MESSAGE: return NULL;
354
355 // No default because we want the compiler to complain if any new
356 // JavaTypes are added.
357 }
358
359 GOOGLE_LOG(FATAL) << "Can't get here.";
360 return NULL;
361 }
362
FieldTypeName(FieldDescriptor::Type field_type)363 const char* FieldTypeName(FieldDescriptor::Type field_type) {
364 switch (field_type) {
365 case FieldDescriptor::TYPE_INT32 : return "INT32";
366 case FieldDescriptor::TYPE_UINT32 : return "UINT32";
367 case FieldDescriptor::TYPE_SINT32 : return "SINT32";
368 case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
369 case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
370 case FieldDescriptor::TYPE_INT64 : return "INT64";
371 case FieldDescriptor::TYPE_UINT64 : return "UINT64";
372 case FieldDescriptor::TYPE_SINT64 : return "SINT64";
373 case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
374 case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
375 case FieldDescriptor::TYPE_FLOAT : return "FLOAT";
376 case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE";
377 case FieldDescriptor::TYPE_BOOL : return "BOOL";
378 case FieldDescriptor::TYPE_STRING : return "STRING";
379 case FieldDescriptor::TYPE_BYTES : return "BYTES";
380 case FieldDescriptor::TYPE_ENUM : return "ENUM";
381 case FieldDescriptor::TYPE_GROUP : return "GROUP";
382 case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
383
384 // No default because we want the compiler to complain if any new
385 // types are added.
386 }
387
388 GOOGLE_LOG(FATAL) << "Can't get here.";
389 return NULL;
390 }
391
AllAscii(const string & text)392 bool AllAscii(const string& text) {
393 for (int i = 0; i < text.size(); i++) {
394 if ((text[i] & 0x80) != 0) {
395 return false;
396 }
397 }
398 return true;
399 }
400
DefaultValue(const FieldDescriptor * field,bool immutable,ClassNameResolver * name_resolver)401 string DefaultValue(const FieldDescriptor* field, bool immutable,
402 ClassNameResolver* name_resolver) {
403 // Switch on CppType since we need to know which default_value_* method
404 // of FieldDescriptor to call.
405 switch (field->cpp_type()) {
406 case FieldDescriptor::CPPTYPE_INT32:
407 return SimpleItoa(field->default_value_int32());
408 case FieldDescriptor::CPPTYPE_UINT32:
409 // Need to print as a signed int since Java has no unsigned.
410 return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
411 case FieldDescriptor::CPPTYPE_INT64:
412 return SimpleItoa(field->default_value_int64()) + "L";
413 case FieldDescriptor::CPPTYPE_UINT64:
414 return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
415 "L";
416 case FieldDescriptor::CPPTYPE_DOUBLE: {
417 double value = field->default_value_double();
418 if (value == numeric_limits<double>::infinity()) {
419 return "Double.POSITIVE_INFINITY";
420 } else if (value == -numeric_limits<double>::infinity()) {
421 return "Double.NEGATIVE_INFINITY";
422 } else if (value != value) {
423 return "Double.NaN";
424 } else {
425 return SimpleDtoa(value) + "D";
426 }
427 }
428 case FieldDescriptor::CPPTYPE_FLOAT: {
429 float value = field->default_value_float();
430 if (value == numeric_limits<float>::infinity()) {
431 return "Float.POSITIVE_INFINITY";
432 } else if (value == -numeric_limits<float>::infinity()) {
433 return "Float.NEGATIVE_INFINITY";
434 } else if (value != value) {
435 return "Float.NaN";
436 } else {
437 return SimpleFtoa(value) + "F";
438 }
439 }
440 case FieldDescriptor::CPPTYPE_BOOL:
441 return field->default_value_bool() ? "true" : "false";
442 case FieldDescriptor::CPPTYPE_STRING:
443 if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
444 if (field->has_default_value()) {
445 // See comments in Internal.java for gory details.
446 return strings::Substitute(
447 "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
448 CEscape(field->default_value_string()));
449 } else {
450 return "com.google.protobuf.ByteString.EMPTY";
451 }
452 } else {
453 if (AllAscii(field->default_value_string())) {
454 // All chars are ASCII. In this case CEscape() works fine.
455 return "\"" + CEscape(field->default_value_string()) + "\"";
456 } else {
457 // See comments in Internal.java for gory details.
458 return strings::Substitute(
459 "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
460 CEscape(field->default_value_string()));
461 }
462 }
463
464 case FieldDescriptor::CPPTYPE_ENUM:
465 return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
466 field->default_value_enum()->name();
467
468 case FieldDescriptor::CPPTYPE_MESSAGE:
469 return name_resolver->GetClassName(field->message_type(), immutable) +
470 ".getDefaultInstance()";
471
472 // No default because we want the compiler to complain if any new
473 // types are added.
474 }
475
476 GOOGLE_LOG(FATAL) << "Can't get here.";
477 return "";
478 }
479
IsDefaultValueJavaDefault(const FieldDescriptor * field)480 bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
481 // Switch on CppType since we need to know which default_value_* method
482 // of FieldDescriptor to call.
483 switch (field->cpp_type()) {
484 case FieldDescriptor::CPPTYPE_INT32:
485 return field->default_value_int32() == 0;
486 case FieldDescriptor::CPPTYPE_UINT32:
487 return field->default_value_uint32() == 0;
488 case FieldDescriptor::CPPTYPE_INT64:
489 return field->default_value_int64() == 0L;
490 case FieldDescriptor::CPPTYPE_UINT64:
491 return field->default_value_uint64() == 0L;
492 case FieldDescriptor::CPPTYPE_DOUBLE:
493 return field->default_value_double() == 0.0;
494 case FieldDescriptor::CPPTYPE_FLOAT:
495 return field->default_value_float() == 0.0;
496 case FieldDescriptor::CPPTYPE_BOOL:
497 return field->default_value_bool() == false;
498 case FieldDescriptor::CPPTYPE_ENUM:
499 return field->default_value_enum()->number() == 0;
500 case FieldDescriptor::CPPTYPE_STRING:
501 case FieldDescriptor::CPPTYPE_MESSAGE:
502 return false;
503
504 // No default because we want the compiler to complain if any new
505 // types are added.
506 }
507
508 GOOGLE_LOG(FATAL) << "Can't get here.";
509 return false;
510 }
511
IsByteStringWithCustomDefaultValue(const FieldDescriptor * field)512 bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) {
513 return GetJavaType(field) == JAVATYPE_BYTES &&
514 field->default_value_string() != "";
515 }
516
517 const char* bit_masks[] = {
518 "0x00000001",
519 "0x00000002",
520 "0x00000004",
521 "0x00000008",
522 "0x00000010",
523 "0x00000020",
524 "0x00000040",
525 "0x00000080",
526
527 "0x00000100",
528 "0x00000200",
529 "0x00000400",
530 "0x00000800",
531 "0x00001000",
532 "0x00002000",
533 "0x00004000",
534 "0x00008000",
535
536 "0x00010000",
537 "0x00020000",
538 "0x00040000",
539 "0x00080000",
540 "0x00100000",
541 "0x00200000",
542 "0x00400000",
543 "0x00800000",
544
545 "0x01000000",
546 "0x02000000",
547 "0x04000000",
548 "0x08000000",
549 "0x10000000",
550 "0x20000000",
551 "0x40000000",
552 "0x80000000",
553 };
554
GetBitFieldName(int index)555 string GetBitFieldName(int index) {
556 string varName = "bitField";
557 varName += SimpleItoa(index);
558 varName += "_";
559 return varName;
560 }
561
GetBitFieldNameForBit(int bitIndex)562 string GetBitFieldNameForBit(int bitIndex) {
563 return GetBitFieldName(bitIndex / 32);
564 }
565
566 namespace {
567
GenerateGetBitInternal(const string & prefix,int bitIndex)568 string GenerateGetBitInternal(const string& prefix, int bitIndex) {
569 string varName = prefix + GetBitFieldNameForBit(bitIndex);
570 int bitInVarIndex = bitIndex % 32;
571
572 string mask = bit_masks[bitInVarIndex];
573 string result = "((" + varName + " & " + mask + ") == " + mask + ")";
574 return result;
575 }
576
GenerateSetBitInternal(const string & prefix,int bitIndex)577 string GenerateSetBitInternal(const string& prefix, int bitIndex) {
578 string varName = prefix + GetBitFieldNameForBit(bitIndex);
579 int bitInVarIndex = bitIndex % 32;
580
581 string mask = bit_masks[bitInVarIndex];
582 string result = varName + " |= " + mask;
583 return result;
584 }
585
586 } // namespace
587
GenerateGetBit(int bitIndex)588 string GenerateGetBit(int bitIndex) {
589 return GenerateGetBitInternal("", bitIndex);
590 }
591
GenerateSetBit(int bitIndex)592 string GenerateSetBit(int bitIndex) {
593 return GenerateSetBitInternal("", bitIndex);
594 }
595
GenerateClearBit(int bitIndex)596 string GenerateClearBit(int bitIndex) {
597 string varName = GetBitFieldNameForBit(bitIndex);
598 int bitInVarIndex = bitIndex % 32;
599
600 string mask = bit_masks[bitInVarIndex];
601 string result = varName + " = (" + varName + " & ~" + mask + ")";
602 return result;
603 }
604
GenerateGetBitFromLocal(int bitIndex)605 string GenerateGetBitFromLocal(int bitIndex) {
606 return GenerateGetBitInternal("from_", bitIndex);
607 }
608
GenerateSetBitToLocal(int bitIndex)609 string GenerateSetBitToLocal(int bitIndex) {
610 return GenerateSetBitInternal("to_", bitIndex);
611 }
612
GenerateGetBitMutableLocal(int bitIndex)613 string GenerateGetBitMutableLocal(int bitIndex) {
614 return GenerateGetBitInternal("mutable_", bitIndex);
615 }
616
GenerateSetBitMutableLocal(int bitIndex)617 string GenerateSetBitMutableLocal(int bitIndex) {
618 return GenerateSetBitInternal("mutable_", bitIndex);
619 }
620
IsReferenceType(JavaType type)621 bool IsReferenceType(JavaType type) {
622 switch (type) {
623 case JAVATYPE_INT : return false;
624 case JAVATYPE_LONG : return false;
625 case JAVATYPE_FLOAT : return false;
626 case JAVATYPE_DOUBLE : return false;
627 case JAVATYPE_BOOLEAN: return false;
628 case JAVATYPE_STRING : return true;
629 case JAVATYPE_BYTES : return true;
630 case JAVATYPE_ENUM : return true;
631 case JAVATYPE_MESSAGE: return true;
632
633 // No default because we want the compiler to complain if any new
634 // JavaTypes are added.
635 }
636
637 GOOGLE_LOG(FATAL) << "Can't get here.";
638 return false;
639 }
640
GetCapitalizedType(const FieldDescriptor * field,bool immutable)641 const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
642 switch (GetType(field)) {
643 case FieldDescriptor::TYPE_INT32 : return "Int32";
644 case FieldDescriptor::TYPE_UINT32 : return "UInt32";
645 case FieldDescriptor::TYPE_SINT32 : return "SInt32";
646 case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
647 case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
648 case FieldDescriptor::TYPE_INT64 : return "Int64";
649 case FieldDescriptor::TYPE_UINT64 : return "UInt64";
650 case FieldDescriptor::TYPE_SINT64 : return "SInt64";
651 case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
652 case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
653 case FieldDescriptor::TYPE_FLOAT : return "Float";
654 case FieldDescriptor::TYPE_DOUBLE : return "Double";
655 case FieldDescriptor::TYPE_BOOL : return "Bool";
656 case FieldDescriptor::TYPE_STRING : return "String";
657 case FieldDescriptor::TYPE_BYTES : {
658 return "Bytes";
659 }
660 case FieldDescriptor::TYPE_ENUM : return "Enum";
661 case FieldDescriptor::TYPE_GROUP : return "Group";
662 case FieldDescriptor::TYPE_MESSAGE : return "Message";
663
664 // No default because we want the compiler to complain if any new
665 // types are added.
666 }
667
668 GOOGLE_LOG(FATAL) << "Can't get here.";
669 return NULL;
670 }
671
672 // For encodings with fixed sizes, returns that size in bytes. Otherwise
673 // returns -1.
FixedSize(FieldDescriptor::Type type)674 int FixedSize(FieldDescriptor::Type type) {
675 switch (type) {
676 case FieldDescriptor::TYPE_INT32 : return -1;
677 case FieldDescriptor::TYPE_INT64 : return -1;
678 case FieldDescriptor::TYPE_UINT32 : return -1;
679 case FieldDescriptor::TYPE_UINT64 : return -1;
680 case FieldDescriptor::TYPE_SINT32 : return -1;
681 case FieldDescriptor::TYPE_SINT64 : return -1;
682 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
683 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
684 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
685 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
686 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
687 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
688
689 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
690 case FieldDescriptor::TYPE_ENUM : return -1;
691
692 case FieldDescriptor::TYPE_STRING : return -1;
693 case FieldDescriptor::TYPE_BYTES : return -1;
694 case FieldDescriptor::TYPE_GROUP : return -1;
695 case FieldDescriptor::TYPE_MESSAGE : return -1;
696
697 // No default because we want the compiler to complain if any new
698 // types are added.
699 }
700 GOOGLE_LOG(FATAL) << "Can't get here.";
701 return -1;
702 }
703
704 // Sort the fields of the given Descriptor by number into a new[]'d array
705 // and return it. The caller should delete the returned array.
SortFieldsByNumber(const Descriptor * descriptor)706 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
707 const FieldDescriptor** fields =
708 new const FieldDescriptor*[descriptor->field_count()];
709 for (int i = 0; i < descriptor->field_count(); i++) {
710 fields[i] = descriptor->field(i);
711 }
712 std::sort(fields, fields + descriptor->field_count(),
713 FieldOrderingByNumber());
714 return fields;
715 }
716
717 // Returns true if the message type has any required fields. If it doesn't,
718 // we can optimize out calls to its isInitialized() method.
719 //
720 // already_seen is used to avoid checking the same type multiple times
721 // (and also to protect against recursion).
HasRequiredFields(const Descriptor * type,hash_set<const Descriptor * > * already_seen)722 bool HasRequiredFields(
723 const Descriptor* type,
724 hash_set<const Descriptor*>* already_seen) {
725 if (already_seen->count(type) > 0) {
726 // The type is already in cache. This means that either:
727 // a. The type has no required fields.
728 // b. We are in the midst of checking if the type has required fields,
729 // somewhere up the stack. In this case, we know that if the type
730 // has any required fields, they'll be found when we return to it,
731 // and the whole call to HasRequiredFields() will return true.
732 // Therefore, we don't have to check if this type has required fields
733 // here.
734 return false;
735 }
736 already_seen->insert(type);
737
738 // If the type has extensions, an extension with message type could contain
739 // required fields, so we have to be conservative and assume such an
740 // extension exists.
741 if (type->extension_range_count() > 0) return true;
742
743 for (int i = 0; i < type->field_count(); i++) {
744 const FieldDescriptor* field = type->field(i);
745 if (field->is_required()) {
746 return true;
747 }
748 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
749 if (HasRequiredFields(field->message_type(), already_seen)) {
750 return true;
751 }
752 }
753 }
754
755 return false;
756 }
757
HasRequiredFields(const Descriptor * type)758 bool HasRequiredFields(const Descriptor* type) {
759 hash_set<const Descriptor*> already_seen;
760 return HasRequiredFields(type, &already_seen);
761 }
762
HasRepeatedFields(const Descriptor * descriptor)763 bool HasRepeatedFields(const Descriptor* descriptor) {
764 for (int i = 0; i < descriptor->field_count(); ++i) {
765 const FieldDescriptor* field = descriptor->field(i);
766 if (field->is_repeated()) {
767 return true;
768 }
769 }
770 return false;
771 }
772
773 } // namespace java
774 } // namespace compiler
775 } // namespace protobuf
776 } // namespace google
777