mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
157 lines
6.1 KiB
C++
157 lines
6.1 KiB
C++
/* Copyright (C) 2015, Tim Cooper <tim.cooper@layeh.com>
|
|
|
|
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 the Mumble Developers 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 FOUNDATION 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 <map>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
#include <google/protobuf/compiler/code_generator.h>
|
|
#include <google/protobuf/compiler/plugin.h>
|
|
#include <google/protobuf/descriptor.h>
|
|
#include <google/protobuf/io/printer.h>
|
|
|
|
#include <boost/algorithm/string/replace.hpp>
|
|
|
|
using namespace std;
|
|
|
|
using namespace google::protobuf;
|
|
using namespace google::protobuf::compiler;
|
|
using namespace google::protobuf::io;
|
|
|
|
class WrapperGenerator : public CodeGenerator {
|
|
bool Generate(const FileDescriptor *input, const string ¶meter, GeneratorContext *context, string *error) const {
|
|
auto cpp_source = context->Open(input->name() + ".Wrapper.cpp");
|
|
Printer cpp(cpp_source, '$');
|
|
|
|
cpp.Print("// DO NOT EDIT!\n");
|
|
cpp.Print("// Auto generated by scripts/protoc-gen-grpcwrapper\n");
|
|
cpp.Print("\n");
|
|
|
|
auto ns = ConvertDot(input->package());
|
|
|
|
int namespaces = 1;
|
|
{
|
|
stringstream stream(input->package());
|
|
string current;
|
|
while (getline(stream, current, '.')) {
|
|
cpp.Print("namespace $current$ {\n", "current", current);
|
|
namespaces++;
|
|
}
|
|
}
|
|
cpp.Print("namespace Wrapper {\n", "ns", ns);
|
|
|
|
map<string, string> tpl;
|
|
tpl["ns"] = ns;
|
|
|
|
for (int i = 0; i < input->service_count(); i++) {
|
|
if (i > 0) {
|
|
cpp.Print("\n\n");
|
|
}
|
|
auto service = input->service(i);
|
|
tpl["service"] = service->name();
|
|
|
|
for (int j = 0; j < service->method_count(); j++) {
|
|
auto method = service->method(j);
|
|
tpl["method"] = method->name();
|
|
tpl["in"] = ConvertDot(method->input_type()->full_name());
|
|
tpl["out"] = ConvertDot(method->output_type()->full_name());
|
|
|
|
if (method->client_streaming() || method->server_streaming()) {
|
|
cpp.Print(tpl, "// Skipping $service$.$method$; streaming not implemented\n\n");
|
|
continue;
|
|
}
|
|
|
|
cpp.Print(tpl, "void $service$_$method$_Create(MurmurRPCImpl*, ::$ns$::$service$::AsyncService*);\n");
|
|
cpp.Print(tpl, "void $service$_$method$_Impl(::grpc::ServerContext *context, ::$in$ *request, ::grpc::ServerAsyncResponseWriter< ::$out$ > *response, ::boost::function<void()> *next);\n");
|
|
|
|
cpp.Print(tpl, "void $service$_$method$_Done(MurmurRPCImpl*, ::$ns$::$service$::AsyncService*, ::grpc::ServerContext *context, ::$in$ *in, ::grpc::ServerAsyncResponseWriter< ::$out$ > *out) {\n");
|
|
cpp.Indent();
|
|
cpp.Print("delete context;\n");
|
|
cpp.Print("delete in;\n");
|
|
cpp.Print("delete out;\n");
|
|
cpp.Outdent();
|
|
cpp.Print("}\n");
|
|
|
|
cpp.Print(tpl, "void $service$_$method$_Handle(MurmurRPCImpl *impl, ::$ns$::$service$::AsyncService *service, ::grpc::ServerContext *context, ::$in$ *in, ::grpc::ServerAsyncResponseWriter< ::$out$ > *out) {\n");
|
|
cpp.Indent();
|
|
cpp.Print(tpl, "$service$_$method$_Create(impl, service);\n");
|
|
cpp.Print(tpl, "auto done_fn = ::boost::bind($service$_$method$_Done, impl, service, context, in, out);\n");
|
|
cpp.Print(tpl, "auto done_fn_ptr = new ::boost::function<void()>(done_fn);\n");
|
|
cpp.Print(tpl, "auto ie = new ExecEvent(::boost::bind($service$_$method$_Impl, context, in, out, done_fn_ptr));\n");
|
|
cpp.Print(tpl, "QCoreApplication::instance()->postEvent(impl, ie);\n");
|
|
cpp.Outdent();
|
|
cpp.Print("}\n");
|
|
|
|
cpp.Print(tpl, "void $service$_$method$_Create(MurmurRPCImpl *impl, ::$ns$::$service$::AsyncService *service) {\n");
|
|
cpp.Indent();
|
|
cpp.Print(tpl, "auto context = new ::grpc::ServerContext();\n");
|
|
cpp.Print(tpl, "auto request = new ::$in$();\n");
|
|
cpp.Print(tpl, "auto response = new ::grpc::ServerAsyncResponseWriter< ::$out$ >(context);\n");
|
|
cpp.Print(tpl, "auto fn = ::boost::bind($service$_$method$_Handle, impl, service, context, request, response);\n");
|
|
cpp.Print(tpl, "auto fn_ptr = new ::boost::function<void()>(fn);\n");
|
|
cpp.Print(tpl, "service->Request$method$(context, request, response, impl->mCQ.get(), impl->mCQ.get(), fn_ptr);\n");
|
|
cpp.Outdent();
|
|
cpp.Print("}\n");
|
|
|
|
cpp.Print("\n");
|
|
}
|
|
|
|
cpp.Print(tpl, "void $service$_Init(MurmurRPCImpl *impl, ::$ns$::$service$::AsyncService *service) {\n");
|
|
cpp.Indent();
|
|
for (int j = 0; j < service->method_count(); j++) {
|
|
auto method = service->method(j);
|
|
tpl["method"] = method->name();
|
|
if (method->client_streaming() || method->server_streaming()) {
|
|
continue;
|
|
}
|
|
cpp.Print(tpl, "$service$_$method$_Create(impl, service);\n");
|
|
}
|
|
cpp.Outdent();
|
|
cpp.Print("}\n");
|
|
}
|
|
|
|
cpp.Print("\n");
|
|
while (namespaces--) {
|
|
cpp.Print("}\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static string ConvertDot(const string &str, const string &replace = "::") {
|
|
return boost::replace_all_copy(str, ".", replace);
|
|
}
|
|
};
|
|
|
|
int main(int argc, char *argv[]) {
|
|
WrapperGenerator generator;
|
|
return PluginMain(argc, argv, &generator);
|
|
}
|