cpp_service.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. #include <google/protobuf/compiler/cpp/cpp_service.h>
  34. #include <google/protobuf/compiler/cpp/cpp_helpers.h>
  35. #include <google/protobuf/io/printer.h>
  36. #include <google/protobuf/stubs/strutil.h>
  37. namespace google {
  38. namespace protobuf {
  39. namespace compiler {
  40. namespace cpp {
  41. ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
  42. const Options& options)
  43. : descriptor_(descriptor) {
  44. vars_["classname"] = descriptor_->name();
  45. vars_["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
  46. vars_["full_name"] = descriptor_->full_name();
  47. if (options.dllexport_decl.empty()) {
  48. vars_["dllexport"] = "";
  49. } else {
  50. vars_["dllexport"] = options.dllexport_decl + " ";
  51. }
  52. }
  53. ServiceGenerator::~ServiceGenerator() {}
  54. void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
  55. // Forward-declare the stub type.
  56. printer->Print(vars_,
  57. "class $classname$_Stub;\n"
  58. "\n");
  59. GenerateInterface(printer);
  60. GenerateStubDefinition(printer);
  61. }
  62. void ServiceGenerator::GenerateInterface(io::Printer* printer) {
  63. printer->Print(vars_,
  64. "class $dllexport$$classname$ : public ::google::protobuf::Service {\n"
  65. " protected:\n"
  66. " // This class should be treated as an abstract interface.\n"
  67. " inline $classname$() {};\n"
  68. " public:\n"
  69. " virtual ~$classname$();\n");
  70. printer->Indent();
  71. printer->Print(vars_,
  72. "\n"
  73. "typedef $classname$_Stub Stub;\n"
  74. "\n"
  75. "static const ::google::protobuf::ServiceDescriptor* descriptor();\n"
  76. "\n");
  77. GenerateMethodSignatures(VIRTUAL, printer);
  78. printer->Print(
  79. "\n"
  80. "// implements Service ----------------------------------------------\n"
  81. "\n"
  82. "const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n"
  83. "void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
  84. " ::google::protobuf::RpcController* controller,\n"
  85. " const ::google::protobuf::Message* request,\n"
  86. " ::google::protobuf::Message* response,\n"
  87. " ::google::protobuf::Closure* done);\n"
  88. "const ::google::protobuf::Message& GetRequestPrototype(\n"
  89. " const ::google::protobuf::MethodDescriptor* method) const;\n"
  90. "const ::google::protobuf::Message& GetResponsePrototype(\n"
  91. " const ::google::protobuf::MethodDescriptor* method) const;\n");
  92. printer->Outdent();
  93. printer->Print(vars_,
  94. "\n"
  95. " private:\n"
  96. " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n"
  97. "};\n"
  98. "\n");
  99. }
  100. void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) {
  101. printer->Print(vars_,
  102. "class $dllexport$$classname$_Stub : public $classname$ {\n"
  103. " public:\n");
  104. printer->Indent();
  105. printer->Print(vars_,
  106. "$classname$_Stub(::google::protobuf::RpcChannel* channel);\n"
  107. "$classname$_Stub(::google::protobuf::RpcChannel* channel,\n"
  108. " ::google::protobuf::Service::ChannelOwnership ownership);\n"
  109. "~$classname$_Stub();\n"
  110. "\n"
  111. "inline ::google::protobuf::RpcChannel* channel() { return channel_; }\n"
  112. "\n"
  113. "// implements $classname$ ------------------------------------------\n"
  114. "\n");
  115. GenerateMethodSignatures(NON_VIRTUAL, printer);
  116. printer->Outdent();
  117. printer->Print(vars_,
  118. " private:\n"
  119. " ::google::protobuf::RpcChannel* channel_;\n"
  120. " bool owns_channel_;\n"
  121. " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n"
  122. "};\n"
  123. "\n");
  124. }
  125. void ServiceGenerator::GenerateMethodSignatures(
  126. VirtualOrNon virtual_or_non, io::Printer* printer) {
  127. for (int i = 0; i < descriptor_->method_count(); i++) {
  128. const MethodDescriptor* method = descriptor_->method(i);
  129. std::map<string, string> sub_vars;
  130. sub_vars["name"] = method->name();
  131. sub_vars["input_type"] = ClassName(method->input_type(), true);
  132. sub_vars["output_type"] = ClassName(method->output_type(), true);
  133. sub_vars["virtual"] = virtual_or_non == VIRTUAL ? "virtual " : "";
  134. printer->Print(sub_vars,
  135. "$virtual$void $name$(::google::protobuf::RpcController* controller,\n"
  136. " const $input_type$* request,\n"
  137. " $output_type$* response,\n"
  138. " ::google::protobuf::Closure* done);\n");
  139. }
  140. }
  141. // ===================================================================
  142. void ServiceGenerator::GenerateDescriptorInitializer(
  143. io::Printer* printer, int index) {
  144. std::map<string, string> vars;
  145. vars["classname"] = descriptor_->name();
  146. vars["index"] = SimpleItoa(index);
  147. printer->Print(vars,
  148. "$classname$_descriptor_ = file->service($index$);\n");
  149. }
  150. // ===================================================================
  151. void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
  152. vars_["index"] = SimpleItoa(index_in_metadata_);
  153. printer->Print(
  154. vars_,
  155. "$classname$::~$classname$() {}\n"
  156. "\n"
  157. "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
  158. " $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
  159. " return $file_namespace$::file_level_service_descriptors[$index$];\n"
  160. "}\n"
  161. "\n"
  162. "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
  163. " return descriptor();\n"
  164. "}\n"
  165. "\n");
  166. // Generate methods of the interface.
  167. GenerateNotImplementedMethods(printer);
  168. GenerateCallMethod(printer);
  169. GenerateGetPrototype(REQUEST, printer);
  170. GenerateGetPrototype(RESPONSE, printer);
  171. // Generate stub implementation.
  172. printer->Print(vars_,
  173. "$classname$_Stub::$classname$_Stub(::google::protobuf::RpcChannel* channel)\n"
  174. " : channel_(channel), owns_channel_(false) {}\n"
  175. "$classname$_Stub::$classname$_Stub(\n"
  176. " ::google::protobuf::RpcChannel* channel,\n"
  177. " ::google::protobuf::Service::ChannelOwnership ownership)\n"
  178. " : channel_(channel),\n"
  179. " owns_channel_(ownership == ::google::protobuf::Service::STUB_OWNS_CHANNEL) {}\n"
  180. "$classname$_Stub::~$classname$_Stub() {\n"
  181. " if (owns_channel_) delete channel_;\n"
  182. "}\n"
  183. "\n");
  184. GenerateStubMethods(printer);
  185. }
  186. void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
  187. for (int i = 0; i < descriptor_->method_count(); i++) {
  188. const MethodDescriptor* method = descriptor_->method(i);
  189. std::map<string, string> sub_vars;
  190. sub_vars["classname"] = descriptor_->name();
  191. sub_vars["name"] = method->name();
  192. sub_vars["index"] = SimpleItoa(i);
  193. sub_vars["input_type"] = ClassName(method->input_type(), true);
  194. sub_vars["output_type"] = ClassName(method->output_type(), true);
  195. printer->Print(sub_vars,
  196. "void $classname$::$name$(::google::protobuf::RpcController* controller,\n"
  197. " const $input_type$*,\n"
  198. " $output_type$*,\n"
  199. " ::google::protobuf::Closure* done) {\n"
  200. " controller->SetFailed(\"Method $name$() not implemented.\");\n"
  201. " done->Run();\n"
  202. "}\n"
  203. "\n");
  204. }
  205. }
  206. void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
  207. printer->Print(
  208. vars_,
  209. "void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
  210. " ::google::protobuf::RpcController* controller,\n"
  211. " const ::google::protobuf::Message* request,\n"
  212. " ::google::protobuf::Message* response,\n"
  213. " ::google::protobuf::Closure* done) {\n"
  214. " GOOGLE_DCHECK_EQ(method->service(), "
  215. "$file_namespace$::file_level_service_descriptors[$index$]);\n"
  216. " switch(method->index()) {\n");
  217. for (int i = 0; i < descriptor_->method_count(); i++) {
  218. const MethodDescriptor* method = descriptor_->method(i);
  219. std::map<string, string> sub_vars;
  220. sub_vars["name"] = method->name();
  221. sub_vars["index"] = SimpleItoa(i);
  222. sub_vars["input_type"] = ClassName(method->input_type(), true);
  223. sub_vars["output_type"] = ClassName(method->output_type(), true);
  224. // Note: down_cast does not work here because it only works on pointers,
  225. // not references.
  226. printer->Print(sub_vars,
  227. " case $index$:\n"
  228. " $name$(controller,\n"
  229. " ::google::protobuf::down_cast<const $input_type$*>(request),\n"
  230. " ::google::protobuf::down_cast< $output_type$*>(response),\n"
  231. " done);\n"
  232. " break;\n");
  233. }
  234. printer->Print(vars_,
  235. " default:\n"
  236. " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
  237. " break;\n"
  238. " }\n"
  239. "}\n"
  240. "\n");
  241. }
  242. void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
  243. io::Printer* printer) {
  244. if (which == REQUEST) {
  245. printer->Print(vars_,
  246. "const ::google::protobuf::Message& $classname$::GetRequestPrototype(\n");
  247. } else {
  248. printer->Print(vars_,
  249. "const ::google::protobuf::Message& $classname$::GetResponsePrototype(\n");
  250. }
  251. printer->Print(vars_,
  252. " const ::google::protobuf::MethodDescriptor* method) const {\n"
  253. " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n"
  254. " switch(method->index()) {\n");
  255. for (int i = 0; i < descriptor_->method_count(); i++) {
  256. const MethodDescriptor* method = descriptor_->method(i);
  257. const Descriptor* type =
  258. (which == REQUEST) ? method->input_type() : method->output_type();
  259. std::map<string, string> sub_vars;
  260. sub_vars["index"] = SimpleItoa(i);
  261. sub_vars["type"] = ClassName(type, true);
  262. printer->Print(sub_vars,
  263. " case $index$:\n"
  264. " return $type$::default_instance();\n");
  265. }
  266. printer->Print(
  267. " default:\n"
  268. " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
  269. " return *::google::protobuf::MessageFactory::generated_factory()\n"
  270. " ->GetPrototype(method->$input_or_output$_type());\n"
  271. " }\n"
  272. "}\n"
  273. "\n",
  274. "input_or_output", which == REQUEST ? "input" : "output");
  275. }
  276. void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
  277. for (int i = 0; i < descriptor_->method_count(); i++) {
  278. const MethodDescriptor* method = descriptor_->method(i);
  279. std::map<string, string> sub_vars;
  280. sub_vars["classname"] = descriptor_->name();
  281. sub_vars["name"] = method->name();
  282. sub_vars["index"] = SimpleItoa(i);
  283. sub_vars["input_type"] = ClassName(method->input_type(), true);
  284. sub_vars["output_type"] = ClassName(method->output_type(), true);
  285. printer->Print(sub_vars,
  286. "void $classname$_Stub::$name$(::google::protobuf::RpcController* controller,\n"
  287. " const $input_type$* request,\n"
  288. " $output_type$* response,\n"
  289. " ::google::protobuf::Closure* done) {\n"
  290. " channel_->CallMethod(descriptor()->method($index$),\n"
  291. " controller, request, response, done);\n"
  292. "}\n");
  293. }
  294. }
  295. } // namespace cpp
  296. } // namespace compiler
  297. } // namespace protobuf
  298. } // namespace google