• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
36 #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
37 
38 #include <algorithm>
39 #include <iterator>
40 #include <map>
41 #include <string>
42 
43 #include <google/protobuf/compiler/cpp/cpp_options.h>
44 #include <google/protobuf/compiler/scc.h>
45 #include <google/protobuf/compiler/code_generator.h>
46 #include <google/protobuf/descriptor.pb.h>
47 #include <google/protobuf/io/printer.h>
48 #include <google/protobuf/descriptor.h>
49 #include <google/protobuf/port.h>
50 #include <google/protobuf/stubs/strutil.h>
51 
52 // Must be included last.
53 #include <google/protobuf/port_def.inc>
54 
55 namespace google {
56 namespace protobuf {
57 namespace compiler {
58 namespace cpp {
59 
ProtobufNamespace(const Options & options)60 inline std::string ProtobufNamespace(const Options& options) {
61   return "PROTOBUF_NAMESPACE_ID";
62 }
63 
MacroPrefix(const Options & options)64 inline std::string MacroPrefix(const Options& options) {
65   return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF";
66 }
67 
DeprecatedAttribute(const Options & options,const FieldDescriptor * d)68 inline std::string DeprecatedAttribute(const Options& options,
69                                        const FieldDescriptor* d) {
70   return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : "";
71 }
72 
DeprecatedAttribute(const Options & options,const EnumValueDescriptor * d)73 inline std::string DeprecatedAttribute(const Options& options,
74                                        const EnumValueDescriptor* d) {
75   return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : "";
76 }
77 
78 // Commonly-used separator comments.  Thick is a line of '=', thin is a line
79 // of '-'.
80 extern const char kThickSeparator[];
81 extern const char kThinSeparator[];
82 
83 void SetCommonVars(const Options& options,
84                    std::map<std::string, std::string>* variables);
85 
86 void SetUnknkownFieldsVariable(const Descriptor* descriptor,
87                                const Options& options,
88                                std::map<std::string, std::string>* variables);
89 
90 bool GetBootstrapBasename(const Options& options, const std::string& basename,
91                           std::string* bootstrap_basename);
92 bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
93                     bool bootstrap_flag, std::string* basename);
94 bool IsBootstrapProto(const Options& options, const FileDescriptor* file);
95 
96 // Name space of the proto file. This namespace is such that the string
97 // "<namespace>::some_name" is the correct fully qualified namespace.
98 // This means if the package is empty the namespace is "", and otherwise
99 // the namespace is "::foo::bar::...::baz" without trailing semi-colons.
100 std::string Namespace(const FileDescriptor* d, const Options& options);
101 std::string Namespace(const Descriptor* d, const Options& options);
102 std::string Namespace(const FieldDescriptor* d, const Options& options);
103 std::string Namespace(const EnumDescriptor* d, const Options& options);
104 
105 // Returns true if it's safe to reset "field" to zero.
106 bool CanInitializeByZeroing(const FieldDescriptor* field);
107 
108 std::string ClassName(const Descriptor* descriptor);
109 std::string ClassName(const EnumDescriptor* enum_descriptor);
110 
111 std::string QualifiedClassName(const Descriptor* d, const Options& options);
112 std::string QualifiedClassName(const EnumDescriptor* d, const Options& options);
113 
114 std::string QualifiedClassName(const Descriptor* d);
115 std::string QualifiedClassName(const EnumDescriptor* d);
116 
117 // DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
118 // unreadable at the callsite.
119 // Returns the non-nested type name for the given type.  If "qualified" is
120 // true, prefix the type with the full namespace.  For example, if you had:
121 //   package foo.bar;
122 //   message Baz { message Qux {} }
123 // Then the qualified ClassName for Qux would be:
124 //   ::foo::bar::Baz_Qux
125 // While the non-qualified version would be:
126 //   Baz_Qux
ClassName(const Descriptor * descriptor,bool qualified)127 inline std::string ClassName(const Descriptor* descriptor, bool qualified) {
128   return qualified ? QualifiedClassName(descriptor, Options())
129                    : ClassName(descriptor);
130 }
131 
ClassName(const EnumDescriptor * descriptor,bool qualified)132 inline std::string ClassName(const EnumDescriptor* descriptor, bool qualified) {
133   return qualified ? QualifiedClassName(descriptor, Options())
134                    : ClassName(descriptor);
135 }
136 
137 std::string QualifiedExtensionName(const FieldDescriptor* d,
138                                    const Options& options);
139 std::string QualifiedExtensionName(const FieldDescriptor* d);
140 
141 // Type name of default instance.
142 std::string DefaultInstanceType(const Descriptor* descriptor,
143                                 const Options& options);
144 
145 // Non-qualified name of the default_instance of this message.
146 std::string DefaultInstanceName(const Descriptor* descriptor,
147                                 const Options& options);
148 
149 // Non-qualified name of the default instance pointer. This is used only for
150 // implicit weak fields, where we need an extra indirection.
151 std::string DefaultInstancePtr(const Descriptor* descriptor,
152                                const Options& options);
153 
154 // Fully qualified name of the default_instance of this message.
155 std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
156                                          const Options& options);
157 
158 // Fully qualified name of the default instance pointer.
159 std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
160                                         const Options& options);
161 
162 // DescriptorTable variable name.
163 std::string DescriptorTableName(const FileDescriptor* file,
164                                 const Options& options);
165 
166 // When declaring symbol externs from another file, this macro will supply the
167 // dllexport needed for the target file, if any.
168 std::string FileDllExport(const FileDescriptor* file, const Options& options);
169 
170 // Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
171 std::string SuperClassName(const Descriptor* descriptor,
172                            const Options& options);
173 
174 // Adds an underscore if necessary to prevent conflicting with a keyword.
175 std::string ResolveKeyword(const std::string& name);
176 
177 // Get the (unqualified) name that should be used for this field in C++ code.
178 // The name is coerced to lower-case to emulate proto1 behavior.  People
179 // should be using lowercase-with-underscores style for proto field names
180 // anyway, so normally this just returns field->name().
181 std::string FieldName(const FieldDescriptor* field);
182 
183 // Get the sanitized name that should be used for the given enum in C++ code.
184 std::string EnumValueName(const EnumValueDescriptor* enum_value);
185 
186 // Returns an estimate of the compiler's alignment for the field.  This
187 // can't guarantee to be correct because the generated code could be compiled on
188 // different systems with different alignment rules.  The estimates below assume
189 // 64-bit pointers.
190 int EstimateAlignmentSize(const FieldDescriptor* field);
191 
192 // Get the unqualified name that should be used for a field's field
193 // number constant.
194 std::string FieldConstantName(const FieldDescriptor* field);
195 
196 // Returns the scope where the field was defined (for extensions, this is
197 // different from the message type to which the field applies).
FieldScope(const FieldDescriptor * field)198 inline const Descriptor* FieldScope(const FieldDescriptor* field) {
199   return field->is_extension() ? field->extension_scope()
200                                : field->containing_type();
201 }
202 
203 // Returns the fully-qualified type name field->message_type().  Usually this
204 // is just ClassName(field->message_type(), true);
205 std::string FieldMessageTypeName(const FieldDescriptor* field,
206                                  const Options& options);
207 
208 // Strips ".proto" or ".protodevel" from the end of a filename.
209 PROTOC_EXPORT std::string StripProto(const std::string& filename);
210 
211 // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
212 const char* PrimitiveTypeName(FieldDescriptor::CppType type);
213 std::string PrimitiveTypeName(const Options& options,
214                               FieldDescriptor::CppType type);
215 
216 // Get the declared type name in CamelCase format, as is used e.g. for the
217 // methods of WireFormat.  For example, TYPE_INT32 becomes "Int32".
218 const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
219 
220 // Return the code that evaluates to the number when compiled.
221 std::string Int32ToString(int number);
222 
223 // Return the code that evaluates to the number when compiled.
224 std::string Int64ToString(const Options& options, int64 number);
225 
226 // Get code that evaluates to the field's default value.
227 std::string DefaultValue(const Options& options, const FieldDescriptor* field);
228 
229 // Compatibility function for callers outside proto2.
230 std::string DefaultValue(const FieldDescriptor* field);
231 
232 // Convert a file name into a valid identifier.
233 std::string FilenameIdentifier(const std::string& filename);
234 
235 // For each .proto file generates a unique name. To prevent collisions of
236 // symbols in the global namespace
237 std::string UniqueName(const std::string& name, const std::string& filename,
238                        const Options& options);
UniqueName(const std::string & name,const FileDescriptor * d,const Options & options)239 inline std::string UniqueName(const std::string& name, const FileDescriptor* d,
240                               const Options& options) {
241   return UniqueName(name, d->name(), options);
242 }
UniqueName(const std::string & name,const Descriptor * d,const Options & options)243 inline std::string UniqueName(const std::string& name, const Descriptor* d,
244                               const Options& options) {
245   return UniqueName(name, d->file(), options);
246 }
UniqueName(const std::string & name,const EnumDescriptor * d,const Options & options)247 inline std::string UniqueName(const std::string& name, const EnumDescriptor* d,
248                               const Options& options) {
249   return UniqueName(name, d->file(), options);
250 }
UniqueName(const std::string & name,const ServiceDescriptor * d,const Options & options)251 inline std::string UniqueName(const std::string& name,
252                               const ServiceDescriptor* d,
253                               const Options& options) {
254   return UniqueName(name, d->file(), options);
255 }
256 
257 // Versions for call sites that only support the internal runtime (like proto1
258 // support).
InternalRuntimeOptions()259 inline Options InternalRuntimeOptions() {
260   Options options;
261   options.opensource_runtime = false;
262   return options;
263 }
UniqueName(const std::string & name,const std::string & filename)264 inline std::string UniqueName(const std::string& name,
265                               const std::string& filename) {
266   return UniqueName(name, filename, InternalRuntimeOptions());
267 }
UniqueName(const std::string & name,const FileDescriptor * d)268 inline std::string UniqueName(const std::string& name,
269                               const FileDescriptor* d) {
270   return UniqueName(name, d->name(), InternalRuntimeOptions());
271 }
UniqueName(const std::string & name,const Descriptor * d)272 inline std::string UniqueName(const std::string& name, const Descriptor* d) {
273   return UniqueName(name, d->file(), InternalRuntimeOptions());
274 }
UniqueName(const std::string & name,const EnumDescriptor * d)275 inline std::string UniqueName(const std::string& name,
276                               const EnumDescriptor* d) {
277   return UniqueName(name, d->file(), InternalRuntimeOptions());
278 }
UniqueName(const std::string & name,const ServiceDescriptor * d)279 inline std::string UniqueName(const std::string& name,
280                               const ServiceDescriptor* d) {
281   return UniqueName(name, d->file(), InternalRuntimeOptions());
282 }
283 
284 // Return the qualified C++ name for a file level symbol.
285 std::string QualifiedFileLevelSymbol(const FileDescriptor* file,
286                                      const std::string& name,
287                                      const Options& options);
288 
289 // Escape C++ trigraphs by escaping question marks to \?
290 std::string EscapeTrigraphs(const std::string& to_escape);
291 
292 // Escaped function name to eliminate naming conflict.
293 std::string SafeFunctionName(const Descriptor* descriptor,
294                              const FieldDescriptor* field,
295                              const std::string& prefix);
296 
297 // Returns true if generated messages have public unknown fields accessors
PublicUnknownFieldsAccessors(const Descriptor * message)298 inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
299   return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
300 }
301 
302 // Returns the optimize mode for <file>, respecting <options.enforce_lite>.
303 FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
304                                         const Options& options);
305 
306 // Determines whether unknown fields will be stored in an UnknownFieldSet or
307 // a string.
UseUnknownFieldSet(const FileDescriptor * file,const Options & options)308 inline bool UseUnknownFieldSet(const FileDescriptor* file,
309                                const Options& options) {
310   return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
311 }
312 
IsWeak(const FieldDescriptor * field,const Options & options)313 inline bool IsWeak(const FieldDescriptor* field, const Options& options) {
314   if (field->options().weak()) {
315     GOOGLE_CHECK(!options.opensource_runtime);
316     return true;
317   }
318   return false;
319 }
320 
321 bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
322 
323 // For a string field, returns the effective ctype.  If the actual ctype is
324 // not supported, returns the default of STRING.
325 FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field,
326                                          const Options& options);
327 
IsCord(const FieldDescriptor * field,const Options & options)328 inline bool IsCord(const FieldDescriptor* field, const Options& options) {
329   return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
330          EffectiveStringCType(field, options) == FieldOptions::CORD;
331 }
332 
IsStringPiece(const FieldDescriptor * field,const Options & options)333 inline bool IsStringPiece(const FieldDescriptor* field,
334                           const Options& options) {
335   return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
336          EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
337 }
338 
339 // Does the given FileDescriptor use lazy fields?
340 bool HasLazyFields(const FileDescriptor* file, const Options& options);
341 
342 // Is the given field a supported lazy field?
IsLazy(const FieldDescriptor * field,const Options & options)343 inline bool IsLazy(const FieldDescriptor* field, const Options& options) {
344   return field->options().lazy() && !field->is_repeated() &&
345          field->type() == FieldDescriptor::TYPE_MESSAGE &&
346          GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME &&
347          !options.opensource_runtime;
348 }
349 
350 // Returns true if "field" is used.
IsFieldUsed(const FieldDescriptor *,const Options &)351 inline bool IsFieldUsed(const FieldDescriptor* /*field*/,
352                         const Options& /*options*/) {
353   return true;
354 }
355 
356 // Does the file contain any definitions that need extension_set.h?
357 bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
358 
359 // Does the file have any repeated fields, necessitating the file to include
360 // repeated_field.h? This does not include repeated extensions, since those are
361 // all stored internally in an ExtensionSet, not a separate RepeatedField*.
362 bool HasRepeatedFields(const FileDescriptor* file);
363 
364 // Does the file have any string/bytes fields with ctype=STRING_PIECE? This
365 // does not include extensions, since ctype is ignored for extensions.
366 bool HasStringPieceFields(const FileDescriptor* file, const Options& options);
367 
368 // Does the file have any string/bytes fields with ctype=CORD? This does not
369 // include extensions, since ctype is ignored for extensions.
370 bool HasCordFields(const FileDescriptor* file, const Options& options);
371 
372 // Does the file have any map fields, necessitating the file to include
373 // map_field_inl.h and map.h.
374 bool HasMapFields(const FileDescriptor* file);
375 
376 // Does this file have any enum type definitions?
377 bool HasEnumDefinitions(const FileDescriptor* file);
378 
379 // Does this file have generated parsing, serialization, and other
380 // standard methods for which reflection-based fallback implementations exist?
HasGeneratedMethods(const FileDescriptor * file,const Options & options)381 inline bool HasGeneratedMethods(const FileDescriptor* file,
382                                 const Options& options) {
383   return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
384 }
385 
386 // Do message classes in this file have descriptor and reflection methods?
HasDescriptorMethods(const FileDescriptor * file,const Options & options)387 inline bool HasDescriptorMethods(const FileDescriptor* file,
388                                  const Options& options) {
389   return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
390 }
391 
392 // Should we generate generic services for this file?
HasGenericServices(const FileDescriptor * file,const Options & options)393 inline bool HasGenericServices(const FileDescriptor* file,
394                                const Options& options) {
395   return file->service_count() > 0 &&
396          GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
397          file->options().cc_generic_services();
398 }
399 
IsProto2MessageSet(const Descriptor * descriptor,const Options & options)400 inline bool IsProto2MessageSet(const Descriptor* descriptor,
401                                const Options& options) {
402   return !options.opensource_runtime &&
403          options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
404          !options.lite_implicit_weak_fields &&
405          descriptor->options().message_set_wire_format() &&
406          descriptor->full_name() == "google.protobuf.bridge.MessageSet";
407 }
408 
IsProto2MessageSetFile(const FileDescriptor * file,const Options & options)409 inline bool IsProto2MessageSetFile(const FileDescriptor* file,
410                                    const Options& options) {
411   return !options.opensource_runtime &&
412          options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
413          !options.lite_implicit_weak_fields &&
414          file->name() == "net/proto2/bridge/proto/message_set.proto";
415 }
416 
IsMapEntryMessage(const Descriptor * descriptor)417 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
418   return descriptor->options().map_entry();
419 }
420 
421 // Returns true if the field's CPPTYPE is string or message.
422 bool IsStringOrMessage(const FieldDescriptor* field);
423 
424 std::string UnderscoresToCamelCase(const std::string& input,
425                                    bool cap_next_letter);
426 
HasFieldPresence(const FileDescriptor * file)427 inline bool HasFieldPresence(const FileDescriptor* file) {
428   return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
429 }
430 
HasHasbit(const FieldDescriptor * field)431 inline bool HasHasbit(const FieldDescriptor* field) {
432   // This predicate includes proto3 message fields only if they have "optional".
433   //   Foo submsg1 = 1;           // HasHasbit() == false
434   //   optional Foo submsg2 = 2;  // HasHasbit() == true
435   // This is slightly odd, as adding "optional" to a singular proto3 field does
436   // not change the semantics or API. However whenever any field in a message
437   // has a hasbit, it forces reflection to include hasbit offsets for *all*
438   // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
439   // causing a sudden size regression for ~all proto3 messages, we give proto3
440   // message fields a hasbit only if "optional" is present. If the user is
441   // explicitly writing "optional", it is likely they are writing it on
442   // primitive fields also.
443   return (field->has_optional_keyword() || field->is_required()) &&
444          !field->options().weak();
445 }
446 
447 // Returns true if 'enum' semantics are such that unknown values are preserved
448 // in the enum field itself, rather than going to the UnknownFieldSet.
HasPreservingUnknownEnumSemantics(const FieldDescriptor * field)449 inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
450   return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
451 }
452 
SupportsArenas(const FileDescriptor * file)453 inline bool SupportsArenas(const FileDescriptor* file) {
454   return file->options().cc_enable_arenas();
455 }
456 
SupportsArenas(const Descriptor * desc)457 inline bool SupportsArenas(const Descriptor* desc) {
458   return SupportsArenas(desc->file());
459 }
460 
SupportsArenas(const FieldDescriptor * field)461 inline bool SupportsArenas(const FieldDescriptor* field) {
462   return SupportsArenas(field->file());
463 }
464 
IsCrossFileMessage(const FieldDescriptor * field)465 inline bool IsCrossFileMessage(const FieldDescriptor* field) {
466   return field->type() == FieldDescriptor::TYPE_MESSAGE &&
467          field->message_type()->file() != field->file();
468 }
469 
MessageCreateFunction(const Descriptor * d)470 inline std::string MessageCreateFunction(const Descriptor* d) {
471   return SupportsArenas(d) ? "CreateMessage" : "Create";
472 }
473 
MakeDefaultName(const FieldDescriptor * field)474 inline std::string MakeDefaultName(const FieldDescriptor* field) {
475   return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
476          "_";
477 }
478 
479 bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options);
480 bool IsAnyMessage(const Descriptor* descriptor, const Options& options);
481 
482 bool IsWellKnownMessage(const FileDescriptor* descriptor);
483 
IncludeGuard(const FileDescriptor * file,bool pb_h,const Options & options)484 inline std::string IncludeGuard(const FileDescriptor* file, bool pb_h,
485                                 const Options& options) {
486   // If we are generating a .pb.h file and the proto_h option is enabled, then
487   // the .pb.h gets an extra suffix.
488   std::string filename_identifier = FilenameIdentifier(
489       file->name() + (pb_h && options.proto_h ? ".pb.h" : ""));
490 
491   if (IsWellKnownMessage(file)) {
492     // For well-known messages we need third_party/protobuf and net/proto2 to
493     // have distinct include guards, because some source files include both and
494     // both need to be defined (the third_party copies will be in the
495     // google::protobuf_opensource namespace).
496     return MacroPrefix(options) + "_INCLUDED_" + filename_identifier;
497   } else {
498     // Ideally this case would use distinct include guards for opensource and
499     // google3 protos also.  (The behavior of "first #included wins" is not
500     // ideal).  But unfortunately some legacy code includes both and depends on
501     // the identical include guards to avoid compile errors.
502     //
503     // We should clean this up so that this case can be removed.
504     return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier;
505   }
506 }
507 
508 // Returns the OptimizeMode for this file, furthermore it updates a status
509 // bool if has_opt_codesize_extension is non-null. If this status bool is true
510 // it means this file contains an extension that itself is defined as
511 // optimized_for = CODE_SIZE.
512 FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
513                                         const Options& options,
514                                         bool* has_opt_codesize_extension);
GetOptimizeFor(const FileDescriptor * file,const Options & options)515 inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
516                                                const Options& options) {
517   return GetOptimizeFor(file, options, nullptr);
518 }
NeedsEagerDescriptorAssignment(const FileDescriptor * file,const Options & options)519 inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file,
520                                            const Options& options) {
521   bool has_opt_codesize_extension;
522   if (GetOptimizeFor(file, options, &has_opt_codesize_extension) ==
523           FileOptions::CODE_SIZE &&
524       has_opt_codesize_extension) {
525     // If this filedescriptor contains an extension from another file which
526     // is optimized_for = CODE_SIZE. We need to be careful in the ordering so
527     // we eagerly build the descriptors in the dependencies before building
528     // the descriptors of this file.
529     return true;
530   } else {
531     // If we have a generated code based parser we never need eager
532     // initialization of descriptors of our deps.
533     return false;
534   }
535 }
536 
537 // This orders the messages in a .pb.cc as it's outputted by file.cc
538 void FlattenMessagesInFile(const FileDescriptor* file,
539                            std::vector<const Descriptor*>* result);
FlattenMessagesInFile(const FileDescriptor * file)540 inline std::vector<const Descriptor*> FlattenMessagesInFile(
541     const FileDescriptor* file) {
542   std::vector<const Descriptor*> result;
543   FlattenMessagesInFile(file, &result);
544   return result;
545 }
546 
547 bool HasWeakFields(const Descriptor* desc, const Options& options);
548 bool HasWeakFields(const FileDescriptor* desc, const Options& options);
549 
550 // Returns true if the "required" restriction check should be ignored for the
551 // given field.
ShouldIgnoreRequiredFieldCheck(const FieldDescriptor * field,const Options & options)552 inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
553                                                   const Options& options) {
554   // Do not check "required" for lazy fields.
555   return IsLazy(field, options);
556 }
557 
558 struct MessageAnalysis {
559   bool is_recursive;
560   bool contains_cord;
561   bool contains_extension;
562   bool contains_required;
563   bool constructor_requires_initialization;
564 };
565 
566 // This class is used in FileGenerator, to ensure linear instead of
567 // quadratic performance, if we do this per message we would get O(V*(V+E)).
568 // Logically this is just only used in message.cc, but in the header for
569 // FileGenerator to help share it.
570 class PROTOC_EXPORT MessageSCCAnalyzer {
571  public:
MessageSCCAnalyzer(const Options & options)572   explicit MessageSCCAnalyzer(const Options& options) : options_(options) {}
573 
574   MessageAnalysis GetSCCAnalysis(const SCC* scc);
575 
HasRequiredFields(const Descriptor * descriptor)576   bool HasRequiredFields(const Descriptor* descriptor) {
577     MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
578     return result.contains_required || result.contains_extension;
579   }
GetSCC(const Descriptor * descriptor)580   const SCC* GetSCC(const Descriptor* descriptor) {
581     return analyzer_.GetSCC(descriptor);
582   }
583 
584  private:
585   struct DepsGenerator {
operatorDepsGenerator586     std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
587       std::vector<const Descriptor*> deps;
588       for (int i = 0; i < desc->field_count(); i++) {
589         if (desc->field(i)->message_type()) {
590           deps.push_back(desc->field(i)->message_type());
591         }
592       }
593       return deps;
594     }
595   };
596   SCCAnalyzer<DepsGenerator> analyzer_;
597   Options options_;
598   std::map<const SCC*, MessageAnalysis> analysis_cache_;
599 };
600 
SccInfoSymbol(const SCC * scc,const Options & options)601 inline std::string SccInfoSymbol(const SCC* scc, const Options& options) {
602   return UniqueName("scc_info_" + ClassName(scc->GetRepresentative()),
603                     scc->GetRepresentative(), options);
604 }
605 
SccInfoPtrSymbol(const SCC * scc,const Options & options)606 inline std::string SccInfoPtrSymbol(const SCC* scc, const Options& options) {
607   return UniqueName("scc_info_ptr_" + ClassName(scc->GetRepresentative()),
608                     scc->GetRepresentative(), options);
609 }
610 
611 void ListAllFields(const Descriptor* d,
612                    std::vector<const FieldDescriptor*>* fields);
613 void ListAllFields(const FileDescriptor* d,
614                    std::vector<const FieldDescriptor*>* fields);
615 
616 template <class T>
ForEachField(const Descriptor * d,T && func)617 void ForEachField(const Descriptor* d, T&& func) {
618   for (int i = 0; i < d->nested_type_count(); i++) {
619     ForEachField(d->nested_type(i), std::forward<T&&>(func));
620   }
621   for (int i = 0; i < d->extension_count(); i++) {
622     func(d->extension(i));
623   }
624   for (int i = 0; i < d->field_count(); i++) {
625     func(d->field(i));
626   }
627 }
628 
629 template <class T>
ForEachField(const FileDescriptor * d,T && func)630 void ForEachField(const FileDescriptor* d, T&& func) {
631   for (int i = 0; i < d->message_type_count(); i++) {
632     ForEachField(d->message_type(i), std::forward<T&&>(func));
633   }
634   for (int i = 0; i < d->extension_count(); i++) {
635     func(d->extension(i));
636   }
637 }
638 
639 void ListAllTypesForServices(const FileDescriptor* fd,
640                              std::vector<const Descriptor*>* types);
641 
642 // Indicates whether we should use implicit weak fields for this file.
643 bool UsingImplicitWeakFields(const FileDescriptor* file,
644                              const Options& options);
645 
646 // Indicates whether to treat this field as implicitly weak.
647 bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
648                          MessageSCCAnalyzer* scc_analyzer);
649 
650 // Formatter is a functor class which acts as a closure around printer and
651 // the variable map. It's much like printer->Print except it supports both named
652 // variables that are substituted using a key value map and direct arguments. In
653 // the format string $1$, $2$, etc... are substituted for the first, second, ...
654 // direct argument respectively in the format call, it accepts both strings and
655 // integers. The implementation verifies all arguments are used and are "first"
656 // used in order of appearance in the argument list. For example,
657 //
658 // Format("return array[$1$];", 3) -> "return array[3];"
659 // Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order)
660 // Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;"
661 //
662 // The arguments can be used more than once like
663 //
664 // Format("array[$1$] = $2$;  // Index = $1$", 3, "Bla") ->
665 //        "array[3] = Bla;  // Index = 3"
666 //
667 // If you use more arguments use the following style to help the reader,
668 //
669 // Format("int $1$() {\n"
670 //        "  array[$2$] = $3$;\n"
671 //        "  return $4$;"
672 //        "}\n",
673 //        funname, // 1
674 //        idx,  // 2
675 //        varname,  // 3
676 //        retval);  // 4
677 //
678 // but consider using named variables. Named variables like $foo$, with some
679 // identifier foo, are looked up in the map. One additional feature is that
680 // spaces are accepted between the '$' delimiters, $ foo$ will
681 // substiture to " bar" if foo stands for "bar", but in case it's empty
682 // will substitute to "". Hence, for example,
683 //
684 // Format(vars, "$dllexport $void fun();") -> "void fun();"
685 //                                            "__declspec(export) void fun();"
686 //
687 // which is convenient to prevent double, leading or trailing spaces.
688 class PROTOC_EXPORT Formatter {
689  public:
Formatter(io::Printer * printer)690   explicit Formatter(io::Printer* printer) : printer_(printer) {}
Formatter(io::Printer * printer,const std::map<std::string,std::string> & vars)691   Formatter(io::Printer* printer,
692             const std::map<std::string, std::string>& vars)
693       : printer_(printer), vars_(vars) {}
694 
695   template <typename T>
Set(const std::string & key,const T & value)696   void Set(const std::string& key, const T& value) {
697     vars_[key] = ToString(value);
698   }
699 
AddMap(const std::map<std::string,std::string> & vars)700   void AddMap(const std::map<std::string, std::string>& vars) {
701     for (const auto& keyval : vars) vars_[keyval.first] = keyval.second;
702   }
703 
704   template <typename... Args>
operator()705   void operator()(const char* format, const Args&... args) const {
706     printer_->FormatInternal({ToString(args)...}, vars_, format);
707   }
708 
Indent()709   void Indent() const { printer_->Indent(); }
Outdent()710   void Outdent() const { printer_->Outdent(); }
printer()711   io::Printer* printer() const { return printer_; }
712 
713   class PROTOC_EXPORT SaveState {
714    public:
SaveState(Formatter * format)715     explicit SaveState(Formatter* format)
716         : format_(format), vars_(format->vars_) {}
~SaveState()717     ~SaveState() { format_->vars_.swap(vars_); }
718 
719    private:
720     Formatter* format_;
721     std::map<std::string, std::string> vars_;
722   };
723 
724  private:
725   io::Printer* printer_;
726   std::map<std::string, std::string> vars_;
727 
728   // Convenience overloads to accept different types as arguments.
ToString(const std::string & s)729   static std::string ToString(const std::string& s) { return s; }
730   template <typename I, typename = typename std::enable_if<
731                             std::is_integral<I>::value>::type>
ToString(I x)732   static std::string ToString(I x) {
733     return StrCat(x);
734   }
ToString(strings::Hex x)735   static std::string ToString(strings::Hex x) { return StrCat(x); }
ToString(const FieldDescriptor * d)736   static std::string ToString(const FieldDescriptor* d) { return Payload(d); }
ToString(const Descriptor * d)737   static std::string ToString(const Descriptor* d) { return Payload(d); }
ToString(const EnumDescriptor * d)738   static std::string ToString(const EnumDescriptor* d) { return Payload(d); }
ToString(const EnumValueDescriptor * d)739   static std::string ToString(const EnumValueDescriptor* d) {
740     return Payload(d);
741   }
ToString(const OneofDescriptor * d)742   static std::string ToString(const OneofDescriptor* d) { return Payload(d); }
743 
744   template <typename Descriptor>
Payload(const Descriptor * descriptor)745   static std::string Payload(const Descriptor* descriptor) {
746     std::vector<int> path;
747     descriptor->GetLocationPath(&path);
748     GeneratedCodeInfo::Annotation annotation;
749     for (int i = 0; i < path.size(); ++i) {
750       annotation.add_path(path[i]);
751     }
752     annotation.set_source_file(descriptor->file()->name());
753     return annotation.SerializeAsString();
754   }
755 };
756 
757 template <class T>
PrintFieldComment(const Formatter & format,const T * field)758 void PrintFieldComment(const Formatter& format, const T* field) {
759   // Print the field's (or oneof's) proto-syntax definition as a comment.
760   // We don't want to print group bodies so we cut off after the first
761   // line.
762   DebugStringOptions options;
763   options.elide_group_body = true;
764   options.elide_oneof_body = true;
765   std::string def = field->DebugStringWithOptions(options);
766   format("// $1$\n", def.substr(0, def.find_first_of('\n')));
767 }
768 
769 class PROTOC_EXPORT NamespaceOpener {
770  public:
NamespaceOpener(const Formatter & format)771   explicit NamespaceOpener(const Formatter& format)
772       : printer_(format.printer()) {}
NamespaceOpener(const std::string & name,const Formatter & format)773   NamespaceOpener(const std::string& name, const Formatter& format)
774       : NamespaceOpener(format) {
775     ChangeTo(name);
776   }
~NamespaceOpener()777   ~NamespaceOpener() { ChangeTo(""); }
778 
ChangeTo(const std::string & name)779   void ChangeTo(const std::string& name) {
780     std::vector<std::string> new_stack_ =
781         Split(name, "::", true);
782     int len = std::min(name_stack_.size(), new_stack_.size());
783     int common_idx = 0;
784     while (common_idx < len) {
785       if (name_stack_[common_idx] != new_stack_[common_idx]) break;
786       common_idx++;
787     }
788     for (int i = name_stack_.size() - 1; i >= common_idx; i--) {
789       if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
790         printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n");
791       } else {
792         printer_->Print("}  // namespace $ns$\n", "ns", name_stack_[i]);
793       }
794     }
795     name_stack_.swap(new_stack_);
796     for (int i = common_idx; i < name_stack_.size(); i++) {
797       if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
798         printer_->Print("PROTOBUF_NAMESPACE_OPEN\n");
799       } else {
800         printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
801       }
802     }
803   }
804 
805  private:
806   io::Printer* printer_;
807   std::vector<std::string> name_stack_;
808 };
809 
810 enum Utf8CheckMode {
811   STRICT = 0,  // Parsing will fail if non UTF-8 data is in string fields.
812   VERIFY = 1,  // Only log an error but parsing will succeed.
813   NONE = 2,    // No UTF-8 check.
814 };
815 
816 Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
817                                const Options& options);
818 
819 void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
820                                     const Options& options, bool for_parse,
821                                     const char* parameters,
822                                     const Formatter& format);
823 
824 void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
825                                   const Options& options, bool for_parse,
826                                   const char* parameters,
827                                   const Formatter& format);
828 
829 template <typename T>
830 struct FieldRangeImpl {
831   struct Iterator {
832     using iterator_category = std::forward_iterator_tag;
833     using value_type = const FieldDescriptor*;
834     using difference_type = int;
835 
836     value_type operator*() { return descriptor->field(idx); }
837 
838     friend bool operator==(const Iterator& a, const Iterator& b) {
839       GOOGLE_DCHECK(a.descriptor == b.descriptor);
840       return a.idx == b.idx;
841     }
842     friend bool operator!=(const Iterator& a, const Iterator& b) {
843       return !(a == b);
844     }
845 
846     Iterator& operator++() {
847       idx++;
848       return *this;
849     }
850 
851     int idx;
852     const T* descriptor;
853   };
854 
beginFieldRangeImpl855   Iterator begin() const { return {0, descriptor}; }
endFieldRangeImpl856   Iterator end() const { return {descriptor->field_count(), descriptor}; }
857 
858   const T* descriptor;
859 };
860 
861 template <typename T>
FieldRange(const T * desc)862 FieldRangeImpl<T> FieldRange(const T* desc) {
863   return {desc};
864 }
865 
866 struct OneOfRangeImpl {
867   struct Iterator {
868     using iterator_category = std::forward_iterator_tag;
869     using value_type = const OneofDescriptor*;
870     using difference_type = int;
871 
872     value_type operator*() { return descriptor->oneof_decl(idx); }
873 
874     friend bool operator==(const Iterator& a, const Iterator& b) {
875       GOOGLE_DCHECK(a.descriptor == b.descriptor);
876       return a.idx == b.idx;
877     }
878     friend bool operator!=(const Iterator& a, const Iterator& b) {
879       return !(a == b);
880     }
881 
882     Iterator& operator++() {
883       idx++;
884       return *this;
885     }
886 
887     int idx;
888     const Descriptor* descriptor;
889   };
890 
beginOneOfRangeImpl891   Iterator begin() const { return {0, descriptor}; }
endOneOfRangeImpl892   Iterator end() const {
893     return {descriptor->real_oneof_decl_count(), descriptor};
894   }
895 
896   const Descriptor* descriptor;
897 };
898 
OneOfRange(const Descriptor * desc)899 inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
900 
901 void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits,
902                         const Options& options,
903                         MessageSCCAnalyzer* scc_analyzer, io::Printer* printer);
904 
905 }  // namespace cpp
906 }  // namespace compiler
907 }  // namespace protobuf
908 }  // namespace google
909 
910 #include <google/protobuf/port_undef.inc>
911 
912 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
913