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 <google/protobuf/compiler/java/helpers.h> |
36 | |
37 | #include <algorithm> |
38 | #include <cstdint> |
39 | #include <limits> |
40 | #include <unordered_set> |
41 | #include <vector> |
42 | |
43 | #include <google/protobuf/wire_format.h> |
44 | #include <google/protobuf/stubs/strutil.h> |
45 | #include <google/protobuf/stubs/stringprintf.h> |
46 | #include <google/protobuf/stubs/substitute.h> |
47 | #include <google/protobuf/compiler/java/name_resolver.h> |
48 | #include <google/protobuf/compiler/java/names.h> |
49 | #include <google/protobuf/descriptor.pb.h> |
50 | #include <google/protobuf/stubs/hash.h> // for hash<T *> |
51 | |
52 | // Must be last. |
53 | #include <google/protobuf/port_def.inc> |
54 | |
55 | namespace google { |
56 | namespace protobuf { |
57 | namespace compiler { |
58 | namespace java { |
59 | |
60 | using internal::WireFormat; |
61 | using internal::WireFormatLite; |
62 | |
63 | const char kThickSeparator[] = |
64 | "// ===================================================================\n" ; |
65 | const char kThinSeparator[] = |
66 | "// -------------------------------------------------------------------\n" ; |
67 | |
68 | namespace { |
69 | |
70 | const char* kDefaultPackage = "" ; |
71 | |
72 | // Names that should be avoided (in UpperCamelCase format). |
73 | // Using them will cause the compiler to generate accessors whose names |
74 | // collide with methods defined in base classes. |
75 | // Keep this list in sync with specialFieldNames in |
76 | // java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java |
77 | const char* kForbiddenWordList[] = { |
78 | // java.lang.Object: |
79 | "Class" , |
80 | // com.google.protobuf.MessageLiteOrBuilder: |
81 | "DefaultInstanceForType" , |
82 | // com.google.protobuf.MessageLite: |
83 | "ParserForType" , |
84 | "SerializedSize" , |
85 | // com.google.protobuf.MessageOrBuilder: |
86 | "AllFields" , |
87 | "DescriptorForType" , |
88 | "InitializationErrorString" , |
89 | "UnknownFields" , |
90 | // obsolete. kept for backwards compatibility of generated code |
91 | "CachedSize" , |
92 | }; |
93 | |
94 | const std::unordered_set<std::string>* kReservedNames = |
95 | new std::unordered_set<std::string>({ |
96 | "abstract" , "assert" , "boolean" , "break" , "byte" , |
97 | "case" , "catch" , "char" , "class" , "const" , |
98 | "continue" , "default" , "do" , "double" , "else" , |
99 | "enum" , "extends" , "final" , "finally" , "float" , |
100 | "for" , "goto" , "if" , "implements" , "import" , |
101 | "instanceof" , "int" , "interface" , "long" , "native" , |
102 | "new" , "package" , "private" , "protected" , "public" , |
103 | "return" , "short" , "static" , "strictfp" , "super" , |
104 | "switch" , "synchronized" , "this" , "throw" , "throws" , |
105 | "transient" , "try" , "void" , "volatile" , "while" , |
106 | }); |
107 | |
108 | bool IsForbidden(const std::string& field_name) { |
109 | for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { |
110 | if (UnderscoresToCamelCase(name: field_name, cap_first_letter: true) == kForbiddenWordList[i]) { |
111 | return true; |
112 | } |
113 | } |
114 | return false; |
115 | } |
116 | |
117 | std::string FieldName(const FieldDescriptor* field) { |
118 | std::string field_name; |
119 | // Groups are hacky: The name of the field is just the lower-cased name |
120 | // of the group type. In Java, though, we would like to retain the original |
121 | // capitalization of the type name. |
122 | if (GetType(field) == FieldDescriptor::TYPE_GROUP) { |
123 | field_name = field->message_type()->name(); |
124 | } else { |
125 | field_name = field->name(); |
126 | } |
127 | if (IsForbidden(field_name)) { |
128 | // Append a trailing "#" to indicate that the name should be decorated to |
129 | // avoid collision with other names. |
130 | field_name += "#" ; |
131 | } |
132 | return field_name; |
133 | } |
134 | |
135 | |
136 | } // namespace |
137 | |
138 | void PrintGeneratedAnnotation(io::Printer* printer, char delimiter, |
139 | const std::string& annotation_file) { |
140 | if (annotation_file.empty()) { |
141 | return; |
142 | } |
143 | std::string ptemplate = |
144 | "@javax.annotation.Generated(value=\"protoc\", comments=\"annotations:" ; |
145 | ptemplate.push_back(c: delimiter); |
146 | ptemplate.append(s: "annotation_file" ); |
147 | ptemplate.push_back(c: delimiter); |
148 | ptemplate.append(s: "\")\n" ); |
149 | printer->Print(text: ptemplate.c_str(), args: "annotation_file" , args: annotation_file); |
150 | } |
151 | |
152 | void PrintEnumVerifierLogic(io::Printer* printer, |
153 | const FieldDescriptor* descriptor, |
154 | const std::map<std::string, std::string>& variables, |
155 | const char* var_name, |
156 | const char* terminating_string, bool enforce_lite) { |
157 | std::string enum_verifier_string = |
158 | enforce_lite ? StrCat(a: var_name, b: ".internalGetVerifier()" ) |
159 | : StrCat( |
160 | a: "new com.google.protobuf.Internal.EnumVerifier() {\n" |
161 | " @java.lang.Override\n" |
162 | " public boolean isInRange(int number) {\n" |
163 | " return " , |
164 | b: var_name, |
165 | c: ".forNumber(number) != null;\n" |
166 | " }\n" |
167 | " }" ); |
168 | printer->Print( |
169 | variables, |
170 | text: StrCat(a: enum_verifier_string, b: terminating_string).c_str()); |
171 | } |
172 | |
173 | std::string UnderscoresToCamelCase(const std::string& input, |
174 | bool cap_next_letter) { |
175 | GOOGLE_CHECK(!input.empty()); |
176 | std::string result; |
177 | // Note: I distrust ctype.h due to locales. |
178 | for (int i = 0; i < input.size(); i++) { |
179 | if ('a' <= input[i] && input[i] <= 'z') { |
180 | if (cap_next_letter) { |
181 | result += input[i] + ('A' - 'a'); |
182 | } else { |
183 | result += input[i]; |
184 | } |
185 | cap_next_letter = false; |
186 | } else if ('A' <= input[i] && input[i] <= 'Z') { |
187 | if (i == 0 && !cap_next_letter) { |
188 | // Force first letter to lower-case unless explicitly told to |
189 | // capitalize it. |
190 | result += input[i] + ('a' - 'A'); |
191 | } else { |
192 | // Capital letters after the first are left as-is. |
193 | result += input[i]; |
194 | } |
195 | cap_next_letter = false; |
196 | } else if ('0' <= input[i] && input[i] <= '9') { |
197 | result += input[i]; |
198 | cap_next_letter = true; |
199 | } else { |
200 | cap_next_letter = true; |
201 | } |
202 | } |
203 | // Add a trailing "_" if the name should be altered. |
204 | if (input[input.size() - 1] == '#') { |
205 | result += '_'; |
206 | } |
207 | return result; |
208 | } |
209 | |
210 | std::string ToCamelCase(const std::string& input, bool lower_first) { |
211 | bool capitalize_next = !lower_first; |
212 | std::string result; |
213 | result.reserve(res_arg: input.size()); |
214 | |
215 | for (char i : input) { |
216 | if (i == '_') { |
217 | capitalize_next = true; |
218 | } else if (capitalize_next) { |
219 | result.push_back(c: ToUpperCh(ch: i)); |
220 | capitalize_next = false; |
221 | } else { |
222 | result.push_back(c: i); |
223 | } |
224 | } |
225 | |
226 | // Lower-case the first letter. |
227 | if (lower_first && !result.empty()) { |
228 | result[0] = ToLowerCh(ch: result[0]); |
229 | } |
230 | |
231 | return result; |
232 | } |
233 | |
234 | char ToUpperCh(char ch) { |
235 | return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch; |
236 | } |
237 | |
238 | char ToLowerCh(char ch) { |
239 | return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch; |
240 | } |
241 | |
242 | std::string UnderscoresToCamelCase(const FieldDescriptor* field) { |
243 | return UnderscoresToCamelCase(input: FieldName(field), cap_next_letter: false); |
244 | } |
245 | |
246 | std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { |
247 | return UnderscoresToCamelCase(input: FieldName(field), cap_next_letter: true); |
248 | } |
249 | |
250 | std::string CapitalizedFieldName(const FieldDescriptor* field) { |
251 | return UnderscoresToCapitalizedCamelCase(field); |
252 | } |
253 | |
254 | std::string UnderscoresToCamelCase(const MethodDescriptor* method) { |
255 | return UnderscoresToCamelCase(input: method->name(), cap_next_letter: false); |
256 | } |
257 | |
258 | std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) { |
259 | std::string name = UnderscoresToCamelCase(field); |
260 | if (kReservedNames->find(x: name) != kReservedNames->end()) { |
261 | return name + "_" ; |
262 | } |
263 | return name; |
264 | } |
265 | |
266 | // Names that should be avoided as field names in Kotlin. |
267 | // All Kotlin hard keywords are in this list. |
268 | const std::unordered_set<std::string>* kKotlinForbiddenNames = |
269 | new std::unordered_set<std::string>({ |
270 | "as" , "as?" , "break" , "class" , "continue" , "do" , "else" , |
271 | "false" , "for" , "fun" , "if" , "in" , "!in" , "interface" , |
272 | "is" , "!is" , "null" , "object" , "package" , "return" , "super" , |
273 | "this" , "throw" , "true" , "try" , "typealias" , "typeof" , "val" , |
274 | "var" , "when" , "while" , |
275 | }); |
276 | |
277 | bool IsForbiddenKotlin(const std::string& field_name) { |
278 | return kKotlinForbiddenNames->find(x: field_name) != |
279 | kKotlinForbiddenNames->end(); |
280 | } |
281 | |
282 | std::string UniqueFileScopeIdentifier(const Descriptor* descriptor) { |
283 | return "static_" + StringReplace(s: descriptor->full_name(), oldsub: "." , newsub: "_" , replace_all: true); |
284 | } |
285 | |
286 | std::string CamelCaseFieldName(const FieldDescriptor* field) { |
287 | std::string fieldName = UnderscoresToCamelCase(field); |
288 | if ('0' <= fieldName[0] && fieldName[0] <= '9') { |
289 | return '_' + fieldName; |
290 | } |
291 | return fieldName; |
292 | } |
293 | |
294 | std::string FileClassName(const FileDescriptor* file, bool immutable) { |
295 | ClassNameResolver name_resolver; |
296 | return name_resolver.GetFileClassName(file, immutable); |
297 | } |
298 | |
299 | std::string FileJavaPackage(const FileDescriptor* file, bool immutable) { |
300 | std::string result; |
301 | |
302 | if (file->options().has_java_package()) { |
303 | result = file->options().java_package(); |
304 | } else { |
305 | result = kDefaultPackage; |
306 | if (!file->package().empty()) { |
307 | if (!result.empty()) result += '.'; |
308 | result += file->package(); |
309 | } |
310 | } |
311 | |
312 | return result; |
313 | } |
314 | |
315 | std::string FileJavaPackage(const FileDescriptor* file) { |
316 | return FileJavaPackage(file, immutable: true /* immutable */); |
317 | } |
318 | |
319 | std::string JavaPackageToDir(std::string package_name) { |
320 | std::string package_dir = StringReplace(s: package_name, oldsub: "." , newsub: "/" , replace_all: true); |
321 | if (!package_dir.empty()) package_dir += "/" ; |
322 | return package_dir; |
323 | } |
324 | |
325 | std::string ClassName(const Descriptor* descriptor) { |
326 | ClassNameResolver name_resolver; |
327 | return name_resolver.GetClassName(descriptor, immutable: true); |
328 | } |
329 | |
330 | std::string ClassName(const EnumDescriptor* descriptor) { |
331 | ClassNameResolver name_resolver; |
332 | return name_resolver.GetClassName(descriptor, immutable: true); |
333 | } |
334 | |
335 | std::string ClassName(const ServiceDescriptor* descriptor) { |
336 | ClassNameResolver name_resolver; |
337 | return name_resolver.GetClassName(descriptor, immutable: true); |
338 | } |
339 | |
340 | std::string ClassName(const FileDescriptor* descriptor) { |
341 | ClassNameResolver name_resolver; |
342 | return name_resolver.GetClassName(descriptor, immutable: true); |
343 | } |
344 | |
345 | |
346 | std::string (const Descriptor* descriptor) { |
347 | std::string interfaces = "// @@protoc_insertion_point(message_implements:" + |
348 | descriptor->full_name() + ")" ; |
349 | return interfaces; |
350 | } |
351 | |
352 | |
353 | std::string (const Descriptor* descriptor) { |
354 | std::string interfaces = "// @@protoc_insertion_point(builder_implements:" + |
355 | descriptor->full_name() + ")" ; |
356 | return interfaces; |
357 | } |
358 | |
359 | std::string (const Descriptor* descriptor) { |
360 | std::string interfaces = "// @@protoc_insertion_point(interface_extends:" + |
361 | descriptor->full_name() + ")" ; |
362 | return interfaces; |
363 | } |
364 | |
365 | std::string FieldConstantName(const FieldDescriptor* field) { |
366 | std::string name = field->name() + "_FIELD_NUMBER" ; |
367 | ToUpper(s: &name); |
368 | return name; |
369 | } |
370 | |
371 | FieldDescriptor::Type GetType(const FieldDescriptor* field) { |
372 | return field->type(); |
373 | } |
374 | |
375 | JavaType GetJavaType(const FieldDescriptor* field) { |
376 | switch (GetType(field)) { |
377 | case FieldDescriptor::TYPE_INT32: |
378 | case FieldDescriptor::TYPE_UINT32: |
379 | case FieldDescriptor::TYPE_SINT32: |
380 | case FieldDescriptor::TYPE_FIXED32: |
381 | case FieldDescriptor::TYPE_SFIXED32: |
382 | return JAVATYPE_INT; |
383 | |
384 | case FieldDescriptor::TYPE_INT64: |
385 | case FieldDescriptor::TYPE_UINT64: |
386 | case FieldDescriptor::TYPE_SINT64: |
387 | case FieldDescriptor::TYPE_FIXED64: |
388 | case FieldDescriptor::TYPE_SFIXED64: |
389 | return JAVATYPE_LONG; |
390 | |
391 | case FieldDescriptor::TYPE_FLOAT: |
392 | return JAVATYPE_FLOAT; |
393 | |
394 | case FieldDescriptor::TYPE_DOUBLE: |
395 | return JAVATYPE_DOUBLE; |
396 | |
397 | case FieldDescriptor::TYPE_BOOL: |
398 | return JAVATYPE_BOOLEAN; |
399 | |
400 | case FieldDescriptor::TYPE_STRING: |
401 | return JAVATYPE_STRING; |
402 | |
403 | case FieldDescriptor::TYPE_BYTES: |
404 | return JAVATYPE_BYTES; |
405 | |
406 | case FieldDescriptor::TYPE_ENUM: |
407 | return JAVATYPE_ENUM; |
408 | |
409 | case FieldDescriptor::TYPE_GROUP: |
410 | case FieldDescriptor::TYPE_MESSAGE: |
411 | return JAVATYPE_MESSAGE; |
412 | |
413 | // No default because we want the compiler to complain if any new |
414 | // types are added. |
415 | } |
416 | |
417 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
418 | return JAVATYPE_INT; |
419 | } |
420 | |
421 | const char* PrimitiveTypeName(JavaType type) { |
422 | switch (type) { |
423 | case JAVATYPE_INT: |
424 | return "int" ; |
425 | case JAVATYPE_LONG: |
426 | return "long" ; |
427 | case JAVATYPE_FLOAT: |
428 | return "float" ; |
429 | case JAVATYPE_DOUBLE: |
430 | return "double" ; |
431 | case JAVATYPE_BOOLEAN: |
432 | return "boolean" ; |
433 | case JAVATYPE_STRING: |
434 | return "java.lang.String" ; |
435 | case JAVATYPE_BYTES: |
436 | return "com.google.protobuf.ByteString" ; |
437 | case JAVATYPE_ENUM: |
438 | return NULL; |
439 | case JAVATYPE_MESSAGE: |
440 | return NULL; |
441 | |
442 | // No default because we want the compiler to complain if any new |
443 | // JavaTypes are added. |
444 | } |
445 | |
446 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
447 | return NULL; |
448 | } |
449 | |
450 | const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { |
451 | return PrimitiveTypeName(type: GetJavaType(field: descriptor)); |
452 | } |
453 | |
454 | const char* BoxedPrimitiveTypeName(JavaType type) { |
455 | switch (type) { |
456 | case JAVATYPE_INT: |
457 | return "java.lang.Integer" ; |
458 | case JAVATYPE_LONG: |
459 | return "java.lang.Long" ; |
460 | case JAVATYPE_FLOAT: |
461 | return "java.lang.Float" ; |
462 | case JAVATYPE_DOUBLE: |
463 | return "java.lang.Double" ; |
464 | case JAVATYPE_BOOLEAN: |
465 | return "java.lang.Boolean" ; |
466 | case JAVATYPE_STRING: |
467 | return "java.lang.String" ; |
468 | case JAVATYPE_BYTES: |
469 | return "com.google.protobuf.ByteString" ; |
470 | case JAVATYPE_ENUM: |
471 | return NULL; |
472 | case JAVATYPE_MESSAGE: |
473 | return NULL; |
474 | |
475 | // No default because we want the compiler to complain if any new |
476 | // JavaTypes are added. |
477 | } |
478 | |
479 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
480 | return NULL; |
481 | } |
482 | |
483 | const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) { |
484 | return BoxedPrimitiveTypeName(type: GetJavaType(field: descriptor)); |
485 | } |
486 | |
487 | const char* KotlinTypeName(JavaType type) { |
488 | switch (type) { |
489 | case JAVATYPE_INT: |
490 | return "kotlin.Int" ; |
491 | case JAVATYPE_LONG: |
492 | return "kotlin.Long" ; |
493 | case JAVATYPE_FLOAT: |
494 | return "kotlin.Float" ; |
495 | case JAVATYPE_DOUBLE: |
496 | return "kotlin.Double" ; |
497 | case JAVATYPE_BOOLEAN: |
498 | return "kotlin.Boolean" ; |
499 | case JAVATYPE_STRING: |
500 | return "kotlin.String" ; |
501 | case JAVATYPE_BYTES: |
502 | return "com.google.protobuf.ByteString" ; |
503 | case JAVATYPE_ENUM: |
504 | return NULL; |
505 | case JAVATYPE_MESSAGE: |
506 | return NULL; |
507 | |
508 | // No default because we want the compiler to complain if any new |
509 | // JavaTypes are added. |
510 | } |
511 | |
512 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
513 | return NULL; |
514 | } |
515 | |
516 | std::string GetOneofStoredType(const FieldDescriptor* field) { |
517 | const JavaType javaType = GetJavaType(field); |
518 | switch (javaType) { |
519 | case JAVATYPE_ENUM: |
520 | return "java.lang.Integer" ; |
521 | case JAVATYPE_MESSAGE: |
522 | return ClassName(descriptor: field->message_type()); |
523 | default: |
524 | return BoxedPrimitiveTypeName(type: javaType); |
525 | } |
526 | } |
527 | |
528 | const char* FieldTypeName(FieldDescriptor::Type field_type) { |
529 | switch (field_type) { |
530 | case FieldDescriptor::TYPE_INT32: |
531 | return "INT32" ; |
532 | case FieldDescriptor::TYPE_UINT32: |
533 | return "UINT32" ; |
534 | case FieldDescriptor::TYPE_SINT32: |
535 | return "SINT32" ; |
536 | case FieldDescriptor::TYPE_FIXED32: |
537 | return "FIXED32" ; |
538 | case FieldDescriptor::TYPE_SFIXED32: |
539 | return "SFIXED32" ; |
540 | case FieldDescriptor::TYPE_INT64: |
541 | return "INT64" ; |
542 | case FieldDescriptor::TYPE_UINT64: |
543 | return "UINT64" ; |
544 | case FieldDescriptor::TYPE_SINT64: |
545 | return "SINT64" ; |
546 | case FieldDescriptor::TYPE_FIXED64: |
547 | return "FIXED64" ; |
548 | case FieldDescriptor::TYPE_SFIXED64: |
549 | return "SFIXED64" ; |
550 | case FieldDescriptor::TYPE_FLOAT: |
551 | return "FLOAT" ; |
552 | case FieldDescriptor::TYPE_DOUBLE: |
553 | return "DOUBLE" ; |
554 | case FieldDescriptor::TYPE_BOOL: |
555 | return "BOOL" ; |
556 | case FieldDescriptor::TYPE_STRING: |
557 | return "STRING" ; |
558 | case FieldDescriptor::TYPE_BYTES: |
559 | return "BYTES" ; |
560 | case FieldDescriptor::TYPE_ENUM: |
561 | return "ENUM" ; |
562 | case FieldDescriptor::TYPE_GROUP: |
563 | return "GROUP" ; |
564 | case FieldDescriptor::TYPE_MESSAGE: |
565 | return "MESSAGE" ; |
566 | |
567 | // No default because we want the compiler to complain if any new |
568 | // types are added. |
569 | } |
570 | |
571 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
572 | return NULL; |
573 | } |
574 | |
575 | bool AllAscii(const std::string& text) { |
576 | for (int i = 0; i < text.size(); i++) { |
577 | if ((text[i] & 0x80) != 0) { |
578 | return false; |
579 | } |
580 | } |
581 | return true; |
582 | } |
583 | |
584 | std::string DefaultValue(const FieldDescriptor* field, bool immutable, |
585 | ClassNameResolver* name_resolver) { |
586 | // Switch on CppType since we need to know which default_value_* method |
587 | // of FieldDescriptor to call. |
588 | switch (field->cpp_type()) { |
589 | case FieldDescriptor::CPPTYPE_INT32: |
590 | return StrCat(a: field->default_value_int32()); |
591 | case FieldDescriptor::CPPTYPE_UINT32: |
592 | // Need to print as a signed int since Java has no unsigned. |
593 | return StrCat(a: static_cast<int32_t>(field->default_value_uint32())); |
594 | case FieldDescriptor::CPPTYPE_INT64: |
595 | return StrCat(a: field->default_value_int64()) + "L" ; |
596 | case FieldDescriptor::CPPTYPE_UINT64: |
597 | return StrCat(a: static_cast<int64_t>(field->default_value_uint64())) + |
598 | "L" ; |
599 | case FieldDescriptor::CPPTYPE_DOUBLE: { |
600 | double value = field->default_value_double(); |
601 | if (value == std::numeric_limits<double>::infinity()) { |
602 | return "Double.POSITIVE_INFINITY" ; |
603 | } else if (value == -std::numeric_limits<double>::infinity()) { |
604 | return "Double.NEGATIVE_INFINITY" ; |
605 | } else if (value != value) { |
606 | return "Double.NaN" ; |
607 | } else { |
608 | return SimpleDtoa(value) + "D" ; |
609 | } |
610 | } |
611 | case FieldDescriptor::CPPTYPE_FLOAT: { |
612 | float value = field->default_value_float(); |
613 | if (value == std::numeric_limits<float>::infinity()) { |
614 | return "Float.POSITIVE_INFINITY" ; |
615 | } else if (value == -std::numeric_limits<float>::infinity()) { |
616 | return "Float.NEGATIVE_INFINITY" ; |
617 | } else if (value != value) { |
618 | return "Float.NaN" ; |
619 | } else { |
620 | return SimpleFtoa(value) + "F" ; |
621 | } |
622 | } |
623 | case FieldDescriptor::CPPTYPE_BOOL: |
624 | return field->default_value_bool() ? "true" : "false" ; |
625 | case FieldDescriptor::CPPTYPE_STRING: |
626 | if (GetType(field) == FieldDescriptor::TYPE_BYTES) { |
627 | if (field->has_default_value()) { |
628 | // See comments in Internal.java for gory details. |
629 | return strings::Substitute( |
630 | format: "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")" , |
631 | arg0: CEscape(src: field->default_value_string())); |
632 | } else { |
633 | return "com.google.protobuf.ByteString.EMPTY" ; |
634 | } |
635 | } else { |
636 | if (AllAscii(text: field->default_value_string())) { |
637 | // All chars are ASCII. In this case CEscape() works fine. |
638 | return "\"" + CEscape(src: field->default_value_string()) + "\"" ; |
639 | } else { |
640 | // See comments in Internal.java for gory details. |
641 | return strings::Substitute( |
642 | format: "com.google.protobuf.Internal.stringDefaultValue(\"$0\")" , |
643 | arg0: CEscape(src: field->default_value_string())); |
644 | } |
645 | } |
646 | |
647 | case FieldDescriptor::CPPTYPE_ENUM: |
648 | return name_resolver->GetClassName(descriptor: field->enum_type(), immutable) + "." + |
649 | field->default_value_enum()->name(); |
650 | |
651 | case FieldDescriptor::CPPTYPE_MESSAGE: |
652 | return name_resolver->GetClassName(descriptor: field->message_type(), immutable) + |
653 | ".getDefaultInstance()" ; |
654 | |
655 | // No default because we want the compiler to complain if any new |
656 | // types are added. |
657 | } |
658 | |
659 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
660 | return "" ; |
661 | } |
662 | |
663 | bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { |
664 | // Switch on CppType since we need to know which default_value_* method |
665 | // of FieldDescriptor to call. |
666 | switch (field->cpp_type()) { |
667 | case FieldDescriptor::CPPTYPE_INT32: |
668 | return field->default_value_int32() == 0; |
669 | case FieldDescriptor::CPPTYPE_UINT32: |
670 | return field->default_value_uint32() == 0; |
671 | case FieldDescriptor::CPPTYPE_INT64: |
672 | return field->default_value_int64() == 0L; |
673 | case FieldDescriptor::CPPTYPE_UINT64: |
674 | return field->default_value_uint64() == 0L; |
675 | case FieldDescriptor::CPPTYPE_DOUBLE: |
676 | return field->default_value_double() == 0.0; |
677 | case FieldDescriptor::CPPTYPE_FLOAT: |
678 | return field->default_value_float() == 0.0; |
679 | case FieldDescriptor::CPPTYPE_BOOL: |
680 | return field->default_value_bool() == false; |
681 | case FieldDescriptor::CPPTYPE_ENUM: |
682 | return field->default_value_enum()->number() == 0; |
683 | case FieldDescriptor::CPPTYPE_STRING: |
684 | case FieldDescriptor::CPPTYPE_MESSAGE: |
685 | return false; |
686 | |
687 | // No default because we want the compiler to complain if any new |
688 | // types are added. |
689 | } |
690 | |
691 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
692 | return false; |
693 | } |
694 | |
695 | bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) { |
696 | return GetJavaType(field) == JAVATYPE_BYTES && |
697 | field->default_value_string() != "" ; |
698 | } |
699 | |
700 | const char* bit_masks[] = { |
701 | "0x00000001" , "0x00000002" , "0x00000004" , "0x00000008" , |
702 | "0x00000010" , "0x00000020" , "0x00000040" , "0x00000080" , |
703 | |
704 | "0x00000100" , "0x00000200" , "0x00000400" , "0x00000800" , |
705 | "0x00001000" , "0x00002000" , "0x00004000" , "0x00008000" , |
706 | |
707 | "0x00010000" , "0x00020000" , "0x00040000" , "0x00080000" , |
708 | "0x00100000" , "0x00200000" , "0x00400000" , "0x00800000" , |
709 | |
710 | "0x01000000" , "0x02000000" , "0x04000000" , "0x08000000" , |
711 | "0x10000000" , "0x20000000" , "0x40000000" , "0x80000000" , |
712 | }; |
713 | |
714 | std::string GetBitFieldName(int index) { |
715 | std::string varName = "bitField" ; |
716 | varName += StrCat(a: index); |
717 | varName += "_" ; |
718 | return varName; |
719 | } |
720 | |
721 | std::string GetBitFieldNameForBit(int bitIndex) { |
722 | return GetBitFieldName(index: bitIndex / 32); |
723 | } |
724 | |
725 | namespace { |
726 | |
727 | std::string GenerateGetBitInternal(const std::string& prefix, int bitIndex) { |
728 | std::string varName = prefix + GetBitFieldNameForBit(bitIndex); |
729 | int bitInVarIndex = bitIndex % 32; |
730 | |
731 | std::string mask = bit_masks[bitInVarIndex]; |
732 | std::string result = "((" + varName + " & " + mask + ") != 0)" ; |
733 | return result; |
734 | } |
735 | |
736 | std::string GenerateSetBitInternal(const std::string& prefix, int bitIndex) { |
737 | std::string varName = prefix + GetBitFieldNameForBit(bitIndex); |
738 | int bitInVarIndex = bitIndex % 32; |
739 | |
740 | std::string mask = bit_masks[bitInVarIndex]; |
741 | std::string result = varName + " |= " + mask; |
742 | return result; |
743 | } |
744 | |
745 | } // namespace |
746 | |
747 | std::string GenerateGetBit(int bitIndex) { |
748 | return GenerateGetBitInternal(prefix: "" , bitIndex); |
749 | } |
750 | |
751 | std::string GenerateSetBit(int bitIndex) { |
752 | return GenerateSetBitInternal(prefix: "" , bitIndex); |
753 | } |
754 | |
755 | std::string GenerateClearBit(int bitIndex) { |
756 | std::string varName = GetBitFieldNameForBit(bitIndex); |
757 | int bitInVarIndex = bitIndex % 32; |
758 | |
759 | std::string mask = bit_masks[bitInVarIndex]; |
760 | std::string result = varName + " = (" + varName + " & ~" + mask + ")" ; |
761 | return result; |
762 | } |
763 | |
764 | std::string GenerateGetBitFromLocal(int bitIndex) { |
765 | return GenerateGetBitInternal(prefix: "from_" , bitIndex); |
766 | } |
767 | |
768 | std::string GenerateSetBitToLocal(int bitIndex) { |
769 | return GenerateSetBitInternal(prefix: "to_" , bitIndex); |
770 | } |
771 | |
772 | std::string GenerateGetBitMutableLocal(int bitIndex) { |
773 | return GenerateGetBitInternal(prefix: "mutable_" , bitIndex); |
774 | } |
775 | |
776 | std::string GenerateSetBitMutableLocal(int bitIndex) { |
777 | return GenerateSetBitInternal(prefix: "mutable_" , bitIndex); |
778 | } |
779 | |
780 | bool IsReferenceType(JavaType type) { |
781 | switch (type) { |
782 | case JAVATYPE_INT: |
783 | return false; |
784 | case JAVATYPE_LONG: |
785 | return false; |
786 | case JAVATYPE_FLOAT: |
787 | return false; |
788 | case JAVATYPE_DOUBLE: |
789 | return false; |
790 | case JAVATYPE_BOOLEAN: |
791 | return false; |
792 | case JAVATYPE_STRING: |
793 | return true; |
794 | case JAVATYPE_BYTES: |
795 | return true; |
796 | case JAVATYPE_ENUM: |
797 | return true; |
798 | case JAVATYPE_MESSAGE: |
799 | return true; |
800 | |
801 | // No default because we want the compiler to complain if any new |
802 | // JavaTypes are added. |
803 | } |
804 | |
805 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
806 | return false; |
807 | } |
808 | |
809 | const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { |
810 | switch (GetType(field)) { |
811 | case FieldDescriptor::TYPE_INT32: |
812 | return "Int32" ; |
813 | case FieldDescriptor::TYPE_UINT32: |
814 | return "UInt32" ; |
815 | case FieldDescriptor::TYPE_SINT32: |
816 | return "SInt32" ; |
817 | case FieldDescriptor::TYPE_FIXED32: |
818 | return "Fixed32" ; |
819 | case FieldDescriptor::TYPE_SFIXED32: |
820 | return "SFixed32" ; |
821 | case FieldDescriptor::TYPE_INT64: |
822 | return "Int64" ; |
823 | case FieldDescriptor::TYPE_UINT64: |
824 | return "UInt64" ; |
825 | case FieldDescriptor::TYPE_SINT64: |
826 | return "SInt64" ; |
827 | case FieldDescriptor::TYPE_FIXED64: |
828 | return "Fixed64" ; |
829 | case FieldDescriptor::TYPE_SFIXED64: |
830 | return "SFixed64" ; |
831 | case FieldDescriptor::TYPE_FLOAT: |
832 | return "Float" ; |
833 | case FieldDescriptor::TYPE_DOUBLE: |
834 | return "Double" ; |
835 | case FieldDescriptor::TYPE_BOOL: |
836 | return "Bool" ; |
837 | case FieldDescriptor::TYPE_STRING: |
838 | return "String" ; |
839 | case FieldDescriptor::TYPE_BYTES: { |
840 | return "Bytes" ; |
841 | } |
842 | case FieldDescriptor::TYPE_ENUM: |
843 | return "Enum" ; |
844 | case FieldDescriptor::TYPE_GROUP: |
845 | return "Group" ; |
846 | case FieldDescriptor::TYPE_MESSAGE: |
847 | return "Message" ; |
848 | |
849 | // No default because we want the compiler to complain if any new |
850 | // types are added. |
851 | } |
852 | |
853 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
854 | return NULL; |
855 | } |
856 | |
857 | // For encodings with fixed sizes, returns that size in bytes. Otherwise |
858 | // returns -1. |
859 | int FixedSize(FieldDescriptor::Type type) { |
860 | switch (type) { |
861 | case FieldDescriptor::TYPE_INT32: |
862 | return -1; |
863 | case FieldDescriptor::TYPE_INT64: |
864 | return -1; |
865 | case FieldDescriptor::TYPE_UINT32: |
866 | return -1; |
867 | case FieldDescriptor::TYPE_UINT64: |
868 | return -1; |
869 | case FieldDescriptor::TYPE_SINT32: |
870 | return -1; |
871 | case FieldDescriptor::TYPE_SINT64: |
872 | return -1; |
873 | case FieldDescriptor::TYPE_FIXED32: |
874 | return WireFormatLite::kFixed32Size; |
875 | case FieldDescriptor::TYPE_FIXED64: |
876 | return WireFormatLite::kFixed64Size; |
877 | case FieldDescriptor::TYPE_SFIXED32: |
878 | return WireFormatLite::kSFixed32Size; |
879 | case FieldDescriptor::TYPE_SFIXED64: |
880 | return WireFormatLite::kSFixed64Size; |
881 | case FieldDescriptor::TYPE_FLOAT: |
882 | return WireFormatLite::kFloatSize; |
883 | case FieldDescriptor::TYPE_DOUBLE: |
884 | return WireFormatLite::kDoubleSize; |
885 | |
886 | case FieldDescriptor::TYPE_BOOL: |
887 | return WireFormatLite::kBoolSize; |
888 | case FieldDescriptor::TYPE_ENUM: |
889 | return -1; |
890 | |
891 | case FieldDescriptor::TYPE_STRING: |
892 | return -1; |
893 | case FieldDescriptor::TYPE_BYTES: |
894 | return -1; |
895 | case FieldDescriptor::TYPE_GROUP: |
896 | return -1; |
897 | case FieldDescriptor::TYPE_MESSAGE: |
898 | return -1; |
899 | |
900 | // No default because we want the compiler to complain if any new |
901 | // types are added. |
902 | } |
903 | GOOGLE_LOG(FATAL) << "Can't get here." ; |
904 | return -1; |
905 | } |
906 | |
907 | // Sort the fields of the given Descriptor by number into a new[]'d array |
908 | // and return it. The caller should delete the returned array. |
909 | const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { |
910 | const FieldDescriptor** fields = |
911 | new const FieldDescriptor*[descriptor->field_count()]; |
912 | for (int i = 0; i < descriptor->field_count(); i++) { |
913 | fields[i] = descriptor->field(index: i); |
914 | } |
915 | std::sort(first: fields, last: fields + descriptor->field_count(), |
916 | comp: FieldOrderingByNumber()); |
917 | return fields; |
918 | } |
919 | |
920 | // Returns true if the message type has any required fields. If it doesn't, |
921 | // we can optimize out calls to its isInitialized() method. |
922 | // |
923 | // already_seen is used to avoid checking the same type multiple times |
924 | // (and also to protect against recursion). |
925 | bool HasRequiredFields(const Descriptor* type, |
926 | std::unordered_set<const Descriptor*>* already_seen) { |
927 | if (already_seen->count(x: type) > 0) { |
928 | // The type is already in cache. This means that either: |
929 | // a. The type has no required fields. |
930 | // b. We are in the midst of checking if the type has required fields, |
931 | // somewhere up the stack. In this case, we know that if the type |
932 | // has any required fields, they'll be found when we return to it, |
933 | // and the whole call to HasRequiredFields() will return true. |
934 | // Therefore, we don't have to check if this type has required fields |
935 | // here. |
936 | return false; |
937 | } |
938 | already_seen->insert(x: type); |
939 | |
940 | // If the type has extensions, an extension with message type could contain |
941 | // required fields, so we have to be conservative and assume such an |
942 | // extension exists. |
943 | if (type->extension_range_count() > 0) return true; |
944 | |
945 | for (int i = 0; i < type->field_count(); i++) { |
946 | const FieldDescriptor* field = type->field(index: i); |
947 | if (field->is_required()) { |
948 | return true; |
949 | } |
950 | if (GetJavaType(field) == JAVATYPE_MESSAGE) { |
951 | if (HasRequiredFields(type: field->message_type(), already_seen)) { |
952 | return true; |
953 | } |
954 | } |
955 | } |
956 | |
957 | return false; |
958 | } |
959 | |
960 | bool HasRequiredFields(const Descriptor* type) { |
961 | std::unordered_set<const Descriptor*> already_seen; |
962 | return HasRequiredFields(type, already_seen: &already_seen); |
963 | } |
964 | |
965 | bool HasRepeatedFields(const Descriptor* descriptor) { |
966 | for (int i = 0; i < descriptor->field_count(); ++i) { |
967 | const FieldDescriptor* field = descriptor->field(index: i); |
968 | if (field->is_repeated()) { |
969 | return true; |
970 | } |
971 | } |
972 | return false; |
973 | } |
974 | |
975 | // Encode an unsigned 32-bit value into a sequence of UTF-16 characters. |
976 | // |
977 | // If the value is in [0x0000, 0xD7FF], we encode it with a single character |
978 | // with the same numeric value. |
979 | // |
980 | // If the value is larger than 0xD7FF, we encode its lowest 13 bits into a |
981 | // character in the range [0xE000, 0xFFFF] by combining these 13 bits with |
982 | // 0xE000 using logic-or. Then we shift the value to the right by 13 bits, and |
983 | // encode the remaining value by repeating this same process until we get to |
984 | // a value in [0x0000, 0xD7FF] where we will encode it using a character with |
985 | // the same numeric value. |
986 | // |
987 | // Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF]. |
988 | // There will be no surrogate pairs in the encoded character sequence. |
989 | void WriteUInt32ToUtf16CharSequence(uint32_t number, |
990 | std::vector<uint16_t>* output) { |
991 | // For values in [0x0000, 0xD7FF], only use one char to encode it. |
992 | if (number < 0xD800) { |
993 | output->push_back(x: static_cast<uint16_t>(number)); |
994 | return; |
995 | } |
996 | // Encode into multiple chars. All except the last char will be in the range |
997 | // [0xE000, 0xFFFF], and the last char will be in the range [0x0000, 0xD7FF]. |
998 | // Note that we don't use any value in range [0xD800, 0xDFFF] because they |
999 | // have to come in pairs and the encoding is just more space-efficient w/o |
1000 | // them. |
1001 | while (number >= 0xD800) { |
1002 | // [0xE000, 0xFFFF] can represent 13 bits of info. |
1003 | output->push_back(x: static_cast<uint16_t>(0xE000 | (number & 0x1FFF))); |
1004 | number >>= 13; |
1005 | } |
1006 | output->push_back(x: static_cast<uint16_t>(number)); |
1007 | } |
1008 | |
1009 | int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) { |
1010 | // j/c/g/protobuf/FieldType.java lists field types in a slightly different |
1011 | // order from FieldDescriptor::Type so we can't do a simple cast. |
1012 | // |
1013 | // TODO(xiaofeng): Make j/c/g/protobuf/FieldType.java follow the same order. |
1014 | int result = field->type(); |
1015 | if (result == FieldDescriptor::TYPE_GROUP) { |
1016 | return 17; |
1017 | } else if (result < FieldDescriptor::TYPE_GROUP) { |
1018 | return result - 1; |
1019 | } else { |
1020 | return result - 2; |
1021 | } |
1022 | } |
1023 | |
1024 | int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) { |
1025 | if (field->type() == FieldDescriptor::TYPE_GROUP) { |
1026 | return 49; |
1027 | } else { |
1028 | return GetExperimentalJavaFieldTypeForSingular(field) + 18; |
1029 | } |
1030 | } |
1031 | |
1032 | int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) { |
1033 | int result = field->type(); |
1034 | if (result < FieldDescriptor::TYPE_STRING) { |
1035 | return result + 34; |
1036 | } else if (result > FieldDescriptor::TYPE_BYTES) { |
1037 | return result + 30; |
1038 | } else { |
1039 | GOOGLE_LOG(FATAL) << field->full_name() << " can't be packed." ; |
1040 | return 0; |
1041 | } |
1042 | } |
1043 | |
1044 | int GetExperimentalJavaFieldType(const FieldDescriptor* field) { |
1045 | static const int kMapFieldType = 50; |
1046 | static const int kOneofFieldTypeOffset = 51; |
1047 | static const int kRequiredBit = 0x100; |
1048 | static const int kUtf8CheckBit = 0x200; |
1049 | static const int kCheckInitialized = 0x400; |
1050 | static const int kMapWithProto2EnumValue = 0x800; |
1051 | static const int kHasHasBit = 0x1000; |
1052 | int = field->is_required() ? kRequiredBit : 0; |
1053 | if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(descriptor: field)) { |
1054 | extra_bits |= kUtf8CheckBit; |
1055 | } |
1056 | if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE && |
1057 | HasRequiredFields(type: field->message_type()))) { |
1058 | extra_bits |= kCheckInitialized; |
1059 | } |
1060 | if (HasHasbit(descriptor: field)) { |
1061 | extra_bits |= kHasHasBit; |
1062 | } |
1063 | |
1064 | if (field->is_map()) { |
1065 | if (!SupportUnknownEnumValue(field)) { |
1066 | const FieldDescriptor* value = field->message_type()->map_value(); |
1067 | if (GetJavaType(field: value) == JAVATYPE_ENUM) { |
1068 | extra_bits |= kMapWithProto2EnumValue; |
1069 | } |
1070 | } |
1071 | return kMapFieldType | extra_bits; |
1072 | } else if (field->is_packed()) { |
1073 | return GetExperimentalJavaFieldTypeForPacked(field); |
1074 | } else if (field->is_repeated()) { |
1075 | return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits; |
1076 | } else if (IsRealOneof(descriptor: field)) { |
1077 | return (GetExperimentalJavaFieldTypeForSingular(field) + |
1078 | kOneofFieldTypeOffset) | |
1079 | extra_bits; |
1080 | } else { |
1081 | return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits; |
1082 | } |
1083 | } |
1084 | |
1085 | // Escape a UTF-16 character to be embedded in a Java string. |
1086 | void EscapeUtf16ToString(uint16_t code, std::string* output) { |
1087 | if (code == '\t') { |
1088 | output->append(s: "\\t" ); |
1089 | } else if (code == '\b') { |
1090 | output->append(s: "\\b" ); |
1091 | } else if (code == '\n') { |
1092 | output->append(s: "\\n" ); |
1093 | } else if (code == '\r') { |
1094 | output->append(s: "\\r" ); |
1095 | } else if (code == '\f') { |
1096 | output->append(s: "\\f" ); |
1097 | } else if (code == '\'') { |
1098 | output->append(s: "\\'" ); |
1099 | } else if (code == '\"') { |
1100 | output->append(s: "\\\"" ); |
1101 | } else if (code == '\\') { |
1102 | output->append(s: "\\\\" ); |
1103 | } else if (code >= 0x20 && code <= 0x7f) { |
1104 | output->push_back(c: static_cast<char>(code)); |
1105 | } else { |
1106 | output->append(str: StringPrintf(format: "\\u%04x" , code)); |
1107 | } |
1108 | } |
1109 | |
1110 | } // namespace java |
1111 | } // namespace compiler |
1112 | } // namespace protobuf |
1113 | } // namespace google |
1114 | |
1115 | #include <google/protobuf/port_undef.inc> |
1116 | |