| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 | /* * * Copyright 2014, Google Inc. * All rights reserved. * * 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. * */#include "src/compiler/cpp_generator.h"#include "src/compiler/cpp_generator_helpers.h"#include <google/protobuf/descriptor.h>#include <google/protobuf/descriptor.pb.h>#include <google/protobuf/io/printer.h>#include <google/protobuf/io/zero_copy_stream_impl_lite.h>namespace grpc_cpp_generator {namespace {bool NoStreaming(const google::protobuf::MethodDescriptor* method) {  return !method->client_streaming() && !method->server_streaming();}bool ClientOnlyStreaming(const google::protobuf::MethodDescriptor* method) {  return method->client_streaming() && !method->server_streaming();}bool ServerOnlyStreaming(const google::protobuf::MethodDescriptor* method) {  return !method->client_streaming() && method->server_streaming();}bool BidiStreaming(const google::protobuf::MethodDescriptor* method) {  return method->client_streaming() && method->server_streaming();}bool HasClientOnlyStreaming(const google::protobuf::FileDescriptor* file) {  for (int i = 0; i < file->service_count(); i++) {    for (int j = 0; j < file->service(i)->method_count(); j++) {      if (ClientOnlyStreaming(file->service(i)->method(j))) {        return true;      }    }  }  return false;}bool HasServerOnlyStreaming(const google::protobuf::FileDescriptor* file) {  for (int i = 0; i < file->service_count(); i++) {    for (int j = 0; j < file->service(i)->method_count(); j++) {      if (ServerOnlyStreaming(file->service(i)->method(j))) {        return true;      }    }  }  return false;}bool HasBidiStreaming(const google::protobuf::FileDescriptor* file) {  for (int i = 0; i < file->service_count(); i++) {    for (int j = 0; j < file->service(i)->method_count(); j++) {      if (BidiStreaming(file->service(i)->method(j))) {        return true;      }    }  }  return false;}}  // namespacestring GetHeaderIncludes(const google::protobuf::FileDescriptor* file) {  string temp =      "#include \"grpc++/impl/internal_stub.h\"\n"      "#include \"grpc++/status.h\"\n"      "\n"      "namespace grpc {\n"      "class ChannelInterface;\n"      "class RpcService;\n"      "class ServerContext;\n";  if (HasClientOnlyStreaming(file)) {    temp.append("template <class OutMessage> class ClientWriter;\n");    temp.append("template <class InMessage> class ServerReader;\n");  }  if (HasServerOnlyStreaming(file)) {    temp.append("template <class InMessage> class ClientReader;\n");    temp.append("template <class OutMessage> class ServerWriter;\n");  }  if (HasBidiStreaming(file)) {    temp.append(        "template <class OutMessage, class InMessage>\n"        "class ClientReaderWriter;\n");    temp.append(        "template <class OutMessage, class InMessage>\n"        "class ServerReaderWriter;\n");  }  temp.append("}  // namespace grpc\n");  return temp;}string GetSourceIncludes() {  return "#include \"grpc++/channel_interface.h\"\n"         "#include \"grpc++/impl/rpc_method.h\"\n"         "#include \"grpc++/impl/rpc_service_method.h\"\n"         "#include \"grpc++/stream.h\"\n";}void PrintHeaderClientMethod(google::protobuf::io::Printer* printer,                             const google::protobuf::MethodDescriptor* method,                             map<string, string>* vars) {  (*vars)["Method"] = method->name();  (*vars)["Request"] =      grpc_cpp_generator::ClassName(method->input_type(), true);  (*vars)["Response"] =      grpc_cpp_generator::ClassName(method->output_type(), true);  if (NoStreaming(method)) {    printer->Print(*vars,                   "::grpc::Status $Method$(::grpc::ClientContext* context, "                   "const $Request$& request, $Response$* response);\n\n");  } else if (ClientOnlyStreaming(method)) {    printer->Print(        *vars,        "::grpc::ClientWriter< $Request$>* $Method$("        "::grpc::ClientContext* context, $Response$* response);\n\n");  } else if (ServerOnlyStreaming(method)) {    printer->Print(        *vars,        "::grpc::ClientReader< $Response$>* $Method$("        "::grpc::ClientContext* context, const $Request$* request);\n\n");  } else if (BidiStreaming(method)) {    printer->Print(*vars,                   "::grpc::ClientReaderWriter< $Request$, $Response$>* "                   "$Method$(::grpc::ClientContext* context);\n\n");  }}void PrintHeaderServerMethod(google::protobuf::io::Printer* printer,                             const google::protobuf::MethodDescriptor* method,                             map<string, string>* vars) {  (*vars)["Method"] = method->name();  (*vars)["Request"] =      grpc_cpp_generator::ClassName(method->input_type(), true);  (*vars)["Response"] =      grpc_cpp_generator::ClassName(method->output_type(), true);  if (NoStreaming(method)) {    printer->Print(*vars,                   "virtual ::grpc::Status $Method$("                   "::grpc::ServerContext* context, const $Request$* request, "                   "$Response$* response);\n");  } else if (ClientOnlyStreaming(method)) {    printer->Print(*vars,                   "virtual ::grpc::Status $Method$("                   "::grpc::ServerContext* context, "                   "::grpc::ServerReader< $Request$>* reader, "                   "$Response$* response);\n");  } else if (ServerOnlyStreaming(method)) {    printer->Print(*vars,                   "virtual ::grpc::Status $Method$("                   "::grpc::ServerContext* context, const $Request$* request, "                   "::grpc::ServerWriter< $Response$>* writer);\n");  } else if (BidiStreaming(method)) {    printer->Print(        *vars,        "virtual ::grpc::Status $Method$("        "::grpc::ServerContext* context, "        "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"        "\n");  }}void PrintHeaderService(google::protobuf::io::Printer* printer,                        const google::protobuf::ServiceDescriptor* service,                        map<string, string>* vars) {  (*vars)["Service"] = service->name();  printer->Print(*vars,                 "class $Service$ {\n"                 " public:\n");  printer->Indent();  // Client side  printer->Print(      "class Stub : public ::grpc::InternalStub {\n"      " public:\n");  printer->Indent();  for (int i = 0; i < service->method_count(); ++i) {    PrintHeaderClientMethod(printer, service->method(i), vars);  }  printer->Outdent();  printer->Print("};\n");  printer->Print(      "static Stub* NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& "      "channel);\n");  printer->Print("\n");  // Server side  printer->Print(      "class Service {\n"      " public:\n");  printer->Indent();  printer->Print("Service() : service_(nullptr) {}\n");  printer->Print("virtual ~Service();\n");  for (int i = 0; i < service->method_count(); ++i) {    PrintHeaderServerMethod(printer, service->method(i), vars);  }  printer->Print("::grpc::RpcService* service();\n");  printer->Outdent();  printer->Print(      " private:\n"      "  ::grpc::RpcService* service_;\n");  printer->Print("};\n");  printer->Outdent();  printer->Print("};\n");}string GetHeaderServices(const google::protobuf::FileDescriptor* file) {  string output;  google::protobuf::io::StringOutputStream output_stream(&output);  google::protobuf::io::Printer printer(&output_stream, '$');  map<string, string> vars;  for (int i = 0; i < file->service_count(); ++i) {    PrintHeaderService(&printer, file->service(i), &vars);    printer.Print("\n");  }  return output;}void PrintSourceClientMethod(google::protobuf::io::Printer* printer,                             const google::protobuf::MethodDescriptor* method,                             map<string, string>* vars) {  (*vars)["Method"] = method->name();  (*vars)["Request"] =      grpc_cpp_generator::ClassName(method->input_type(), true);  (*vars)["Response"] =      grpc_cpp_generator::ClassName(method->output_type(), true);  if (NoStreaming(method)) {    printer->Print(*vars,                   "::grpc::Status $Service$::Stub::$Method$("                   "::grpc::ClientContext* context, "                   "const $Request$& request, $Response$* response) {\n");    printer->Print(*vars,                   "  return channel()->StartBlockingRpc("                   "::grpc::RpcMethod(\"/$Package$$Service$/$Method$\"), "                   "context, request, response);\n"                   "}\n\n");  } else if (ClientOnlyStreaming(method)) {    printer->Print(        *vars,        "::grpc::ClientWriter< $Request$>* $Service$::Stub::$Method$("        "::grpc::ClientContext* context, $Response$* response) {\n");    printer->Print(*vars,                   "  return new ::grpc::ClientWriter< $Request$>("                   "channel()->CreateStream("                   "::grpc::RpcMethod(\"/$Package$$Service$/$Method$\", "                   "::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "                   "context, nullptr, response));\n"                   "}\n\n");  } else if (ServerOnlyStreaming(method)) {    printer->Print(        *vars,        "::grpc::ClientReader< $Response$>* $Service$::Stub::$Method$("        "::grpc::ClientContext* context, const $Request$* request) {\n");    printer->Print(*vars,                   "  return new ::grpc::ClientReader< $Response$>("                   "channel()->CreateStream("                   "::grpc::RpcMethod(\"/$Package$$Service$/$Method$\", "                   "::grpc::RpcMethod::RpcType::SERVER_STREAMING), "                   "context, request, nullptr));\n"                   "}\n\n");  } else if (BidiStreaming(method)) {    printer->Print(        *vars,        "::grpc::ClientReaderWriter< $Request$, $Response$>* "        "$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n");    printer->Print(        *vars,        "  return new ::grpc::ClientReaderWriter< $Request$, $Response$>("        "channel()->CreateStream("        "::grpc::RpcMethod(\"/$Package$$Service$/$Method$\", "        "::grpc::RpcMethod::RpcType::BIDI_STREAMING), "        "context, nullptr, nullptr));\n"        "}\n\n");  }}void PrintSourceServerMethod(google::protobuf::io::Printer* printer,                             const google::protobuf::MethodDescriptor* method,                             map<string, string>* vars) {  (*vars)["Method"] = method->name();  (*vars)["Request"] =      grpc_cpp_generator::ClassName(method->input_type(), true);  (*vars)["Response"] =      grpc_cpp_generator::ClassName(method->output_type(), true);  if (NoStreaming(method)) {    printer->Print(*vars,                   "::grpc::Status $Service$::Service::$Method$("                   "::grpc::ServerContext* context, "                   "const $Request$* request, $Response$* response) {\n");    printer->Print(        "  return ::grpc::Status("        "::grpc::StatusCode::UNIMPLEMENTED);\n");    printer->Print("}\n\n");  } else if (ClientOnlyStreaming(method)) {    printer->Print(*vars,                   "::grpc::Status $Service$::Service::$Method$("                   "::grpc::ServerContext* context, "                   "::grpc::ServerReader< $Request$>* reader, "                   "$Response$* response) {\n");    printer->Print(        "  return ::grpc::Status("        "::grpc::StatusCode::UNIMPLEMENTED);\n");    printer->Print("}\n\n");  } else if (ServerOnlyStreaming(method)) {    printer->Print(*vars,                   "::grpc::Status $Service$::Service::$Method$("                   "::grpc::ServerContext* context, "                   "const $Request$* request, "                   "::grpc::ServerWriter< $Response$>* writer) {\n");    printer->Print(        "  return ::grpc::Status("        "::grpc::StatusCode::UNIMPLEMENTED);\n");    printer->Print("}\n\n");  } else if (BidiStreaming(method)) {    printer->Print(*vars,                   "::grpc::Status $Service$::Service::$Method$("                   "::grpc::ServerContext* context, "                   "::grpc::ServerReaderWriter< $Response$, $Request$>* "                   "stream) {\n");    printer->Print(        "  return ::grpc::Status("        "::grpc::StatusCode::UNIMPLEMENTED);\n");    printer->Print("}\n\n");  }}void PrintSourceService(google::protobuf::io::Printer* printer,                        const google::protobuf::ServiceDescriptor* service,                        map<string, string>* vars) {  (*vars)["Service"] = service->name();  printer->Print(      *vars,      "$Service$::Stub* $Service$::NewStub("      "const std::shared_ptr< ::grpc::ChannelInterface>& channel) {\n"      "  $Service$::Stub* stub = new $Service$::Stub();\n"      "  stub->set_channel(channel);\n"      "  return stub;\n"      "};\n\n");  for (int i = 0; i < service->method_count(); ++i) {    PrintSourceClientMethod(printer, service->method(i), vars);  }  printer->Print(*vars,                 "$Service$::Service::~Service() {\n"                 "  delete service_;\n"                 "}\n\n");  for (int i = 0; i < service->method_count(); ++i) {    PrintSourceServerMethod(printer, service->method(i), vars);  }  printer->Print(*vars,                 "::grpc::RpcService* $Service$::Service::service() {\n");  printer->Indent();  printer->Print(      "if (service_ != nullptr) {\n"      "  return service_;\n"      "}\n");  printer->Print("service_ = new ::grpc::RpcService();\n");  for (int i = 0; i < service->method_count(); ++i) {    const google::protobuf::MethodDescriptor* method = service->method(i);    (*vars)["Method"] = method->name();    (*vars)["Request"] =        grpc_cpp_generator::ClassName(method->input_type(), true);    (*vars)["Response"] =        grpc_cpp_generator::ClassName(method->output_type(), true);    if (NoStreaming(method)) {      printer->Print(          *vars,          "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"          "    \"/$Package$$Service$/$Method$\",\n"          "    ::grpc::RpcMethod::NORMAL_RPC,\n"          "    new ::grpc::RpcMethodHandler< $Service$::Service, $Request$, "          "$Response$>(\n"          "        std::function< ::grpc::Status($Service$::Service*, "          "::grpc::ServerContext*, const $Request$*, $Response$*)>("          "&$Service$::Service::$Method$), this),\n"          "    new $Request$, new $Response$));\n");    } else if (ClientOnlyStreaming(method)) {      printer->Print(          *vars,          "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"          "    \"/$Package$$Service$/$Method$\",\n"          "    ::grpc::RpcMethod::CLIENT_STREAMING,\n"          "    new ::grpc::ClientStreamingHandler< "          "$Service$::Service, $Request$, $Response$>(\n"          "        std::function< ::grpc::Status($Service$::Service*, "          "::grpc::ServerContext*, "          "::grpc::ServerReader< $Request$>*, $Response$*)>("          "&$Service$::Service::$Method$), this),\n"          "    new $Request$, new $Response$));\n");    } else if (ServerOnlyStreaming(method)) {      printer->Print(          *vars,          "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"          "    \"/$Package$$Service$/$Method$\",\n"          "    ::grpc::RpcMethod::SERVER_STREAMING,\n"          "    new ::grpc::ServerStreamingHandler< "          "$Service$::Service, $Request$, $Response$>(\n"          "        std::function< ::grpc::Status($Service$::Service*, "          "::grpc::ServerContext*, "          "const $Request$*, ::grpc::ServerWriter< $Response$>*)>("          "&$Service$::Service::$Method$), this),\n"          "    new $Request$, new $Response$));\n");    } else if (BidiStreaming(method)) {      printer->Print(          *vars,          "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"          "    \"/$Package$$Service$/$Method$\",\n"          "    ::grpc::RpcMethod::BIDI_STREAMING,\n"          "    new ::grpc::BidiStreamingHandler< "          "$Service$::Service, $Request$, $Response$>(\n"          "        std::function< ::grpc::Status($Service$::Service*, "          "::grpc::ServerContext*, "          "::grpc::ServerReaderWriter< $Response$, $Request$>*)>("          "&$Service$::Service::$Method$), this),\n"          "    new $Request$, new $Response$));\n");    }  }  printer->Print("return service_;\n");  printer->Outdent();  printer->Print("}\n\n");}string GetSourceServices(const google::protobuf::FileDescriptor* file) {  string output;  google::protobuf::io::StringOutputStream output_stream(&output);  google::protobuf::io::Printer printer(&output_stream, '$');  map<string, string> vars;  // Package string is empty or ends with a dot. It is used to fully qualify  // method names.  vars["Package"] = file->package();  if (!file->package().empty()) {    vars["Package"].append(".");  }  for (int i = 0; i < file->service_count(); ++i) {    PrintSourceService(&printer, file->service(i), &vars);    printer.Print("\n");  }  return output;}}  // namespace grpc_cpp_generator
 |