| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412 |
- // Protocol Buffers - Google's data interchange format
- // Copyright 2008 Google Inc. All rights reserved.
- // https://developers.google.com/protocol-buffers/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- // Author: kenton@google.com (Kenton Varda)
- // Based on original Protocol Buffers design by
- // Sanjay Ghemawat, Jeff Dean, and others.
- #include <google/protobuf/compiler/cpp/cpp_file.h>
- #include <map>
- #include <memory>
- #include <set>
- #include <vector>
- #include <google/protobuf/compiler/cpp/cpp_enum.h>
- #include <google/protobuf/compiler/cpp/cpp_extension.h>
- #include <google/protobuf/compiler/cpp/cpp_field.h>
- #include <google/protobuf/compiler/cpp/cpp_helpers.h>
- #include <google/protobuf/compiler/cpp/cpp_message.h>
- #include <google/protobuf/compiler/cpp/cpp_service.h>
- #include <google/protobuf/descriptor.pb.h>
- #include <google/protobuf/io/printer.h>
- #include <google/protobuf/stubs/strutil.h>
- namespace google {
- namespace protobuf {
- namespace compiler {
- namespace cpp {
- FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
- : file_(file),
- options_(options),
- scc_analyzer_(options),
- enum_generators_owner_(
- new std::unique_ptr<EnumGenerator>[file->enum_type_count()]),
- service_generators_owner_(
- new std::unique_ptr<ServiceGenerator>[file->service_count()]),
- extension_generators_owner_(
- new std::unique_ptr<ExtensionGenerator>[file->extension_count()]) {
- std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file);
- for (int i = 0; i < msgs.size(); i++) {
- // Deleted in destructor
- MessageGenerator* msg_gen =
- new MessageGenerator(msgs[i], i, options, &scc_analyzer_);
- message_generators_.push_back(msg_gen);
- msg_gen->AddGenerators(&enum_generators_, &extension_generators_);
- }
- for (int i = 0; i < file->enum_type_count(); i++) {
- enum_generators_owner_[i].reset(
- new EnumGenerator(file->enum_type(i), options));
- enum_generators_.push_back(enum_generators_owner_[i].get());
- }
- for (int i = 0; i < file->service_count(); i++) {
- service_generators_owner_[i].reset(
- new ServiceGenerator(file->service(i), options));
- service_generators_.push_back(service_generators_owner_[i].get());
- }
- if (HasGenericServices(file_, options_)) {
- for (int i = 0; i < service_generators_.size(); i++) {
- service_generators_[i]->index_in_metadata_ = i;
- }
- }
- for (int i = 0; i < file->extension_count(); i++) {
- extension_generators_owner_[i].reset(
- new ExtensionGenerator(file->extension(i), options));
- extension_generators_.push_back(extension_generators_owner_[i].get());
- }
- package_parts_ = Split(file_->package(), ".", true);
- }
- FileGenerator::~FileGenerator() {
- for (int i = 0; i < message_generators_.size(); i++) {
- delete message_generators_[i];
- }
- }
- void FileGenerator::GenerateMacroUndefs(io::Printer* printer) {
- // Only do this for protobuf's own types. There are some google3 protos using
- // macros as field names and the generated code compiles after the macro
- // expansion. Undefing these macros actually breaks such code.
- if (file_->name() != "google/protobuf/compiler/plugin.proto") {
- return;
- }
- std::vector<string> names_to_undef;
- std::vector<const FieldDescriptor*> fields;
- ListAllFields(file_, &fields);
- for (int i = 0; i < fields.size(); i++) {
- const string& name = fields[i]->name();
- static const char* kMacroNames[] = {"major", "minor"};
- for (int i = 0; i < GOOGLE_ARRAYSIZE(kMacroNames); ++i) {
- if (name == kMacroNames[i]) {
- names_to_undef.push_back(name);
- break;
- }
- }
- }
- for (int i = 0; i < names_to_undef.size(); ++i) {
- printer->Print(
- "#ifdef $name$\n"
- "#undef $name$\n"
- "#endif\n",
- "name", names_to_undef[i]);
- }
- }
- void FileGenerator::GenerateHeader(io::Printer* printer) {
- printer->Print(
- "// @@protoc_insertion_point(includes)\n");
- printer->Print("#define PROTOBUF_INTERNAL_EXPORT_$filename$ $export$\n",
- "filename", FileLevelNamespace(file_),
- "export", options_.dllexport_decl);
- GenerateMacroUndefs(printer);
- GenerateGlobalStateFunctionDeclarations(printer);
- GenerateForwardDeclarations(printer);
- {
- NamespaceOpener ns(Namespace(file_), printer);
- printer->Print("\n");
- GenerateEnumDefinitions(printer);
- printer->Print(kThickSeparator);
- printer->Print("\n");
- GenerateMessageDefinitions(printer);
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- GenerateServiceDefinitions(printer);
- GenerateExtensionIdentifiers(printer);
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- GenerateInlineFunctionDefinitions(printer);
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n"
- "\n");
- }
- // We need to specialize some templates in the ::google::protobuf namespace:
- GenerateProto2NamespaceEnumSpecializations(printer);
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(global_scope)\n"
- "\n");
- }
- void FileGenerator::GenerateProtoHeader(io::Printer* printer,
- const string& info_path) {
- if (!options_.proto_h) {
- return;
- }
- string filename_identifier = FilenameIdentifier(file_->name());
- GenerateTopHeaderGuard(printer, filename_identifier);
- GenerateLibraryIncludes(printer);
- for (int i = 0; i < file_->public_dependency_count(); i++) {
- const FileDescriptor* dep = file_->public_dependency(i);
- const char* extension = ".proto.h";
- string dependency = StripProto(dep->name()) + extension;
- printer->Print(
- "#include \"$dependency$\" // IWYU pragma: export\n",
- "dependency", dependency);
- }
- GenerateMetadataPragma(printer, info_path);
- GenerateHeader(printer);
- GenerateBottomHeaderGuard(printer, filename_identifier);
- }
- void FileGenerator::GeneratePBHeader(io::Printer* printer,
- const string& info_path) {
- string filename_identifier =
- FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
- GenerateTopHeaderGuard(printer, filename_identifier);
- if (options_.proto_h) {
- string target_basename = StripProto(file_->name());
- printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
- "basename", target_basename);
- } else {
- GenerateLibraryIncludes(printer);
- }
- GenerateDependencyIncludes(printer);
- GenerateMetadataPragma(printer, info_path);
- if (!options_.proto_h) {
- GenerateHeader(printer);
- } else {
- // This is unfortunately necessary for some plugins. I don't see why we
- // need two of the same insertion points.
- // TODO(gerbens) remove this.
- printer->Print(
- "// @@protoc_insertion_point(includes)\n");
- {
- NamespaceOpener ns(Namespace(file_), printer);
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
- }
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(global_scope)\n"
- "\n");
- }
- GenerateBottomHeaderGuard(printer, filename_identifier);
- }
- void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
- string target_basename = StripProto(file_->name());
- const bool use_system_include = IsWellKnownMessage(file_);
- string header = target_basename + (options_.proto_h ? ".proto.h" : ".pb.h");
- printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "// source: $filename$\n"
- "\n"
- "#include $left$$header$$right$\n"
- "\n"
- "#include <algorithm>\n" // for swap()
- "\n"
- "#include <google/protobuf/stubs/common.h>\n"
- "#include <google/protobuf/stubs/port.h>\n"
- "#include <google/protobuf/io/coded_stream.h>\n"
- "#include <google/protobuf/wire_format_lite_inl.h>\n",
- "filename", file_->name(),
- "header", header,
- "left", use_system_include ? "<" : "\"",
- "right", use_system_include ? ">" : "\"");
- // Unknown fields implementation in lite mode uses StringOutputStream
- if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
- printer->Print(
- "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
- }
- if (HasDescriptorMethods(file_, options_)) {
- printer->Print(
- "#include <google/protobuf/descriptor.h>\n"
- "#include <google/protobuf/generated_message_reflection.h>\n"
- "#include <google/protobuf/reflection_ops.h>\n"
- "#include <google/protobuf/wire_format.h>\n");
- }
- if (options_.proto_h) {
- // Use the smaller .proto.h files.
- for (int i = 0; i < file_->dependency_count(); i++) {
- const FileDescriptor* dep = file_->dependency(i);
- const char* extension = ".proto.h";
- string basename = StripProto(dep->name());
- string dependency = basename + extension;
- printer->Print(
- "#include \"$dependency$\"\n",
- "dependency", dependency);
- }
- }
- // TODO(gerbens) Remove this when all code in google is using the same
- // proto library. This is a temporary hack to force build errors if
- // the proto library is compiled with GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
- // and is also linking internal proto2. This is to prevent regressions while
- // we work cleaning up the code base. After this is completed and we have
- // one proto lib all code uses this should be removed.
- printer->Print(
- "// This is a temporary google only hack\n"
- "#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS\n"
- "#include \"third_party/protobuf/version.h\"\n"
- "#endif\n");
- printer->Print(
- "// @@protoc_insertion_point(includes)\n");
- }
- void FileGenerator::GenerateSourceDefaultInstance(int idx,
- io::Printer* printer) {
- printer->Print(
- "class $classname$DefaultTypeInternal {\n"
- " public:\n"
- " ::google::protobuf::internal::ExplicitlyConstructed<$classname$>\n"
- " _instance;\n",
- "classname", message_generators_[idx]->classname_);
- printer->Indent();
- message_generators_[idx]->GenerateExtraDefaultFields(printer);
- printer->Outdent();
- printer->Print("} _$classname$_default_instance_;\n", "classname",
- message_generators_[idx]->classname_);
- }
- namespace {
- // Generates weak symbol declarations for types that are to be considered weakly
- // referenced.
- void GenerateInternalForwardDeclarations(
- const std::vector<const FieldDescriptor*>& fields, const Options& options,
- SCCAnalyzer* scc_analyzer, io::Printer* printer) {
- // To ensure determinism and minimize the number of namespace statements,
- // we output the forward declarations sorted on namespace and type / function
- // name.
- std::set<std::pair<string, string> > messages;
- std::set<std::pair<string, string> > sccs;
- std::set<std::pair<string, string> > inits;
- for (int i = 0; i < fields.size(); ++i) {
- const FieldDescriptor* field = fields[i];
- const Descriptor* msg = field->message_type();
- if (msg == nullptr) continue;
- bool is_weak = IsImplicitWeakField(field, options, scc_analyzer);
- string flns = FileLevelNamespace(msg);
- auto scc = scc_analyzer->GetSCC(msg);
- string repr = ClassName(scc->GetRepresentative());
- string weak_attr;
- if (is_weak) {
- inits.insert(std::make_pair(flns, "AddDescriptors"));
- messages.insert(std::make_pair(Namespace(msg), ClassName(msg)));
- weak_attr = " __attribute__((weak))";
- }
- string dllexport = "PROTOBUF_INTERNAL_EXPORT_" + FileLevelNamespace(msg);
- sccs.insert(std::make_pair(flns, "extern " + dllexport + weak_attr +
- " ::google::protobuf::internal::SCCInfo<" +
- SimpleItoa(scc->children.size()) +
- "> scc_info_" + repr + ";\n"));
- }
- printer->Print("\n");
- NamespaceOpener ns(printer);
- for (std::set<std::pair<string, string> >::const_iterator it =
- messages.begin();
- it != messages.end(); ++it) {
- ns.ChangeTo(it->first);
- printer->Print(
- "extern __attribute__((weak)) $classname$DefaultTypeInternal "
- "_$classname$_default_instance_;\n",
- "classname", it->second);
- }
- for (std::set<std::pair<string, string> >::const_iterator it = inits.begin();
- it != inits.end(); ++it) {
- ns.ChangeTo(it->first);
- printer->Print("void $name$() __attribute__((weak));\n",
- "name", it->second);
- }
- for (const auto& p : sccs) {
- ns.ChangeTo(p.first);
- printer->Print(p.second.c_str());
- }
- }
- } // namespace
- void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
- GenerateSourceIncludes(printer);
- // Generate weak declarations. We do this for the whole strongly-connected
- // component (SCC), because we have a single InitDefaults* function for the
- // SCC.
- std::vector<const FieldDescriptor*> fields;
- for (const Descriptor* message :
- scc_analyzer_.GetSCC(message_generators_[idx]->descriptor_)
- ->descriptors) {
- ListAllFields(message, &fields);
- }
- GenerateInternalForwardDeclarations(fields, options_, &scc_analyzer_,
- printer);
- if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
- NamespaceOpener ns(FileLevelNamespace(file_), printer);
- GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer);
- }
- { // package namespace
- NamespaceOpener ns(Namespace(file_), printer);
- // Define default instances
- GenerateSourceDefaultInstance(idx, printer);
- if (options_.lite_implicit_weak_fields) {
- printer->Print("void $classname$_ReferenceStrong() {}\n", "classname",
- message_generators_[idx]->classname_);
- }
- // Generate classes.
- printer->Print("\n");
- message_generators_[idx]->GenerateClassMethods(printer);
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
- } // end package namespace
- printer->Print(
- "namespace google {\nnamespace protobuf {\n");
- message_generators_[idx]->GenerateSourceInProto2Namespace(printer);
- printer->Print(
- "} // namespace protobuf\n} // namespace google\n");
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(global_scope)\n");
- }
- void FileGenerator::GenerateGlobalSource(io::Printer* printer) {
- GenerateSourceIncludes(printer);
- {
- NamespaceOpener ns(FileLevelNamespace(file_), printer);
- GenerateTables(printer);
- // Define the code to initialize reflection. This code uses a global
- // constructor to register reflection data with the runtime pre-main.
- if (HasDescriptorMethods(file_, options_)) {
- GenerateReflectionInitializationCode(printer);
- }
- }
- NamespaceOpener ns(Namespace(file_), printer);
- // Generate enums.
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->GenerateMethods(i, printer);
- }
- // Define extensions.
- for (int i = 0; i < extension_generators_.size(); i++) {
- extension_generators_[i]->GenerateDefinition(printer);
- }
- if (HasGenericServices(file_, options_)) {
- // Generate services.
- for (int i = 0; i < service_generators_.size(); i++) {
- if (i == 0) printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- service_generators_[i]->GenerateImplementation(printer);
- }
- }
- }
- void FileGenerator::GenerateSource(io::Printer* printer) {
- GenerateSourceIncludes(printer);
- std::vector<const FieldDescriptor*> fields;
- ListAllFields(file_, &fields);
- GenerateInternalForwardDeclarations(fields, options_, &scc_analyzer_,
- printer);
- {
- NamespaceOpener ns(Namespace(file_), printer);
- // Define default instances
- for (int i = 0; i < message_generators_.size(); i++) {
- GenerateSourceDefaultInstance(i, printer);
- if (options_.lite_implicit_weak_fields) {
- printer->Print("void $classname$_ReferenceStrong() {}\n", "classname",
- message_generators_[i]->classname_);
- }
- }
- }
- {
- NamespaceOpener ns(FileLevelNamespace(file_), printer);
- GenerateTables(printer);
- // Now generate the InitDefaults for each SCC.
- for (int i = 0; i < message_generators_.size(); i++) {
- if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
- GenerateInitForSCC(GetSCC(message_generators_[i]->descriptor_),
- printer);
- }
- }
- printer->Print("void InitDefaults() {\n");
- for (int i = 0; i < message_generators_.size(); i++) {
- if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue;
- string scc_name = ClassName(message_generators_[i]->descriptor_);
- printer->Print(
- " ::google::protobuf::internal::InitSCC(&scc_info_$scc_name$.base);\n",
- "scc_name", scc_name);
- }
- printer->Print("}\n\n");
- // Define the code to initialize reflection. This code uses a global
- // constructor to register reflection data with the runtime pre-main.
- if (HasDescriptorMethods(file_, options_)) {
- GenerateReflectionInitializationCode(printer);
- }
- }
- {
- NamespaceOpener ns(Namespace(file_), printer);
- // Actually implement the protos
- // Generate enums.
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->GenerateMethods(i, printer);
- }
- // Generate classes.
- for (int i = 0; i < message_generators_.size(); i++) {
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- message_generators_[i]->GenerateClassMethods(printer);
- }
- if (HasGenericServices(file_, options_)) {
- // Generate services.
- for (int i = 0; i < service_generators_.size(); i++) {
- if (i == 0) printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- service_generators_[i]->GenerateImplementation(printer);
- }
- }
- // Define extensions.
- for (int i = 0; i < extension_generators_.size(); i++) {
- extension_generators_[i]->GenerateDefinition(printer);
- }
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
- }
- printer->Print(
- "namespace google {\nnamespace protobuf {\n");
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->GenerateSourceInProto2Namespace(printer);
- }
- printer->Print(
- "} // namespace protobuf\n} // namespace google\n");
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(global_scope)\n");
- }
- class FileGenerator::ForwardDeclarations {
- public:
- ~ForwardDeclarations() {
- for (std::map<string, ForwardDeclarations*>::iterator
- it = namespaces_.begin(),
- end = namespaces_.end();
- it != end; ++it) {
- delete it->second;
- }
- namespaces_.clear();
- }
- ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
- ForwardDeclarations*& ns = namespaces_[ns_name];
- if (ns == nullptr) {
- ns = new ForwardDeclarations;
- }
- return ns;
- }
- std::map<string, const Descriptor*>& classes() { return classes_; }
- std::map<string, const EnumDescriptor*>& enums() { return enums_; }
- void PrintForwardDeclarations(io::Printer* printer,
- const Options& options) const {
- PrintNestedDeclarations(printer, options);
- PrintTopLevelDeclarations(printer, options);
- }
- private:
- void PrintNestedDeclarations(io::Printer* printer,
- const Options& options) const {
- PrintDeclarationsInsideNamespace(printer, options);
- for (std::map<string, ForwardDeclarations *>::const_iterator
- it = namespaces_.begin(),
- end = namespaces_.end();
- it != end; ++it) {
- printer->Print("namespace $nsname$ {\n",
- "nsname", it->first);
- it->second->PrintNestedDeclarations(printer, options);
- printer->Print("} // namespace $nsname$\n",
- "nsname", it->first);
- }
- }
- void PrintTopLevelDeclarations(io::Printer* printer,
- const Options& options) const {
- PrintDeclarationsOutsideNamespace(printer, options);
- for (std::map<string, ForwardDeclarations *>::const_iterator
- it = namespaces_.begin(),
- end = namespaces_.end();
- it != end; ++it) {
- it->second->PrintTopLevelDeclarations(printer, options);
- }
- }
- void PrintDeclarationsInsideNamespace(io::Printer* printer,
- const Options& options) const {
- for (std::map<string, const EnumDescriptor *>::const_iterator
- it = enums_.begin(),
- end = enums_.end();
- it != end; ++it) {
- printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
- printer->Annotate("enumname", it->second);
- printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
- it->first);
- }
- for (std::map<string, const Descriptor*>::const_iterator
- it = classes_.begin(),
- end = classes_.end();
- it != end; ++it) {
- printer->Print("class $classname$;\n", "classname", it->first);
- printer->Annotate("classname", it->second);
- printer->Print(
- "class $classname$DefaultTypeInternal;\n"
- "$dllexport_decl$"
- "extern $classname$DefaultTypeInternal "
- "_$classname$_default_instance_;\n", // NOLINT
- "dllexport_decl",
- options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ",
- "classname",
- it->first);
- if (options.lite_implicit_weak_fields) {
- printer->Print("void $classname$_ReferenceStrong();\n",
- "classname", it->first);
- }
- }
- }
- void PrintDeclarationsOutsideNamespace(io::Printer* printer,
- const Options& options) const {
- if (classes_.size() == 0) return;
- printer->Print(
- "namespace google {\nnamespace protobuf {\n");
- for (std::map<string, const Descriptor*>::const_iterator
- it = classes_.begin(),
- end = classes_.end();
- it != end; ++it) {
- const Descriptor* d = it->second;
- printer->Print(
- "template<> "
- "$dllexport_decl$"
- "$classname$* Arena::CreateMaybeMessage<$classname$>"
- "(Arena*);\n",
- "classname", QualifiedClassName(d), "dllexport_decl",
- options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ");
- }
- printer->Print(
- "} // namespace protobuf\n} // namespace google\n");
- }
- std::map<string, ForwardDeclarations*> namespaces_;
- std::map<string, const Descriptor*> classes_;
- std::map<string, const EnumDescriptor*> enums_;
- };
- void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
- // AddDescriptors() is a file-level procedure which adds the encoded
- // FileDescriptorProto for this .proto file to the global DescriptorPool for
- // generated files (DescriptorPool::generated_pool()). It ordinarily runs at
- // static initialization time, but is not used at all in LITE_RUNTIME mode.
- //
- // Its sibling, AssignDescriptors(), actually pulls the compiled
- // FileDescriptor from the DescriptorPool and uses it to populate all of
- // the global variables which store pointers to the descriptor objects.
- // It also constructs the reflection objects. It is called the first time
- // anyone calls descriptor() or GetReflection() on one of the types defined
- // in the file.
- if (!message_generators_.empty()) {
- printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n", "size",
- SimpleItoa(message_generators_.size()));
- }
- if (!enum_generators_.empty()) {
- printer->Print(
- "const ::google::protobuf::EnumDescriptor* "
- "file_level_enum_descriptors[$size$];\n",
- "size", SimpleItoa(enum_generators_.size()));
- }
- if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
- printer->Print(
- "const ::google::protobuf::ServiceDescriptor* "
- "file_level_service_descriptors[$size$];\n",
- "size", SimpleItoa(file_->service_count()));
- }
- if (!message_generators_.empty()) {
- printer->Print(
- "\n"
- "const ::google::protobuf::uint32 TableStruct::offsets[] "
- "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
- std::vector<std::pair<size_t, size_t> > pairs;
- pairs.reserve(message_generators_.size());
- for (int i = 0; i < message_generators_.size(); i++) {
- pairs.push_back(message_generators_[i]->GenerateOffsets(printer));
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "static const ::google::protobuf::internal::MigrationSchema schemas[] "
- "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
- {
- int offset = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->GenerateSchema(printer, offset,
- pairs[i].second);
- offset += pairs[i].first;
- }
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "\nstatic "
- "::google::protobuf::Message const * const file_default_instances[] = {\n");
- printer->Indent();
- for (int i = 0; i < message_generators_.size(); i++) {
- const Descriptor* descriptor = message_generators_[i]->descriptor_;
- printer->Print(
- "reinterpret_cast<const "
- "::google::protobuf::Message*>(&$ns$::_$classname$_default_instance_),\n",
- "classname", ClassName(descriptor), "ns", Namespace(descriptor));
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "\n");
- } else {
- // we still need these symbols to exist
- printer->Print(
- // MSVC doesn't like empty arrays, so we add a dummy.
- "const ::google::protobuf::uint32 TableStruct::offsets[1] = {};\n"
- "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n"
- "static const ::google::protobuf::Message* const* "
- "file_default_instances = NULL;\n"
- "\n");
- }
- // ---------------------------------------------------------------
- // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
- // AssignDescriptors(). All later times, waits for the first call to
- // complete and then returns.
- printer->Print(
- "void protobuf_AssignDescriptors() {\n"
- // Make sure the file has found its way into the pool. If a descriptor
- // is requested *during* static init then AddDescriptors() may not have
- // been called yet, so we call it manually. Note that it's fine if
- // AddDescriptors() is called multiple times.
- " AddDescriptors();\n"
- " AssignDescriptors(\n"
- " \"$filename$\", schemas, file_default_instances, "
- "TableStruct::offsets,\n"
- " $metadata$, $enum_descriptors$, $service_descriptors$);\n",
- "filename", file_->name(), "metadata",
- !message_generators_.empty() ? "file_level_metadata" : "NULL",
- "enum_descriptors",
- !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL",
- "service_descriptors",
- HasGenericServices(file_, options_) && file_->service_count() > 0
- ? "file_level_service_descriptors"
- : "NULL");
- printer->Print(
- "}\n"
- "\n"
- "void protobuf_AssignDescriptorsOnce() {\n"
- " static ::google::protobuf::internal::once_flag once;\n"
- " ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);\n"
- "}\n"
- "\n",
- "filename", file_->name(), "metadata",
- !message_generators_.empty() ? "file_level_metadata" : "NULL",
- "enum_descriptors",
- !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL",
- "service_descriptors",
- HasGenericServices(file_, options_) && file_->service_count() > 0
- ? "file_level_service_descriptors"
- : "NULL");
- // Only here because of useless string reference that we don't want in
- // protobuf_AssignDescriptorsOnce, because that is called from all the
- // GetMetadata member methods.
- printer->Print(
- "void protobuf_RegisterTypes(const ::std::string&) "
- "GOOGLE_PROTOBUF_ATTRIBUTE_COLD;\n"
- "void protobuf_RegisterTypes(const ::std::string&) {\n"
- " protobuf_AssignDescriptorsOnce();\n");
- printer->Indent();
- // All normal messages can be done generically
- if (!message_generators_.empty()) {
- printer->Print(
- "::google::protobuf::internal::RegisterAllTypes(file_level_metadata, $size$);\n",
- "size", SimpleItoa(message_generators_.size()));
- }
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n");
- // Now generate the AddDescriptors() function.
- printer->Print(
- "void AddDescriptorsImpl() {\n"
- " InitDefaults();\n");
- printer->Indent();
- // Embed the descriptor. We simply serialize the entire
- // FileDescriptorProto
- // and embed it as a string literal, which is parsed and built into real
- // descriptors at initialization time.
- FileDescriptorProto file_proto;
- file_->CopyTo(&file_proto);
- string file_data;
- file_proto.SerializeToString(&file_data);
- printer->Print("static const char descriptor[] "
- "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) "
- "= {\n");
- printer->Indent();
- if (file_data.size() > 65535) {
- // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
- // bytes in length". Declare a static array of characters rather than use
- // a string literal. Only write 25 bytes per line.
- static const int kBytesPerLine = 25;
- for (int i = 0; i < file_data.size();) {
- for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
- printer->Print("'$char$', ", "char",
- CEscape(file_data.substr(i, 1)));
- }
- printer->Print("\n");
- }
- } else {
- // Only write 40 bytes per line.
- static const int kBytesPerLine = 40;
- for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
- printer->Print(" \"$data$\"\n", "data",
- EscapeTrigraphs(CEscape(
- file_data.substr(i, kBytesPerLine))));
- }
- }
- printer->Outdent();
- printer->Print("};\n");
- printer->Print(
- "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(\n"
- " descriptor, $size$);\n",
- "size", SimpleItoa(file_data.size()));
- // Call MessageFactory::InternalRegisterGeneratedFile().
- printer->Print(
- "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
- " \"$filename$\", &protobuf_RegisterTypes);\n",
- "filename", file_->name());
- // Call the AddDescriptors() methods for all of our dependencies, to make
- // sure they get added first.
- for (int i = 0; i < file_->dependency_count(); i++) {
- const FileDescriptor* dependency = file_->dependency(i);
- // Print the namespace prefix for the dependency.
- string file_namespace = FileLevelNamespace(dependency);
- // Call its AddDescriptors function.
- printer->Print("::$file_namespace$::AddDescriptors();\n", "file_namespace",
- file_namespace);
- }
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n"
- "void AddDescriptors() {\n"
- " static ::google::protobuf::internal::once_flag once;\n"
- " ::google::protobuf::internal::call_once(once, AddDescriptorsImpl);\n"
- "}\n");
- printer->Print(
- "// Force AddDescriptors() to be called at dynamic initialization "
- "time.\n"
- "struct StaticDescriptorInitializer {\n"
- " StaticDescriptorInitializer() {\n"
- " AddDescriptors();\n"
- " }\n"
- "} static_descriptor_initializer;\n");
- }
- void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
- const string scc_name = ClassName(scc->GetRepresentative());
- // We use static and not anonymous namespace because symbol names are
- // substantially shorter.
- printer->Print(
- "static void InitDefaults$scc_name$() {\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n"
- , // awkward comma due to macro
- "scc_name", scc_name);
- printer->Indent();
- // First construct all the necessary default instances.
- for (int i = 0; i < message_generators_.size(); i++) {
- if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
- continue;
- }
- // TODO(gerbens) This requires this function to be friend. Remove
- // the need for this.
- message_generators_[i]->GenerateFieldDefaultInstances(printer);
- printer->Print(
- "{\n"
- " void* ptr = &$ns$::_$classname$_default_instance_;\n"
- " new (ptr) $ns$::$classname$();\n",
- "ns", Namespace(message_generators_[i]->descriptor_),
- "classname", ClassName(message_generators_[i]->descriptor_));
- if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) {
- printer->Print(
- " ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);\n");
- }
- printer->Print("}\n");
- }
- // TODO(gerbens) make default instances be the same as normal instances.
- // Default instances differ from normal instances because they have cross
- // linked message fields.
- for (int i = 0; i < message_generators_.size(); i++) {
- if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
- continue;
- }
- printer->Print("$classname$::InitAsDefaultInstance();\n", "classname",
- QualifiedClassName(message_generators_[i]->descriptor_));
- }
- printer->Outdent();
- printer->Print("}\n\n");
- printer->Print(
- "$dllexport_decl$::google::protobuf::internal::SCCInfo<$size$> "
- "scc_info_$scc_name$ =\n"
- " {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), "
- "$size$, InitDefaults$scc_name$}, {",
- "size", SimpleItoa(scc->children.size()), "scc_name",
- ClassName(scc->GetRepresentative()), "dllexport_decl",
- options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
- for (const SCC* child : scc->children) {
- auto repr = child->GetRepresentative();
- printer->Print("\n &$ns$::scc_info_$child$.base,", "ns",
- FileLevelNamespace(repr), "child", ClassName(repr));
- }
- printer->Print("}};\n\n");
- }
- void FileGenerator::GenerateTables(io::Printer* printer) {
- if (options_.table_driven_parsing) {
- // TODO(ckennelly): Gate this with the same options flag to enable
- // table-driven parsing.
- printer->Print(
- "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField\n"
- " const TableStruct::entries[] "
- "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
- std::vector<size_t> entries;
- size_t count = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- size_t value = message_generators_[i]->GenerateParseOffsets(printer);
- entries.push_back(value);
- count += value;
- }
- // We need these arrays to exist, and MSVC does not like empty arrays.
- if (count == 0) {
- printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n");
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "\n"
- "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField\n"
- " const TableStruct::aux[] "
- "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
- std::vector<size_t> aux_entries;
- count = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- size_t value = message_generators_[i]->GenerateParseAuxTable(printer);
- aux_entries.push_back(value);
- count += value;
- }
- if (count == 0) {
- printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n");
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const\n"
- " TableStruct::schema[] "
- "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
- size_t offset = 0;
- size_t aux_offset = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->GenerateParseTable(printer, offset, aux_offset);
- offset += entries[i];
- aux_offset += aux_entries[i];
- }
- if (message_generators_.empty()) {
- printer->Print("{ NULL, NULL, 0, -1, -1, false },\n");
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "\n");
- }
- if (!message_generators_.empty() && options_.table_driven_serialization) {
- printer->Print(
- "const ::google::protobuf::internal::FieldMetadata TableStruct::field_metadata[] "
- "= {\n");
- printer->Indent();
- std::vector<int> field_metadata_offsets;
- int idx = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- field_metadata_offsets.push_back(idx);
- idx += message_generators_[i]->GenerateFieldMetadata(printer);
- }
- field_metadata_offsets.push_back(idx);
- printer->Outdent();
- printer->Print(
- "};\n"
- "const ::google::protobuf::internal::SerializationTable "
- "TableStruct::serialization_table[] = {\n");
- printer->Indent();
- // We rely on the order we layout the tables to match the order we
- // calculate them with FlattenMessagesInFile, so we check here that
- // these match exactly.
- std::vector<const Descriptor*> calculated_order =
- FlattenMessagesInFile(file_);
- GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size());
- for (int i = 0; i < message_generators_.size(); i++) {
- GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_);
- printer->Print(
- "{$num_fields$, TableStruct::field_metadata + $index$},\n",
- "classname", message_generators_[i]->classname_, "num_fields",
- SimpleItoa(field_metadata_offsets[i + 1] - field_metadata_offsets[i]),
- "index", SimpleItoa(field_metadata_offsets[i]));
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "\n");
- }
- }
- void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
- ForwardDeclarations decls;
- FillForwardDeclarations(&decls);
- decls.PrintForwardDeclarations(printer, options_);
- }
- void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
- for (int i = 0; i < package_parts_.size(); i++) {
- decls = decls->AddOrGetNamespace(package_parts_[i]);
- }
- // Generate enum definitions.
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->FillForwardDeclaration(&decls->enums());
- }
- // Generate forward declarations of classes.
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->FillMessageForwardDeclarations(
- &decls->classes());
- }
- }
- void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
- const string& filename_identifier) {
- // Generate top of header.
- printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "// source: $filename$\n"
- "\n"
- "#ifndef PROTOBUF_INCLUDED_$filename_identifier$\n"
- "#define PROTOBUF_INCLUDED_$filename_identifier$\n"
- "\n"
- "#include <string>\n",
- "filename", file_->name(), "filename_identifier", filename_identifier);
- printer->Print("\n");
- }
- void FileGenerator::GenerateBottomHeaderGuard(
- io::Printer* printer, const string& filename_identifier) {
- printer->Print(
- "#endif // PROTOBUF_INCLUDED_$filename_identifier$\n",
- "filename_identifier", filename_identifier);
- }
- void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
- if (UsingImplicitWeakFields(file_, options_)) {
- printer->Print("#include <google/protobuf/implicit_weak_message.h>\n");
- }
- printer->Print(
- "#include <google/protobuf/stubs/common.h>\n"
- "\n");
- // Verify the protobuf library header version is compatible with the protoc
- // version before going any further.
- printer->Print(
- "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
- "#error This file was generated by a newer version of protoc which is\n"
- "#error incompatible with your Protocol Buffer headers. Please update\n"
- "#error your headers.\n"
- "#endif\n"
- "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
- "#error This file was generated by an older version of protoc which is\n"
- "#error incompatible with your Protocol Buffer headers. Please\n"
- "#error regenerate this file with a newer version of protoc.\n"
- "#endif\n"
- "\n",
- "min_header_version",
- SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
- "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
- // OK, it's now safe to #include other files.
- printer->Print(
- "#include <google/protobuf/io/coded_stream.h>\n"
- "#include <google/protobuf/arena.h>\n"
- "#include <google/protobuf/arenastring.h>\n"
- "#include <google/protobuf/generated_message_table_driven.h>\n"
- "#include <google/protobuf/generated_message_util.h>\n"
- "#include <google/protobuf/inlined_string_field.h>\n");
- if (HasDescriptorMethods(file_, options_)) {
- printer->Print(
- "#include <google/protobuf/metadata.h>\n");
- } else {
- printer->Print(
- "#include <google/protobuf/metadata_lite.h>\n");
- }
- if (!message_generators_.empty()) {
- if (HasDescriptorMethods(file_, options_)) {
- printer->Print(
- "#include <google/protobuf/message.h>\n");
- } else {
- printer->Print(
- "#include <google/protobuf/message_lite.h>\n");
- }
- }
- printer->Print(
- "#include <google/protobuf/repeated_field.h>"
- " // IWYU pragma: export\n"
- "#include <google/protobuf/extension_set.h>"
- " // IWYU pragma: export\n");
- if (HasMapFields(file_)) {
- printer->Print(
- "#include <google/protobuf/map.h>"
- " // IWYU pragma: export\n");
- if (HasDescriptorMethods(file_, options_)) {
- printer->Print("#include <google/protobuf/map_entry.h>\n");
- printer->Print("#include <google/protobuf/map_field_inl.h>\n");
- } else {
- printer->Print("#include <google/protobuf/map_entry_lite.h>\n");
- printer->Print("#include <google/protobuf/map_field_lite.h>\n");
- }
- }
- if (HasEnumDefinitions(file_)) {
- if (HasDescriptorMethods(file_, options_)) {
- printer->Print(
- "#include <google/protobuf/generated_enum_reflection.h>\n");
- } else {
- printer->Print(
- "#include <google/protobuf/generated_enum_util.h>\n");
- }
- }
- if (HasGenericServices(file_, options_)) {
- printer->Print(
- "#include <google/protobuf/service.h>\n");
- }
- if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
- printer->Print(
- "#include <google/protobuf/unknown_field_set.h>\n");
- }
- if (IsAnyMessage(file_)) {
- printer->Print(
- "#include <google/protobuf/any.h>\n");
- }
- }
- void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
- const string& info_path) {
- if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
- !options_.annotation_guard_name.empty()) {
- printer->Print(
- "#ifdef $guard$\n"
- "#pragma $pragma$ \"$info_path$\"\n"
- "#endif // $guard$\n",
- "guard", options_.annotation_guard_name, "pragma",
- options_.annotation_pragma_name, "info_path", info_path);
- }
- }
- void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
- std::set<string> public_import_names;
- for (int i = 0; i < file_->public_dependency_count(); i++) {
- public_import_names.insert(file_->public_dependency(i)->name());
- }
- for (int i = 0; i < file_->dependency_count(); i++) {
- const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
- const string& name = file_->dependency(i)->name();
- bool public_import = (public_import_names.count(name) != 0);
- string basename = StripProto(name);
- printer->Print(
- "#include $left$$dependency$.pb.h$right$$iwyu$\n",
- "dependency", basename,
- "iwyu", (public_import) ? " // IWYU pragma: export" : "",
- "left", use_system_include ? "<" : "\"",
- "right", use_system_include ? ">" : "\"");
- }
- }
- void FileGenerator::GenerateGlobalStateFunctionDeclarations(
- io::Printer* printer) {
- // Forward-declare the AddDescriptors, InitDefaults because these are called
- // by .pb.cc files depending on this file.
- printer->Print(
- "\n"
- "namespace $file_namespace$ {\n"
- "// Internal implementation detail -- do not use these members.\n"
- "struct $dllexport_decl$TableStruct {\n"
- // These tables describe how to serialize and parse messages. Used
- // for table driven code.
- " static const ::google::protobuf::internal::ParseTableField entries[];\n"
- " static const ::google::protobuf::internal::AuxillaryParseTableField aux[];\n"
- " static const ::google::protobuf::internal::ParseTable schema[$num$];\n"
- " static const ::google::protobuf::internal::FieldMetadata field_metadata[];\n"
- " static const ::google::protobuf::internal::SerializationTable "
- "serialization_table[];\n"
- " static const ::google::protobuf::uint32 offsets[];\n"
- "};\n",
- "file_namespace", FileLevelNamespace(file_), "dllexport_decl",
- options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ",
- "num", SimpleItoa(std::max(size_t(1), message_generators_.size())));
- if (HasDescriptorMethods(file_, options_)) {
- printer->Print(
- "void $dllexport_decl$AddDescriptors();\n", "dllexport_decl",
- options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
- }
- printer->Print(
- "} // namespace $file_namespace$\n",
- "file_namespace", FileLevelNamespace(file_));
- }
- void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
- // Generate class definitions.
- for (int i = 0; i < message_generators_.size(); i++) {
- if (i > 0) {
- printer->Print("\n");
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- message_generators_[i]->GenerateClassDefinition(printer);
- }
- }
- void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
- // Generate enum definitions.
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->GenerateDefinition(printer);
- }
- }
- void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
- if (HasGenericServices(file_, options_)) {
- // Generate service definitions.
- for (int i = 0; i < service_generators_.size(); i++) {
- if (i > 0) {
- printer->Print("\n");
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- service_generators_[i]->GenerateDeclarations(printer);
- }
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- }
- }
- void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
- // Declare extension identifiers. These are in global scope and so only
- // the global scope extensions.
- for (int i = 0; i < file_->extension_count(); i++) {
- extension_generators_owner_[i]->GenerateDeclaration(printer);
- }
- }
- void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
- // TODO(gerbens) remove pragmas when gcc is no longer used. Current version
- // of gcc fires a bogus error when compiled with strict-aliasing.
- printer->Print(
- "#ifdef __GNUC__\n"
- " #pragma GCC diagnostic push\n"
- " #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n"
- "#endif // __GNUC__\n");
- // Generate class inline methods.
- for (int i = 0; i < message_generators_.size(); i++) {
- if (i > 0) {
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- message_generators_[i]->GenerateInlineMethods(printer);
- }
- printer->Print(
- "#ifdef __GNUC__\n"
- " #pragma GCC diagnostic pop\n"
- "#endif // __GNUC__\n");
- for (int i = 0; i < message_generators_.size(); i++) {
- if (i > 0) {
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- }
- }
- void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
- io::Printer* printer) {
- // Emit GetEnumDescriptor specializations into google::protobuf namespace:
- if (HasEnumDefinitions(file_)) {
- printer->Print(
- "\n"
- "namespace google {\nnamespace protobuf {\n"
- "\n");
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
- }
- printer->Print(
- "\n"
- "} // namespace protobuf\n} // namespace google\n");
- }
- }
- } // namespace cpp
- } // namespace compiler
- } // namespace protobuf
- } // namespace google
|