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