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
PrimitiveTypeName(JavaType type)309 const char* PrimitiveTypeName(JavaType type) {
310 switch (type) {
311 case JAVATYPE_INT : return "int";
312 case JAVATYPE_LONG : return "long";
313 case JAVATYPE_FLOAT : return "float";
314 case JAVATYPE_DOUBLE : return "double";
315 case JAVATYPE_BOOLEAN: return "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
BoxedPrimitiveTypeName(JavaType type)329 const char* BoxedPrimitiveTypeName(JavaType type) {
330 switch (type) {
331 case JAVATYPE_INT : return "java.lang.Integer";
332 case JAVATYPE_LONG : return "java.lang.Long";
333 case JAVATYPE_FLOAT : return "java.lang.Float";
334 case JAVATYPE_DOUBLE : return "java.lang.Double";
335 case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
336 case JAVATYPE_STRING : return "java.lang.String";
337 case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
338 case JAVATYPE_ENUM : return NULL;
339 case JAVATYPE_MESSAGE: return NULL;
340
341 // No default because we want the compiler to complain if any new
342 // JavaTypes are added.
343 }
344
345 GOOGLE_LOG(FATAL) << "Can't get here.";
346 return NULL;
347 }
348
FieldTypeName(FieldDescriptor::Type field_type)349 const char* FieldTypeName(FieldDescriptor::Type field_type) {
350 switch (field_type) {
351 case FieldDescriptor::TYPE_INT32 : return "INT32";
352 case FieldDescriptor::TYPE_UINT32 : return "UINT32";
353 case FieldDescriptor::TYPE_SINT32 : return "SINT32";
354 case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
355 case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
356 case FieldDescriptor::TYPE_INT64 : return "INT64";
357 case FieldDescriptor::TYPE_UINT64 : return "UINT64";
358 case FieldDescriptor::TYPE_SINT64 : return "SINT64";
359 case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
360 case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
361 case FieldDescriptor::TYPE_FLOAT : return "FLOAT";
362 case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE";
363 case FieldDescriptor::TYPE_BOOL : return "BOOL";
364 case FieldDescriptor::TYPE_STRING : return "STRING";
365 case FieldDescriptor::TYPE_BYTES : return "BYTES";
366 case FieldDescriptor::TYPE_ENUM : return "ENUM";
367 case FieldDescriptor::TYPE_GROUP : return "GROUP";
368 case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
369
370 // No default because we want the compiler to complain if any new
371 // types are added.
372 }
373
374 GOOGLE_LOG(FATAL) << "Can't get here.";
375 return NULL;
376 }
377
AllAscii(const string & text)378 bool AllAscii(const string& text) {
379 for (int i = 0; i < text.size(); i++) {
380 if ((text[i] & 0x80) != 0) {
381 return false;
382 }
383 }
384 return true;
385 }
386
DefaultValue(const FieldDescriptor * field,bool immutable,ClassNameResolver * name_resolver)387 string DefaultValue(const FieldDescriptor* field, bool immutable,
388 ClassNameResolver* name_resolver) {
389 // Switch on CppType since we need to know which default_value_* method
390 // of FieldDescriptor to call.
391 switch (field->cpp_type()) {
392 case FieldDescriptor::CPPTYPE_INT32:
393 return SimpleItoa(field->default_value_int32());
394 case FieldDescriptor::CPPTYPE_UINT32:
395 // Need to print as a signed int since Java has no unsigned.
396 return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
397 case FieldDescriptor::CPPTYPE_INT64:
398 return SimpleItoa(field->default_value_int64()) + "L";
399 case FieldDescriptor::CPPTYPE_UINT64:
400 return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
401 "L";
402 case FieldDescriptor::CPPTYPE_DOUBLE: {
403 double value = field->default_value_double();
404 if (value == numeric_limits<double>::infinity()) {
405 return "Double.POSITIVE_INFINITY";
406 } else if (value == -numeric_limits<double>::infinity()) {
407 return "Double.NEGATIVE_INFINITY";
408 } else if (value != value) {
409 return "Double.NaN";
410 } else {
411 return SimpleDtoa(value) + "D";
412 }
413 }
414 case FieldDescriptor::CPPTYPE_FLOAT: {
415 float value = field->default_value_float();
416 if (value == numeric_limits<float>::infinity()) {
417 return "Float.POSITIVE_INFINITY";
418 } else if (value == -numeric_limits<float>::infinity()) {
419 return "Float.NEGATIVE_INFINITY";
420 } else if (value != value) {
421 return "Float.NaN";
422 } else {
423 return SimpleFtoa(value) + "F";
424 }
425 }
426 case FieldDescriptor::CPPTYPE_BOOL:
427 return field->default_value_bool() ? "true" : "false";
428 case FieldDescriptor::CPPTYPE_STRING:
429 if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
430 if (field->has_default_value()) {
431 // See comments in Internal.java for gory details.
432 return strings::Substitute(
433 "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
434 CEscape(field->default_value_string()));
435 } else {
436 return "com.google.protobuf.ByteString.EMPTY";
437 }
438 } else {
439 if (AllAscii(field->default_value_string())) {
440 // All chars are ASCII. In this case CEscape() works fine.
441 return "\"" + CEscape(field->default_value_string()) + "\"";
442 } else {
443 // See comments in Internal.java for gory details.
444 return strings::Substitute(
445 "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
446 CEscape(field->default_value_string()));
447 }
448 }
449
450 case FieldDescriptor::CPPTYPE_ENUM:
451 return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
452 field->default_value_enum()->name();
453
454 case FieldDescriptor::CPPTYPE_MESSAGE:
455 return name_resolver->GetClassName(field->message_type(), immutable) +
456 ".getDefaultInstance()";
457
458 // No default because we want the compiler to complain if any new
459 // types are added.
460 }
461
462 GOOGLE_LOG(FATAL) << "Can't get here.";
463 return "";
464 }
465
IsDefaultValueJavaDefault(const FieldDescriptor * field)466 bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
467 // Switch on CppType since we need to know which default_value_* method
468 // of FieldDescriptor to call.
469 switch (field->cpp_type()) {
470 case FieldDescriptor::CPPTYPE_INT32:
471 return field->default_value_int32() == 0;
472 case FieldDescriptor::CPPTYPE_UINT32:
473 return field->default_value_uint32() == 0;
474 case FieldDescriptor::CPPTYPE_INT64:
475 return field->default_value_int64() == 0L;
476 case FieldDescriptor::CPPTYPE_UINT64:
477 return field->default_value_uint64() == 0L;
478 case FieldDescriptor::CPPTYPE_DOUBLE:
479 return field->default_value_double() == 0.0;
480 case FieldDescriptor::CPPTYPE_FLOAT:
481 return field->default_value_float() == 0.0;
482 case FieldDescriptor::CPPTYPE_BOOL:
483 return field->default_value_bool() == false;
484
485 case FieldDescriptor::CPPTYPE_STRING:
486 case FieldDescriptor::CPPTYPE_ENUM:
487 case FieldDescriptor::CPPTYPE_MESSAGE:
488 return false;
489
490 // No default because we want the compiler to complain if any new
491 // types are added.
492 }
493
494 GOOGLE_LOG(FATAL) << "Can't get here.";
495 return false;
496 }
497
498 const char* bit_masks[] = {
499 "0x00000001",
500 "0x00000002",
501 "0x00000004",
502 "0x00000008",
503 "0x00000010",
504 "0x00000020",
505 "0x00000040",
506 "0x00000080",
507
508 "0x00000100",
509 "0x00000200",
510 "0x00000400",
511 "0x00000800",
512 "0x00001000",
513 "0x00002000",
514 "0x00004000",
515 "0x00008000",
516
517 "0x00010000",
518 "0x00020000",
519 "0x00040000",
520 "0x00080000",
521 "0x00100000",
522 "0x00200000",
523 "0x00400000",
524 "0x00800000",
525
526 "0x01000000",
527 "0x02000000",
528 "0x04000000",
529 "0x08000000",
530 "0x10000000",
531 "0x20000000",
532 "0x40000000",
533 "0x80000000",
534 };
535
GetBitFieldName(int index)536 string GetBitFieldName(int index) {
537 string varName = "bitField";
538 varName += SimpleItoa(index);
539 varName += "_";
540 return varName;
541 }
542
GetBitFieldNameForBit(int bitIndex)543 string GetBitFieldNameForBit(int bitIndex) {
544 return GetBitFieldName(bitIndex / 32);
545 }
546
547 namespace {
548
GenerateGetBitInternal(const string & prefix,int bitIndex)549 string GenerateGetBitInternal(const string& prefix, int bitIndex) {
550 string varName = prefix + GetBitFieldNameForBit(bitIndex);
551 int bitInVarIndex = bitIndex % 32;
552
553 string mask = bit_masks[bitInVarIndex];
554 string result = "((" + varName + " & " + mask + ") == " + mask + ")";
555 return result;
556 }
557
GenerateSetBitInternal(const string & prefix,int bitIndex)558 string GenerateSetBitInternal(const string& prefix, int bitIndex) {
559 string varName = prefix + GetBitFieldNameForBit(bitIndex);
560 int bitInVarIndex = bitIndex % 32;
561
562 string mask = bit_masks[bitInVarIndex];
563 string result = varName + " |= " + mask;
564 return result;
565 }
566
567 } // namespace
568
GenerateGetBit(int bitIndex)569 string GenerateGetBit(int bitIndex) {
570 return GenerateGetBitInternal("", bitIndex);
571 }
572
GenerateSetBit(int bitIndex)573 string GenerateSetBit(int bitIndex) {
574 return GenerateSetBitInternal("", bitIndex);
575 }
576
GenerateClearBit(int bitIndex)577 string GenerateClearBit(int bitIndex) {
578 string varName = GetBitFieldNameForBit(bitIndex);
579 int bitInVarIndex = bitIndex % 32;
580
581 string mask = bit_masks[bitInVarIndex];
582 string result = varName + " = (" + varName + " & ~" + mask + ")";
583 return result;
584 }
585
GenerateGetBitFromLocal(int bitIndex)586 string GenerateGetBitFromLocal(int bitIndex) {
587 return GenerateGetBitInternal("from_", bitIndex);
588 }
589
GenerateSetBitToLocal(int bitIndex)590 string GenerateSetBitToLocal(int bitIndex) {
591 return GenerateSetBitInternal("to_", bitIndex);
592 }
593
GenerateGetBitMutableLocal(int bitIndex)594 string GenerateGetBitMutableLocal(int bitIndex) {
595 return GenerateGetBitInternal("mutable_", bitIndex);
596 }
597
GenerateSetBitMutableLocal(int bitIndex)598 string GenerateSetBitMutableLocal(int bitIndex) {
599 return GenerateSetBitInternal("mutable_", bitIndex);
600 }
601
IsReferenceType(JavaType type)602 bool IsReferenceType(JavaType type) {
603 switch (type) {
604 case JAVATYPE_INT : return false;
605 case JAVATYPE_LONG : return false;
606 case JAVATYPE_FLOAT : return false;
607 case JAVATYPE_DOUBLE : return false;
608 case JAVATYPE_BOOLEAN: return false;
609 case JAVATYPE_STRING : return true;
610 case JAVATYPE_BYTES : return true;
611 case JAVATYPE_ENUM : return true;
612 case JAVATYPE_MESSAGE: return true;
613
614 // No default because we want the compiler to complain if any new
615 // JavaTypes are added.
616 }
617
618 GOOGLE_LOG(FATAL) << "Can't get here.";
619 return false;
620 }
621
GetCapitalizedType(const FieldDescriptor * field,bool immutable)622 const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
623 switch (GetType(field)) {
624 case FieldDescriptor::TYPE_INT32 : return "Int32";
625 case FieldDescriptor::TYPE_UINT32 : return "UInt32";
626 case FieldDescriptor::TYPE_SINT32 : return "SInt32";
627 case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
628 case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
629 case FieldDescriptor::TYPE_INT64 : return "Int64";
630 case FieldDescriptor::TYPE_UINT64 : return "UInt64";
631 case FieldDescriptor::TYPE_SINT64 : return "SInt64";
632 case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
633 case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
634 case FieldDescriptor::TYPE_FLOAT : return "Float";
635 case FieldDescriptor::TYPE_DOUBLE : return "Double";
636 case FieldDescriptor::TYPE_BOOL : return "Bool";
637 case FieldDescriptor::TYPE_STRING : return "String";
638 case FieldDescriptor::TYPE_BYTES : {
639 return "Bytes";
640 }
641 case FieldDescriptor::TYPE_ENUM : return "Enum";
642 case FieldDescriptor::TYPE_GROUP : return "Group";
643 case FieldDescriptor::TYPE_MESSAGE : return "Message";
644
645 // No default because we want the compiler to complain if any new
646 // types are added.
647 }
648
649 GOOGLE_LOG(FATAL) << "Can't get here.";
650 return NULL;
651 }
652
653 // For encodings with fixed sizes, returns that size in bytes. Otherwise
654 // returns -1.
FixedSize(FieldDescriptor::Type type)655 int FixedSize(FieldDescriptor::Type type) {
656 switch (type) {
657 case FieldDescriptor::TYPE_INT32 : return -1;
658 case FieldDescriptor::TYPE_INT64 : return -1;
659 case FieldDescriptor::TYPE_UINT32 : return -1;
660 case FieldDescriptor::TYPE_UINT64 : return -1;
661 case FieldDescriptor::TYPE_SINT32 : return -1;
662 case FieldDescriptor::TYPE_SINT64 : return -1;
663 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
664 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
665 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
666 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
667 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
668 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
669
670 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
671 case FieldDescriptor::TYPE_ENUM : return -1;
672
673 case FieldDescriptor::TYPE_STRING : return -1;
674 case FieldDescriptor::TYPE_BYTES : return -1;
675 case FieldDescriptor::TYPE_GROUP : return -1;
676 case FieldDescriptor::TYPE_MESSAGE : return -1;
677
678 // No default because we want the compiler to complain if any new
679 // types are added.
680 }
681 GOOGLE_LOG(FATAL) << "Can't get here.";
682 return -1;
683 }
684
685 // Sort the fields of the given Descriptor by number into a new[]'d array
686 // and return it. The caller should delete the returned array.
SortFieldsByNumber(const Descriptor * descriptor)687 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
688 const FieldDescriptor** fields =
689 new const FieldDescriptor*[descriptor->field_count()];
690 for (int i = 0; i < descriptor->field_count(); i++) {
691 fields[i] = descriptor->field(i);
692 }
693 std::sort(fields, fields + descriptor->field_count(),
694 FieldOrderingByNumber());
695 return fields;
696 }
697
698 // Returns true if the message type has any required fields. If it doesn't,
699 // we can optimize out calls to its isInitialized() method.
700 //
701 // already_seen is used to avoid checking the same type multiple times
702 // (and also to protect against recursion).
HasRequiredFields(const Descriptor * type,hash_set<const Descriptor * > * already_seen)703 bool HasRequiredFields(
704 const Descriptor* type,
705 hash_set<const Descriptor*>* already_seen) {
706 if (already_seen->count(type) > 0) {
707 // The type is already in cache. This means that either:
708 // a. The type has no required fields.
709 // b. We are in the midst of checking if the type has required fields,
710 // somewhere up the stack. In this case, we know that if the type
711 // has any required fields, they'll be found when we return to it,
712 // and the whole call to HasRequiredFields() will return true.
713 // Therefore, we don't have to check if this type has required fields
714 // here.
715 return false;
716 }
717 already_seen->insert(type);
718
719 // If the type has extensions, an extension with message type could contain
720 // required fields, so we have to be conservative and assume such an
721 // extension exists.
722 if (type->extension_range_count() > 0) return true;
723
724 for (int i = 0; i < type->field_count(); i++) {
725 const FieldDescriptor* field = type->field(i);
726 if (field->is_required()) {
727 return true;
728 }
729 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
730 if (HasRequiredFields(field->message_type(), already_seen)) {
731 return true;
732 }
733 }
734 }
735
736 return false;
737 }
738
HasRequiredFields(const Descriptor * type)739 bool HasRequiredFields(const Descriptor* type) {
740 hash_set<const Descriptor*> already_seen;
741 return HasRequiredFields(type, &already_seen);
742 }
743
HasRepeatedFields(const Descriptor * descriptor)744 bool HasRepeatedFields(const Descriptor* descriptor) {
745 for (int i = 0; i < descriptor->field_count(); ++i) {
746 const FieldDescriptor* field = descriptor->field(i);
747 if (field->is_repeated()) {
748 return true;
749 }
750 }
751 return false;
752 }
753
754 } // namespace java
755 } // namespace compiler
756 } // namespace protobuf
757 } // namespace google
758