#include "sqlgen.h" #include "../stringtools.h" #include #include enum CPPFileTokenType { CPPFileTokenType_Code, CPPFileTokenType_Comment }; struct CPPToken { CPPToken(const std::string& data, CPPFileTokenType type) : data(data), type(type) { } std::string data; CPPFileTokenType type; }; enum TokenizeState { TokenizeState_None, TokenizeState_CommentMultiline, TokenizeState_CommentSingleline }; std::vector tokenizeFile(std::string &cppfile) { std::regex find_comments("(/\\*(\\S|\\s)*?\\*/)|(//.*)", std::regex::ECMAScript); auto comments_begin=std::regex_iterator(cppfile.begin(), cppfile.end(), find_comments); auto comments_end=std::regex_iterator(); std::vector tokens; size_t lastPos=0; for(auto i=comments_begin;i!=comments_end;++i) { auto m=*i; size_t pos=m.position(0); if(lastPos annotations, std::string code) : annotations(annotations), code(code) { } AnnotatedCode(std::string code) : code(code) { } std::map annotations; std::string code; }; std::string cleanup_annotation(const std::string& annotation) { int state=0; std::string ret; for(size_t i=0;i0) { was_in_function=true; } if(c==0 && was_in_function) { return data.substr(0, i+1); } } return std::string(); } std::vector getAnnotatedCode(const std::vector& tokens) { std::vector ret; for(size_t i=0;i annotations; std::regex find_annotations("@([^ \\r\\n]*)[ ]*(((?!@)(?!\\*/)(\\S|\\s))*)", std::regex::ECMAScript); for(auto it=std::regex_iterator(tokens[i].data.begin(), tokens[i].data.end(), find_annotations); it!=std::regex_iterator();++it) { auto m=*it; std::string annotation_text=m[2].str(); annotations[m[1].str()]=trim(cleanup_annotation(annotation_text)); } ret.push_back(AnnotatedCode(tokens[i].data)); if(!annotations.empty()) { if(i+1 parseReturnTypes(std::string return_str) { std::vector toks; Tokenize(return_str, toks, ","); std::vector ret; for(size_t i=0;i& types) { std::regex find_var(":([^ (]*)\\(([^)]*?)\\)",std::regex::ECMAScript); size_t lastPos=0; std::string retSql; for(auto it=std::regex_iterator(sql.begin(), sql.end(), find_var); it!=std::regex_iterator();++it) { auto m=*it; if(m.position()>lastPos) { retSql+=sql.substr(lastPos, m.position()-lastPos); lastPos=m.position()+m[0].length(); } retSql+="?"; types.push_back(ReturnType(m[2].str(), m[1].str())); } if(lastPos return_types, GeneratedData& gen_data, bool use_exists) { if(gen_data.structures.find("struct "+name+"\r\n")!=std::string::npos) { return; } gen_data.structures+="\tstruct "+name+"\r\n"; gen_data.structures+="\t{\r\n"; if(use_exists) { gen_data.structures+="\t\tbool exists;\r\n"; } for(size_t i=0;i", return_type); return_vector=true; } StatementType stmt_type=StatementType_None; if(strlower(sql).find("select")!=std::string::npos) { stmt_type=StatementType_Select; } if(strlower(sql).find("delete")!=std::string::npos) { stmt_type=StatementType_Delete; } if(strlower(sql).find("insert")!=std::string::npos) { stmt_type=StatementType_Insert; } std::string return_vals=input.annotations["return"]; std::vector return_types=parseReturnTypes(return_vals); bool use_struct=false; bool use_cond=false; bool use_exists=false; if(return_types.size()>1) { use_struct=true; } if(return_vector) { if(return_types.size()>1) { generateStructure(struct_name, return_types, gen_data, false); } } else if(strlower(return_type)!="void") { if(return_types.size()==1) { use_cond=true; use_exists=true; struct_name=generateConditional(return_types[0], gen_data); } else { generateStructure(struct_name, return_types, gen_data, true); use_exists=true; } } std::vector params; std::string parsedSql=parseSqlString(sql, params); IQuery *q=db->Prepare("EXPLAIN "+parsedSql, true); if(q==NULL) { std::cout << "ERROR preparing statement: " << parsedSql << std::endl; return AnnotatedCode(input.annotations, ""); } else { q->Read(); } std::string return_outer=return_type; if(return_vector) { return_outer="std::vector<"; if(use_struct) { return_outer+=(classname.empty()?"":classname+"::")+struct_name; } else { return_outer+=return_types[0].type; } return_outer+=">"; } else if(use_cond) { return_outer=(classname.empty()?"":classname+"::")+struct_name; return_type=struct_name; } else if(struct_name!="string" && struct_name!="void" && struct_name!="int") { return_outer=(classname.empty()?"":classname+"::")+struct_name; return_type=struct_name; } if(return_outer=="string") return_outer="std::wstring"; if(return_type=="string") return_type="std::wstring"; std::string funcdecl=return_type+" "+func_s_name+"("; std::string code="\r\n"+return_outer+" "+funcsig+"("; for(size_t i=0;i0) { code+=", "; funcdecl+=", "; } std::string type=params[i].type; if(type=="string" || type=="std::wstring" ) { type="const std::wstring&"; } else if(type=="blob") { type="const std::string&"; } code+=type+" "+params[i].name; funcdecl+=type+" "+params[i].name; } if(params.empty()) { code+="void"; funcdecl+="void"; } code+=")\r\n{\r\n"; funcdecl+=");"; gen_data.funcdecls+="\t"+funcdecl+"\r\n"; gen_data.variables+="\tIQuery* "+query_name+";\r\n"; gen_data.createQueriesCode+="\t"+query_name+"="+"db->Prepare(\""+parsedSql+"\", false);\r\n"; gen_data.destroyQueriesCode+="\tdb->destroyQuery("+query_name+");\r\n"; for(size_t i=0;iBind("+params[i].name+".c_str(), (_u32)"+params[i].name+".size());\r\n"; } else { code+="\t"+query_name+"->Bind("+params[i].name+");\r\n"; } } if(stmt_type==StatementType_Select) { code+="\tdb_results res="+query_name+"->Read();\r\n"; } else if(stmt_type==StatementType_Delete || stmt_type==StatementType_Insert) { code+="\t"+query_name+"->Write();\r\n"; } if(!params.empty()) { code+="\t"+query_name+"->Reset();\r\n"; } if(return_vector) { code+="\tstd::vector<"; if(use_struct) { code+=(classname.empty()?"":classname+"::")+struct_name; } else { code+=return_types[0].type; } code+="> ret;\r\n"; code+="\tret.resize(res.size());\r\n"; code+="\tfor(size_t i=0;i& annotated_code) { for(size_t i=0;i::iterator sql_it=curr.annotations.find("sql"); if(sql_it!=curr.annotations.end()) { db->Write(sql_it->second); } } } } } void generateCode1(IDatabase* db, std::vector& annotated_code, GeneratedData& generated_data) { for(size_t i=0;i0) { if(!new_content.empty()) ret+="{"; ret+=new_content; new_content.clear(); } else { ret+=data[i]; } } return ret; } std::string generateSetupFunction(std::string data, GeneratedData& generated_data) { return replaceFunctionContent("\r\n"+generated_data.createQueriesCode, data); } std::string generateDestructionFunction(std::string data, GeneratedData& generated_data) { return replaceFunctionContent("\r\n"+generated_data.destroyQueriesCode, data); } void generateCode2(std::vector& annotated_code, GeneratedData& generated_data) { for(size_t i=0;i& annotated_code) { std::string code; for(size_t i=0;i tokens=tokenizeFile(cppfile); std::vector annotated_code=getAnnotatedCode(tokens); GeneratedData generated_data; setup1(db, annotated_code); generateCode1(db, annotated_code, generated_data); generateCode2(annotated_code, generated_data); cppfile=getCode(annotated_code); headerfile=placeData(headerfile, generated_data); }