1 /*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34 #include <map>
35
36 #include "src/compiler/cpp_generator.h"
37
38 #include <sstream>
39
40 namespace grpc_cpp_generator {
41 namespace {
42
43 template <class T>
as_string(T x)44 grpc::string as_string(T x) {
45 std::ostringstream out;
46 out << x;
47 return out.str();
48 }
49
FilenameIdentifier(const grpc::string & filename)50 grpc::string FilenameIdentifier(const grpc::string &filename) {
51 grpc::string result;
52 for (unsigned i = 0; i < filename.size(); i++) {
53 char c = filename[i];
54 if (isalnum(c)) {
55 result.push_back(c);
56 } else {
57 static char hex[] = "0123456789abcdef";
58 result.push_back('_');
59 result.push_back(hex[(c >> 4) & 0xf]);
60 result.push_back(hex[c & 0xf]);
61 }
62 }
63 return result;
64 }
65 } // namespace
66
67 template<class T, size_t N>
array_end(T (& array)[N])68 T *array_end(T (&array)[N]) { return array + N; }
69
PrintIncludes(grpc_generator::Printer * printer,const std::vector<grpc::string> & headers,const Parameters & params)70 void PrintIncludes(grpc_generator::Printer *printer,
71 const std::vector<grpc::string>& headers, const Parameters ¶ms) {
72 std::map<grpc::string, grpc::string> vars;
73
74 vars["l"] = params.use_system_headers ? '<' : '"';
75 vars["r"] = params.use_system_headers ? '>' : '"';
76
77 if (!params.grpc_search_path.empty()) {
78 vars["l"] += params.grpc_search_path;
79 if (params.grpc_search_path.back() != '/') {
80 vars["l"] += '/';
81 }
82 }
83
84 for (auto i = headers.begin(); i != headers.end(); i++) {
85 vars["h"] = *i;
86 printer->Print(vars, "#include $l$$h$$r$\n");
87 }
88 }
89
GetHeaderPrologue(grpc_generator::File * file,const Parameters &)90 grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters & /*params*/) {
91 grpc::string output;
92 {
93 // Scope the output stream so it closes and finalizes output to the string.
94 auto printer = file->CreatePrinter(&output);
95 std::map<grpc::string, grpc::string> vars;
96
97 vars["filename"] = file->filename();
98 vars["filename_identifier"] = FilenameIdentifier(file->filename());
99 vars["filename_base"] = file->filename_without_ext();
100 vars["message_header_ext"] = file->message_header_ext();
101
102 printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
103 printer->Print(vars,
104 "// If you make any local change, they will be lost.\n");
105 printer->Print(vars, "// source: $filename$\n");
106 printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
107 printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
108 printer->Print(vars, "\n");
109 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
110 printer->Print(vars, file->additional_headers().c_str());
111 printer->Print(vars, "\n");
112 }
113 return output;
114 }
115
GetHeaderIncludes(grpc_generator::File * file,const Parameters & params)116 grpc::string GetHeaderIncludes(grpc_generator::File *file,
117 const Parameters ¶ms) {
118 grpc::string output;
119 {
120 // Scope the output stream so it closes and finalizes output to the string.
121 auto printer = file->CreatePrinter(&output);
122 std::map<grpc::string, grpc::string> vars;
123
124 static const char *headers_strs[] = {
125 "grpc++/impl/codegen/async_stream.h",
126 "grpc++/impl/codegen/async_unary_call.h",
127 "grpc++/impl/codegen/rpc_method.h",
128 "grpc++/impl/codegen/service_type.h",
129 "grpc++/impl/codegen/status.h",
130 "grpc++/impl/codegen/stub_options.h",
131 "grpc++/impl/codegen/sync_stream.h"
132 };
133 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
134 PrintIncludes(printer.get(), headers, params);
135 printer->Print(vars, "\n");
136 printer->Print(vars, "namespace grpc {\n");
137 printer->Print(vars, "class CompletionQueue;\n");
138 printer->Print(vars, "class Channel;\n");
139 printer->Print(vars, "class RpcService;\n");
140 printer->Print(vars, "class ServerCompletionQueue;\n");
141 printer->Print(vars, "class ServerContext;\n");
142 printer->Print(vars, "} // namespace grpc\n\n");
143
144 if (!file->package().empty()) {
145 std::vector<grpc::string> parts = file->package_parts();
146
147 for (auto part = parts.begin(); part != parts.end(); part++) {
148 vars["part"] = *part;
149 printer->Print(vars, "namespace $part$ {\n");
150 }
151 printer->Print(vars, "\n");
152 }
153 }
154 return output;
155 }
156
PrintHeaderClientMethodInterfaces(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars,bool is_public)157 void PrintHeaderClientMethodInterfaces(
158 grpc_generator::Printer *printer, const grpc_generator::Method *method,
159 std::map<grpc::string, grpc::string> *vars, bool is_public) {
160 (*vars)["Method"] = method->name();
161 (*vars)["Request"] = method->input_type_name();
162 (*vars)["Response"] = method->output_type_name();
163
164 if (is_public) {
165 if (method->NoStreaming()) {
166 printer->Print(
167 *vars,
168 "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
169 "const $Request$& request, $Response$* response) = 0;\n");
170 printer->Print(*vars,
171 "std::unique_ptr< "
172 "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
173 "Async$Method$(::grpc::ClientContext* context, "
174 "const $Request$& request, "
175 "::grpc::CompletionQueue* cq) {\n");
176 printer->Indent();
177 printer->Print(*vars,
178 "return std::unique_ptr< "
179 "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
180 "Async$Method$Raw(context, request, cq));\n");
181 printer->Outdent();
182 printer->Print("}\n");
183 } else if (method->ClientOnlyStreaming()) {
184 printer->Print(
185 *vars,
186 "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
187 " $Method$("
188 "::grpc::ClientContext* context, $Response$* response) {\n");
189 printer->Indent();
190 printer->Print(
191 *vars,
192 "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
193 "($Method$Raw(context, response));\n");
194 printer->Outdent();
195 printer->Print("}\n");
196 printer->Print(
197 *vars,
198 "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
199 " Async$Method$(::grpc::ClientContext* context, $Response$* "
200 "response, "
201 "::grpc::CompletionQueue* cq, void* tag) {\n");
202 printer->Indent();
203 printer->Print(*vars,
204 "return std::unique_ptr< "
205 "::grpc::ClientAsyncWriterInterface< $Request$>>("
206 "Async$Method$Raw(context, response, cq, tag));\n");
207 printer->Outdent();
208 printer->Print("}\n");
209 } else if (method->ServerOnlyStreaming()) {
210 printer->Print(
211 *vars,
212 "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
213 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
214 " {\n");
215 printer->Indent();
216 printer->Print(
217 *vars,
218 "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
219 "($Method$Raw(context, request));\n");
220 printer->Outdent();
221 printer->Print("}\n");
222 printer->Print(
223 *vars,
224 "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
225 "Async$Method$("
226 "::grpc::ClientContext* context, const $Request$& request, "
227 "::grpc::CompletionQueue* cq, void* tag) {\n");
228 printer->Indent();
229 printer->Print(*vars,
230 "return std::unique_ptr< "
231 "::grpc::ClientAsyncReaderInterface< $Response$>>("
232 "Async$Method$Raw(context, request, cq, tag));\n");
233 printer->Outdent();
234 printer->Print("}\n");
235 } else if (method->BidiStreaming()) {
236 printer->Print(*vars,
237 "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
238 "$Request$, $Response$>> "
239 "$Method$(::grpc::ClientContext* context) {\n");
240 printer->Indent();
241 printer->Print(
242 *vars,
243 "return std::unique_ptr< "
244 "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
245 "$Method$Raw(context));\n");
246 printer->Outdent();
247 printer->Print("}\n");
248 printer->Print(
249 *vars,
250 "std::unique_ptr< "
251 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
252 "Async$Method$(::grpc::ClientContext* context, "
253 "::grpc::CompletionQueue* cq, void* tag) {\n");
254 printer->Indent();
255 printer->Print(
256 *vars,
257 "return std::unique_ptr< "
258 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
259 "Async$Method$Raw(context, cq, tag));\n");
260 printer->Outdent();
261 printer->Print("}\n");
262 }
263 } else {
264 if (method->NoStreaming()) {
265 printer->Print(
266 *vars,
267 "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
268 "Async$Method$Raw(::grpc::ClientContext* context, "
269 "const $Request$& request, "
270 "::grpc::CompletionQueue* cq) = 0;\n");
271 } else if (method->ClientOnlyStreaming()) {
272 printer->Print(
273 *vars,
274 "virtual ::grpc::ClientWriterInterface< $Request$>*"
275 " $Method$Raw("
276 "::grpc::ClientContext* context, $Response$* response) = 0;\n");
277 printer->Print(*vars,
278 "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
279 " Async$Method$Raw(::grpc::ClientContext* context, "
280 "$Response$* response, "
281 "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
282 } else if (method->ServerOnlyStreaming()) {
283 printer->Print(
284 *vars,
285 "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw("
286 "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
287 printer->Print(
288 *vars,
289 "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
290 "Async$Method$Raw("
291 "::grpc::ClientContext* context, const $Request$& request, "
292 "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
293 } else if (method->BidiStreaming()) {
294 printer->Print(*vars,
295 "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
296 "$Response$>* "
297 "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
298 printer->Print(*vars,
299 "virtual ::grpc::ClientAsyncReaderWriterInterface< "
300 "$Request$, $Response$>* "
301 "Async$Method$Raw(::grpc::ClientContext* context, "
302 "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
303 }
304 }
305 }
306
PrintHeaderClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars,bool is_public)307 void PrintHeaderClientMethod(grpc_generator::Printer *printer,
308 const grpc_generator::Method *method,
309 std::map<grpc::string, grpc::string> *vars,
310 bool is_public) {
311 (*vars)["Method"] = method->name();
312 (*vars)["Request"] = method->input_type_name();
313 (*vars)["Response"] = method->output_type_name();
314 if (is_public) {
315 if (method->NoStreaming()) {
316 printer->Print(
317 *vars,
318 "::grpc::Status $Method$(::grpc::ClientContext* context, "
319 "const $Request$& request, $Response$* response) GRPC_OVERRIDE;\n");
320 printer->Print(
321 *vars,
322 "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
323 "Async$Method$(::grpc::ClientContext* context, "
324 "const $Request$& request, "
325 "::grpc::CompletionQueue* cq) {\n");
326 printer->Indent();
327 printer->Print(*vars,
328 "return std::unique_ptr< "
329 "::grpc::ClientAsyncResponseReader< $Response$>>("
330 "Async$Method$Raw(context, request, cq));\n");
331 printer->Outdent();
332 printer->Print("}\n");
333 } else if (method->ClientOnlyStreaming()) {
334 printer->Print(
335 *vars,
336 "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
337 " $Method$("
338 "::grpc::ClientContext* context, $Response$* response) {\n");
339 printer->Indent();
340 printer->Print(*vars,
341 "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
342 "($Method$Raw(context, response));\n");
343 printer->Outdent();
344 printer->Print("}\n");
345 printer->Print(*vars,
346 "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
347 " Async$Method$(::grpc::ClientContext* context, "
348 "$Response$* response, "
349 "::grpc::CompletionQueue* cq, void* tag) {\n");
350 printer->Indent();
351 printer->Print(
352 *vars,
353 "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
354 "Async$Method$Raw(context, response, cq, tag));\n");
355 printer->Outdent();
356 printer->Print("}\n");
357 } else if (method->ServerOnlyStreaming()) {
358 printer->Print(
359 *vars,
360 "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
361 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
362 " {\n");
363 printer->Indent();
364 printer->Print(
365 *vars,
366 "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
367 "($Method$Raw(context, request));\n");
368 printer->Outdent();
369 printer->Print("}\n");
370 printer->Print(
371 *vars,
372 "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
373 "Async$Method$("
374 "::grpc::ClientContext* context, const $Request$& request, "
375 "::grpc::CompletionQueue* cq, void* tag) {\n");
376 printer->Indent();
377 printer->Print(
378 *vars,
379 "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
380 "Async$Method$Raw(context, request, cq, tag));\n");
381 printer->Outdent();
382 printer->Print("}\n");
383 } else if (method->BidiStreaming()) {
384 printer->Print(
385 *vars,
386 "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
387 " $Method$(::grpc::ClientContext* context) {\n");
388 printer->Indent();
389 printer->Print(*vars,
390 "return std::unique_ptr< "
391 "::grpc::ClientReaderWriter< $Request$, $Response$>>("
392 "$Method$Raw(context));\n");
393 printer->Outdent();
394 printer->Print("}\n");
395 printer->Print(*vars,
396 "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
397 "$Request$, $Response$>> "
398 "Async$Method$(::grpc::ClientContext* context, "
399 "::grpc::CompletionQueue* cq, void* tag) {\n");
400 printer->Indent();
401 printer->Print(*vars,
402 "return std::unique_ptr< "
403 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
404 "Async$Method$Raw(context, cq, tag));\n");
405 printer->Outdent();
406 printer->Print("}\n");
407 }
408 } else {
409 if (method->NoStreaming()) {
410 printer->Print(*vars,
411 "::grpc::ClientAsyncResponseReader< $Response$>* "
412 "Async$Method$Raw(::grpc::ClientContext* context, "
413 "const $Request$& request, "
414 "::grpc::CompletionQueue* cq) GRPC_OVERRIDE;\n");
415 } else if (method->ClientOnlyStreaming()) {
416 printer->Print(*vars,
417 "::grpc::ClientWriter< $Request$>* $Method$Raw("
418 "::grpc::ClientContext* context, $Response$* response) "
419 "GRPC_OVERRIDE;\n");
420 printer->Print(
421 *vars,
422 "::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw("
423 "::grpc::ClientContext* context, $Response$* response, "
424 "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
425 } else if (method->ServerOnlyStreaming()) {
426 printer->Print(*vars,
427 "::grpc::ClientReader< $Response$>* $Method$Raw("
428 "::grpc::ClientContext* context, const $Request$& request)"
429 " GRPC_OVERRIDE;\n");
430 printer->Print(
431 *vars,
432 "::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw("
433 "::grpc::ClientContext* context, const $Request$& request, "
434 "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
435 } else if (method->BidiStreaming()) {
436 printer->Print(
437 *vars,
438 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
439 "$Method$Raw(::grpc::ClientContext* context) GRPC_OVERRIDE;\n");
440 printer->Print(
441 *vars,
442 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
443 "Async$Method$Raw(::grpc::ClientContext* context, "
444 "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
445 }
446 }
447 }
448
PrintHeaderClientMethodData(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)449 void PrintHeaderClientMethodData(grpc_generator::Printer *printer, const grpc_generator::Method *method,
450 std::map<grpc::string, grpc::string> *vars) {
451 (*vars)["Method"] = method->name();
452 printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
453 }
454
PrintHeaderServerMethodSync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)455 void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, const grpc_generator::Method *method,
456 std::map<grpc::string, grpc::string> *vars) {
457 (*vars)["Method"] = method->name();
458 (*vars)["Request"] = method->input_type_name();
459 (*vars)["Response"] = method->output_type_name();
460 if (method->NoStreaming()) {
461 printer->Print(*vars,
462 "virtual ::grpc::Status $Method$("
463 "::grpc::ServerContext* context, const $Request$* request, "
464 "$Response$* response);\n");
465 } else if (method->ClientOnlyStreaming()) {
466 printer->Print(*vars,
467 "virtual ::grpc::Status $Method$("
468 "::grpc::ServerContext* context, "
469 "::grpc::ServerReader< $Request$>* reader, "
470 "$Response$* response);\n");
471 } else if (method->ServerOnlyStreaming()) {
472 printer->Print(*vars,
473 "virtual ::grpc::Status $Method$("
474 "::grpc::ServerContext* context, const $Request$* request, "
475 "::grpc::ServerWriter< $Response$>* writer);\n");
476 } else if (method->BidiStreaming()) {
477 printer->Print(
478 *vars,
479 "virtual ::grpc::Status $Method$("
480 "::grpc::ServerContext* context, "
481 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
482 "\n");
483 }
484 }
485
PrintHeaderServerMethodAsync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)486 void PrintHeaderServerMethodAsync(
487 grpc_generator::Printer *printer,
488 const grpc_generator::Method *method,
489 std::map<grpc::string, grpc::string> *vars) {
490 (*vars)["Method"] = method->name();
491 (*vars)["Request"] = method->input_type_name();
492 (*vars)["Response"] = method->output_type_name();
493 printer->Print(*vars, "template <class BaseClass>\n");
494 printer->Print(*vars,
495 "class WithAsyncMethod_$Method$ : public BaseClass {\n");
496 printer->Print(
497 " private:\n"
498 " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
499 printer->Print(" public:\n");
500 printer->Indent();
501 printer->Print(*vars,
502 "WithAsyncMethod_$Method$() {\n"
503 " ::grpc::Service::MarkMethodAsync($Idx$);\n"
504 "}\n");
505 printer->Print(*vars,
506 "~WithAsyncMethod_$Method$() GRPC_OVERRIDE {\n"
507 " BaseClassMustBeDerivedFromService(this);\n"
508 "}\n");
509 if (method->NoStreaming()) {
510 printer->Print(
511 *vars,
512 "// disable synchronous version of this method\n"
513 "::grpc::Status $Method$("
514 "::grpc::ServerContext* context, const $Request$* request, "
515 "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
516 " abort();\n"
517 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
518 "}\n");
519 printer->Print(
520 *vars,
521 "void Request$Method$("
522 "::grpc::ServerContext* context, $Request$* request, "
523 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
524 "::grpc::CompletionQueue* new_call_cq, "
525 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
526 printer->Print(*vars,
527 " ::grpc::Service::RequestAsyncUnary($Idx$, context, "
528 "request, response, new_call_cq, notification_cq, tag);\n");
529 printer->Print("}\n");
530 } else if (method->ClientOnlyStreaming()) {
531 printer->Print(
532 *vars,
533 "// disable synchronous version of this method\n"
534 "::grpc::Status $Method$("
535 "::grpc::ServerContext* context, "
536 "::grpc::ServerReader< $Request$>* reader, "
537 "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
538 " abort();\n"
539 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
540 "}\n");
541 printer->Print(
542 *vars,
543 "void Request$Method$("
544 "::grpc::ServerContext* context, "
545 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
546 "::grpc::CompletionQueue* new_call_cq, "
547 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
548 printer->Print(*vars,
549 " ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
550 "context, reader, new_call_cq, notification_cq, tag);\n");
551 printer->Print("}\n");
552 } else if (method->ServerOnlyStreaming()) {
553 printer->Print(
554 *vars,
555 "// disable synchronous version of this method\n"
556 "::grpc::Status $Method$("
557 "::grpc::ServerContext* context, const $Request$* request, "
558 "::grpc::ServerWriter< $Response$>* writer) GRPC_FINAL GRPC_OVERRIDE "
559 "{\n"
560 " abort();\n"
561 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
562 "}\n");
563 printer->Print(
564 *vars,
565 "void Request$Method$("
566 "::grpc::ServerContext* context, $Request$* request, "
567 "::grpc::ServerAsyncWriter< $Response$>* writer, "
568 "::grpc::CompletionQueue* new_call_cq, "
569 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
570 printer->Print(
571 *vars,
572 " ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
573 "context, request, writer, new_call_cq, notification_cq, tag);\n");
574 printer->Print("}\n");
575 } else if (method->BidiStreaming()) {
576 printer->Print(
577 *vars,
578 "// disable synchronous version of this method\n"
579 "::grpc::Status $Method$("
580 "::grpc::ServerContext* context, "
581 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
582 "GRPC_FINAL GRPC_OVERRIDE {\n"
583 " abort();\n"
584 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
585 "}\n");
586 printer->Print(
587 *vars,
588 "void Request$Method$("
589 "::grpc::ServerContext* context, "
590 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
591 "::grpc::CompletionQueue* new_call_cq, "
592 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
593 printer->Print(*vars,
594 " ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
595 "context, stream, new_call_cq, notification_cq, tag);\n");
596 printer->Print("}\n");
597 }
598 printer->Outdent();
599 printer->Print(*vars, "};\n");
600 }
601
PrintHeaderServerMethodGeneric(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)602 void PrintHeaderServerMethodGeneric(
603 grpc_generator::Printer *printer,
604 const grpc_generator::Method *method,
605 std::map<grpc::string, grpc::string> *vars) {
606 (*vars)["Method"] = method->name();
607 (*vars)["Request"] = method->input_type_name();
608 (*vars)["Response"] = method->output_type_name();
609 printer->Print(*vars, "template <class BaseClass>\n");
610 printer->Print(*vars,
611 "class WithGenericMethod_$Method$ : public BaseClass {\n");
612 printer->Print(
613 " private:\n"
614 " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
615 printer->Print(" public:\n");
616 printer->Indent();
617 printer->Print(*vars,
618 "WithGenericMethod_$Method$() {\n"
619 " ::grpc::Service::MarkMethodGeneric($Idx$);\n"
620 "}\n");
621 printer->Print(*vars,
622 "~WithGenericMethod_$Method$() GRPC_OVERRIDE {\n"
623 " BaseClassMustBeDerivedFromService(this);\n"
624 "}\n");
625 if (method->NoStreaming()) {
626 printer->Print(
627 *vars,
628 "// disable synchronous version of this method\n"
629 "::grpc::Status $Method$("
630 "::grpc::ServerContext* context, const $Request$* request, "
631 "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
632 " abort();\n"
633 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
634 "}\n");
635 } else if (method->ClientOnlyStreaming()) {
636 printer->Print(
637 *vars,
638 "// disable synchronous version of this method\n"
639 "::grpc::Status $Method$("
640 "::grpc::ServerContext* context, "
641 "::grpc::ServerReader< $Request$>* reader, "
642 "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
643 " abort();\n"
644 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
645 "}\n");
646 } else if (method->ServerOnlyStreaming()) {
647 printer->Print(
648 *vars,
649 "// disable synchronous version of this method\n"
650 "::grpc::Status $Method$("
651 "::grpc::ServerContext* context, const $Request$* request, "
652 "::grpc::ServerWriter< $Response$>* writer) GRPC_FINAL GRPC_OVERRIDE "
653 "{\n"
654 " abort();\n"
655 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
656 "}\n");
657 } else if (method->BidiStreaming()) {
658 printer->Print(
659 *vars,
660 "// disable synchronous version of this method\n"
661 "::grpc::Status $Method$("
662 "::grpc::ServerContext* context, "
663 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
664 "GRPC_FINAL GRPC_OVERRIDE {\n"
665 " abort();\n"
666 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
667 "}\n");
668 }
669 printer->Outdent();
670 printer->Print(*vars, "};\n");
671 }
672
PrintHeaderService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<grpc::string,grpc::string> * vars)673 void PrintHeaderService(grpc_generator::Printer *printer,
674 const grpc_generator::Service *service,
675 std::map<grpc::string, grpc::string> *vars) {
676 (*vars)["Service"] = service->name();
677
678 printer->Print(*vars,
679 "class $Service$ GRPC_FINAL {\n"
680 " public:\n");
681 printer->Indent();
682
683 // Client side
684 printer->Print(
685 "class StubInterface {\n"
686 " public:\n");
687 printer->Indent();
688 printer->Print("virtual ~StubInterface() {}\n");
689 for (int i = 0; i < service->method_count(); ++i) {
690 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true);
691 }
692 printer->Outdent();
693 printer->Print("private:\n");
694 printer->Indent();
695 for (int i = 0; i < service->method_count(); ++i) {
696 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, false);
697 }
698 printer->Outdent();
699 printer->Print("};\n");
700 printer->Print(
701 "class Stub GRPC_FINAL : public StubInterface"
702 " {\n public:\n");
703 printer->Indent();
704 printer->Print("Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
705 for (int i = 0; i < service->method_count(); ++i) {
706 PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
707 }
708 printer->Outdent();
709 printer->Print("\n private:\n");
710 printer->Indent();
711 printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
712 for (int i = 0; i < service->method_count(); ++i) {
713 PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
714 }
715 for (int i = 0; i < service->method_count(); ++i) {
716 PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
717 }
718 printer->Outdent();
719 printer->Print("};\n");
720 printer->Print(
721 "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
722 "::grpc::ChannelInterface>& channel, "
723 "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
724
725 printer->Print("\n");
726
727 // Server side - base
728 printer->Print(
729 "class Service : public ::grpc::Service {\n"
730 " public:\n");
731 printer->Indent();
732 printer->Print("Service();\n");
733 printer->Print("virtual ~Service();\n");
734 for (int i = 0; i < service->method_count(); ++i) {
735 PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
736 }
737 printer->Outdent();
738 printer->Print("};\n");
739
740 // Server side - Asynchronous
741 for (int i = 0; i < service->method_count(); ++i) {
742 (*vars)["Idx"] = as_string(i);
743 PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
744 }
745
746 printer->Print("typedef ");
747
748 for (int i = 0; i < service->method_count(); ++i) {
749 (*vars)["method_name"] = service->method(i).get()->name();
750 printer->Print(*vars, "WithAsyncMethod_$method_name$<");
751 }
752 printer->Print("Service");
753 for (int i = 0; i < service->method_count(); ++i) {
754 printer->Print(" >");
755 }
756 printer->Print(" AsyncService;\n");
757
758 // Server side - Generic
759 for (int i = 0; i < service->method_count(); ++i) {
760 (*vars)["Idx"] = as_string(i);
761 PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
762 }
763
764 printer->Outdent();
765 printer->Print("};\n");
766 }
767
GetHeaderServices(grpc_generator::File * file,const Parameters & params)768 grpc::string GetHeaderServices(grpc_generator::File *file,
769 const Parameters ¶ms) {
770 grpc::string output;
771 {
772 // Scope the output stream so it closes and finalizes output to the string.
773 auto printer = file->CreatePrinter(&output);
774 std::map<grpc::string, grpc::string> vars;
775 // Package string is empty or ends with a dot. It is used to fully qualify
776 // method names.
777 vars["Package"] = file->package();
778 if (!file->package().empty()) {
779 vars["Package"].append(".");
780 }
781
782 if (!params.services_namespace.empty()) {
783 vars["services_namespace"] = params.services_namespace;
784 printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
785 }
786
787 for (int i = 0; i < file->service_count(); ++i) {
788 PrintHeaderService(printer.get(), file->service(i).get(), &vars);
789 printer->Print("\n");
790 }
791
792 if (!params.services_namespace.empty()) {
793 printer->Print(vars, "} // namespace $services_namespace$\n\n");
794 }
795 }
796 return output;
797 }
798
GetHeaderEpilogue(grpc_generator::File * file,const Parameters &)799 grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
800 grpc::string output;
801 {
802 // Scope the output stream so it closes and finalizes output to the string.
803 auto printer = file->CreatePrinter(&output);
804 std::map<grpc::string, grpc::string> vars;
805
806 vars["filename"] = file->filename();
807 vars["filename_identifier"] = FilenameIdentifier(file->filename());
808
809 if (!file->package().empty()) {
810 std::vector<grpc::string> parts = file->package_parts();
811
812 for (auto part = parts.rbegin(); part != parts.rend(); part++) {
813 vars["part"] = *part;
814 printer->Print(vars, "} // namespace $part$\n");
815 }
816 printer->Print(vars, "\n");
817 }
818
819 printer->Print(vars, "\n");
820 printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
821 }
822 return output;
823 }
824
GetSourcePrologue(grpc_generator::File * file,const Parameters &)825 grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters & /*params*/) {
826 grpc::string output;
827 {
828 // Scope the output stream so it closes and finalizes output to the string.
829 auto printer = file->CreatePrinter(&output);
830 std::map<grpc::string, grpc::string> vars;
831
832 vars["filename"] = file->filename();
833 vars["filename_base"] = file->filename_without_ext();
834 vars["message_header_ext"] = file->message_header_ext();
835 vars["service_header_ext"] = file->service_header_ext();
836
837 printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
838 printer->Print(vars,
839 "// If you make any local change, they will be lost.\n");
840 printer->Print(vars, "// source: $filename$\n\n");
841 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
842 printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
843 printer->Print("\n");
844 }
845 return output;
846 }
847
GetSourceIncludes(grpc_generator::File * file,const Parameters & params)848 grpc::string GetSourceIncludes(grpc_generator::File *file,
849 const Parameters ¶ms) {
850 grpc::string output;
851 {
852 // Scope the output stream so it closes and finalizes output to the string.
853 auto printer = file->CreatePrinter(&output);
854 std::map<grpc::string, grpc::string> vars;
855
856 static const char *headers_strs[] = {
857 "grpc++/impl/codegen/async_stream.h",
858 "grpc++/impl/codegen/async_unary_call.h",
859 "grpc++/impl/codegen/channel_interface.h",
860 "grpc++/impl/codegen/client_unary_call.h",
861 "grpc++/impl/codegen/method_handler_impl.h",
862 "grpc++/impl/codegen/rpc_service_method.h",
863 "grpc++/impl/codegen/service_type.h",
864 "grpc++/impl/codegen/sync_stream.h"
865 };
866 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
867 PrintIncludes(printer.get(), headers, params);
868
869 if (!file->package().empty()) {
870 printer->Print("\n");
871 std::vector<grpc::string> parts = file->package_parts();
872
873 for (auto part = parts.begin(); part != parts.end(); part++) {
874 vars["part"] = *part;
875 printer->Print(vars, "namespace $part$ {\n");
876 }
877 }
878
879 printer->Print(vars, "\n");
880 }
881 return output;
882 }
883
PrintSourceClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)884 void PrintSourceClientMethod(grpc_generator::Printer *printer,
885 const grpc_generator::Method *method,
886 std::map<grpc::string, grpc::string> *vars) {
887 (*vars)["Method"] = method->name();
888 (*vars)["Request"] = method->input_type_name();
889 (*vars)["Response"] = method->output_type_name();
890 if (method->NoStreaming()) {
891 printer->Print(*vars,
892 "::grpc::Status $ns$$Service$::Stub::$Method$("
893 "::grpc::ClientContext* context, "
894 "const $Request$& request, $Response$* response) {\n");
895 printer->Print(*vars,
896 " return ::grpc::BlockingUnaryCall(channel_.get(), "
897 "rpcmethod_$Method$_, "
898 "context, request, response);\n"
899 "}\n\n");
900 printer->Print(
901 *vars,
902 "::grpc::ClientAsyncResponseReader< $Response$>* "
903 "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
904 "const $Request$& request, "
905 "::grpc::CompletionQueue* cq) {\n");
906 printer->Print(*vars,
907 " return new "
908 "::grpc::ClientAsyncResponseReader< $Response$>("
909 "channel_.get(), cq, "
910 "rpcmethod_$Method$_, "
911 "context, request);\n"
912 "}\n\n");
913 } else if (method->ClientOnlyStreaming()) {
914 printer->Print(*vars,
915 "::grpc::ClientWriter< $Request$>* "
916 "$ns$$Service$::Stub::$Method$Raw("
917 "::grpc::ClientContext* context, $Response$* response) {\n");
918 printer->Print(*vars,
919 " return new ::grpc::ClientWriter< $Request$>("
920 "channel_.get(), "
921 "rpcmethod_$Method$_, "
922 "context, response);\n"
923 "}\n\n");
924 printer->Print(*vars,
925 "::grpc::ClientAsyncWriter< $Request$>* "
926 "$ns$$Service$::Stub::Async$Method$Raw("
927 "::grpc::ClientContext* context, $Response$* response, "
928 "::grpc::CompletionQueue* cq, void* tag) {\n");
929 printer->Print(*vars,
930 " return new ::grpc::ClientAsyncWriter< $Request$>("
931 "channel_.get(), cq, "
932 "rpcmethod_$Method$_, "
933 "context, response, tag);\n"
934 "}\n\n");
935 } else if (method->ServerOnlyStreaming()) {
936 printer->Print(
937 *vars,
938 "::grpc::ClientReader< $Response$>* "
939 "$ns$$Service$::Stub::$Method$Raw("
940 "::grpc::ClientContext* context, const $Request$& request) {\n");
941 printer->Print(*vars,
942 " return new ::grpc::ClientReader< $Response$>("
943 "channel_.get(), "
944 "rpcmethod_$Method$_, "
945 "context, request);\n"
946 "}\n\n");
947 printer->Print(*vars,
948 "::grpc::ClientAsyncReader< $Response$>* "
949 "$ns$$Service$::Stub::Async$Method$Raw("
950 "::grpc::ClientContext* context, const $Request$& request, "
951 "::grpc::CompletionQueue* cq, void* tag) {\n");
952 printer->Print(*vars,
953 " return new ::grpc::ClientAsyncReader< $Response$>("
954 "channel_.get(), cq, "
955 "rpcmethod_$Method$_, "
956 "context, request, tag);\n"
957 "}\n\n");
958 } else if (method->BidiStreaming()) {
959 printer->Print(
960 *vars,
961 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
962 "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
963 printer->Print(*vars,
964 " return new ::grpc::ClientReaderWriter< "
965 "$Request$, $Response$>("
966 "channel_.get(), "
967 "rpcmethod_$Method$_, "
968 "context);\n"
969 "}\n\n");
970 printer->Print(
971 *vars,
972 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
973 "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
974 "::grpc::CompletionQueue* cq, void* tag) {\n");
975 printer->Print(*vars,
976 " return new "
977 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>("
978 "channel_.get(), cq, "
979 "rpcmethod_$Method$_, "
980 "context, tag);\n"
981 "}\n\n");
982 }
983 }
984
PrintSourceServerMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)985 void PrintSourceServerMethod(grpc_generator::Printer *printer,
986 const grpc_generator::Method *method,
987 std::map<grpc::string, grpc::string> *vars) {
988 (*vars)["Method"] = method->name();
989 (*vars)["Request"] = method->input_type_name();
990 (*vars)["Response"] = method->output_type_name();
991 if (method->NoStreaming()) {
992 printer->Print(*vars,
993 "::grpc::Status $ns$$Service$::Service::$Method$("
994 "::grpc::ServerContext* context, "
995 "const $Request$* request, $Response$* response) {\n");
996 printer->Print(" (void) context;\n");
997 printer->Print(" (void) request;\n");
998 printer->Print(" (void) response;\n");
999 printer->Print(
1000 " return ::grpc::Status("
1001 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1002 printer->Print("}\n\n");
1003 } else if (method->ClientOnlyStreaming()) {
1004 printer->Print(*vars,
1005 "::grpc::Status $ns$$Service$::Service::$Method$("
1006 "::grpc::ServerContext* context, "
1007 "::grpc::ServerReader< $Request$>* reader, "
1008 "$Response$* response) {\n");
1009 printer->Print(" (void) context;\n");
1010 printer->Print(" (void) reader;\n");
1011 printer->Print(" (void) response;\n");
1012 printer->Print(
1013 " return ::grpc::Status("
1014 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1015 printer->Print("}\n\n");
1016 } else if (method->ServerOnlyStreaming()) {
1017 printer->Print(*vars,
1018 "::grpc::Status $ns$$Service$::Service::$Method$("
1019 "::grpc::ServerContext* context, "
1020 "const $Request$* request, "
1021 "::grpc::ServerWriter< $Response$>* writer) {\n");
1022 printer->Print(" (void) context;\n");
1023 printer->Print(" (void) request;\n");
1024 printer->Print(" (void) writer;\n");
1025 printer->Print(
1026 " return ::grpc::Status("
1027 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1028 printer->Print("}\n\n");
1029 } else if (method->BidiStreaming()) {
1030 printer->Print(*vars,
1031 "::grpc::Status $ns$$Service$::Service::$Method$("
1032 "::grpc::ServerContext* context, "
1033 "::grpc::ServerReaderWriter< $Response$, $Request$>* "
1034 "stream) {\n");
1035 printer->Print(" (void) context;\n");
1036 printer->Print(" (void) stream;\n");
1037 printer->Print(
1038 " return ::grpc::Status("
1039 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1040 printer->Print("}\n\n");
1041 }
1042 }
1043
PrintSourceService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<grpc::string,grpc::string> * vars)1044 void PrintSourceService(grpc_generator::Printer *printer,
1045 const grpc_generator::Service *service,
1046 std::map<grpc::string, grpc::string> *vars) {
1047 (*vars)["Service"] = service->name();
1048
1049 printer->Print(*vars,
1050 "static const char* $prefix$$Service$_method_names[] = {\n");
1051 for (int i = 0; i < service->method_count(); ++i) {
1052 (*vars)["Method"] = service->method(i).get()->name();
1053 printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
1054 }
1055 printer->Print(*vars, "};\n\n");
1056
1057 printer->Print(*vars,
1058 "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
1059 "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
1060 "const ::grpc::StubOptions& options) {\n"
1061 " std::unique_ptr< $ns$$Service$::Stub> stub(new "
1062 "$ns$$Service$::Stub(channel));\n"
1063 " return stub;\n"
1064 "}\n\n");
1065 printer->Print(*vars,
1066 "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
1067 "::grpc::ChannelInterface>& channel)\n");
1068 printer->Indent();
1069 printer->Print(": channel_(channel)");
1070 for (int i = 0; i < service->method_count(); ++i) {
1071 auto method = service->method(i);
1072 (*vars)["Method"] = method->name();
1073 (*vars)["Idx"] = as_string(i);
1074 if (method->NoStreaming()) {
1075 (*vars)["StreamingType"] = "NORMAL_RPC";
1076 } else if (method->ClientOnlyStreaming()) {
1077 (*vars)["StreamingType"] = "CLIENT_STREAMING";
1078 } else if (method->ServerOnlyStreaming()) {
1079 (*vars)["StreamingType"] = "SERVER_STREAMING";
1080 } else {
1081 (*vars)["StreamingType"] = "BIDI_STREAMING";
1082 }
1083 printer->Print(*vars,
1084 ", rpcmethod_$Method$_("
1085 "$prefix$$Service$_method_names[$Idx$], "
1086 "::grpc::RpcMethod::$StreamingType$, "
1087 "channel"
1088 ")\n");
1089 }
1090 printer->Print("{}\n\n");
1091 printer->Outdent();
1092
1093 for (int i = 0; i < service->method_count(); ++i) {
1094 (*vars)["Idx"] = as_string(i);
1095 PrintSourceClientMethod(printer, service->method(i).get(), vars);
1096 }
1097
1098 printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
1099 printer->Indent();
1100 printer->Print(*vars, "(void)$prefix$$Service$_method_names;\n");
1101 for (int i = 0; i < service->method_count(); ++i) {
1102 auto method = service->method(i);
1103 (*vars)["Idx"] = as_string(i);
1104 (*vars)["Method"] = method->name();
1105 (*vars)["Request"] = method->input_type_name();
1106 (*vars)["Response"] = method->output_type_name();
1107 if (method->NoStreaming()) {
1108 printer->Print(
1109 *vars,
1110 "AddMethod(new ::grpc::RpcServiceMethod(\n"
1111 " $prefix$$Service$_method_names[$Idx$],\n"
1112 " ::grpc::RpcMethod::NORMAL_RPC,\n"
1113 " new ::grpc::RpcMethodHandler< $ns$$Service$::Service, "
1114 "$Request$, "
1115 "$Response$>(\n"
1116 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1117 } else if (method->ClientOnlyStreaming()) {
1118 printer->Print(
1119 *vars,
1120 "AddMethod(new ::grpc::RpcServiceMethod(\n"
1121 " $prefix$$Service$_method_names[$Idx$],\n"
1122 " ::grpc::RpcMethod::CLIENT_STREAMING,\n"
1123 " new ::grpc::ClientStreamingHandler< "
1124 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1125 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1126 } else if (method->ServerOnlyStreaming()) {
1127 printer->Print(
1128 *vars,
1129 "AddMethod(new ::grpc::RpcServiceMethod(\n"
1130 " $prefix$$Service$_method_names[$Idx$],\n"
1131 " ::grpc::RpcMethod::SERVER_STREAMING,\n"
1132 " new ::grpc::ServerStreamingHandler< "
1133 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1134 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1135 } else if (method->BidiStreaming()) {
1136 printer->Print(
1137 *vars,
1138 "AddMethod(new ::grpc::RpcServiceMethod(\n"
1139 " $prefix$$Service$_method_names[$Idx$],\n"
1140 " ::grpc::RpcMethod::BIDI_STREAMING,\n"
1141 " new ::grpc::BidiStreamingHandler< "
1142 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1143 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1144 }
1145 }
1146 printer->Outdent();
1147 printer->Print(*vars, "}\n\n");
1148 printer->Print(*vars,
1149 "$ns$$Service$::Service::~Service() {\n"
1150 "}\n\n");
1151 for (int i = 0; i < service->method_count(); ++i) {
1152 (*vars)["Idx"] = as_string(i);
1153 PrintSourceServerMethod(printer, service->method(i).get(), vars);
1154 }
1155 }
1156
GetSourceServices(grpc_generator::File * file,const Parameters & params)1157 grpc::string GetSourceServices(grpc_generator::File *file,
1158 const Parameters ¶ms) {
1159 grpc::string output;
1160 {
1161 // Scope the output stream so it closes and finalizes output to the string.
1162 auto printer = file->CreatePrinter(&output);
1163 std::map<grpc::string, grpc::string> vars;
1164 // Package string is empty or ends with a dot. It is used to fully qualify
1165 // method names.
1166 vars["Package"] = file->package();
1167 if (!file->package().empty()) {
1168 vars["Package"].append(".");
1169 }
1170 if (!params.services_namespace.empty()) {
1171 vars["ns"] = params.services_namespace + "::";
1172 vars["prefix"] = params.services_namespace;
1173 } else {
1174 vars["ns"] = "";
1175 vars["prefix"] = "";
1176 }
1177
1178 for (int i = 0; i < file->service_count(); ++i) {
1179 PrintSourceService(printer.get(), file->service(i).get(), &vars);
1180 printer->Print("\n");
1181 }
1182 }
1183 return output;
1184 }
1185
GetSourceEpilogue(grpc_generator::File * file,const Parameters &)1186 grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
1187 grpc::string temp;
1188
1189 if (!file->package().empty()) {
1190 std::vector<grpc::string> parts = file->package_parts();
1191
1192 for (auto part = parts.begin(); part != parts.end(); part++) {
1193 temp.append("} // namespace ");
1194 temp.append(*part);
1195 temp.append("\n");
1196 }
1197 temp.append("\n");
1198 }
1199
1200 return temp;
1201 }
1202
1203 } // namespace grpc_cpp_generator
1204