All checks were successful
phxrpc / build (Debug, aarch64-linux-gnu) (push) Successful in 3m57s
phxrpc / build (Debug, host.gcc) (push) Successful in 4m0s
phxrpc / build (Debug, mipsel-linux-gnu) (push) Successful in 5m7s
phxrpc / build (Debug, arm-linux-gnueabihf) (push) Successful in 28m44s
phxrpc / build (Release, aarch64-linux-gnu) (push) Successful in 3m59s
phxrpc / build (Release, host.gcc) (push) Successful in 4m46s
phxrpc / build (Release, mipsel-linux-gnu) (push) Successful in 3m26s
phxrpc / build (Release, arm-linux-gnueabihf) (push) Successful in 9m11s
378 lines
13 KiB
C++
378 lines
13 KiB
C++
/*
|
|
Tencent is pleased to support the open source community by making
|
|
PhxRPC available.
|
|
Copyright (C) 2016 THL A29 Limited, a Tencent company.
|
|
All rights reserved.
|
|
|
|
Licensed under the BSD 3-Clause License (the "License"); you may
|
|
not use this file except in compliance with the License. You may
|
|
obtain a copy of the License at
|
|
|
|
https://opensource.org/licenses/BSD-3-Clause
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
implied. See the License for the specific language governing
|
|
permissions and limitations under the License.
|
|
|
|
See the AUTHORS file for names of contributors.
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "tool_code_render.h"
|
|
#include "tool_template.h"
|
|
|
|
#include "code_utils.h"
|
|
#include "name_render.h"
|
|
#include "syntax_tree.h"
|
|
|
|
using namespace phxrpc;
|
|
using namespace std;
|
|
|
|
ToolCodeRender::ToolCodeRender(NameRender &name_render) : name_render_(name_render) {}
|
|
|
|
ToolCodeRender::~ToolCodeRender() {}
|
|
|
|
void
|
|
ToolCodeRender::GenerateToolHpp(SyntaxTree *stree, FILE *write)
|
|
{
|
|
char file_name[128]{'\0'};
|
|
name_render_.GetToolFileName(stree->GetName(), file_name, sizeof(file_name));
|
|
|
|
string buffer;
|
|
name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer);
|
|
|
|
fprintf(write, "/* %s.h\n", file_name);
|
|
fprintf(write, "%s", buffer.c_str());
|
|
fprintf(write, "*/\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "#pragma once\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "namespace phxrpc {\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "class OptMap;\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "}\n");
|
|
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
|
|
char class_name[128]{'\0'};
|
|
name_render_.GetToolClassName(stree->GetName(), class_name, sizeof(class_name));
|
|
|
|
fprintf(write, "class %s {\n", class_name);
|
|
fprintf(write, " public:\n");
|
|
fprintf(write, " %s();\n", class_name);
|
|
fprintf(write, " virtual ~%s();\n", class_name);
|
|
fprintf(write, "\n");
|
|
|
|
SyntaxFuncVector *flist{stree->GetFuncList()};
|
|
auto fit(flist->cbegin());
|
|
for (; flist->cend() != fit; ++fit) {
|
|
fprintf(write, " virtual int %s(phxrpc::OptMap &bigmap);\n", fit->GetName());
|
|
}
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, " typedef int (%s::*ToolFunc_t)(phxrpc::OptMap &);\n", class_name);
|
|
fprintf(write, "\n");
|
|
fprintf(write, " typedef struct tagName2Func {\n");
|
|
fprintf(write, " const char *name;\n");
|
|
fprintf(write, " %s::ToolFunc_t func;\n", class_name);
|
|
fprintf(write, " const char *opt_string;\n");
|
|
fprintf(write, " const char *usage;\n");
|
|
fprintf(write, " } Name2Func_t;\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, " static Name2Func_t *GetName2Func() {\n");
|
|
fprintf(write, " static Name2Func_t name2func[]{\n");
|
|
{
|
|
SyntaxFuncVector *flist{stree->GetFuncList()};
|
|
auto fit(flist->cbegin());
|
|
for (; flist->cend() != fit; ++fit) {
|
|
if (0 < strlen(fit->GetOptString())) {
|
|
fprintf(write, " {\"%s\", &%s::%s, \"c:f:v%s\",\n \"%s\"},\n",
|
|
fit->GetName(), class_name, fit->GetName(), fit->GetOptString(), fit->GetUsage());
|
|
}
|
|
}
|
|
|
|
fprintf(write, " {nullptr, nullptr}\n");
|
|
}
|
|
fprintf(write, " };\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, " return name2func;\n");
|
|
fprintf(write, " };\n");
|
|
fprintf(write, "};\n");
|
|
|
|
fprintf(write, "\n");
|
|
}
|
|
|
|
void
|
|
ToolCodeRender::GenerateToolCpp(SyntaxTree *stree, FILE *write)
|
|
{
|
|
char file_name[128]{'\0'};
|
|
name_render_.GetToolFileName(stree->GetName(), file_name, sizeof(file_name));
|
|
|
|
string buffer;
|
|
name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer);
|
|
|
|
fprintf(write, "/* %s.cpp\n", file_name);
|
|
fprintf(write, "%s", buffer.c_str());
|
|
fprintf(write, "*/\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "#include \"phxrpc/file.h\"\n\n");
|
|
fprintf(write, "#include \"%s.h\"\n", file_name);
|
|
|
|
name_render_.GetClientFileName(stree->GetName(), file_name, sizeof(file_name));
|
|
fprintf(write, "#include \"%s.h\"\n", file_name);
|
|
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "using namespace phxrpc;\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
|
|
char class_name[128]{'\0'};
|
|
name_render_.GetToolClassName(stree->GetName(), class_name, sizeof(class_name));
|
|
|
|
fprintf(write, "%s::%s() {\n", class_name, class_name);
|
|
fprintf(write, "}\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "%s::~%s() {\n", class_name, class_name);
|
|
fprintf(write, "}\n");
|
|
fprintf(write, "\n");
|
|
|
|
char client_class[128]{'\0'};
|
|
name_render_.GetClientClassName(stree->GetName(), client_class, sizeof(client_class));
|
|
|
|
SyntaxFuncVector *flist{stree->GetFuncList()};
|
|
auto fit(flist->cbegin());
|
|
for (; flist->cend() != fit; ++fit) {
|
|
fprintf(write, "int %s::%s(phxrpc::OptMap &/* opt_map */) {\n", class_name, fit->GetName());
|
|
fprintf(write, " printf(\"\\n *** %s unimplement ***\\n\");\n\n", fit->GetName());
|
|
fprintf(write, " return -1;\n");
|
|
fprintf(write, "}\n");
|
|
fprintf(write, "\n");
|
|
}
|
|
}
|
|
|
|
void
|
|
ToolCodeRender::GenerateToolImplHpp(SyntaxTree *stree, FILE *write)
|
|
{
|
|
char file_name[128]{'\0'};
|
|
name_render_.GetToolImplFileName(stree->GetName(), file_name, sizeof(file_name));
|
|
|
|
string buffer;
|
|
name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer, false);
|
|
|
|
fprintf(write, "/* %s.h\n", file_name);
|
|
fprintf(write, "%s", buffer.c_str());
|
|
fprintf(write, "*/\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "#pragma once\n");
|
|
|
|
fprintf(write, "\n");
|
|
|
|
char tool_file[128]{'\0'};
|
|
name_render_.GetToolFileName(stree->GetName(), tool_file, sizeof(tool_file));
|
|
|
|
fprintf(write, "#include \"%s.h\"\n", tool_file);
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "namespace phxrpc {\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "class OptMap;\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, "}\n");
|
|
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
|
|
char class_name[128]{'\0'};
|
|
name_render_.GetToolClassName(stree->GetName(), class_name, sizeof(class_name));
|
|
|
|
fprintf(write, "class %sImpl : public %s {\n", class_name, class_name);
|
|
fprintf(write, " public:\n");
|
|
fprintf(write, " %sImpl();\n", class_name);
|
|
fprintf(write, " virtual ~%sImpl() override;\n", class_name);
|
|
fprintf(write, "\n");
|
|
|
|
SyntaxFuncVector *flist{stree->GetFuncList()};
|
|
auto fit(flist->cbegin());
|
|
for (; flist->cend() != fit; ++fit) {
|
|
fprintf(write, " virtual int %s(phxrpc::OptMap &opt_map) override;\n", fit->GetName());
|
|
}
|
|
|
|
fprintf(write, "};\n");
|
|
|
|
fprintf(write, "\n");
|
|
}
|
|
|
|
void
|
|
ToolCodeRender::GenerateToolImplCpp(SyntaxTree *stree, FILE *write)
|
|
{
|
|
char file_name[128]{'\0'};
|
|
name_render_.GetToolImplFileName(stree->GetName(), file_name, sizeof(file_name));
|
|
|
|
string buffer;
|
|
name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer, false);
|
|
|
|
fprintf(write, "/* %s.cpp\n", file_name);
|
|
fprintf(write, "%s", buffer.c_str());
|
|
fprintf(write, "*/\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "#include \"%s.h\"\n", file_name);
|
|
fprintf(write, "\n");
|
|
|
|
name_render_.GetClientFileName(stree->GetName(), file_name, sizeof(file_name));
|
|
fprintf(write, "#include \"%s.h\"\n", file_name);
|
|
fprintf(write, "\n");
|
|
fprintf(write, "#include \"phxrpc/file.h\"\n");
|
|
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "using namespace phxrpc;\n");
|
|
fprintf(write, "using namespace std;\n");
|
|
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
|
|
char class_name[128]{'\0'};
|
|
name_render_.GetToolImplClassName(stree->GetName(), class_name, sizeof(class_name));
|
|
|
|
fprintf(write, "%s::%s() {\n", class_name, class_name);
|
|
fprintf(write, "}\n");
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, "%s::~%s() {\n", class_name, class_name);
|
|
fprintf(write, "}\n");
|
|
fprintf(write, "\n");
|
|
|
|
char client_class[128]{'\0'}, req_class[128]{'\0'}, resp_class[128]{'\0'};
|
|
name_render_.GetClientClassName(stree->GetName(), client_class, sizeof(client_class));
|
|
|
|
SyntaxFuncVector *flist{stree->GetFuncList()};
|
|
auto fit(flist->cbegin());
|
|
for (; flist->cend() != fit; ++fit) {
|
|
name_render_.GetMessageClassName(fit->GetReq()->GetType(), req_class, sizeof(req_class));
|
|
name_render_.GetMessageClassName(fit->GetResp()->GetType(), resp_class, sizeof(resp_class));
|
|
|
|
fprintf(write, "int %s::%s(phxrpc::OptMap &opt_map) {\n", class_name, fit->GetName());
|
|
fprintf(write, " %s req;\n", req_class);
|
|
fprintf(write, " %s resp;\n", resp_class);
|
|
fprintf(write, "\n");
|
|
|
|
fprintf(write, " int request_num = 1;\n");
|
|
|
|
// Time Cost
|
|
if (0 == strcmp("PHXEcho", fit->GetName())) {
|
|
fprintf(write, " if (opt_map.Get('s')) {;\n");
|
|
fprintf(write, " req.set_value(opt_map.Get('s'));\n");
|
|
fprintf(write, " } else if (opt_map.Get('l')) {\n");
|
|
fprintf(write, " int size = strtol(opt_map.Get('l'), NULL, 10);\n");
|
|
fprintf(write, " size = size <= 0 ? 1 : size;\n");
|
|
fprintf(write, " req.set_value(std::string(size, 't'));\n");
|
|
fprintf(write, " } else {\n");
|
|
fprintf(write, " return -1;\n");
|
|
fprintf(write, " }\n\n");
|
|
|
|
fprintf(write, " if (opt_map.Get('n')) {;\n");
|
|
fprintf(write, " int num = strtol(opt_map.Get('n'), NULL, 10);\n");
|
|
fprintf(write, " request_num = num > 0 ? num : request_num;\n");
|
|
fprintf(write, " }\n\n");
|
|
|
|
} else {
|
|
fprintf(write, " // TODO: fill req from opt_map\n\n");
|
|
}
|
|
|
|
fprintf(write, " auto call_start_time = std::chrono::steady_clock::now();\n\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, " %s client;\n", client_class);
|
|
|
|
if (0 == strcmp("PHXEcho", fit->GetName())) {
|
|
fprintf(write, " int ret = 0;\n", fit->GetName());
|
|
fprintf(write, " for (int i = 0; i < request_num; ++i) {\n", fit->GetName());
|
|
fprintf(write, " ret += client.%s(req, &resp);\n", fit->GetName());
|
|
fprintf(write, " }\n\n");
|
|
|
|
} else {
|
|
fprintf(write, " int ret{client.%s(req, &resp)};\n", fit->GetName());
|
|
}
|
|
|
|
fprintf(write, " auto call_end_time = std::chrono::steady_clock::now();\n\n");
|
|
fprintf(write,
|
|
" auto us = "
|
|
"std::chrono::duration_cast<std::chrono::microseconds>(call_end_time-call_start_time).count();\n\n");
|
|
|
|
fprintf(write,
|
|
" double speed = 1. * request_num *(req.SpaceUsedLong() + resp.SpaceUsedLong()) / us * 1000000;\n");
|
|
|
|
fprintf(write, " if(speed > 2000000ULL) printf(\"speed : %%.0lfMB/s\\n\", speed / 1048576ULL);\n");
|
|
fprintf(write, " else if(speed > 2000ULL) printf(\"speed : %%.0lfKB/s\\n\", speed / 1024ULL);\n");
|
|
fprintf(write, " else printf(\"speed : %%.0lfB/s\\n\", speed);\n\n");
|
|
|
|
fprintf(write, " printf(\"QPS: %%.0lf\\n\", 1000000. * request_num / us);\n\n");
|
|
fprintf(write, " printf(\"cost_us: %%ld\\n\", us);\n\n");
|
|
|
|
fprintf(write, " printf(\"%%s return %%d\\n\", __func__, ret);\n");
|
|
fprintf(write, " printf(\"resp: {\\n%%s}\\n\", resp.DebugString().c_str());\n");
|
|
fprintf(write, "\n");
|
|
fprintf(write, " return ret;\n");
|
|
fprintf(write, "}\n");
|
|
fprintf(write, "\n");
|
|
}
|
|
}
|
|
|
|
void
|
|
ToolCodeRender::GenerateToolMainCpp(SyntaxTree *stree, FILE *write)
|
|
{
|
|
char file_name[128]{'\0'};
|
|
name_render_.GetToolMainFileName(stree->GetName(), file_name, sizeof(file_name));
|
|
|
|
string buffer;
|
|
name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer, false);
|
|
|
|
fprintf(write, "/* %s.cpp\n", file_name);
|
|
fprintf(write, "%s", buffer.c_str());
|
|
fprintf(write, "*/\n");
|
|
fprintf(write, "\n");
|
|
|
|
char tool_class[128]{'\0'}, tool_file[128]{'\0'};
|
|
char tool_impl_class[128]{'\0'}, tool_impl_file[128]{'\0'};
|
|
char client_class[128]{'\0'}, client_file[128]{'\0'};
|
|
|
|
name_render_.GetToolClassName(stree->GetName(), tool_class, sizeof(tool_class));
|
|
name_render_.GetToolFileName(stree->GetName(), tool_file, sizeof(tool_file));
|
|
name_render_.GetToolImplClassName(stree->GetName(), tool_impl_class, sizeof(tool_impl_class));
|
|
name_render_.GetToolImplFileName(stree->GetName(), tool_impl_file, sizeof(tool_impl_file));
|
|
name_render_.GetClientClassName(stree->GetName(), client_class, sizeof(client_class));
|
|
name_render_.GetClientFileName(stree->GetName(), client_file, sizeof(client_file));
|
|
|
|
string content(PHXRPC_TOOL_MAIN_TEMPLATE);
|
|
StrTrim(&content);
|
|
StrReplaceAll(&content, "$ClientFile$", client_file);
|
|
StrReplaceAll(&content, "$ClientClass$", client_class);
|
|
StrReplaceAll(&content, "$ToolFile$", tool_file);
|
|
StrReplaceAll(&content, "$ToolClass$", tool_class);
|
|
StrReplaceAll(&content, "$ToolImplFile$", tool_impl_file);
|
|
StrReplaceAll(&content, "$ToolImplClass$", tool_impl_class);
|
|
|
|
fprintf(write, "%s", content.c_str());
|
|
|
|
fprintf(write, "\n");
|
|
fprintf(write, "\n");
|
|
}
|