2018-05-31 17:00:31 +08:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @author An Tao
|
|
|
|
* @section LICENSE
|
|
|
|
*
|
|
|
|
* Copyright 2018, An Tao. All rights reserved.
|
|
|
|
* Use of this source code is governed by a MIT license
|
|
|
|
* that can be found in the License file.
|
|
|
|
*
|
|
|
|
* @section DESCRIPTION
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-05-29 17:21:37 +08:00
|
|
|
#include "create_view.h"
|
|
|
|
#include "cmd.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <string>
|
2018-05-29 21:24:04 +08:00
|
|
|
#include <algorithm>
|
2018-05-29 17:21:37 +08:00
|
|
|
static const std::string cxx_include="<%inc";
|
|
|
|
static const std::string cxx_end="%>";
|
|
|
|
static const std::string cxx_lang="<%c++";
|
|
|
|
static const std::string cxx_view_data="@@";
|
|
|
|
static const std::string cxx_output="$$";
|
2018-10-05 19:17:12 +08:00
|
|
|
static const std::string cxx_val_start="{{";
|
|
|
|
static const std::string cxx_val_end="}}";
|
2018-05-29 17:21:37 +08:00
|
|
|
|
|
|
|
using namespace drogon_ctl;
|
|
|
|
|
|
|
|
static std::string& replace_all(std::string& str,const std::string& old_value,const std::string& new_value)
|
|
|
|
{
|
|
|
|
std::string::size_type pos(0);
|
|
|
|
while(true) {
|
|
|
|
|
|
|
|
|
|
|
|
//std::cout<<str<<endl;
|
|
|
|
//std::cout<<"pos="<<pos<<endl;
|
|
|
|
if( (pos=str.find(old_value,pos))!=std::string::npos ) {
|
|
|
|
str = str.replace(pos, old_value.length(), new_value);
|
|
|
|
pos += new_value.length()-old_value.length();
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
2018-06-01 14:07:34 +08:00
|
|
|
static void parseCxxLine(std::ofstream &oSrcFile,const std::string& line,const std::string& streamName,const std::string& viewDataName)
|
2018-05-29 17:21:37 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
if(line.length()>0)
|
|
|
|
{ std::string tmp=line;
|
|
|
|
replace_all(tmp,cxx_output,streamName);
|
|
|
|
replace_all(tmp,cxx_view_data,viewDataName);
|
|
|
|
oSrcFile<<tmp<<"\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2018-10-05 19:17:12 +08:00
|
|
|
static void outputVal(std::ofstream &oSrcFile,const std::string& streamName,const std::string& viewDataName,const std::string &keyName)
|
|
|
|
{
|
|
|
|
oSrcFile<<"{\n";
|
|
|
|
oSrcFile<<" auto & val="<<viewDataName<<"[\""<<keyName<<"\"];\n";
|
|
|
|
oSrcFile<<" if(val.type()==typeid(const char *)){\n";
|
|
|
|
oSrcFile<<" "<<streamName<<"<<any_cast<const char *>(val);\n";
|
|
|
|
oSrcFile<<" }else if(val.type()==typeid(std::string)||val.type()==typeid(const std::string)){\n";
|
|
|
|
oSrcFile<<" "<<streamName<<"<<any_cast<const std::string>(val);\n";
|
|
|
|
oSrcFile<<" }\n";
|
|
|
|
oSrcFile<<"}\n";
|
|
|
|
}
|
2018-05-29 17:21:37 +08:00
|
|
|
static void parseLine(std::ofstream &oSrcFile,std::string& line,const std::string& streamName,const std::string& viewDataName,int &cxx_flag,int returnFlag=1)
|
|
|
|
{
|
|
|
|
std::string::size_type pos(0);
|
|
|
|
if(line.length()==0)
|
|
|
|
return;
|
|
|
|
if(cxx_flag==0)
|
|
|
|
{
|
|
|
|
//find cxx lang begin
|
|
|
|
if((pos=line.find(cxx_lang))!=std::string::npos)
|
|
|
|
{
|
|
|
|
std::string oldLine=line.substr(0,pos);
|
|
|
|
parseLine(oSrcFile,oldLine,streamName,viewDataName,cxx_flag,0);
|
|
|
|
std::string newLine=line.substr(pos+cxx_lang.length());
|
|
|
|
cxx_flag=1;
|
|
|
|
parseLine(oSrcFile,newLine,streamName,viewDataName,cxx_flag,returnFlag);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-05 19:17:12 +08:00
|
|
|
if((pos=line.find(cxx_val_start))!=std::string::npos)
|
|
|
|
{
|
|
|
|
std::string oldLine=line.substr(0,pos);
|
|
|
|
parseLine(oSrcFile,oldLine,streamName,viewDataName,cxx_flag,0);
|
|
|
|
std::string newLine=line.substr(pos+cxx_val_start.length());
|
|
|
|
if((pos=newLine.find(cxx_val_end))!=std::string::npos)
|
|
|
|
{
|
|
|
|
std::string keyName=newLine.substr(0,pos);
|
|
|
|
auto iter=keyName.begin();
|
|
|
|
while(iter!=keyName.end()&&*iter==' ')
|
|
|
|
iter++;
|
|
|
|
auto iterEnd=iter;
|
|
|
|
while(iterEnd!=keyName.end()&&*iterEnd!=' ')
|
|
|
|
iterEnd++;
|
|
|
|
keyName=std::string(iter,iterEnd);
|
|
|
|
outputVal(oSrcFile,streamName,viewDataName,keyName);
|
|
|
|
std::string tailLine=newLine.substr(pos+cxx_val_end.length());
|
|
|
|
parseLine(oSrcFile,tailLine,streamName,viewDataName,cxx_flag,returnFlag);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cerr<<"format err!"<<std::endl;
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2018-05-29 17:21:37 +08:00
|
|
|
else
|
2018-10-05 19:17:12 +08:00
|
|
|
{
|
|
|
|
if(line.length()>0)
|
|
|
|
oSrcFile<<"\t"<<streamName<<" << \""<<replace_all(line,"\"","\\\"");
|
|
|
|
if(returnFlag)
|
|
|
|
oSrcFile<<"\\n\";\n";
|
|
|
|
else
|
|
|
|
oSrcFile<<"\";\n";
|
|
|
|
}
|
|
|
|
|
2018-05-29 17:21:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if((pos=line.find(cxx_end))!=std::string::npos)
|
|
|
|
{
|
|
|
|
std::string newLine=line.substr(0,pos);
|
|
|
|
parseCxxLine(oSrcFile,newLine,streamName,viewDataName);
|
|
|
|
std::string oldLine=line.substr(pos+cxx_end.length());
|
|
|
|
cxx_flag=0;
|
|
|
|
parseLine(oSrcFile,oldLine,streamName,viewDataName,cxx_flag,returnFlag);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parseCxxLine(oSrcFile,line,streamName,viewDataName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void create_view::handleCommand(std::vector<std::string> ¶meters)
|
|
|
|
{
|
2018-06-14 18:51:26 +08:00
|
|
|
for(auto iter=parameters.begin();iter!=parameters.end();iter++)
|
2018-05-29 17:21:37 +08:00
|
|
|
{
|
2018-06-14 18:51:26 +08:00
|
|
|
auto file=*iter;
|
|
|
|
if(file=="-o"||file=="--output")
|
|
|
|
{
|
|
|
|
iter=parameters.erase(iter);
|
|
|
|
if(iter!=parameters.end())
|
|
|
|
{
|
|
|
|
_outputPath=*iter;
|
|
|
|
iter=parameters.erase(iter);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if(file[0]=='-')
|
2018-05-29 17:21:37 +08:00
|
|
|
{
|
|
|
|
std::cout<<ARGS_ERROR_STR<<std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
createViewFiles(parameters);
|
|
|
|
}
|
|
|
|
void create_view::createViewFiles(std::vector<std::string> &cspFileNames)
|
|
|
|
{
|
|
|
|
|
|
|
|
for(auto file:cspFileNames)
|
|
|
|
{
|
|
|
|
std::cout<<"create view:"<<file<<std::endl;
|
|
|
|
createViewFile(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int create_view::createViewFile(const std::string &script_filename)
|
|
|
|
{
|
|
|
|
std::cout<<"create HttpView Class file by "<<script_filename<<std::endl;
|
|
|
|
std::ifstream infile(script_filename.c_str(),std::ifstream::in);
|
|
|
|
if(infile)
|
|
|
|
{
|
|
|
|
std::string::size_type pos = script_filename.rfind(".");
|
|
|
|
if(pos!=std::string::npos)
|
|
|
|
{
|
|
|
|
std::string className=script_filename.substr(0,pos);
|
|
|
|
if((pos=className.rfind("/"))!=std::string::npos)
|
|
|
|
{
|
|
|
|
className=className.substr(pos+1);
|
|
|
|
}
|
|
|
|
std::cout<<"className="<<className<<std::endl;
|
2018-06-14 18:51:26 +08:00
|
|
|
std::string headFileName=_outputPath+"/"+className+".h";
|
|
|
|
std::string sourceFilename=_outputPath+"/"+className+".cc";
|
2018-05-29 17:21:37 +08:00
|
|
|
std::ofstream oHeadFile(headFileName.c_str(),std::ofstream::out);
|
|
|
|
std::ofstream oSourceFile(sourceFilename.c_str(),std::ofstream::out);
|
|
|
|
if(!oHeadFile||!oSourceFile)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
newViewHeaderFile(oHeadFile,className);
|
|
|
|
newViewSourceFile(oSourceFile,className,infile);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cerr<<"can't open file "<<script_filename<<std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void create_view::newViewHeaderFile(std::ofstream &file,const std::string &className)
|
|
|
|
{
|
|
|
|
file<<"//this file is generated by program automatically,don't modify it!\n";
|
|
|
|
file<<"#include <drogon/HttpView.h>\n";
|
|
|
|
file<<"using namespace drogon;\n";
|
|
|
|
file<<"class "<<className<<":public HttpView<"<<className<<">\n";
|
2018-05-30 18:22:46 +08:00
|
|
|
file<<"{\npublic:\n\t"<<className<<"(){};\n\tvirtual ~"<<className<<"(){};\nprotected:\n\t"
|
2018-05-30 21:23:46 +08:00
|
|
|
"virtual HttpResponsePtr genHttpResponse(const HttpViewData&) override;\n};";
|
2018-05-29 17:21:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void create_view::newViewSourceFile(std::ofstream &file,const std::string &className,std::ifstream &infile)
|
|
|
|
{
|
2018-09-07 19:03:31 +08:00
|
|
|
file << "//this file is generated by program(drogon_ctl) automatically,don't modify it!\n";
|
2018-05-29 17:21:37 +08:00
|
|
|
file << "#include \"" << className << ".h\"\n";
|
2018-09-07 19:03:31 +08:00
|
|
|
file <<"#include <drogon/config.h>\n";
|
2018-05-29 17:21:37 +08:00
|
|
|
file <<"#include <string>\n";
|
|
|
|
file <<"#include <sstream>\n";
|
|
|
|
file <<"#include <map>\n";
|
|
|
|
file <<"#include <vector>\n";
|
|
|
|
file <<"#include <set>\n";
|
2018-06-14 18:51:26 +08:00
|
|
|
file <<"#include <iostream>\n";
|
2018-09-07 19:03:31 +08:00
|
|
|
file <<"#include <unordered_map>\n";
|
|
|
|
file <<"#include <unordered_set>\n";
|
|
|
|
file <<"#include <algorithm>\n";
|
|
|
|
file <<"#include <list>\n";
|
|
|
|
file <<"#include <deque>\n";
|
|
|
|
file <<"#include <queue>\n";
|
|
|
|
|
|
|
|
|
2018-05-29 17:21:37 +08:00
|
|
|
file <<"using namespace std;\n";
|
2018-06-14 18:51:26 +08:00
|
|
|
// file <<"void __attribute__((constructor)) startup()\n";
|
|
|
|
// file <<"{std::cout<<\"dynamic lib start to load!\"<<std::endl;}\n";
|
|
|
|
// file <<"void __attribute__((destructor)) shutdown()\n";
|
|
|
|
// file <<"{std::cout<<\"dynamic lib start to unload!\"<<std::endl;}\n";
|
2018-05-29 17:21:37 +08:00
|
|
|
std::string buffer;
|
|
|
|
char line[8192];
|
|
|
|
int import_flag=0;
|
|
|
|
|
|
|
|
|
|
|
|
while(infile.getline(line,sizeof(line)))
|
|
|
|
{
|
|
|
|
buffer=line;
|
|
|
|
|
|
|
|
std::string::size_type pos(0);
|
|
|
|
|
|
|
|
|
|
|
|
if(!import_flag)
|
|
|
|
{
|
|
|
|
std::string lowerBuffer=buffer;
|
|
|
|
std::transform(lowerBuffer.begin(), lowerBuffer.end(), lowerBuffer.begin(), ::tolower);
|
|
|
|
if((pos=lowerBuffer.find(cxx_include))!=std::string::npos)
|
|
|
|
{
|
|
|
|
//std::cout<<"haha find it!"<<endl;
|
|
|
|
std::string newLine=buffer.substr(pos+cxx_include.length());
|
|
|
|
import_flag=1;
|
|
|
|
if((pos=newLine.find(cxx_end))!=std::string::npos)
|
|
|
|
{
|
|
|
|
newLine=newLine.substr(0,pos);
|
|
|
|
file<<newLine<<"\n";
|
|
|
|
break;
|
|
|
|
}else{
|
|
|
|
file<<newLine<<"\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//std::cout<<buffer<<endl;
|
|
|
|
if((pos=buffer.find(cxx_end))!=std::string::npos)
|
|
|
|
{
|
|
|
|
std::string newLine=buffer.substr(0,pos);
|
|
|
|
file<<newLine<<"\n";
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//std::cout<<"to source file"<<buffer<<endl;
|
|
|
|
file<<buffer<<"\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
//std::cout<<"import_flag="<<import_flag<<std::endl;
|
|
|
|
if(import_flag==0)
|
|
|
|
{
|
|
|
|
infile.clear();
|
|
|
|
infile.seekg(0,std::ifstream::beg);
|
|
|
|
}
|
|
|
|
|
|
|
|
//std::cout<<"file pos:"<<infile.tellg()<<std::endl;
|
|
|
|
|
|
|
|
std::string viewDataName=className+"_view_data";
|
2018-05-30 21:23:46 +08:00
|
|
|
file <<"HttpResponsePtr "<<className<<"::genHttpResponse(const HttpViewData& "<<viewDataName<<")\n{\n";
|
2018-05-29 17:21:37 +08:00
|
|
|
//std::string bodyName=className+"_bodystr";
|
|
|
|
std::string streamName=className+"_tmp_stream";
|
|
|
|
|
|
|
|
//oSrcFile <<"\tstd::string "<<bodyName<<";\n";
|
|
|
|
file<<"\tstd::stringstream "<<streamName<<";\n";
|
|
|
|
int cxx_flag=0;
|
|
|
|
while(infile.getline(line,sizeof(line)))
|
|
|
|
{
|
|
|
|
buffer=line;
|
|
|
|
parseLine(file,buffer,streamName,viewDataName,cxx_flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
file<<"\tauto res = HttpResponse::newHttpResponse();\n";
|
2018-09-06 19:06:25 +08:00
|
|
|
file<<"\tres->setStatusCode(HttpResponse::k200OK);\n";
|
2018-05-29 17:21:37 +08:00
|
|
|
file<<"#ifdef CONTENT_TYPE\n";
|
|
|
|
file<<"\tres->setContentTypeCode(CONTENT_TYPE);\n";
|
|
|
|
file<<"#else\n";
|
|
|
|
file<<"\tres->setContentTypeCode(CT_TEXT_HTML);\n";
|
|
|
|
file<<"#endif\n";
|
2018-09-10 18:06:00 +08:00
|
|
|
file<<"\tres->setBody("<<streamName<<".str());\n\treturn res;\n}\n";
|
2018-05-29 17:21:37 +08:00
|
|
|
}
|