File indexing completed on 2025-01-31 10:11:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
0013 #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
0014
0015 #include <iterator>
0016 #include <string>
0017 #include <tuple>
0018 #include <vector>
0019
0020 #include "absl/container/flat_hash_map.h"
0021 #include "absl/log/absl_check.h"
0022 #include "absl/strings/str_cat.h"
0023 #include "absl/strings/str_split.h"
0024 #include "absl/strings/string_view.h"
0025 #include "absl/types/optional.h"
0026 #include "google/protobuf/compiler/code_generator.h"
0027 #include "google/protobuf/compiler/cpp/names.h"
0028 #include "google/protobuf/compiler/cpp/options.h"
0029 #include "google/protobuf/compiler/scc.h"
0030 #include "google/protobuf/descriptor.h"
0031 #include "google/protobuf/descriptor.pb.h"
0032 #include "google/protobuf/io/printer.h"
0033 #include "google/protobuf/port.h"
0034
0035
0036
0037 #include "google/protobuf/port_def.inc"
0038
0039 namespace google {
0040 namespace protobuf {
0041 namespace compiler {
0042 namespace cpp {
0043 enum class ArenaDtorNeeds { kNone = 0, kOnDemand = 1, kRequired = 2 };
0044
0045 inline absl::string_view ProtobufNamespace(const Options& opts) {
0046
0047 constexpr absl::string_view kGoogle3Ns = "proto2";
0048 constexpr absl::string_view kOssNs = "google::protobuf";
0049
0050 return opts.opensource_runtime ? kOssNs : kGoogle3Ns;
0051 }
0052
0053 inline std::string MacroPrefix(const Options& options) {
0054
0055 return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF";
0056 }
0057
0058 inline std::string DeprecatedAttribute(const Options&,
0059 const FieldDescriptor* d) {
0060 return d->options().deprecated() ? "[[deprecated]] " : "";
0061 }
0062
0063 inline std::string DeprecatedAttribute(const Options&,
0064 const EnumValueDescriptor* d) {
0065 return d->options().deprecated() ? "[[deprecated]] " : "";
0066 }
0067
0068
0069
0070 extern const char kThickSeparator[];
0071 extern const char kThinSeparator[];
0072
0073 absl::flat_hash_map<absl::string_view, std::string> MessageVars(
0074 const Descriptor* desc);
0075
0076
0077 void SetCommonMessageDataVariables(
0078 const Descriptor* descriptor,
0079 absl::flat_hash_map<absl::string_view, std::string>* variables);
0080
0081 absl::flat_hash_map<absl::string_view, std::string> UnknownFieldsVars(
0082 const Descriptor* desc, const Options& opts);
0083
0084 void SetUnknownFieldsVariable(
0085 const Descriptor* descriptor, const Options& options,
0086 absl::flat_hash_map<absl::string_view, std::string>* variables);
0087
0088 bool GetBootstrapBasename(const Options& options, absl::string_view basename,
0089 std::string* bootstrap_basename);
0090 bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
0091 bool bootstrap_flag, std::string* basename);
0092 bool IsBootstrapProto(const Options& options, const FileDescriptor* file);
0093
0094
0095
0096
0097
0098 std::string Namespace(const FileDescriptor* d, const Options& options);
0099 std::string Namespace(const Descriptor* d, const Options& options);
0100 std::string Namespace(const FieldDescriptor* d, const Options& options);
0101 std::string Namespace(const EnumDescriptor* d, const Options& options);
0102 PROTOC_EXPORT std::string Namespace(const FileDescriptor* d);
0103 PROTOC_EXPORT std::string Namespace(const Descriptor* d);
0104 PROTOC_EXPORT std::string Namespace(const FieldDescriptor* d);
0105 PROTOC_EXPORT std::string Namespace(const EnumDescriptor* d);
0106
0107 class MessageSCCAnalyzer;
0108
0109
0110 bool CanInitializeByZeroing(const FieldDescriptor* field,
0111 const Options& options,
0112 MessageSCCAnalyzer* scc_analyzer);
0113
0114 bool CanClearByZeroing(const FieldDescriptor* field);
0115
0116 bool HasTrivialSwap(const FieldDescriptor* field, const Options& options,
0117 MessageSCCAnalyzer* scc_analyzer);
0118
0119 PROTOC_EXPORT std::string ClassName(const Descriptor* descriptor);
0120 PROTOC_EXPORT std::string ClassName(const EnumDescriptor* enum_descriptor);
0121
0122 std::string QualifiedClassName(const Descriptor* d, const Options& options);
0123 std::string QualifiedClassName(const EnumDescriptor* d, const Options& options);
0124
0125 PROTOC_EXPORT std::string QualifiedClassName(const Descriptor* d);
0126 PROTOC_EXPORT std::string QualifiedClassName(const EnumDescriptor* d);
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 inline std::string ClassName(const Descriptor* descriptor, bool qualified) {
0139 return qualified ? QualifiedClassName(descriptor, Options())
0140 : ClassName(descriptor);
0141 }
0142
0143 inline std::string ClassName(const EnumDescriptor* descriptor, bool qualified) {
0144 return qualified ? QualifiedClassName(descriptor, Options())
0145 : ClassName(descriptor);
0146 }
0147
0148
0149
0150 std::string ExtensionName(const FieldDescriptor* d);
0151
0152 std::string QualifiedExtensionName(const FieldDescriptor* d,
0153 const Options& options);
0154 std::string QualifiedExtensionName(const FieldDescriptor* d);
0155
0156
0157 std::string DefaultInstanceType(const Descriptor* descriptor,
0158 const Options& options, bool split = false);
0159
0160
0161 std::string DefaultInstanceName(const Descriptor* descriptor,
0162 const Options& options, bool split = false);
0163
0164
0165
0166 std::string DefaultInstancePtr(const Descriptor* descriptor,
0167 const Options& options, bool split = false);
0168
0169
0170 std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
0171 const Options& options,
0172 bool split = false);
0173
0174
0175 std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
0176 const Options& options,
0177 bool split = false);
0178
0179
0180 std::string DescriptorTableName(const FileDescriptor* file,
0181 const Options& options);
0182
0183
0184
0185 std::string FileDllExport(const FileDescriptor* file, const Options& options);
0186
0187
0188 std::string SuperClassName(const Descriptor* descriptor,
0189 const Options& options);
0190
0191
0192 std::string ResolveKeyword(absl::string_view name);
0193
0194
0195
0196
0197
0198 PROTOC_EXPORT std::string FieldName(const FieldDescriptor* field);
0199
0200
0201 std::string FieldMemberName(const FieldDescriptor* field, bool split);
0202
0203
0204
0205
0206
0207 int EstimateAlignmentSize(const FieldDescriptor* field);
0208
0209
0210
0211
0212
0213 int EstimateSize(const FieldDescriptor* field);
0214
0215
0216
0217 std::string FieldConstantName(const FieldDescriptor* field);
0218
0219
0220
0221 inline const Descriptor* FieldScope(const FieldDescriptor* field) {
0222 return field->is_extension() ? field->extension_scope()
0223 : field->containing_type();
0224 }
0225
0226
0227
0228 std::string FieldMessageTypeName(const FieldDescriptor* field,
0229 const Options& options);
0230
0231
0232 const char* PrimitiveTypeName(FieldDescriptor::CppType type);
0233 std::string PrimitiveTypeName(const Options& options,
0234 FieldDescriptor::CppType type);
0235
0236
0237
0238 const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
0239
0240
0241 std::string Int32ToString(int number);
0242
0243
0244 std::string DefaultValue(const Options& options, const FieldDescriptor* field);
0245
0246
0247 std::string DefaultValue(const FieldDescriptor* field);
0248
0249
0250 std::string FilenameIdentifier(absl::string_view filename);
0251
0252
0253
0254 std::string UniqueName(absl::string_view name, absl::string_view filename,
0255 const Options& options);
0256 inline std::string UniqueName(absl::string_view name, const FileDescriptor* d,
0257 const Options& options) {
0258 return UniqueName(name, d->name(), options);
0259 }
0260 inline std::string UniqueName(absl::string_view name, const Descriptor* d,
0261 const Options& options) {
0262 return UniqueName(name, d->file(), options);
0263 }
0264 inline std::string UniqueName(absl::string_view name, const EnumDescriptor* d,
0265 const Options& options) {
0266 return UniqueName(name, d->file(), options);
0267 }
0268 inline std::string UniqueName(absl::string_view name,
0269 const ServiceDescriptor* d,
0270 const Options& options) {
0271 return UniqueName(name, d->file(), options);
0272 }
0273
0274
0275
0276 inline Options InternalRuntimeOptions() {
0277 Options options;
0278 options.opensource_runtime = false;
0279 return options;
0280 }
0281 inline std::string UniqueName(absl::string_view name,
0282 absl::string_view filename) {
0283 return UniqueName(name, filename, InternalRuntimeOptions());
0284 }
0285 inline std::string UniqueName(absl::string_view name, const FileDescriptor* d) {
0286 return UniqueName(name, d->name(), InternalRuntimeOptions());
0287 }
0288 inline std::string UniqueName(absl::string_view name, const Descriptor* d) {
0289 return UniqueName(name, d->file(), InternalRuntimeOptions());
0290 }
0291 inline std::string UniqueName(absl::string_view name, const EnumDescriptor* d) {
0292 return UniqueName(name, d->file(), InternalRuntimeOptions());
0293 }
0294 inline std::string UniqueName(absl::string_view name,
0295 const ServiceDescriptor* d) {
0296 return UniqueName(name, d->file(), InternalRuntimeOptions());
0297 }
0298
0299
0300 std::string QualifiedFileLevelSymbol(const FileDescriptor* file,
0301 absl::string_view name,
0302 const Options& options);
0303
0304
0305 std::string EscapeTrigraphs(absl::string_view to_escape);
0306
0307
0308 std::string SafeFunctionName(const Descriptor* descriptor,
0309 const FieldDescriptor* field,
0310 absl::string_view prefix);
0311
0312
0313 FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
0314 const Options& options);
0315
0316
0317
0318 inline bool UseUnknownFieldSet(const FileDescriptor* file,
0319 const Options& options) {
0320 return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
0321 }
0322
0323 inline bool IsWeak(const FieldDescriptor* field, const Options& options) {
0324 if (field->options().weak()) {
0325 ABSL_CHECK(!options.opensource_runtime);
0326 return true;
0327 }
0328 return false;
0329 }
0330
0331 inline bool IsCord(const FieldDescriptor* field) {
0332 return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
0333 internal::cpp::EffectiveStringCType(field) == FieldOptions::CORD;
0334 }
0335
0336 inline bool IsString(const FieldDescriptor* field) {
0337 return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
0338 internal::cpp::EffectiveStringCType(field) == FieldOptions::STRING;
0339 }
0340
0341 inline bool IsStringPiece(const FieldDescriptor* field) {
0342 return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
0343 internal::cpp::EffectiveStringCType(field) ==
0344 FieldOptions::STRING_PIECE;
0345 }
0346
0347 bool IsProfileDriven(const Options& options);
0348
0349
0350 bool IsRarelyPresent(const FieldDescriptor* field, const Options& options);
0351
0352
0353 bool IsLikelyPresent(const FieldDescriptor* field, const Options& options);
0354
0355 float GetPresenceProbability(const FieldDescriptor* field,
0356 const Options& options);
0357
0358 bool IsStringInliningEnabled(const Options& options);
0359
0360
0361 bool CanStringBeInlined(const FieldDescriptor* field);
0362
0363
0364
0365 bool IsStringInlined(const FieldDescriptor* field, const Options& options);
0366
0367
0368
0369
0370 inline bool IsFieldInlined(const FieldDescriptor* field,
0371 const Options& options) {
0372 return IsStringInlined(field, options);
0373 }
0374
0375
0376 bool HasLazyFields(const FileDescriptor* file, const Options& options,
0377 MessageSCCAnalyzer* scc_analyzer);
0378
0379
0380 bool IsLazy(const FieldDescriptor* field, const Options& options,
0381 MessageSCCAnalyzer* scc_analyzer);
0382
0383
0384
0385 inline bool IsExplicitLazy(const FieldDescriptor* field) {
0386 if (field->is_map() || field->is_repeated()) {
0387 return false;
0388 }
0389
0390 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
0391 return false;
0392 }
0393
0394 return field->options().lazy() || field->options().unverified_lazy();
0395 }
0396
0397 internal::field_layout::TransformValidation GetLazyStyle(
0398 const FieldDescriptor* field, const Options& options,
0399 MessageSCCAnalyzer* scc_analyzer);
0400
0401 bool IsEagerlyVerifiedLazy(const FieldDescriptor* field, const Options& options,
0402 MessageSCCAnalyzer* scc_analyzer);
0403
0404 bool IsLazilyVerifiedLazy(const FieldDescriptor* field, const Options& options);
0405
0406 bool ShouldVerify(const Descriptor* descriptor, const Options& options,
0407 MessageSCCAnalyzer* scc_analyzer);
0408 bool ShouldVerify(const FileDescriptor* file, const Options& options,
0409 MessageSCCAnalyzer* scc_analyzer);
0410 bool ShouldVerifyRecursively(const FieldDescriptor* field);
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 enum class VerifySimpleType {
0421 kSimpleInt32Never,
0422 kSimpleInt32Always,
0423 kCustom,
0424 kCustomInt32Never,
0425 kCustomInt32Always,
0426 };
0427
0428
0429 VerifySimpleType ShouldVerifySimple(const Descriptor* descriptor);
0430
0431
0432
0433 bool ShouldSplit(const Descriptor* desc, const Options& options);
0434
0435
0436 bool ShouldSplit(const FieldDescriptor* field, const Options& options);
0437
0438
0439
0440 bool ShouldForceAllocationOnConstruction(const Descriptor* desc,
0441 const Options& options);
0442
0443
0444 bool IsPresentMessage(const Descriptor* descriptor, const Options& options);
0445
0446
0447 const FieldDescriptor* FindHottestField(
0448 const std::vector<const FieldDescriptor*>& fields, const Options& options);
0449
0450
0451 bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
0452
0453
0454
0455
0456 bool HasRepeatedFields(const FileDescriptor* file);
0457
0458
0459
0460 bool HasStringPieceFields(const FileDescriptor* file, const Options& options);
0461
0462
0463
0464 bool HasCordFields(const FileDescriptor* file, const Options& options);
0465
0466
0467
0468 bool HasMapFields(const FileDescriptor* file);
0469
0470
0471 bool HasEnumDefinitions(const FileDescriptor* file);
0472
0473
0474
0475 inline bool HasGeneratedMethods(const FileDescriptor* file,
0476 const Options& options) {
0477 return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
0478 }
0479
0480
0481 inline bool HasDescriptorMethods(const FileDescriptor* file,
0482 const Options& options) {
0483 return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
0484 }
0485
0486
0487 inline bool HasGenericServices(const FileDescriptor* file,
0488 const Options& options) {
0489 return file->service_count() > 0 &&
0490 GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
0491 file->options().cc_generic_services();
0492 }
0493
0494 inline bool IsProto2MessageSet(const Descriptor* descriptor,
0495 const Options& options) {
0496 return !options.opensource_runtime &&
0497 options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
0498 !options.lite_implicit_weak_fields &&
0499 descriptor->options().message_set_wire_format() &&
0500 descriptor->full_name() == "google.protobuf.bridge.MessageSet";
0501 }
0502
0503 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
0504 return descriptor->options().map_entry();
0505 }
0506
0507
0508 bool IsStringOrMessage(const FieldDescriptor* field);
0509
0510 std::string UnderscoresToCamelCase(absl::string_view input,
0511 bool cap_next_letter);
0512
0513 inline bool IsCrossFileMessage(const FieldDescriptor* field) {
0514 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
0515 field->message_type()->file() != field->file();
0516 }
0517
0518 inline std::string MakeDefaultName(const FieldDescriptor* field) {
0519 return absl::StrCat("_i_give_permission_to_break_this_code_default_",
0520 FieldName(field), "_");
0521 }
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533 inline std::string MakeDefaultFieldName(const FieldDescriptor* field) {
0534 return absl::StrCat("Impl_::", MakeDefaultName(field));
0535 }
0536
0537 inline std::string MakeVarintCachedSizeName(const FieldDescriptor* field) {
0538 return absl::StrCat("_", FieldName(field), "_cached_byte_size_");
0539 }
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552 inline std::string MakeVarintCachedSizeFieldName(const FieldDescriptor* field,
0553 bool split) {
0554 return absl::StrCat("_impl_.", split ? "_split_->" : "", "_",
0555 FieldName(field), "_cached_byte_size_");
0556 }
0557
0558
0559
0560
0561
0562 bool IsAnyMessage(const FileDescriptor* descriptor);
0563 bool IsAnyMessage(const Descriptor* descriptor);
0564
0565 bool IsWellKnownMessage(const FileDescriptor* descriptor);
0566
0567 enum class GeneratedFileType : int { kPbH, kProtoH, kProtoStaticReflectionH };
0568
0569 inline std::string IncludeGuard(const FileDescriptor* file,
0570 GeneratedFileType file_type,
0571 const Options& options) {
0572
0573
0574 std::string extension;
0575 switch (file_type) {
0576 case GeneratedFileType::kPbH:
0577 extension = ".pb.h";
0578 break;
0579 case GeneratedFileType::kProtoH:
0580 extension = ".proto.h";
0581 break;
0582 case GeneratedFileType::kProtoStaticReflectionH:
0583 extension = ".proto.static_reflection.h";
0584 }
0585 std::string filename_identifier =
0586 FilenameIdentifier(absl::StrCat(file->name(), extension));
0587
0588 if (IsWellKnownMessage(file)) {
0589
0590
0591
0592
0593 return absl::StrCat(MacroPrefix(options), "_INCLUDED_",
0594 filename_identifier);
0595 } else {
0596
0597
0598
0599
0600
0601
0602 return absl::StrCat("GOOGLE_PROTOBUF_INCLUDED_", filename_identifier);
0603 }
0604 }
0605
0606
0607
0608
0609
0610 FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
0611 const Options& options,
0612 bool* has_opt_codesize_extension);
0613 inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
0614 const Options& options) {
0615 return GetOptimizeFor(file, options, nullptr);
0616 }
0617 inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file,
0618 const Options& options) {
0619 bool has_opt_codesize_extension;
0620 if (GetOptimizeFor(file, options, &has_opt_codesize_extension) ==
0621 FileOptions::CODE_SIZE &&
0622 has_opt_codesize_extension) {
0623
0624
0625
0626
0627 return true;
0628 } else {
0629
0630
0631 return false;
0632 }
0633 }
0634
0635
0636 void FlattenMessagesInFile(const FileDescriptor* file,
0637 std::vector<const Descriptor*>* result);
0638 inline std::vector<const Descriptor*> FlattenMessagesInFile(
0639 const FileDescriptor* file) {
0640 std::vector<const Descriptor*> result;
0641 FlattenMessagesInFile(file, &result);
0642 return result;
0643 }
0644
0645 std::vector<const Descriptor*> TopologicalSortMessagesInFile(
0646 const FileDescriptor* file, MessageSCCAnalyzer& scc_analyzer);
0647
0648 bool HasWeakFields(const Descriptor* desc, const Options& options);
0649 bool HasWeakFields(const FileDescriptor* desc, const Options& options);
0650
0651
0652
0653 inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
0654 const Options& options) {
0655
0656 return IsLazilyVerifiedLazy(field, options);
0657 }
0658
0659 struct MessageAnalysis {
0660 bool is_recursive = false;
0661 bool contains_cord = false;
0662 bool contains_extension = false;
0663 bool contains_required = false;
0664 bool contains_weak = false;
0665 };
0666
0667
0668
0669
0670
0671 class PROTOC_EXPORT MessageSCCAnalyzer {
0672 public:
0673 explicit MessageSCCAnalyzer(const Options& options) : options_(options) {}
0674
0675 MessageAnalysis GetSCCAnalysis(const SCC* scc);
0676
0677 bool HasRequiredFields(const Descriptor* descriptor) {
0678 MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
0679 return result.contains_required || result.contains_extension;
0680 }
0681 bool HasWeakField(const Descriptor* descriptor) {
0682 MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
0683 return result.contains_weak;
0684 }
0685 const SCC* GetSCC(const Descriptor* descriptor) {
0686 return analyzer_.GetSCC(descriptor);
0687 }
0688
0689 private:
0690 struct DepsGenerator {
0691 std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
0692 std::vector<const Descriptor*> deps;
0693 for (int i = 0; i < desc->field_count(); i++) {
0694 if (desc->field(i)->message_type()) {
0695 deps.push_back(desc->field(i)->message_type());
0696 }
0697 }
0698 return deps;
0699 }
0700 };
0701 SCCAnalyzer<DepsGenerator> analyzer_;
0702 Options options_;
0703 absl::flat_hash_map<const SCC*, MessageAnalysis> analysis_cache_;
0704 };
0705
0706 void ListAllFields(const Descriptor* d,
0707 std::vector<const FieldDescriptor*>* fields);
0708 void ListAllFields(const FileDescriptor* d,
0709 std::vector<const FieldDescriptor*>* fields);
0710
0711 template <bool do_nested_types, class T>
0712 void ForEachField(const Descriptor* d, T&& func) {
0713 if (do_nested_types) {
0714 for (int i = 0; i < d->nested_type_count(); i++) {
0715 ForEachField<true>(d->nested_type(i), std::forward<T&&>(func));
0716 }
0717 }
0718 for (int i = 0; i < d->extension_count(); i++) {
0719 func(d->extension(i));
0720 }
0721 for (int i = 0; i < d->field_count(); i++) {
0722 func(d->field(i));
0723 }
0724 }
0725
0726 template <class T>
0727 void ForEachField(const FileDescriptor* d, T&& func) {
0728 for (int i = 0; i < d->message_type_count(); i++) {
0729 ForEachField<true>(d->message_type(i), std::forward<T&&>(func));
0730 }
0731 for (int i = 0; i < d->extension_count(); i++) {
0732 func(d->extension(i));
0733 }
0734 }
0735
0736 void ListAllTypesForServices(const FileDescriptor* fd,
0737 std::vector<const Descriptor*>* types);
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792 bool UsingImplicitWeakDescriptor(const FileDescriptor* file,
0793 const Options& options);
0794
0795
0796 std::string StrongReferenceToType(const Descriptor* desc,
0797 const Options& options);
0798
0799
0800
0801
0802
0803 std::string WeakDescriptorDataSection(absl::string_view prefix,
0804 const Descriptor* descriptor,
0805 int index_in_file_messages,
0806 const Options& options);
0807
0808
0809
0810 inline std::string WeakDefaultInstanceSection(const Descriptor* descriptor,
0811 int index_in_file_messages,
0812 const Options& options) {
0813 return WeakDescriptorDataSection("def", descriptor, index_in_file_messages,
0814 options);
0815 }
0816
0817
0818 bool UsingImplicitWeakFields(const FileDescriptor* file,
0819 const Options& options);
0820
0821
0822 bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
0823 MessageSCCAnalyzer* scc_analyzer);
0824
0825 inline std::string SimpleBaseClass(const Descriptor* desc,
0826 const Options& options) {
0827
0828 if (!HasDescriptorMethods(desc->file(), options)) return "";
0829
0830 if (UsingImplicitWeakDescriptor(desc->file(), options)) return "";
0831 if (desc->extension_range_count() != 0) return "";
0832
0833
0834 if (options.field_listener_options.inject_field_listener_events) return "";
0835 if (desc->field_count() == 0) {
0836 return "ZeroFieldsBase";
0837 }
0838
0839
0840 return "";
0841 }
0842
0843 inline bool HasSimpleBaseClass(const Descriptor* desc, const Options& options) {
0844 return !SimpleBaseClass(desc, options).empty();
0845 }
0846
0847 inline bool HasSimpleBaseClasses(const FileDescriptor* file,
0848 const Options& options) {
0849 return internal::cpp::VisitDescriptorsInFileOrder(
0850 file, [&](const Descriptor* desc) {
0851 return HasSimpleBaseClass(desc, options);
0852 });
0853 }
0854
0855
0856 inline bool HasTracker(const Descriptor* desc, const Options& options) {
0857 return options.field_listener_options.inject_field_listener_events &&
0858 desc->file()->options().optimize_for() !=
0859 google::protobuf::FileOptions::LITE_RUNTIME &&
0860 !IsMapEntryMessage(desc);
0861 }
0862
0863
0864 inline bool HasImplData(const Descriptor* desc, const Options& options) {
0865 return !HasSimpleBaseClass(desc, options);
0866 }
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908 class PROTOC_EXPORT Formatter {
0909 public:
0910 explicit Formatter(io::Printer* printer) : printer_(printer) {}
0911 Formatter(io::Printer* printer,
0912 const absl::flat_hash_map<absl::string_view, std::string>& vars)
0913 : printer_(printer), vars_(vars) {}
0914
0915 template <typename T>
0916 void Set(absl::string_view key, const T& value) {
0917 vars_[key] = ToString(value);
0918 }
0919
0920 template <typename... Args>
0921 void operator()(const char* format, const Args&... args) const {
0922 printer_->FormatInternal({ToString(args)...}, vars_, format);
0923 }
0924
0925 void Indent() const { printer_->Indent(); }
0926 void Outdent() const { printer_->Outdent(); }
0927 io::Printer* printer() const { return printer_; }
0928
0929 class PROTOC_EXPORT ScopedIndenter {
0930 public:
0931 explicit ScopedIndenter(Formatter* format) : format_(format) {
0932 format_->Indent();
0933 }
0934 ~ScopedIndenter() { format_->Outdent(); }
0935
0936 private:
0937 Formatter* format_;
0938 };
0939
0940 PROTOBUF_NODISCARD ScopedIndenter ScopedIndent() {
0941 return ScopedIndenter(this);
0942 }
0943 template <typename... Args>
0944 PROTOBUF_NODISCARD ScopedIndenter ScopedIndent(const char* format,
0945 const Args&&... args) {
0946 (*this)(format, static_cast<Args&&>(args)...);
0947 return ScopedIndenter(this);
0948 }
0949
0950 private:
0951 io::Printer* printer_;
0952 absl::flat_hash_map<absl::string_view, std::string> vars_;
0953
0954
0955 static std::string ToString(absl::string_view s) { return std::string(s); }
0956 template <typename I, typename = typename std::enable_if<
0957 std::is_integral<I>::value>::type>
0958 static std::string ToString(I x) {
0959 return absl::StrCat(x);
0960 }
0961 static std::string ToString(absl::Hex x) { return absl::StrCat(x); }
0962 static std::string ToString(const FieldDescriptor* d) {
0963 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
0964 }
0965 static std::string ToString(const Descriptor* d) {
0966 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
0967 }
0968 static std::string ToString(const EnumDescriptor* d) {
0969 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
0970 }
0971 static std::string ToString(const EnumValueDescriptor* d) {
0972 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
0973 }
0974 static std::string ToString(const OneofDescriptor* d) {
0975 return Payload(d, GeneratedCodeInfo::Annotation::NONE);
0976 }
0977
0978 static std::string ToString(
0979 std::tuple<const FieldDescriptor*,
0980 GeneratedCodeInfo::Annotation::Semantic>
0981 p) {
0982 return Payload(std::get<0>(p), std::get<1>(p));
0983 }
0984 static std::string ToString(
0985 std::tuple<const Descriptor*, GeneratedCodeInfo::Annotation::Semantic>
0986 p) {
0987 return Payload(std::get<0>(p), std::get<1>(p));
0988 }
0989 static std::string ToString(
0990 std::tuple<const EnumDescriptor*, GeneratedCodeInfo::Annotation::Semantic>
0991 p) {
0992 return Payload(std::get<0>(p), std::get<1>(p));
0993 }
0994 static std::string ToString(
0995 std::tuple<const EnumValueDescriptor*,
0996 GeneratedCodeInfo::Annotation::Semantic>
0997 p) {
0998 return Payload(std::get<0>(p), std::get<1>(p));
0999 }
1000 static std::string ToString(
1001 std::tuple<const OneofDescriptor*,
1002 GeneratedCodeInfo::Annotation::Semantic>
1003 p) {
1004 return Payload(std::get<0>(p), std::get<1>(p));
1005 }
1006
1007 template <typename Descriptor>
1008 static std::string Payload(const Descriptor* descriptor,
1009 GeneratedCodeInfo::Annotation::Semantic semantic) {
1010 std::vector<int> path;
1011 descriptor->GetLocationPath(&path);
1012 GeneratedCodeInfo::Annotation annotation;
1013 for (int index : path) {
1014 annotation.add_path(index);
1015 }
1016 annotation.set_source_file(descriptor->file()->name());
1017 annotation.set_semantic(semantic);
1018 return annotation.SerializeAsString();
1019 }
1020 };
1021
1022 template <typename T>
1023 std::string FieldComment(const T* field, const Options& options) {
1024 if (options.strip_nonfunctional_codegen) {
1025 return std::string(field->name());
1026 }
1027
1028
1029
1030 DebugStringOptions debug_options;
1031 debug_options.elide_group_body = true;
1032 debug_options.elide_oneof_body = true;
1033
1034 for (absl::string_view chunk :
1035 absl::StrSplit(field->DebugStringWithOptions(debug_options), '\n')) {
1036 return std::string(chunk);
1037 }
1038
1039 return "<unknown>";
1040 }
1041
1042 template <class T>
1043 void PrintFieldComment(const Formatter& format, const T* field,
1044 const Options& options) {
1045 format("// $1$\n", FieldComment(field, options));
1046 }
1047
1048 class PROTOC_EXPORT NamespaceOpener {
1049 public:
1050 explicit NamespaceOpener(
1051 io::Printer* p,
1052 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1053 : p_(p), loc_(loc) {}
1054
1055 explicit NamespaceOpener(
1056 const Formatter& format,
1057 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1058 : NamespaceOpener(format.printer(), loc) {}
1059
1060 NamespaceOpener(
1061 absl::string_view name, const Formatter& format,
1062 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1063 : NamespaceOpener(name, format.printer(), loc) {}
1064
1065 NamespaceOpener(
1066 absl::string_view name, io::Printer* p,
1067 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current())
1068 : NamespaceOpener(p, loc) {
1069 ChangeTo(name, loc);
1070 }
1071
1072 ~NamespaceOpener() { ChangeTo("", loc_); }
1073
1074 void ChangeTo(
1075 absl::string_view name,
1076 io::Printer::SourceLocation loc = io::Printer::SourceLocation::current());
1077
1078 private:
1079 io::Printer* p_;
1080 io::Printer::SourceLocation loc_;
1081 std::vector<std::string> name_stack_;
1082 };
1083
1084 void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
1085 const Options& options, bool for_parse,
1086 absl::string_view parameters,
1087 const Formatter& format);
1088
1089 void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
1090 const Options& options, bool for_parse,
1091 absl::string_view parameters,
1092 const Formatter& format);
1093
1094 void GenerateUtf8CheckCodeForString(io::Printer* p,
1095 const FieldDescriptor* field,
1096 const Options& options, bool for_parse,
1097 absl::string_view parameters);
1098
1099 void GenerateUtf8CheckCodeForCord(io::Printer* p, const FieldDescriptor* field,
1100 const Options& options, bool for_parse,
1101 absl::string_view parameters);
1102
1103 inline bool ShouldGenerateExternSpecializations(const Options& options) {
1104
1105
1106
1107
1108 return !options.opensource_runtime;
1109 }
1110
1111 struct OneOfRangeImpl {
1112 struct Iterator {
1113 using iterator_category = std::forward_iterator_tag;
1114 using value_type = const OneofDescriptor*;
1115 using difference_type = int;
1116
1117 value_type operator*() { return descriptor->oneof_decl(idx); }
1118
1119 friend bool operator==(const Iterator& a, const Iterator& b) {
1120 ABSL_DCHECK(a.descriptor == b.descriptor);
1121 return a.idx == b.idx;
1122 }
1123 friend bool operator!=(const Iterator& a, const Iterator& b) {
1124 return !(a == b);
1125 }
1126
1127 Iterator& operator++() {
1128 idx++;
1129 return *this;
1130 }
1131
1132 int idx;
1133 const Descriptor* descriptor;
1134 };
1135
1136 Iterator begin() const { return {0, descriptor}; }
1137 Iterator end() const {
1138 return {descriptor->real_oneof_decl_count(), descriptor};
1139 }
1140
1141 const Descriptor* descriptor;
1142 };
1143
1144 inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
1145
1146
1147 PROTOC_EXPORT std::string StripProto(absl::string_view filename);
1148
1149 bool HasMessageFieldOrExtension(const Descriptor* desc);
1150
1151
1152
1153
1154
1155
1156 std::vector<io::Printer::Sub> AnnotatedAccessors(
1157 const FieldDescriptor* field, absl::Span<const absl::string_view> prefixes,
1158 absl::optional<google::protobuf::io::AnnotationCollector::Semantic> semantic =
1159 absl::nullopt);
1160
1161
1162
1163
1164 bool IsFileDescriptorProto(const FileDescriptor* file, const Options& options);
1165
1166
1167
1168
1169 bool ShouldGenerateClass(const Descriptor* descriptor, const Options& options);
1170
1171
1172
1173
1174
1175 bool HasOnDeserializeTracker(const Descriptor* descriptor,
1176 const Options& options);
1177
1178
1179
1180
1181
1182
1183 bool NeedsPostLoopHandler(const Descriptor* descriptor, const Options& options);
1184
1185
1186 enum InitPriority {
1187 kInitPriority101,
1188 kInitPriority102,
1189 };
1190
1191 }
1192 }
1193 }
1194 }
1195
1196 #include "google/protobuf/port_undef.inc"
1197
1198 #endif