12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394 |
- /*
- Copyright (c) 2020 Sogou, Inc.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- 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.
- */
- #include <ctype.h>
- #include "parser.h"
- #include "thrift/rpc_thrift_enum.h"
- #define LINE_LENGTH_MAX 2048
- static std::string gen_param_var(const std::string& type_name, size_t& cur,
- idl_info& info);
- std::string type_prefix_to_namespace(const std::string& type_name,
- idl_info& info);
- Descriptor *search_cur_file_descriptor(idl_info& info,
- const std::string& block_type,
- const std::string& block_name);
- Descriptor *search_include_file_descriptor(idl_info& info,
- const std::string include_file_name,
- const std::string& block_type,
- const std::string& block_name);
- idl_info *search_include_file(idl_info& info, const std::string file_name);
- idl_info *search_namespace(idl_info& info, const std::string name_space);
- void parse_thrift_type_name(const std::string& type_name,
- std::string& type_prefix,
- std::string& real_type_name);
- std::vector<std::string> parse_thrift_variable(const std::string& str, char sep);
- bool Parser::parse(const std::string& proto_file, idl_info& info)
- {
- std::string idl_file = info.input_dir + proto_file;
- auto pos = idl_file.find_last_of('/');
- if (pos == std::string::npos)
- info.file_name = idl_file;
- else
- info.file_name = idl_file.substr(pos + 1);
- pos = info.file_name.find_last_of('.');
- if (pos == std::string::npos)
- info.file_name_prefix = info.file_name + ".";
- else
- info.file_name_prefix = info.file_name.substr(0, pos + 1);
- info.absolute_file_path = idl_file;
- FILE *in = fopen(idl_file.c_str(), "r");
- if (!in)
- {
- fprintf(stderr, "[Parser] proto file: [%s] not exists.\n",
- idl_file.c_str());
- return false;
- }
- fprintf(stdout, "proto file: [%s]\n", idl_file.c_str());
- char line_buffer[LINE_LENGTH_MAX];
- std::string file_path;
- std::string block;
- int state = PARSER_ST_OUTSIDE_BLOCK;
- bool flag_append;
- int stack_count = 0;
- std::string block_name;
- std::string block_type;
- std::string extends_type;
- std::string old_type_name;
- std::string new_type_name;
- std::string thrift_type_prefix;
- std::string thrift_type_name;
- bool succ;
- while (fgets(line_buffer, LINE_LENGTH_MAX, in))
- {
- std::string line = SGenUtil::lstrip(line_buffer);
- if (line.empty())
- continue;
- this->check_single_comments(line);
- if (line.empty())
- continue;
- this->check_single_comments(line);
- if ((state & PARSER_ST_COMMENT_MASK) == PARSER_ST_INSIDE_COMMENT)
- {
- if (this->check_multi_comments_end(line))
- {
- state -= PARSER_ST_INSIDE_COMMENT;
- // state |= PARSER_ST_OUTSIDE_COMMENT_MASK;
- if (line.empty())
- continue;
- }
- else
- continue;
- }
- else if (this->check_multi_comments_begin(line))
- {
- state = (state & PARSER_ST_OUTSIDE_COMMENT_MASK) + PARSER_ST_INSIDE_COMMENT;
- if (line.empty())
- continue;
- }
- if (this->is_thrift == false)
- {
- int rpc_option = this->parse_pb_rpc_option(line);
- if (rpc_option == 1)
- continue;
- else if (rpc_option == 2)
- {
- fprintf(stderr, "[Parser ERROR] %s must not set "
- "\"option cc_generic_services = true\" for srpc.\n",
- idl_file.c_str());
- return false;
- }
- }
- if (this->parse_package_name(line, info.package_name) == true)
- continue;
- if (this->parse_include_file(line, file_path) == true)
- {
- if (!this->is_thrift)
- {
- if (file_path.rfind("google/protobuf/", 0) == 0)
- continue;
- }
- info.include_list.resize(info.include_list.size() + 1);
- info.include_list.back().input_dir = info.input_dir;
- succ = this->parse(file_path, info.include_list.back());
- if (!succ)
- {
- info.include_list.pop_back();
- fprintf(stderr, "[Parser ERROR] failed to parse "
- "\" %s \" in \" %s \"\n",
- file_path.c_str(), idl_file.c_str());
- return false;
- }
- continue;
- }
- if (this->is_thrift &&
- this->parse_thrift_typedef(line,
- old_type_name,
- new_type_name, info) == true)
- {
- info.typedef_list.push_back(typedef_descriptor{old_type_name,
- new_type_name});
- continue;
- }
- flag_append = false;
- if ((state & PARSER_ST_BLOCK_MASK) == PARSER_ST_OUTSIDE_BLOCK)
- {
- if (this->check_block_begin(in, line) == true)
- {
- state |= PARSER_ST_INSIDE_BLOCK;
- // stack_count++;
- block.clear();
- block = line;
- if (this->parse_block_name(line, block_type,
- block_name, extends_type) == false)
- {
- fprintf(stderr, "Invalid proto file line: %s\n",
- line.c_str());
- fprintf(stderr, "Failed to parse block name or value.\n");
- return false;
- }
- }
- }
- else
- flag_append = true;
- // not else, because { }; can in the same line
- if ((state & PARSER_ST_BLOCK_MASK) == PARSER_ST_INSIDE_BLOCK)
- {
- if (flag_append == true)
- block.append(line);
- if (this->check_block_begin(line) == true)
- ++stack_count;
- if (this->check_block_end(line) == true)
- {
- --stack_count;
- if (stack_count == 0)
- {
- state = PARSER_ST_OUTSIDE_BLOCK;
- //state &= PARSER_ST_OUTSIDE_BLOCK_MASK;
- Descriptor desc;
- if (block_type == "service")
- {
- if (this->is_thrift)
- succ = this->parse_service_thrift(info.file_name_prefix,
- block, desc, info);
- else
- succ = this->parse_service_pb(block, desc);
- if (!succ)
- return false;
- desc.block_type = block_type;
- desc.block_name = block_name;
- desc.extends_type = extends_type;
- if (desc.extends_type != "" && this->is_thrift)
- {
- Descriptor *extended_desc = NULL;
- parse_thrift_type_name(desc.extends_type,
- thrift_type_prefix,
- thrift_type_name);
- if (thrift_type_prefix == "")
- extended_desc = search_cur_file_descriptor(info,
- "service", thrift_type_name);
- else
- extended_desc = search_include_file_descriptor(info,
- thrift_type_prefix+".thrift",
- "service", thrift_type_name);
- if (!extended_desc)
- {
- fprintf(stderr,"service %s extends type %s not found\n",
- desc.block_name.c_str(),
- desc.extends_type.c_str());
- }
- else
- {
- desc.rpcs.insert(desc.rpcs.begin(),
- extended_desc->rpcs.begin(),
- extended_desc->rpcs.end());
- }
- }
- info.desc_list.emplace_back(std::move(desc));
- }
- else if ((block_type == "struct" || block_type == "union") &&
- this->is_thrift)
- {
- succ = this->parse_struct_thrift(info.file_name_prefix,
- block, desc, info);
- if (!succ)
- return false;
- desc.block_type = block_type;
- desc.block_name = block_name;
- info.desc_list.emplace_back(std::move(desc));
- }
- else if (block_type == "exception" && this->is_thrift)
- {
- succ = this->parse_struct_thrift(info.file_name_prefix,
- block, desc, info);
- if (!succ)
- return false;
- desc.block_type = "struct";
- desc.block_name = block_name;
- info.desc_list.emplace_back(std::move(desc));
- }
- else if (block_type == "enum" && this->is_thrift)
- {
- succ = this->parse_enum_thrift(block, desc);
- if (!succ)
- return false;
- SGenUtil::get_enum_set()->insert(info.file_name_prefix + block_name);
- desc.block_type = block_type;
- desc.block_name = block_name;
- info.desc_list.emplace_back(std::move(desc));
- }
- }
- }
- }
- }
- build_typedef_mapping(info);
- fclose(in);
- fprintf(stdout, "finish parsing proto file: [%s]\n", idl_file.c_str());
- return true;
- }
- std::string Parser::find_typedef_mapping_type(std::string& type_name,
- size_t& cur, idl_info& info)
- {
- size_t st = cur;
- cur = SGenUtil::find_next_nonspace(type_name,cur);
- for (; cur < type_name.size(); cur++)
- {
- if (type_name[cur] == ',' || type_name[cur] == '>' ||
- type_name[cur] == '<')
- break;
- }
- auto idl_type = SGenUtil::strip(type_name.substr(st, cur - st));
- if (info.typedef_mapping.find(idl_type) != info.typedef_mapping.end())
- return info.typedef_mapping[idl_type];
- if (idl_type == "bool" ||
- idl_type == "int8_t" ||
- idl_type == "int16_t" ||
- idl_type == "int32_t" ||
- idl_type == "int64_t" ||
- idl_type == "uint64_t" ||
- idl_type == "double" ||
- idl_type == "std::string")
- {
- return idl_type;
- }
- else if (idl_type == "std::map" && cur < type_name.size() &&
- type_name[cur] == '<')
- {
- auto key_type = find_typedef_mapping_type(type_name, ++cur, info);
- auto val_type = find_typedef_mapping_type(type_name, ++cur, info);
- ++cur;
- return "std::map<" + key_type + ", " + val_type + ">";
- }
- else if (idl_type == "std::set" && cur < type_name.size() &&
- type_name[cur] == '<')
- {
- auto val_type = find_typedef_mapping_type(type_name, ++cur, info);
- ++cur;
- return "std::set<" + val_type + ">";
- }
- else if (idl_type == "std::vector" && cur < type_name.size() &&
- type_name[cur] == '<')
- {
- auto val_type = find_typedef_mapping_type(type_name, ++cur, info);
- ++cur;
- return "std::vector<" + val_type + ">";
- }
- size_t pos = idl_type.find("::",0);
- std::string real_type_name;
- std::string type_namespace;
- if (pos == std::string::npos)
- real_type_name = idl_type;
- else
- {
- real_type_name = idl_type.substr(pos+2);
- type_namespace = idl_type.substr(0,pos);
- }
- for (auto& include : info.include_list)
- {
- if ( (type_namespace != "" && include.package_name.size() > 0 &&
- include.package_name[0] == type_namespace) ||
- (type_namespace == "" && include.package_name.size() == 0) )
- {
- for (auto& t : include.typedef_list)
- {
- if (real_type_name == t.new_type_name)
- {
- size_t offset = 0;
- include.typedef_mapping[real_type_name] =
- find_typedef_mapping_type(t.old_type_name, offset, include);
- return include.typedef_mapping[real_type_name];
- }
- }
- }
- }
- for (auto& t : info.typedef_list)
- {
- if (real_type_name == t.new_type_name)
- {
- size_t offset = 0;
- info.typedef_mapping[real_type_name] =
- find_typedef_mapping_type(t.old_type_name, offset, info);
- return info.typedef_mapping[real_type_name];
- }
- }
- return idl_type;
- }
- void Parser::build_typedef_mapping(idl_info& info)
- {
- for (auto &include:info.include_list)
- {
- for (auto &t:include.typedef_list)
- {
- if (include.typedef_mapping.find(t.new_type_name) != include.typedef_mapping.end())
- continue;
- size_t cur = 0;
- include.typedef_mapping[t.new_type_name] =
- find_typedef_mapping_type(t.old_type_name, cur, include);
- }
- }
- for (auto &t:info.typedef_list)
- {
- if (info.typedef_mapping.find(t.new_type_name) != info.typedef_mapping.end())
- continue;
- size_t cur = 0;
- info.typedef_mapping[t.new_type_name] =
- find_typedef_mapping_type(t.old_type_name, cur, info);
- }
- }
- // check / * and cut the first available line
- bool Parser::check_multi_comments_begin(std::string& line)
- {
- size_t pos = line.find("/*");
- if (pos == std::string::npos)
- return false;
- line = line.substr(0, pos);
- return true;
- }
- // check * / and cut the rest available line
- bool Parser::check_multi_comments_end(std::string& line)
- {
- size_t pos = line.find("*/");
- if (pos == std::string::npos)
- return false;
- pos += 2;
- while (line[pos] == ' ')
- pos++;
- line = line.substr(pos, line.length() - 1 - pos);
- return true;
- }
- // [ret] 0: no rpc option; 1: rpc_option = false; 2: rpc_option = true;
- int Parser::parse_pb_rpc_option(const std::string& line)
- {
- size_t pos = line.find("option");
- if (pos == std::string::npos)
- return 0;
- pos = line.find("cc_generic_services", pos);
- if (pos == std::string::npos)
- return 0;
- pos = line.find("true", pos);
- if (pos == std::string::npos)
- return 1;
- return 2;
- }
- bool Parser::parse_thrift_typedef(const std::string& line,
- std::string& old_type_name,
- std::string& new_type_name,
- idl_info&info)
- {
- std::vector<std::string> elems = SGenUtil::split_by_space(line);
- if (elems.size() >= 3 && elems[0] == "typedef")
- {
- size_t offset = 0;
- std::string idl_type;
- for (size_t i = 1; i < elems.size()-1; i++)
- idl_type.append(elems[i]);
- old_type_name = gen_param_var(idl_type,offset,info);
- new_type_name = elems[elems.size()-1];
- return true;
- }
- return false;
- }
- bool Parser::parse_include_file(const std::string& line, std::string& file_name)
- {
- std::string include_prefix = (this->is_thrift ? "include" : "import");
- size_t pos = line.find(include_prefix);
- if (pos != 0)
- return false;
- auto st = line.find_first_of('\"');
- auto ed = line.find_last_of('\"');
- if (st == std::string::npos || ed == std::string::npos || st == ed)
- return false;
- file_name = line.substr(st + 1, ed - st - 1);
- // fprintf(stderr, "parse_include_file(%s,%s)\n", line.c_str(), file_name.c_str());
- return true;
- }
- bool Parser::parse_package_name(const std::string& line,
- std::vector<std::string>& package_name)
- {
- std::string package_prefix = (this->is_thrift ? "namespace" : "package");
- size_t pos = line.find(package_prefix);
- if (pos != 0)
- return false;
- pos += package_prefix.length();
- while (pos < line.length() && isspace(line[pos]))
- pos++;
- if (this->is_thrift)
- {
- pos = line.find("cpp", pos);
- if (pos == std::string::npos)
- return false;
- pos += 3;
- while (pos < line.length() && isspace(line[pos]))
- pos++;
- }
- size_t begin;
- if (this->is_thrift)
- {
- begin = line.find_last_of('/');
- if (begin == std::string::npos)
- begin = pos;
- else
- begin++;
- } else {
- begin = pos;
- }
- while (pos < line.length() && !isspace(line[pos]) &&
- line[pos] != ';')
- {
- pos++;
- }
- std::string names = line.substr(begin, pos - begin);
- pos = names.find('.');
- while (pos != (size_t)-1)
- {
- package_name.push_back(names.substr(0, pos));
- names = names.substr(pos + 1, names.length() - pos);
- pos = names.find('.');
- }
- package_name.push_back(names.substr(0, pos));
- return true;
- }
- static std::string gen_param_var(const std::string& type_name, size_t& cur,
- idl_info& info)
- {
- size_t st = cur;
- cur = SGenUtil::find_next_nonspace(type_name,cur);
- for (; cur < type_name.size(); cur++)
- {
- if (type_name[cur] == ',' || type_name[cur] == '>' ||
- type_name[cur] == '<')
- break;
- }
- auto idl_type = SGenUtil::strip(type_name.substr(st, cur - st));
- if (idl_type == "bool")
- return "bool";
- else if (idl_type == "i8" || idl_type == "byte")
- return "int8_t";
- else if (idl_type == "i16")
- return "int16_t";
- else if (idl_type == "i32")
- return "int32_t";
- else if (idl_type == "i64")
- return "int64_t";
- else if (idl_type == "u64")
- return "uint64_t";
- else if (idl_type == "double")
- return "double";
- else if (idl_type == "string" || idl_type == "binary")
- return "std::string";
- else if (idl_type == "map" && cur < type_name.size() &&
- type_name[cur] == '<')
- {
- auto key_type = gen_param_var(type_name, ++cur, info);
- auto val_type = gen_param_var(type_name, ++cur, info);
- ++cur;
- return "std::map<" + key_type + ", " + val_type + ">";
- }
- else if (idl_type == "set" && cur < type_name.size() &&
- type_name[cur] == '<')
- {
- auto val_type = gen_param_var(type_name, ++cur, info);
- ++cur;
- return "std::set<" + val_type + ">";
- }
- else if (idl_type == "list" && cur < type_name.size() &&
- type_name[cur] == '<')
- {
- auto val_type = gen_param_var(type_name, ++cur, info);
- ++cur;
- return "std::vector<" + val_type + ">";
- }
- return type_prefix_to_namespace(idl_type, info);
- }
- static void fill_rpc_param_type(const std::string& file_name_prefix,
- const std::string idl_type,
- rpc_param& param, idl_info& info)
- {
- if (idl_type == "bool")
- {
- param.data_type = srpc::TDT_BOOL;
- param.type_name = "bool";
- }
- else if (idl_type == "i8" || idl_type == "byte")
- {
- param.data_type = srpc::TDT_I08;
- param.type_name = "int8_t";
- }
- else if (idl_type == "i16")
- {
- param.data_type = srpc::TDT_I16;
- param.type_name = "int16_t";
- }
- else if (idl_type == "i32")
- {
- param.data_type = srpc::TDT_I32;
- param.type_name = "int32_t";
- }
- else if (idl_type == "i64")
- {
- param.data_type = srpc::TDT_I64;
- param.type_name = "int64_t";
- }
- else if (idl_type == "u64")
- {
- param.data_type = srpc::TDT_U64;
- param.type_name = "uint64_t";
- }
- else if (idl_type == "double")
- {
- param.data_type = srpc::TDT_DOUBLE;
- param.type_name = "double";
- }
- else if (idl_type == "string" || idl_type == "binary")
- {
- param.data_type = srpc::TDT_STRING;
- param.type_name = "std::string";
- }
- else if (SGenUtil::start_with(idl_type, "list"))
- {
- size_t cur = 0;
- param.data_type = srpc::TDT_LIST;
- param.type_name = gen_param_var(idl_type, cur, info);
- }
- else if (SGenUtil::start_with(idl_type, "map"))
- {
- size_t cur = 0;
- param.data_type = srpc::TDT_MAP;
- param.type_name = gen_param_var(idl_type, cur, info);
- }
- else if (SGenUtil::start_with(idl_type, "set"))
- {
- size_t cur = 0;
- param.data_type = srpc::TDT_SET;
- param.type_name = gen_param_var(idl_type, cur, info);
- }
- else
- {
- auto *enum_set = SGenUtil::get_enum_set();
- if (enum_set->count(idl_type) > 0 ||
- enum_set->count(file_name_prefix + idl_type) > 0)
- {
- //enum
- param.data_type = srpc::TDT_I32;
- param.type_name = "int32_t";
- }
- else
- {
- //struct
- param.data_type = srpc::TDT_STRUCT;
- param.type_name = type_prefix_to_namespace(idl_type,info);
- }
- }
- }
- std::vector<std::string> Parser::split_thrift_rpc(const std::string& str)
- {
- std::vector<std::string> res;
- std::string::const_iterator start = str.begin();
- std::string::const_iterator parameter_end = str.end();
- std::string::const_iterator throws_end = str.end();
- while (1)
- {
- parameter_end = find(start,str.end(), ')');
- if (parameter_end == str.end())
- {
- res.emplace_back(start,parameter_end);
- break;
- }
- std::string::const_iterator offset = find_if(parameter_end + 1, str.end(),
- [](char c){return !std::isspace(c);});
- if (offset == str.end())
- {
- res.emplace_back(start,parameter_end);
- break;
- }
- if (str.compare(offset-str.begin(), 6, "throws") == 0)
- {
- throws_end = find(offset,str.end(), ')');
- res.emplace_back(start,throws_end);
- start = throws_end + 1;
- }
- else
- {
- res.emplace_back(start,parameter_end);
- start = parameter_end + 1;
- }
- }
- return res;
- }
- bool Parser::parse_rpc_param_thrift(const std::string& file_name_prefix,
- const std::string& str,
- std::vector<rpc_param>& params,
- idl_info& info)
- {
- size_t left_b = 0;
- rpc_param param;
- std::string idl_type;
- if (left_b + 1 < str.size())
- {
- auto bb = parse_thrift_variable(str.substr(left_b + 1), ',');
- for (const auto& ele : bb)
- {
- auto single_line = SGenUtil::split_skip_string(ele, '\n');
- if (single_line.size() != 1)
- continue;
- auto filedparam = SGenUtil::split_skip_string(single_line[0], ':');
- if (filedparam.size() != 2)
- continue;
- auto typevar = parse_thrift_variable(filedparam[1], ' ');
- if (typevar.size() != 2)
- continue;
- param.var_name = typevar[1];
- param.required_state = srpc::THRIFT_STRUCT_FIELD_REQUIRED;
- param.field_id = atoi(SGenUtil::strip(filedparam[0]).c_str());
- idl_type = SGenUtil::strip(typevar[0]);
- fill_rpc_param_type(file_name_prefix, idl_type, param, info);
- params.push_back(param);
- }
- }
- return true;
- }
- bool Parser::parse_service_thrift(const std::string& file_name_prefix,
- const std::string& block,
- Descriptor& desc,
- idl_info& info)
- {
- rpc_descriptor rpc_desc;
- auto st = block.find_first_of('{');
- auto ed = block.find_last_of('}');
- if (st == std::string::npos || ed == std::string::npos || st == ed)
- return false;
- std::string valid_block = block.substr(st + 1, ed - st - 1);
- auto arr = split_thrift_rpc(valid_block);
- for (const auto& ele : arr)
- {
- auto line = SGenUtil::strip(ele);
- size_t i = 0;
- for (; i < line.size(); i++)
- {
- if (line[i] != ';' && line[i] != ',' && !isspace(line[i]))
- break;
- }
- if (i == line.size())
- continue;
- line = line.substr(i);
- if (line.empty())
- continue;
- auto left_b = line.find('(');
- if (left_b == std::string::npos)
- continue;
- auto aa = SGenUtil::split_skip_string(line.substr(0, left_b), ' ');
- if (aa.size() != 2)
- continue;
- rpc_desc.method_name = SGenUtil::strip(aa[1]);
- if (rpc_desc.method_name.empty())
- continue;
- rpc_desc.request_name = rpc_desc.method_name + "Request";
- rpc_desc.response_name = rpc_desc.method_name + "Response";
- auto idl_type = SGenUtil::strip(aa[0]);
- rpc_param param;
- param.var_name = "result";
- param.required_state = srpc::THRIFT_STRUCT_FIELD_REQUIRED;
- param.field_id = 0;
- if (idl_type != "void")
- {
- fill_rpc_param_type(file_name_prefix, idl_type, param, info);
- rpc_desc.resp_params.push_back(param);
- }
- auto right_b = line.find(')',left_b);
- if (right_b == std::string::npos)
- {
- parse_rpc_param_thrift(file_name_prefix, line.substr(left_b),
- rpc_desc.req_params,info);
- }
- else
- {
- parse_rpc_param_thrift(file_name_prefix,
- line.substr(left_b, right_b - left_b),
- rpc_desc.req_params,
- info);
- auto throws_start = line.find("throws", right_b);
- if (throws_start != std::string::npos)
- {
- left_b = line.find('(', throws_start + 6);
- parse_rpc_param_thrift(file_name_prefix, line.substr(left_b),
- rpc_desc.resp_params, info);
- }
- }
- fprintf(stdout, "Successfully parse method:%s req:%s resp:%s\n",
- rpc_desc.method_name.c_str(),
- rpc_desc.request_name.c_str(),
- rpc_desc.response_name.c_str());
- desc.rpcs.emplace_back(std::move(rpc_desc));
- }
- return true;
- }
- void Parser::check_single_comments(std::string& line)
- {
- size_t pos = line.find("#");
- if (pos == std::string::npos)
- pos = line.find("//");
- if (pos != std::string::npos)
- {
- line.resize(pos);
- return;
- }
- if (pos == std::string::npos)
- pos = line.find("/*");
- size_t end;
- while (pos != std::string::npos)
- {
- end = line.find("*/", pos + 2);
- if (end == std::string::npos)
- return; // multi_comments can handle this, except for 'a/*\n'
- line.erase(pos, end - pos + 2);
- pos = line.find("/*", pos);
- }
- }
- bool Parser::parse_enum_thrift(const std::string& block, Descriptor& desc)
- {
- rpc_param param;
- auto st = block.find_first_of('{');
- auto ed = block.find_last_of('}');
- if (st == std::string::npos || ed == std::string::npos || st == ed)
- return false;
- std::string valid_block = block.substr(st + 1, ed - st - 1);
- for (size_t i = 0; i < valid_block.size(); i++)
- if (valid_block[i] == '\n' || valid_block[i] == '\r' || valid_block[i] == ',')
- valid_block[i] = ';';
- auto arr = SGenUtil::split_skip_string(valid_block, ';');
- for (const auto& ele : arr)
- {
- auto line = SGenUtil::strip(ele);
- if (line.empty())
- continue;
- if (line.back() == ';' || line.back() == ',')
- line.resize(line.size() - 1);
- desc.enum_lines.push_back(line);
- }
- return true;
- }
- bool Parser::parse_struct_thrift(const std::string& file_name_prefix,
- const std::string& block,
- Descriptor& desc, idl_info& info)
- {
- auto st = block.find_first_of('{');
- auto ed = block.find_last_of('}');
- if (st == std::string::npos || ed == std::string::npos || st == ed)
- return false;
- std::string valid_block = block.substr(st + 1, ed - st - 1);
- int deep = 0;
- bool in_string = false;
- for (size_t i = 0; i < valid_block.size(); i++)
- {
- int c = valid_block[i];
- if (c == '\n' || c == '\r')
- {
- valid_block[i] = ';';
- in_string = false;
- }
- else if (c == ',' && !in_string && deep == 0)
- valid_block[i] = ';';
- else if (c == '<' && !in_string)
- deep++;
- else if (c == '>' && !in_string)
- deep--;
- else if (c == '[' && !in_string)
- valid_block[i] = '{';
- else if (c == ']' && !in_string)
- valid_block[i] = '}';
- else if (c == '\"')
- in_string = !in_string;
- else if (in_string && c == '\\')
- {
- if (i + 1 < valid_block.size())
- i++;
- }
- }
- auto arr = SGenUtil::split_skip_string(valid_block, ';');
- for (const auto& ele : arr)
- {
- auto line = SGenUtil::strip(ele);
- if (line.empty())
- continue;
- auto aabb = SGenUtil::split_skip_string(line, ':');
- if (aabb.size() != 2)
- continue;
- auto aa = SGenUtil::strip(aabb[0]);
- if (aa.empty())
- continue;
- rpc_param param;
- param.field_id = atoi(aa.c_str());
- auto bb = SGenUtil::strip(aabb[1]);
- auto bbcc = SGenUtil::split_skip_string(bb, '=');
- if (bbcc.size() == 2)
- {
- bb = SGenUtil::strip(bbcc[0]);
- param.default_value = SGenUtil::strip(bbcc[1]);
- }
- auto idx1 = std::string::npos;//bb.find_first_of(' ');
- auto idx2 = std::string::npos;//bb.find_last_of(' ');
- for (size_t i = 0; i < bb.size(); i++)
- {
- if (isspace(bb[i]))
- {
- idx1 = i;
- break;
- }
- }
- for (size_t i = 0; i < bb.size(); i++)
- {
- if (isspace(bb[bb.size() - i - 1]))
- {
- idx2 = bb.size() - i - 1;
- break;
- }
- }
- if (idx1 == std::string::npos || idx2 == std::string::npos)
- continue;
- std::string b1 = SGenUtil::strip(bb.substr(0, idx1));
- std::string b2, b3;
- if (idx1 == idx2 || (b1 != "required" && b1 != "optional"))
- {
- param.required_state = srpc::THRIFT_STRUCT_FIELD_DEFAULT;
- b1 = "default";
- b2 = SGenUtil::strip(bb.substr(0, idx2));
- b3 = SGenUtil::strip(bb.substr(idx2 + 1));
- }
- else
- {
- param.required_state = (b1 == "required") ?
- srpc::THRIFT_STRUCT_FIELD_REQUIRED :
- srpc::THRIFT_STRUCT_FIELD_OPTIONAL;
- b2 = SGenUtil::strip(bb.substr(idx1 + 1, idx2 - idx1 - 1));
- b3 = SGenUtil::strip(bb.substr(idx2 + 1));
- }
- if (b1.empty() || b2.empty() || b3.empty())
- continue;
- param.var_name = b3;
- fill_rpc_param_type(file_name_prefix, b2, param, info);
- fprintf(stdout, "Successfully parse struct param: %s %s %s\n",
- param.type_name.c_str(), param.var_name.c_str(),
- param.default_value.c_str());
- desc.st.params.push_back(param);
- }
- return true;
- }
- bool Parser::parse_service_pb(const std::string& block, Descriptor& desc)
- {
- size_t pos = block.find("{");
- if (pos == std::string::npos)
- return false;
- while (pos < block.length())
- {
- rpc_descriptor rpc_desc;
- pos = block.find("rpc", pos);
- if (pos == std::string::npos)
- {
- if (desc.rpcs.size() == 0)
- {
- fprintf(stderr, "no \"rpc\" in service block [%s]\n",
- block.c_str());
- return false;
- } else {
- return true;
- }
- }
- pos += strlen("rpc");
- while (block[pos] == ' ' && pos < block.length())
- pos++;
- if (pos == block.length())
- return false;
- size_t method_name_pos = block.find("(", pos);
- if (method_name_pos == std::string::npos)
- {
- fprintf(stderr, "no method_name in service block [%s]\n",
- block.c_str());
- return false;
- }
- rpc_desc.method_name = std::string(&block[pos], &block[method_name_pos]);
- rpc_desc.method_name.erase(rpc_desc.method_name.find_last_not_of(" ") + 1);
- pos = method_name_pos;
- while (block[pos] == ' ' && pos < block.length())
- pos++;
- if (pos == block.length())
- return false;
- size_t request_name_pos = block.find(")", pos + 1);
- if (request_name_pos == std::string::npos)
- {
- fprintf(stderr, "no request_name in service block [%s]\n",
- block.c_str());
- return false;
- }
- rpc_desc.request_name = std::string(&block[pos + 1],
- &block[request_name_pos]);
- pos = block.find("returns", pos + 1);
- if (pos == std::string::npos)
- {
- fprintf(stderr, "no \"returns\" in service block [%s]\n",
- block.c_str());
- return false;
- }
- while (block[pos] == ' ' && pos < block.length())
- pos++;
- if (pos == block.length())
- return true;
- size_t response_name_pos = block.find("(", pos + 1);
- size_t response_name_end = block.find(")", pos + 1);
- if (response_name_pos == std::string::npos ||
- response_name_end == std::string::npos)
- {
- fprintf(stderr, "no response_name in service block [%s]\n",
- block.c_str());
- return false;
- }
- rpc_desc.response_name = std::string(&block[response_name_pos + 1],
- &block[response_name_end]);
- fprintf(stdout, "Successfully parse method:%s req:%s resp:%s\n",
- rpc_desc.method_name.c_str(),
- rpc_desc.request_name.c_str(),
- rpc_desc.response_name.c_str());
- desc.rpcs.emplace_back(std::move(rpc_desc));
- pos = response_name_end;
- }
- return true;
- }
- bool Parser::parse_block_name(const std::string& line,
- std::string& block_name,
- std::string& block_name_value,
- std::string& extends_type)
- {
- size_t pos = line.find("{");
- if (pos == std::string::npos)
- {
- fprintf(stderr, "failed to parse block name in %s\n",line.c_str());
- return false;
- }
- std::vector<std::string> elems = SGenUtil::split_by_space(line.substr(0,pos));
- if (elems.size() == 2)
- {
- block_name = elems[0];
- block_name_value = elems[1];
- extends_type = "";
- }
- else if (this->is_thrift && elems.size() == 4 && elems[0] == "service" &&
- elems[2] == "extends")
- {
- block_name = elems[0];
- block_name_value = elems[1];
- extends_type = elems[3];
- }
- else
- {
- fprintf(stderr, "failed to parse block name in %s\n", line.c_str());
- return false;
- }
- fprintf(stdout, "Successfully parse service block [%s] : %s\n",
- block_name.c_str(), block_name_value.c_str());
- return true;
- }
- /*
- bool Parser::parse_block_name(const std::string& line,
- std::string& block_name,
- std::string& block_name_value)
- {
- size_t pos = line.find_first_of(" ", 0);
- if (pos == std::string::npos)
- {
- fprintf(stderr, "failed to parse rpc name in %s\n", line.c_str());
- return false;
- }
- block_name = std::string(&line[0], &line[pos]);
- size_t value_pos = line.find_first_of(" ", pos + 1);
- if (value_pos != std::string::npos)
- {
- block_name_value = std::string(&line[pos + 1], &line[value_pos]);
- } else {
- size_t end = line.find("{");
- if (end == std::string::npos)
- return false;
- end--;
- while (line[end] == '\n' || line[end] == '\r' || line[end] == ' ')
- end --;
- // block_name_value = std::string(&line[pos + 1], &line[line.length() - 1]);
- block_name_value = std::string(&line[pos + 1], &line[end + 1]);
- }
- fprintf(stdout, "Successfully parse service block [%s] : %s\n",
- block_name.c_str(), block_name_value.c_str());
- return true;
- }
- */
- bool Parser::check_block_begin(FILE *in, std::string& line)
- {
- if (line.find(";") != std::string::npos)
- return false;
- if (line.find("{") != std::string::npos)
- return true;
- char line_buffer[LINE_LENGTH_MAX];
- if (fgets(line_buffer, LINE_LENGTH_MAX, in))
- {
- std::string next = SGenUtil::strip(line_buffer);
- if (next.find("{") != std::string::npos)
- {
- line.append(next.c_str());
- return true;
- }
- }
- return false;
- }
- bool Parser::check_block_begin(const std::string& line)
- {
- if (line.find("{") == std::string::npos)
- return false;
- return true;
- }
- bool Parser::check_block_end(const std::string& line)
- {
- if (line.find("}") == std::string::npos
- && line.find("};") == std::string::npos)
- return false;
- return true;
- }
- void parse_thrift_type_name(const std::string& type_name,
- std::string& type_prefix,
- std::string& real_type_name)
- {
- size_t pos = type_name.find('.',0);
- if (pos == std::string::npos)
- {
- type_prefix = "";
- real_type_name = SGenUtil::strip(type_name);
- }
- else
- {
- type_prefix = SGenUtil::strip(type_name.substr(0,pos));
- real_type_name = SGenUtil::strip(type_name.substr(pos+1));
- }
- }
- std::string type_prefix_to_namespace(const std::string& type_name,
- idl_info& info)
- {
- std::string prefix;
- std::string real_type;
- parse_thrift_type_name(type_name, prefix, real_type);
- if (prefix == "")
- return type_name;
- idl_info *include = search_include_file(info, prefix + ".thrift");
- if (include == NULL)
- {
- fprintf(stderr,"cannot find type %s\n",type_name.c_str());
- return type_name;
- }
- if (include->package_name.size() > 0)
- return include->package_name[0]+"::"+real_type;
- return "::"+real_type;
- }
- Descriptor *search_cur_file_descriptor(idl_info& info,
- const std::string& block_type,
- const std::string& block_name)
- {
- for (auto &desc : info.desc_list)
- {
- if (desc.block_type == block_type && desc.block_name == block_name)
- return &desc;
- }
- return NULL;
- }
- Descriptor *search_include_file_descriptor(idl_info& info,
- const std::string include_file_name,
- const std::string& block_type,
- const std::string& block_name)
- {
- for (auto &include : info.include_list)
- {
- if (include.file_name == include_file_name)
- return search_cur_file_descriptor(include, block_type, block_name);
- }
- return NULL;
- }
- idl_info *search_include_file(idl_info& info, const std::string file_name)
- {
- for (auto &include : info.include_list)
- {
- if (include.file_name == file_name)
- return &include;
- }
- return NULL;
- }
- idl_info *search_namespace(idl_info& info, const std::string name_space)
- {
- if (name_space == "")
- return &info;
- for (auto &include : info.include_list)
- {
- if (include.package_name.size() > 0 &&
- include.package_name[0] == name_space)
- return &include;
- }
- return NULL;
- }
- int Parser::find_valid(const std::string& line)
- {
- /*
- char *p = line.c_str();
- char *q = p;
- while (q != p + line.length())
- {
- if(*q != ' ' && *q != '\t')
- return pos;
- }
- */
- return 0;
- }
- std::vector<std::string> parse_thrift_variable(const std::string& str, char sep)
- {
- std::vector<std::string> res;
- if (sep == '\"')
- return res;
- const char *cursor = str.c_str();
- const char *start = cursor;
- bool in_map = false;
- std::string param;
- while (*cursor)
- {
- if (*cursor == '\"')
- {
- cursor = SGenUtil::skip_string(++cursor);
- if (!*cursor)
- break;
- }
- else if (*cursor == sep)
- {
- param = std::string(start, cursor);
- if (in_map == false &&
- param.find("map") != std::string::npos &&
- param.find("<") != std::string::npos)
- {
- in_map = true;
- cursor++;
- continue;
- }
- if (start < cursor)
- res.emplace_back(param);
- start = cursor + 1;
- in_map = false;
- }
- cursor++;
- }
- if (start < cursor)
- res.emplace_back(start, cursor);
- return res;
- }
|