blob: e24894b1b95b18a019a5429f6467113597cc11fe [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
jieluo@google.com4de8f552014-07-18 00:47:59 +000035#include <algorithm>
36#include <google/protobuf/stubs/hash.h>
kenton@google.comfccb1462009-12-18 02:11:36 +000037#include <limits>
temporal40ee5512008-07-10 02:12:20 +000038#include <vector>
39
40#include <google/protobuf/compiler/java/java_helpers.h>
jieluo@google.com4de8f552014-07-18 00:47:59 +000041#include <google/protobuf/compiler/java/java_name_resolver.h>
temporal40ee5512008-07-10 02:12:20 +000042#include <google/protobuf/descriptor.pb.h>
jieluo@google.com4de8f552014-07-18 00:47:59 +000043#include <google/protobuf/wire_format.h>
temporal40ee5512008-07-10 02:12:20 +000044#include <google/protobuf/stubs/strutil.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000045#include <google/protobuf/stubs/substitute.h>
temporal40ee5512008-07-10 02:12:20 +000046
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace java {
51
jieluo@google.com4de8f552014-07-18 00:47:59 +000052using internal::WireFormat;
53using internal::WireFormatLite;
54
temporal40ee5512008-07-10 02:12:20 +000055const char kThickSeparator[] =
56 "// ===================================================================\n";
57const char kThinSeparator[] =
58 "// -------------------------------------------------------------------\n";
59
60namespace {
61
62const char* kDefaultPackage = "";
63
jieluo@google.com4de8f552014-07-18 00:47:59 +000064// 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.
67const char* kForbiddenWordList[] = {
68 // message base class:
69 "cached_size", "serialized_size",
70 // java.lang.Object:
71 "class",
72};
73
74bool 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
83string FieldName(const FieldDescriptor* field) {
84 string field_name;
temporal40ee5512008-07-10 02:12:20 +000085 // 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.
kenton@google.comfccb1462009-12-18 02:11:36 +000088 if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
jieluo@google.com4de8f552014-07-18 00:47:59 +000089 field_name = field->message_type()->name();
temporal40ee5512008-07-10 02:12:20 +000090 } else {
jieluo@google.com4de8f552014-07-18 00:47:59 +000091 field_name = field->name();
temporal40ee5512008-07-10 02:12:20 +000092 }
jieluo@google.com4de8f552014-07-18 00:47:59 +000093 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;
temporal40ee5512008-07-10 02:12:20 +000099}
100
jieluo@google.com4de8f552014-07-18 00:47:59 +0000101
102} // namespace
103
104string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
temporal40ee5512008-07-10 02:12:20 +0000105 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 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000132 // Add a trailing "_" if the name should be altered.
133 if (input[input.size() - 1] == '#') {
134 result += '_';
135 }
temporal40ee5512008-07-10 02:12:20 +0000136 return result;
137}
138
temporal40ee5512008-07-10 02:12:20 +0000139string UnderscoresToCamelCase(const FieldDescriptor* field) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000140 return UnderscoresToCamelCase(FieldName(field), false);
temporal40ee5512008-07-10 02:12:20 +0000141}
142
143string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000144 return UnderscoresToCamelCase(FieldName(field), true);
temporal40ee5512008-07-10 02:12:20 +0000145}
146
147string UnderscoresToCamelCase(const MethodDescriptor* method) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000148 return UnderscoresToCamelCase(method->name(), false);
149}
150
151string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
152 return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
temporal40ee5512008-07-10 02:12:20 +0000153}
154
155string StripProto(const string& filename) {
156 if (HasSuffixString(filename, ".protodevel")) {
157 return StripSuffixString(filename, ".protodevel");
158 } else {
159 return StripSuffixString(filename, ".proto");
160 }
161}
162
jieluo@google.com4de8f552014-07-18 00:47:59 +0000163string FileClassName(const FileDescriptor* file, bool immutable) {
164 ClassNameResolver name_resolver;
165 return name_resolver.GetFileClassName(file, immutable);
temporal40ee5512008-07-10 02:12:20 +0000166}
167
jieluo@google.com4de8f552014-07-18 00:47:59 +0000168string FileJavaPackage(const FileDescriptor* file, bool immutable) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000169 string result;
170
temporal40ee5512008-07-10 02:12:20 +0000171 if (file->options().has_java_package()) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000172 result = file->options().java_package();
temporal40ee5512008-07-10 02:12:20 +0000173 } else {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000174 result = kDefaultPackage;
temporal40ee5512008-07-10 02:12:20 +0000175 if (!file->package().empty()) {
176 if (!result.empty()) result += '.';
177 result += file->package();
178 }
temporal40ee5512008-07-10 02:12:20 +0000179 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000180
liujisi@google.com33165fe2010-11-02 13:14:58 +0000181 return result;
182}
183
184string JavaPackageToDir(string package_name) {
185 string package_dir =
186 StringReplace(package_name, ".", "/", true);
187 if (!package_dir.empty()) package_dir += "/";
188 return package_dir;
temporal40ee5512008-07-10 02:12:20 +0000189}
190
jieluo@google.com4de8f552014-07-18 00:47:59 +0000191// TODO(xiaofeng): This function is only kept for it's publicly referenced.
192// It should be removed after mutable API up-integration.
193string ToJavaName(const string& full_name,
194 const FileDescriptor* file) {
temporal40ee5512008-07-10 02:12:20 +0000195 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
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000214string ClassName(const Descriptor* descriptor) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000215 ClassNameResolver name_resolver;
216 return name_resolver.GetClassName(descriptor, true);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000217}
218
219string ClassName(const EnumDescriptor* descriptor) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000220 ClassNameResolver name_resolver;
221 return name_resolver.GetClassName(descriptor, true);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000222}
223
224string ClassName(const ServiceDescriptor* descriptor) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000225 ClassNameResolver name_resolver;
226 return name_resolver.GetClassName(descriptor, true);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000227}
228
temporal40ee5512008-07-10 02:12:20 +0000229string ClassName(const FileDescriptor* descriptor) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000230 ClassNameResolver name_resolver;
231 return name_resolver.GetClassName(descriptor, true);
232}
233
234string ExtraMessageInterfaces(const Descriptor* descriptor) {
235 string interfaces = "// @@protoc_insertion_point(message_implements:"
236 + descriptor->full_name() + ")";
237 return interfaces;
238}
239
240
241string ExtraBuilderInterfaces(const Descriptor* descriptor) {
242 string interfaces = "// @@protoc_insertion_point(builder_implements:"
243 + descriptor->full_name() + ")";
244 return interfaces;
245}
246
247string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
248 string interfaces = "// @@protoc_insertion_point(interface_extends:"
249 + descriptor->full_name() + ")";
250 return interfaces;
temporal40ee5512008-07-10 02:12:20 +0000251}
252
kenton@google.comcfa2d8a2009-04-18 00:02:12 +0000253string FieldConstantName(const FieldDescriptor *field) {
254 string name = field->name() + "_FIELD_NUMBER";
255 UpperString(&name);
256 return name;
257}
258
kenton@google.comfccb1462009-12-18 02:11:36 +0000259FieldDescriptor::Type GetType(const FieldDescriptor* field) {
260 return field->type();
261}
262
263JavaType GetJavaType(const FieldDescriptor* field) {
264 switch (GetType(field)) {
temporal40ee5512008-07-10 02:12:20 +0000265 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
Feng Xiao6ef984a2014-11-10 17:34:54 -0800309const 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
temporal40ee5512008-07-10 02:12:20 +0000329const 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
jieluo@google.com4de8f552014-07-18 00:47:59 +0000349const 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
kenton@google.com80b1d622009-07-29 01:13:20 +0000378bool 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
jieluo@google.com4de8f552014-07-18 00:47:59 +0000387string DefaultValue(const FieldDescriptor* field, bool immutable,
388 ClassNameResolver* name_resolver) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000389 // Switch on CppType since we need to know which default_value_* method
kenton@google.com80b1d622009-07-29 01:13:20 +0000390 // 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";
kenton@google.comfccb1462009-12-18 02:11:36 +0000402 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 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000426 case FieldDescriptor::CPPTYPE_BOOL:
427 return field->default_value_bool() ? "true" : "false";
428 case FieldDescriptor::CPPTYPE_STRING:
kenton@google.comfccb1462009-12-18 02:11:36 +0000429 if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000430 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(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000445 "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
446 CEscape(field->default_value_string()));
kenton@google.com80b1d622009-07-29 01:13:20 +0000447 }
448 }
449
450 case FieldDescriptor::CPPTYPE_ENUM:
jieluo@google.com4de8f552014-07-18 00:47:59 +0000451 return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000452 field->default_value_enum()->name();
kenton@google.com80b1d622009-07-29 01:13:20 +0000453
454 case FieldDescriptor::CPPTYPE_MESSAGE:
jieluo@google.com4de8f552014-07-18 00:47:59 +0000455 return name_resolver->GetClassName(field->message_type(), immutable) +
456 ".getDefaultInstance()";
kenton@google.com80b1d622009-07-29 01:13:20 +0000457
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
liujisi@google.com33165fe2010-11-02 13:14:58 +0000466bool 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
498const 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
536string GetBitFieldName(int index) {
537 string varName = "bitField";
538 varName += SimpleItoa(index);
539 varName += "_";
540 return varName;
541}
542
543string GetBitFieldNameForBit(int bitIndex) {
544 return GetBitFieldName(bitIndex / 32);
545}
546
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000547namespace {
548
549string GenerateGetBitInternal(const string& prefix, int bitIndex) {
550 string varName = prefix + GetBitFieldNameForBit(bitIndex);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000551 int bitInVarIndex = bitIndex % 32;
552
553 string mask = bit_masks[bitInVarIndex];
554 string result = "((" + varName + " & " + mask + ") == " + mask + ")";
555 return result;
556}
557
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000558string GenerateSetBitInternal(const string& prefix, int bitIndex) {
559 string varName = prefix + GetBitFieldNameForBit(bitIndex);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000560 int bitInVarIndex = bitIndex % 32;
561
562 string mask = bit_masks[bitInVarIndex];
563 string result = varName + " |= " + mask;
564 return result;
565}
566
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000567} // namespace
568
569string GenerateGetBit(int bitIndex) {
570 return GenerateGetBitInternal("", bitIndex);
571}
572
573string GenerateSetBit(int bitIndex) {
574 return GenerateSetBitInternal("", bitIndex);
575}
576
liujisi@google.com33165fe2010-11-02 13:14:58 +0000577string 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
586string GenerateGetBitFromLocal(int bitIndex) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000587 return GenerateGetBitInternal("from_", bitIndex);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000588}
589
590string GenerateSetBitToLocal(int bitIndex) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000591 return GenerateSetBitInternal("to_", bitIndex);
592}
liujisi@google.com33165fe2010-11-02 13:14:58 +0000593
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000594string GenerateGetBitMutableLocal(int bitIndex) {
595 return GenerateGetBitInternal("mutable_", bitIndex);
596}
597
598string GenerateSetBitMutableLocal(int bitIndex) {
599 return GenerateSetBitInternal("mutable_", bitIndex);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000600}
601
jieluo@google.com4de8f552014-07-18 00:47:59 +0000602bool 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
622const 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.
655int 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.
687const 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 }
Jisi Liu885b6122015-02-28 14:51:22 -0800693 std::sort(fields, fields + descriptor->field_count(),
694 FieldOrderingByNumber());
jieluo@google.com4de8f552014-07-18 00:47:59 +0000695 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).
703bool 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
739bool HasRequiredFields(const Descriptor* type) {
740 hash_set<const Descriptor*> already_seen;
741 return HasRequiredFields(type, &already_seen);
742}
743
744bool 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
temporal40ee5512008-07-10 02:12:20 +0000754} // namespace java
755} // namespace compiler
756} // namespace protobuf
757} // namespace google