forked from mirrors/linphone-iphone
split genwrappers into several smaller pieces
This commit is contained in:
parent
f8ead1facb
commit
c6a96174d0
7 changed files with 767 additions and 620 deletions
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit 706f0b59f818a69c673053e831fa1f19a855f80b
|
||||
Subproject commit ce8c19753495b4ad16a6c5df2bf2bf235443f762
|
||||
|
|
@ -59,7 +59,9 @@ lpc2xml_test_LDADD=\
|
|||
$(top_builddir)/coreapi/liblinphone.la \
|
||||
liblpc2xml.la
|
||||
|
||||
lp_gen_wrappers_SOURCES=genwrappers.cc
|
||||
lp_gen_wrappers_SOURCES=genwrappers.cc \
|
||||
software-desc.cc software-desc.hh \
|
||||
generator.cc generator.hh
|
||||
|
||||
lp_gen_wrappers_LDADD= \
|
||||
$(LIBXML2_LIBS)
|
||||
|
|
|
|||
284
tools/generator.cc
Normal file
284
tools/generator.cc
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2013 Belledonne Communications SARL
|
||||
Simon Morlat (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "generator.hh"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
|
||||
CplusplusGenerator::CplusplusGenerator(){
|
||||
}
|
||||
|
||||
void CplusplusGenerator::generate(Project *proj){
|
||||
list<Class*> classes=proj->getClasses();
|
||||
mCurProj=proj;
|
||||
#ifndef WIN32
|
||||
mkdir(proj->getName().c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH);
|
||||
#else
|
||||
_mkdir(proj->getName().c_str());
|
||||
#endif
|
||||
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&CplusplusGenerator::writeClass),this));
|
||||
}
|
||||
|
||||
void CplusplusGenerator::writeClass(Class *klass){
|
||||
ostringstream filename;
|
||||
|
||||
if (klass->getType()!=Type::Class) return;
|
||||
filename<<mCurProj->getName()<<"/"<<klass->getName()<<".hh";
|
||||
mOutfile.open(filename.str().c_str());
|
||||
if (!mOutfile.is_open()){
|
||||
cerr<<"Could not write into "<<filename.str()<<endl;
|
||||
return;
|
||||
}
|
||||
const list<Method*> &methods=klass->getMethods();
|
||||
mCurClass=klass;
|
||||
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
|
||||
mOutfile<<endl;
|
||||
mOutfile<<"#include <string>"<<endl;
|
||||
mOutfile<<endl;
|
||||
if (!mCurProj->getName().empty())
|
||||
mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
|
||||
mOutfile<<"class "<<klass->getName()<<"{"<<endl;
|
||||
mOutfile<<"public:"<<endl;
|
||||
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&CplusplusGenerator::writeMethod),this));
|
||||
mOutfile<<"}"<<endl<<endl;
|
||||
if (!mCurProj->getName().empty())
|
||||
mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
|
||||
mOutfile<<endl;
|
||||
mOutfile.close();
|
||||
}
|
||||
|
||||
void CplusplusGenerator::writeArgument(Argument *arg, bool isReturn){
|
||||
Type *type=arg->getType();
|
||||
|
||||
if (type->getBasicType()==Type::Class){
|
||||
if (arg->isConst()){
|
||||
mOutfile<<"const ";
|
||||
}
|
||||
mOutfile<<type->getName();
|
||||
if (arg->isPointer())
|
||||
mOutfile<<"*";
|
||||
}else if (type->getBasicType()==Type::Integer){
|
||||
mOutfile<<"int";
|
||||
}else if (type->getBasicType()==Type::Enum){
|
||||
mOutfile<<type->getName();
|
||||
}else if (type->getBasicType()==Type::String){
|
||||
if (!isReturn)
|
||||
mOutfile<<"const std::string &";
|
||||
else
|
||||
mOutfile<<"std::string";
|
||||
}else if (type->getBasicType()==Type::Void){
|
||||
mOutfile<<"void";
|
||||
}else if (type->getBasicType()==Type::Boolean){
|
||||
mOutfile<<"bool";
|
||||
}
|
||||
if (!isReturn && !arg->getName().empty())
|
||||
mOutfile<<" "<<arg->getName();
|
||||
}
|
||||
|
||||
void CplusplusGenerator::writeTabs(int ntabs){
|
||||
int i;
|
||||
for(i=0;i<ntabs;++i)
|
||||
mOutfile<<"\t";
|
||||
}
|
||||
|
||||
void CplusplusGenerator::writeHelpComment(const std::string &comment, int ntabs){
|
||||
size_t i;
|
||||
int curindex=0;
|
||||
writeTabs(ntabs);
|
||||
mOutfile<<" * ";
|
||||
for(i=0;i<comment.size();i++,curindex++){
|
||||
|
||||
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
|
||||
mOutfile<<endl;
|
||||
writeTabs(ntabs);
|
||||
mOutfile<<" * ";
|
||||
curindex=0;
|
||||
}else mOutfile<<comment[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CplusplusGenerator::writeMethod(Method *method){
|
||||
Argument *retarg=method->getReturnArg();
|
||||
const list<Argument*> &args=method->getArgs();
|
||||
list<Argument*>::const_iterator it;
|
||||
|
||||
writeTabs(1);
|
||||
mOutfile<<"/**"<<endl;
|
||||
writeHelpComment(method->getHelp(),1);
|
||||
mOutfile<<endl;
|
||||
writeTabs(1);
|
||||
mOutfile<<"**/"<<endl;
|
||||
|
||||
writeTabs(1);
|
||||
writeArgument(retarg,true);
|
||||
mOutfile<<" "<<method->getName()<<"(";
|
||||
|
||||
for(it=args.begin();it!=args.end();++it){
|
||||
if (it!=args.begin()) mOutfile<<", ";
|
||||
writeArgument(*it);
|
||||
}
|
||||
mOutfile<<")";
|
||||
if (method->isConst()) mOutfile<<"const";
|
||||
mOutfile<<";"<<endl;
|
||||
mOutfile<<endl;
|
||||
}
|
||||
|
||||
|
||||
JavascriptGenerator::JavascriptGenerator(){
|
||||
}
|
||||
|
||||
void JavascriptGenerator::generate(Project *proj){
|
||||
list<Class*> classes=proj->getClasses();
|
||||
mCurProj=proj;
|
||||
#ifndef WIN32
|
||||
unlink(proj->getName().c_str());
|
||||
mkdir(proj->getName().c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH);
|
||||
#else
|
||||
_mkdir(proj->getName().c_str());
|
||||
#endif
|
||||
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&JavascriptGenerator::writeClass),this));
|
||||
}
|
||||
|
||||
void JavascriptGenerator::writeClass(Class *klass){
|
||||
ostringstream filename;
|
||||
|
||||
if (klass->getType()!=Type::Class) return;
|
||||
filename<<mCurProj->getName()<<"/"<<klass->getName()<<".js";
|
||||
mOutfile.open(filename.str().c_str());
|
||||
if (!mOutfile.is_open()){
|
||||
cerr<<"Could not write into "<<filename.str()<<endl;
|
||||
return;
|
||||
}
|
||||
const list<Method*> &methods=klass->getMethods();
|
||||
mCurClass=klass;
|
||||
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
|
||||
mOutfile<<endl;
|
||||
|
||||
//if (!mCurProj->getName().empty())
|
||||
// mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
|
||||
mOutfile<<"/**"<<endl;
|
||||
mOutfile<<" * "<<klass->getHelp()<<endl;
|
||||
mOutfile<<" * @external "<<klass->getName()<<endl;
|
||||
mOutfile<<"**/"<<endl;
|
||||
|
||||
list<Property*> properties=klass->getProperties();
|
||||
for_each(properties.begin(),properties.end(),bind1st(mem_fun(&JavascriptGenerator::writeProperty),this));
|
||||
mOutfile<<endl;
|
||||
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&JavascriptGenerator::writeMethod),this));
|
||||
//if (!mCurProj->getName().empty())
|
||||
// mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
|
||||
mOutfile<<endl;
|
||||
mOutfile.close();
|
||||
}
|
||||
|
||||
void JavascriptGenerator::writeType(Type *type){
|
||||
switch(type->getBasicType()){
|
||||
case Type::Float:
|
||||
case Type::Integer:
|
||||
mOutfile<<"number";
|
||||
break;
|
||||
case Type::String:
|
||||
mOutfile<<"string";
|
||||
break;
|
||||
case Type::Boolean:
|
||||
mOutfile<<"boolean";
|
||||
break;
|
||||
case Type::Class:
|
||||
case Type::Enum:
|
||||
mOutfile<<"external:"<<type->getName();
|
||||
break;
|
||||
case Type::Void:
|
||||
mOutfile<<"void";
|
||||
break;
|
||||
case Type::Callback:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JavascriptGenerator::writeArgument(Argument *arg, bool isReturn){
|
||||
if (!isReturn){
|
||||
mOutfile<<" * @param {";
|
||||
writeType(arg->getType());
|
||||
mOutfile<<"} "<<arg->getName()<<" - "<<arg->getHelp()<<endl;
|
||||
}else{
|
||||
mOutfile<<" * @returns {";
|
||||
writeType(arg->getType());
|
||||
mOutfile<<"} "<<arg->getHelp()<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
void JavascriptGenerator::writeTabs(int ntabs){
|
||||
int i;
|
||||
for(i=0;i<ntabs;++i)
|
||||
mOutfile<<"\t";
|
||||
}
|
||||
|
||||
void JavascriptGenerator::writeHelpComment(const std::string &comment, int ntabs){
|
||||
size_t i;
|
||||
int curindex=0;
|
||||
mOutfile<<" * ";
|
||||
for(i=0;i<comment.size();i++,curindex++){
|
||||
|
||||
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
|
||||
mOutfile<<endl;
|
||||
mOutfile<<" * ";
|
||||
curindex=0;
|
||||
}else mOutfile<<comment[i];
|
||||
}
|
||||
}
|
||||
|
||||
void JavascriptGenerator::writeProperty(Property *prop){
|
||||
mOutfile<<"/**"<<endl;
|
||||
writeHelpComment(prop->getHelp(),0);
|
||||
mOutfile<<endl;
|
||||
mOutfile<<" * @member {";
|
||||
writeType(prop->getType());
|
||||
mOutfile<<"} external:"<<mCurClass->getName()<<"#"<<prop->getName()<<endl;
|
||||
if (prop->getAttribute()==Property::ReadOnly)
|
||||
mOutfile<<" * @readonly"<<endl;
|
||||
mOutfile<<"**/"<<endl;
|
||||
}
|
||||
|
||||
void JavascriptGenerator::writeMethod(Method *method){
|
||||
Argument *retarg=method->getReturnArg();
|
||||
const list<Argument*> &args=method->getArgs();
|
||||
list<Argument*>::const_iterator it;
|
||||
|
||||
if (method->getPropertyBehaviour()!=Method::None) return;
|
||||
if (method->getName()=="ref" || method->getName()=="unref") return;
|
||||
|
||||
mOutfile<<"/**"<<endl;
|
||||
writeHelpComment(method->getHelp(),0);
|
||||
mOutfile<<endl;
|
||||
mOutfile<<" * @function external:"<<mCurClass->getName()<<"#"<<method->getName()<<endl;
|
||||
|
||||
for(it=args.begin();it!=args.end();++it){
|
||||
writeArgument(*it);
|
||||
}
|
||||
writeArgument(retarg,true);
|
||||
mOutfile<<"**/"<<endl;
|
||||
mOutfile<<endl;
|
||||
}
|
||||
66
tools/generator.hh
Normal file
66
tools/generator.hh
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2013 Belledonne Communications SARL
|
||||
Simon Morlat (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef generator_hh
|
||||
#define generator_hh
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "software-desc.hh"
|
||||
|
||||
class OutputGenerator{
|
||||
public:
|
||||
virtual void generate(Project *proj)=0;
|
||||
};
|
||||
|
||||
class CplusplusGenerator : public OutputGenerator{
|
||||
public:
|
||||
CplusplusGenerator();
|
||||
virtual void generate(Project *proj);
|
||||
private:
|
||||
void writeClass(Class *klass);
|
||||
void writeArgument(Argument *arg, bool isReturn=false);
|
||||
void writeTabs(int ntabs);
|
||||
void writeHelpComment(const std::string &comment, int ntabs);
|
||||
void writeMethod(Method *method);
|
||||
ofstream mOutfile;
|
||||
Project *mCurProj;
|
||||
Class *mCurClass;
|
||||
};
|
||||
|
||||
class JavascriptGenerator : public OutputGenerator{
|
||||
public:
|
||||
JavascriptGenerator();
|
||||
virtual void generate(Project *proj);
|
||||
private:
|
||||
void writeClass(Class *klass);
|
||||
void writeType(Type *type);
|
||||
void writeArgument(Argument *arg, bool isReturn=false);
|
||||
void writeTabs(int ntabs);
|
||||
void writeHelpComment(const std::string &comment, int ntabs);
|
||||
void writeProperty(Property *prop);
|
||||
void writeMethod(Method *method);
|
||||
ofstream mOutfile;
|
||||
Project *mCurProj;
|
||||
Class *mCurClass;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -18,632 +18,17 @@ along with this program; if not, write to the Free Software
|
|||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "software-desc.hh"
|
||||
#include "generator.hh"
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
using namespace::std;
|
||||
|
||||
|
||||
class Type{
|
||||
public:
|
||||
enum BasicType{
|
||||
Void,
|
||||
Boolean,
|
||||
Integer,
|
||||
Float,
|
||||
String,
|
||||
Enum,
|
||||
Class,
|
||||
Callback
|
||||
};
|
||||
static const char *sBasicTypeNames[];
|
||||
static Type* addType(BasicType bt, const string &name){
|
||||
Type* ret;
|
||||
if ((ret=mTypes[name])==0){
|
||||
//cout<<"Adding new "<<sBasicTypeNames[(int)bt]<<" type '"<<name<<"'"<<endl;
|
||||
ret=mTypes[name]=new Type(bt,name);
|
||||
}else if (bt!=Class){
|
||||
ret->mBasic=bt;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static Type *getType(const std::string &tname){
|
||||
if (strstr(tname.c_str(),"char")!=0 && strchr(tname.c_str(),'*')!=0){
|
||||
return &sStringType;
|
||||
}else if (tname.find("int")==0){
|
||||
return &sIntegerType;
|
||||
}else if (tname.find("float")==0){
|
||||
return &sFloatType;
|
||||
}else if (tname.find("bool_t")==0){
|
||||
return &sBooleanType;
|
||||
}else if (tname.find("void")!=string::npos){
|
||||
return &sVoidType;
|
||||
}else if (tname.find("enum")==0){
|
||||
return addType(Enum,tname.c_str()+strlen("enum "));
|
||||
}else{/*an object?*/
|
||||
|
||||
string tmp=tname;
|
||||
size_t pos;
|
||||
|
||||
/*really ugly and slow*/
|
||||
|
||||
pos=tmp.find('*');
|
||||
if (pos!=string::npos)
|
||||
tmp.erase(pos,1);
|
||||
|
||||
pos=tmp.find("const");
|
||||
if (pos!=string::npos)
|
||||
tmp.erase(pos,strlen("const"));
|
||||
|
||||
while ((pos=tmp.find(' '))!=string::npos){
|
||||
tmp.erase(pos,1);
|
||||
}
|
||||
return addType(Class,tmp);
|
||||
}
|
||||
cerr<<"Unhandled type name"<<tname<<endl;
|
||||
return NULL;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
BasicType getBasicType()const{
|
||||
return mBasic;
|
||||
}
|
||||
private:
|
||||
BasicType mBasic;
|
||||
string mName;
|
||||
Type(BasicType basic, const std::string &tname="") : mBasic(basic), mName(tname){
|
||||
}
|
||||
static Type sStringType;
|
||||
static Type sIntegerType;
|
||||
static Type sVoidType;
|
||||
static Type sBooleanType;
|
||||
static Type sFloatType;
|
||||
static std::map<string,Type*> mTypes;
|
||||
};
|
||||
|
||||
Type Type::sStringType(Type::String);
|
||||
Type Type::sIntegerType(Type::Integer);
|
||||
Type Type::sVoidType(Type::Void);
|
||||
Type Type::sBooleanType(Type::Boolean);
|
||||
Type Type::sFloatType(Type::Float);
|
||||
std::map<string,Type*> Type::mTypes;
|
||||
const char *Type::sBasicTypeNames[]={
|
||||
"Void",
|
||||
"Boolean",
|
||||
"Integer",
|
||||
"Float",
|
||||
"String",
|
||||
"Enum",
|
||||
"Class",
|
||||
"Callback",
|
||||
"undef",
|
||||
"undef"
|
||||
};
|
||||
|
||||
|
||||
class Argument{
|
||||
public:
|
||||
Argument(Type *type, const string &argname, bool isConst, bool isPointer) : mType(type), mName(argname), mConst(isConst), mPointer(isPointer){
|
||||
if (!isPointer) mConst=false;
|
||||
}
|
||||
Type *getType()const{
|
||||
return mType;
|
||||
}
|
||||
bool isConst()const{
|
||||
return mConst;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
bool isPointer()const{
|
||||
return mPointer;
|
||||
}
|
||||
const string &getHelp()const{
|
||||
return mHelp;
|
||||
}
|
||||
void setHelp(const string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
private:
|
||||
|
||||
Type *mType;
|
||||
string mName;
|
||||
string mHelp;
|
||||
bool mConst;
|
||||
bool mPointer;
|
||||
};
|
||||
|
||||
class Method{
|
||||
public:
|
||||
enum PropertyBehaviour{
|
||||
None,
|
||||
Read,
|
||||
Write
|
||||
};
|
||||
Method(const std::string &uid, Argument* return_arg, const std::string &name, const list<Argument*> &args, bool isConst, bool isStatic){
|
||||
mUid=uid;
|
||||
mReturn=return_arg;
|
||||
mName=name;
|
||||
mArgs=args;
|
||||
mConst=isConst;
|
||||
mStatic=isStatic;
|
||||
analyseProperties();
|
||||
}
|
||||
void setHelp(const std::string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
Argument *getReturnArg()const{
|
||||
return mReturn;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
const list<Argument*> &getArgs()const {
|
||||
return mArgs;
|
||||
}
|
||||
bool isConst()const{
|
||||
return mConst;
|
||||
}
|
||||
bool isStatic()const{
|
||||
return mStatic;
|
||||
}
|
||||
const string &getHelp(){
|
||||
return mHelp;
|
||||
}
|
||||
PropertyBehaviour getPropertyBehaviour()const{
|
||||
return mPropertyBehaviour;
|
||||
}
|
||||
const string &getPropertyName()const{
|
||||
return mPropertyName;
|
||||
}
|
||||
private:
|
||||
void analyseProperties(){
|
||||
size_t enabled_pos;
|
||||
mPropertyBehaviour=None;
|
||||
|
||||
if (mName.find("get")==0 && mArgs.size()==0){
|
||||
mPropertyName=mName.substr(3,string::npos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyName[0]=tolower(mPropertyName[0]);
|
||||
mPropertyBehaviour=Read;
|
||||
}
|
||||
}else if (mName.find("enable")==0 && mArgs.size()==1){
|
||||
mPropertyName=mName.substr(6,string::npos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyName[0]=tolower(mPropertyName[0]);
|
||||
mPropertyBehaviour=Write;
|
||||
}
|
||||
}else if (mName.find("set")==0 && mArgs.size()==1){
|
||||
mPropertyName=mName.substr(3,string::npos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyName[0]=tolower(mPropertyName[0]);
|
||||
mPropertyBehaviour=Write;
|
||||
}
|
||||
}else if ((enabled_pos=mName.rfind("Enabled"))!=string::npos && mArgs.size()==0){
|
||||
size_t goodpos=mName.size()-7;
|
||||
if (enabled_pos==goodpos){
|
||||
mPropertyName=mName.substr(0,goodpos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyBehaviour=Read;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mPropertyBehaviour==None)
|
||||
mPropertyName="";
|
||||
}
|
||||
string mUid;
|
||||
Argument *mReturn;
|
||||
string mName;
|
||||
list<Argument*> mArgs;
|
||||
string mHelp;
|
||||
string mPropertyName; /*if it can be a property*/
|
||||
PropertyBehaviour mPropertyBehaviour;
|
||||
bool mConst;
|
||||
bool mStatic;
|
||||
};
|
||||
|
||||
class Property{
|
||||
public:
|
||||
enum Attribute{
|
||||
ReadOnly,
|
||||
ReadWrite
|
||||
};
|
||||
Property(Attribute attr, const string &name, Type *type, const string &help) : mAttr(attr), mName(name), mType(type), mHelp(help){
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
const string &getHelp()const{
|
||||
return mHelp;
|
||||
}
|
||||
void setHelp(const string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
Attribute getAttribute()const{
|
||||
return mAttr;
|
||||
}
|
||||
void setAttribute(Attribute attr){
|
||||
mAttr=attr;
|
||||
}
|
||||
Type* getType()const{
|
||||
return mType;
|
||||
}
|
||||
private:
|
||||
Attribute mAttr;
|
||||
string mName;
|
||||
Type *mType;
|
||||
string mHelp;
|
||||
};
|
||||
|
||||
/*actually a class or an enum*/
|
||||
class Class{
|
||||
public:
|
||||
Class(const std::string &name): mName(name){
|
||||
}
|
||||
Type::BasicType getType(){
|
||||
return Type::getType(mName)->getBasicType();
|
||||
}
|
||||
void addMethod(Method *method){
|
||||
if (mMethods.find(method->getName())==mMethods.end())
|
||||
mMethods.insert(make_pair(method->getName(),method));
|
||||
}
|
||||
void setHelp(const std::string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
const list<Method*> getMethods()const{
|
||||
list<Method*> ret;
|
||||
map<string,Method*>::const_iterator it;
|
||||
for(it=mMethods.begin();it!=mMethods.end();++it){
|
||||
ret.push_back((*it).second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
const string &getHelp()const{
|
||||
return mHelp;
|
||||
}
|
||||
const list<Property*> getProperties(){
|
||||
list<Property*> ret;
|
||||
map<string,Property*>::const_iterator it;
|
||||
for(it=mProperties.begin();it!=mProperties.end();++it){
|
||||
ret.push_back((*it).second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void computeProperties(){
|
||||
map<string,Method*>::const_iterator it;
|
||||
Property *prop;
|
||||
for (it=mMethods.begin();it!=mMethods.end();++it){
|
||||
Method *m=(*it).second;
|
||||
if (m->getPropertyBehaviour()==Method::Read){
|
||||
prop=mProperties[m->getPropertyName()];
|
||||
if (prop==NULL){
|
||||
prop=new Property(Property::ReadOnly,m->getPropertyName(),m->getReturnArg()->getType(), m->getHelp());
|
||||
mProperties[m->getPropertyName()]=prop;
|
||||
}
|
||||
}else if (m->getPropertyBehaviour()==Method::Write){
|
||||
prop=mProperties[m->getPropertyName()];
|
||||
if (prop==NULL){
|
||||
prop=new Property(Property::ReadWrite,m->getPropertyName(),m->getArgs().front()->getType(), m->getHelp());
|
||||
mProperties[m->getPropertyName()]=prop;
|
||||
}else{
|
||||
prop->setHelp(m->getHelp());
|
||||
prop->setAttribute(Property::ReadWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
map<string,Method*> mMethods;
|
||||
map<string,Property*> mProperties;
|
||||
string mName;
|
||||
string mHelp;
|
||||
};
|
||||
|
||||
class Project{
|
||||
public:
|
||||
Project(const string &name="wrapper") : mName(name){
|
||||
}
|
||||
Class *getClass(const std::string &name){
|
||||
Class *ret;
|
||||
if ((ret=mClasses[name])==NULL){
|
||||
ret=mClasses[name]=new Class(name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
list<Class*> getClasses()const{
|
||||
list<Class*> ret;
|
||||
map<string,Class*>::const_iterator it;
|
||||
for(it=mClasses.begin();it!=mClasses.end();++it){
|
||||
ret.push_back((*it).second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
void analyse(){
|
||||
list<Class*> classes=getClasses();
|
||||
for_each(classes.begin(),classes.end(),mem_fun(&Class::computeProperties));
|
||||
}
|
||||
private:
|
||||
map<string,Class*> mClasses;
|
||||
string mName;
|
||||
};
|
||||
|
||||
class OutputGenerator{
|
||||
public:
|
||||
virtual void generate(Project *proj)=0;
|
||||
};
|
||||
|
||||
class CplusplusGenerator : public OutputGenerator{
|
||||
public:
|
||||
CplusplusGenerator(){
|
||||
}
|
||||
virtual void generate(Project *proj){
|
||||
list<Class*> classes=proj->getClasses();
|
||||
mCurProj=proj;
|
||||
#ifndef WIN32
|
||||
mkdir(proj->getName().c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH);
|
||||
#else
|
||||
_mkdir(proj->getName().c_str());
|
||||
#endif
|
||||
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&CplusplusGenerator::writeClass),this));
|
||||
}
|
||||
private:
|
||||
void writeClass(Class *klass){
|
||||
ostringstream filename;
|
||||
|
||||
if (klass->getType()!=Type::Class) return;
|
||||
filename<<mCurProj->getName()<<"/"<<klass->getName()<<".hh";
|
||||
mOutfile.open(filename.str().c_str());
|
||||
if (!mOutfile.is_open()){
|
||||
cerr<<"Could not write into "<<filename.str()<<endl;
|
||||
return;
|
||||
}
|
||||
const list<Method*> &methods=klass->getMethods();
|
||||
mCurClass=klass;
|
||||
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
|
||||
mOutfile<<endl;
|
||||
mOutfile<<"#include <string>"<<endl;
|
||||
mOutfile<<endl;
|
||||
if (!mCurProj->getName().empty())
|
||||
mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
|
||||
mOutfile<<"class "<<klass->getName()<<"{"<<endl;
|
||||
mOutfile<<"public:"<<endl;
|
||||
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&CplusplusGenerator::writeMethod),this));
|
||||
mOutfile<<"}"<<endl<<endl;
|
||||
if (!mCurProj->getName().empty())
|
||||
mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
|
||||
mOutfile<<endl;
|
||||
mOutfile.close();
|
||||
}
|
||||
void writeArgument(Argument *arg, bool isReturn=false){
|
||||
Type *type=arg->getType();
|
||||
|
||||
if (type->getBasicType()==Type::Class){
|
||||
if (arg->isConst()){
|
||||
mOutfile<<"const ";
|
||||
}
|
||||
mOutfile<<type->getName();
|
||||
if (arg->isPointer())
|
||||
mOutfile<<"*";
|
||||
}else if (type->getBasicType()==Type::Integer){
|
||||
mOutfile<<"int";
|
||||
}else if (type->getBasicType()==Type::Enum){
|
||||
mOutfile<<type->getName();
|
||||
}else if (type->getBasicType()==Type::String){
|
||||
if (!isReturn)
|
||||
mOutfile<<"const std::string &";
|
||||
else
|
||||
mOutfile<<"std::string";
|
||||
}else if (type->getBasicType()==Type::Void){
|
||||
mOutfile<<"void";
|
||||
}else if (type->getBasicType()==Type::Boolean){
|
||||
mOutfile<<"bool";
|
||||
}
|
||||
if (!isReturn && !arg->getName().empty())
|
||||
mOutfile<<" "<<arg->getName();
|
||||
}
|
||||
void writeTabs(int ntabs){
|
||||
int i;
|
||||
for(i=0;i<ntabs;++i)
|
||||
mOutfile<<"\t";
|
||||
}
|
||||
void writeHelpComment(const std::string &comment, int ntabs){
|
||||
size_t i;
|
||||
int curindex=0;
|
||||
writeTabs(ntabs);
|
||||
mOutfile<<" * ";
|
||||
for(i=0;i<comment.size();i++,curindex++){
|
||||
|
||||
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
|
||||
mOutfile<<endl;
|
||||
writeTabs(ntabs);
|
||||
mOutfile<<" * ";
|
||||
curindex=0;
|
||||
}else mOutfile<<comment[i];
|
||||
}
|
||||
}
|
||||
void writeMethod(Method *method){
|
||||
Argument *retarg=method->getReturnArg();
|
||||
const list<Argument*> &args=method->getArgs();
|
||||
list<Argument*>::const_iterator it;
|
||||
|
||||
writeTabs(1);
|
||||
mOutfile<<"/**"<<endl;
|
||||
writeHelpComment(method->getHelp(),1);
|
||||
mOutfile<<endl;
|
||||
writeTabs(1);
|
||||
mOutfile<<"**/"<<endl;
|
||||
|
||||
writeTabs(1);
|
||||
writeArgument(retarg,true);
|
||||
mOutfile<<" "<<method->getName()<<"(";
|
||||
|
||||
for(it=args.begin();it!=args.end();++it){
|
||||
if (it!=args.begin()) mOutfile<<", ";
|
||||
writeArgument(*it);
|
||||
}
|
||||
mOutfile<<")";
|
||||
if (method->isConst()) mOutfile<<"const";
|
||||
mOutfile<<";"<<endl;
|
||||
mOutfile<<endl;
|
||||
}
|
||||
ofstream mOutfile;
|
||||
Project *mCurProj;
|
||||
Class *mCurClass;
|
||||
};
|
||||
|
||||
class JavascriptGenerator : public OutputGenerator{
|
||||
public:
|
||||
JavascriptGenerator(){
|
||||
}
|
||||
virtual void generate(Project *proj){
|
||||
list<Class*> classes=proj->getClasses();
|
||||
mCurProj=proj;
|
||||
#ifndef WIN32
|
||||
unlink(proj->getName().c_str());
|
||||
mkdir(proj->getName().c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH);
|
||||
#else
|
||||
_mkdir(proj->getName().c_str());
|
||||
#endif
|
||||
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&JavascriptGenerator::writeClass),this));
|
||||
}
|
||||
private:
|
||||
void writeClass(Class *klass){
|
||||
ostringstream filename;
|
||||
|
||||
if (klass->getType()!=Type::Class) return;
|
||||
filename<<mCurProj->getName()<<"/"<<klass->getName()<<".js";
|
||||
mOutfile.open(filename.str().c_str());
|
||||
if (!mOutfile.is_open()){
|
||||
cerr<<"Could not write into "<<filename.str()<<endl;
|
||||
return;
|
||||
}
|
||||
const list<Method*> &methods=klass->getMethods();
|
||||
mCurClass=klass;
|
||||
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
|
||||
mOutfile<<endl;
|
||||
|
||||
//if (!mCurProj->getName().empty())
|
||||
// mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
|
||||
mOutfile<<"/**"<<endl;
|
||||
mOutfile<<" * "<<klass->getHelp()<<endl;
|
||||
mOutfile<<" * @external "<<klass->getName()<<endl;
|
||||
mOutfile<<"**/"<<endl;
|
||||
|
||||
list<Property*> properties=klass->getProperties();
|
||||
for_each(properties.begin(),properties.end(),bind1st(mem_fun(&JavascriptGenerator::writeProperty),this));
|
||||
mOutfile<<endl;
|
||||
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&JavascriptGenerator::writeMethod),this));
|
||||
//if (!mCurProj->getName().empty())
|
||||
// mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
|
||||
mOutfile<<endl;
|
||||
mOutfile.close();
|
||||
}
|
||||
void writeType(Type *type){
|
||||
switch(type->getBasicType()){
|
||||
case Type::Float:
|
||||
case Type::Integer:
|
||||
mOutfile<<"number";
|
||||
break;
|
||||
case Type::String:
|
||||
mOutfile<<"string";
|
||||
break;
|
||||
case Type::Boolean:
|
||||
mOutfile<<"boolean";
|
||||
break;
|
||||
case Type::Class:
|
||||
case Type::Enum:
|
||||
mOutfile<<"external:"<<type->getName();
|
||||
break;
|
||||
case Type::Void:
|
||||
mOutfile<<"void";
|
||||
break;
|
||||
case Type::Callback:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void writeArgument(Argument *arg, bool isReturn=false){
|
||||
if (!isReturn){
|
||||
mOutfile<<" * @param {";
|
||||
writeType(arg->getType());
|
||||
mOutfile<<"} "<<arg->getName()<<" - "<<arg->getHelp()<<endl;
|
||||
}else{
|
||||
mOutfile<<" * @returns {";
|
||||
writeType(arg->getType());
|
||||
mOutfile<<"} "<<arg->getHelp()<<endl;
|
||||
}
|
||||
}
|
||||
void writeTabs(int ntabs){
|
||||
int i;
|
||||
for(i=0;i<ntabs;++i)
|
||||
mOutfile<<"\t";
|
||||
}
|
||||
void writeHelpComment(const std::string &comment, int ntabs){
|
||||
size_t i;
|
||||
int curindex=0;
|
||||
mOutfile<<" * ";
|
||||
for(i=0;i<comment.size();i++,curindex++){
|
||||
|
||||
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
|
||||
mOutfile<<endl;
|
||||
mOutfile<<" * ";
|
||||
curindex=0;
|
||||
}else mOutfile<<comment[i];
|
||||
}
|
||||
}
|
||||
void writeProperty(Property *prop){
|
||||
mOutfile<<"/**"<<endl;
|
||||
writeHelpComment(prop->getHelp(),0);
|
||||
mOutfile<<endl;
|
||||
mOutfile<<" * @member {";
|
||||
writeType(prop->getType());
|
||||
mOutfile<<"} external:"<<mCurClass->getName()<<"#"<<prop->getName()<<endl;
|
||||
if (prop->getAttribute()==Property::ReadOnly)
|
||||
mOutfile<<" * @readonly"<<endl;
|
||||
mOutfile<<"**/"<<endl;
|
||||
}
|
||||
void writeMethod(Method *method){
|
||||
Argument *retarg=method->getReturnArg();
|
||||
const list<Argument*> &args=method->getArgs();
|
||||
list<Argument*>::const_iterator it;
|
||||
|
||||
if (method->getPropertyBehaviour()!=Method::None) return;
|
||||
if (method->getName()=="ref" || method->getName()=="unref") return;
|
||||
|
||||
mOutfile<<"/**"<<endl;
|
||||
writeHelpComment(method->getHelp(),0);
|
||||
mOutfile<<endl;
|
||||
mOutfile<<" * @function external:"<<mCurClass->getName()<<"#"<<method->getName()<<endl;
|
||||
|
||||
for(it=args.begin();it!=args.end();++it){
|
||||
writeArgument(*it);
|
||||
}
|
||||
writeArgument(retarg,true);
|
||||
mOutfile<<"**/"<<endl;
|
||||
mOutfile<<endl;
|
||||
}
|
||||
ofstream mOutfile;
|
||||
Project *mCurProj;
|
||||
Class *mCurClass;
|
||||
};
|
||||
|
||||
static bool isSpace(const char *str){
|
||||
for(;*str!='\0';++str){
|
||||
|
|
@ -652,6 +37,7 @@ static bool isSpace(const char *str){
|
|||
return true;
|
||||
}
|
||||
|
||||
//Convenient class for examining node recursively
|
||||
class XmlNode{
|
||||
public:
|
||||
XmlNode(const xmlNode *node=NULL) : mNode(node){
|
||||
|
|
|
|||
40
tools/software-desc.cc
Normal file
40
tools/software-desc.cc
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2013 Belledonne Communications SARL
|
||||
Simon Morlat (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "software-desc.hh"
|
||||
|
||||
Type Type::sStringType(Type::String);
|
||||
Type Type::sIntegerType(Type::Integer);
|
||||
Type Type::sVoidType(Type::Void);
|
||||
Type Type::sBooleanType(Type::Boolean);
|
||||
Type Type::sFloatType(Type::Float);
|
||||
std::map<string,Type*> Type::mTypes;
|
||||
const char *Type::sBasicTypeNames[]={
|
||||
"Void",
|
||||
"Boolean",
|
||||
"Integer",
|
||||
"Float",
|
||||
"String",
|
||||
"Enum",
|
||||
"Class",
|
||||
"Callback",
|
||||
"undef",
|
||||
"undef"
|
||||
};
|
||||
369
tools/software-desc.hh
Normal file
369
tools/software-desc.hh
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2013 Belledonne Communications SARL
|
||||
Simon Morlat (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef software_desc_hh
|
||||
#define software_desc_hh
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
using namespace::std;
|
||||
|
||||
|
||||
class Type{
|
||||
public:
|
||||
enum BasicType{
|
||||
Void,
|
||||
Boolean,
|
||||
Integer,
|
||||
Float,
|
||||
String,
|
||||
Enum,
|
||||
Class,
|
||||
Callback
|
||||
};
|
||||
static const char *sBasicTypeNames[];
|
||||
static Type* addType(BasicType bt, const string &name){
|
||||
Type* ret;
|
||||
if ((ret=mTypes[name])==0){
|
||||
//cout<<"Adding new "<<sBasicTypeNames[(int)bt]<<" type '"<<name<<"'"<<endl;
|
||||
ret=mTypes[name]=new Type(bt,name);
|
||||
}else if (bt!=Class){
|
||||
ret->mBasic=bt;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static Type *getType(const std::string &tname){
|
||||
if (strstr(tname.c_str(),"char")!=0 && strchr(tname.c_str(),'*')!=0){
|
||||
return &sStringType;
|
||||
}else if (tname.find("int")==0){
|
||||
return &sIntegerType;
|
||||
}else if (tname.find("float")==0){
|
||||
return &sFloatType;
|
||||
}else if (tname.find("bool_t")==0){
|
||||
return &sBooleanType;
|
||||
}else if (tname.find("void")!=string::npos){
|
||||
return &sVoidType;
|
||||
}else if (tname.find("enum")==0){
|
||||
return addType(Enum,tname.c_str()+strlen("enum "));
|
||||
}else{/*an object?*/
|
||||
|
||||
string tmp=tname;
|
||||
size_t pos;
|
||||
|
||||
/*really ugly and slow*/
|
||||
|
||||
pos=tmp.find('*');
|
||||
if (pos!=string::npos)
|
||||
tmp.erase(pos,1);
|
||||
|
||||
pos=tmp.find("const");
|
||||
if (pos!=string::npos)
|
||||
tmp.erase(pos,strlen("const"));
|
||||
|
||||
while ((pos=tmp.find(' '))!=string::npos){
|
||||
tmp.erase(pos,1);
|
||||
}
|
||||
return addType(Class,tmp);
|
||||
}
|
||||
cerr<<"Unhandled type name"<<tname<<endl;
|
||||
return NULL;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
BasicType getBasicType()const{
|
||||
return mBasic;
|
||||
}
|
||||
private:
|
||||
BasicType mBasic;
|
||||
string mName;
|
||||
Type(BasicType basic, const std::string &tname="") : mBasic(basic), mName(tname){
|
||||
}
|
||||
static Type sStringType;
|
||||
static Type sIntegerType;
|
||||
static Type sVoidType;
|
||||
static Type sBooleanType;
|
||||
static Type sFloatType;
|
||||
static std::map<string,Type*> mTypes;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Argument{
|
||||
public:
|
||||
Argument(Type *type, const string &argname, bool isConst, bool isPointer) : mType(type), mName(argname), mConst(isConst), mPointer(isPointer){
|
||||
if (!isPointer) mConst=false;
|
||||
}
|
||||
Type *getType()const{
|
||||
return mType;
|
||||
}
|
||||
bool isConst()const{
|
||||
return mConst;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
bool isPointer()const{
|
||||
return mPointer;
|
||||
}
|
||||
const string &getHelp()const{
|
||||
return mHelp;
|
||||
}
|
||||
void setHelp(const string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
private:
|
||||
|
||||
Type *mType;
|
||||
string mName;
|
||||
string mHelp;
|
||||
bool mConst;
|
||||
bool mPointer;
|
||||
};
|
||||
|
||||
class Method{
|
||||
public:
|
||||
enum PropertyBehaviour{
|
||||
None,
|
||||
Read,
|
||||
Write
|
||||
};
|
||||
Method(const std::string &uid, Argument* return_arg, const std::string &name, const list<Argument*> &args, bool isConst, bool isStatic){
|
||||
mUid=uid;
|
||||
mReturn=return_arg;
|
||||
mName=name;
|
||||
mArgs=args;
|
||||
mConst=isConst;
|
||||
mStatic=isStatic;
|
||||
analyseProperties();
|
||||
}
|
||||
void setHelp(const std::string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
Argument *getReturnArg()const{
|
||||
return mReturn;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
const list<Argument*> &getArgs()const {
|
||||
return mArgs;
|
||||
}
|
||||
bool isConst()const{
|
||||
return mConst;
|
||||
}
|
||||
bool isStatic()const{
|
||||
return mStatic;
|
||||
}
|
||||
const string &getHelp(){
|
||||
return mHelp;
|
||||
}
|
||||
PropertyBehaviour getPropertyBehaviour()const{
|
||||
return mPropertyBehaviour;
|
||||
}
|
||||
const string &getPropertyName()const{
|
||||
return mPropertyName;
|
||||
}
|
||||
private:
|
||||
void analyseProperties(){
|
||||
size_t enabled_pos;
|
||||
mPropertyBehaviour=None;
|
||||
|
||||
if (mName.find("get")==0 && mArgs.size()==0){
|
||||
mPropertyName=mName.substr(3,string::npos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyName[0]=tolower(mPropertyName[0]);
|
||||
mPropertyBehaviour=Read;
|
||||
}
|
||||
}else if (mName.find("enable")==0 && mArgs.size()==1){
|
||||
mPropertyName=mName.substr(6,string::npos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyName[0]=tolower(mPropertyName[0]);
|
||||
mPropertyBehaviour=Write;
|
||||
}
|
||||
}else if (mName.find("set")==0 && mArgs.size()==1){
|
||||
mPropertyName=mName.substr(3,string::npos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyName[0]=tolower(mPropertyName[0]);
|
||||
mPropertyBehaviour=Write;
|
||||
}
|
||||
}else if ((enabled_pos=mName.rfind("Enabled"))!=string::npos && mArgs.size()==0){
|
||||
size_t goodpos=mName.size()-7;
|
||||
if (enabled_pos==goodpos){
|
||||
mPropertyName=mName.substr(0,goodpos);
|
||||
if (!mPropertyName.empty()){
|
||||
mPropertyBehaviour=Read;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mPropertyBehaviour==None)
|
||||
mPropertyName="";
|
||||
}
|
||||
string mUid;
|
||||
Argument *mReturn;
|
||||
string mName;
|
||||
list<Argument*> mArgs;
|
||||
string mHelp;
|
||||
string mPropertyName; /*if it can be a property*/
|
||||
PropertyBehaviour mPropertyBehaviour;
|
||||
bool mConst;
|
||||
bool mStatic;
|
||||
};
|
||||
|
||||
class Property{
|
||||
public:
|
||||
enum Attribute{
|
||||
ReadOnly,
|
||||
ReadWrite
|
||||
};
|
||||
Property(Attribute attr, const string &name, Type *type, const string &help) : mAttr(attr), mName(name), mType(type), mHelp(help){
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
const string &getHelp()const{
|
||||
return mHelp;
|
||||
}
|
||||
void setHelp(const string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
Attribute getAttribute()const{
|
||||
return mAttr;
|
||||
}
|
||||
void setAttribute(Attribute attr){
|
||||
mAttr=attr;
|
||||
}
|
||||
Type* getType()const{
|
||||
return mType;
|
||||
}
|
||||
private:
|
||||
Attribute mAttr;
|
||||
string mName;
|
||||
Type *mType;
|
||||
string mHelp;
|
||||
};
|
||||
|
||||
/*actually a class or an enum*/
|
||||
class Class{
|
||||
public:
|
||||
Class(const std::string &name): mName(name){
|
||||
}
|
||||
Type::BasicType getType(){
|
||||
return Type::getType(mName)->getBasicType();
|
||||
}
|
||||
void addMethod(Method *method){
|
||||
if (mMethods.find(method->getName())==mMethods.end())
|
||||
mMethods.insert(make_pair(method->getName(),method));
|
||||
}
|
||||
void setHelp(const std::string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
const list<Method*> getMethods()const{
|
||||
list<Method*> ret;
|
||||
map<string,Method*>::const_iterator it;
|
||||
for(it=mMethods.begin();it!=mMethods.end();++it){
|
||||
ret.push_back((*it).second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
const string &getHelp()const{
|
||||
return mHelp;
|
||||
}
|
||||
const list<Property*> getProperties(){
|
||||
list<Property*> ret;
|
||||
map<string,Property*>::const_iterator it;
|
||||
for(it=mProperties.begin();it!=mProperties.end();++it){
|
||||
ret.push_back((*it).second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void computeProperties(){
|
||||
map<string,Method*>::const_iterator it;
|
||||
Property *prop;
|
||||
for (it=mMethods.begin();it!=mMethods.end();++it){
|
||||
Method *m=(*it).second;
|
||||
if (m->getPropertyBehaviour()==Method::Read){
|
||||
prop=mProperties[m->getPropertyName()];
|
||||
if (prop==NULL){
|
||||
prop=new Property(Property::ReadOnly,m->getPropertyName(),m->getReturnArg()->getType(), m->getHelp());
|
||||
mProperties[m->getPropertyName()]=prop;
|
||||
}
|
||||
}else if (m->getPropertyBehaviour()==Method::Write){
|
||||
prop=mProperties[m->getPropertyName()];
|
||||
if (prop==NULL){
|
||||
prop=new Property(Property::ReadWrite,m->getPropertyName(),m->getArgs().front()->getType(), m->getHelp());
|
||||
mProperties[m->getPropertyName()]=prop;
|
||||
}else{
|
||||
prop->setHelp(m->getHelp());
|
||||
prop->setAttribute(Property::ReadWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
map<string,Method*> mMethods;
|
||||
map<string,Property*> mProperties;
|
||||
string mName;
|
||||
string mHelp;
|
||||
};
|
||||
|
||||
class Project{
|
||||
public:
|
||||
Project(const string &name="wrapper") : mName(name){
|
||||
}
|
||||
Class *getClass(const std::string &name){
|
||||
Class *ret;
|
||||
if ((ret=mClasses[name])==NULL){
|
||||
ret=mClasses[name]=new Class(name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
list<Class*> getClasses()const{
|
||||
list<Class*> ret;
|
||||
map<string,Class*>::const_iterator it;
|
||||
for(it=mClasses.begin();it!=mClasses.end();++it){
|
||||
ret.push_back((*it).second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
void analyse(){
|
||||
list<Class*> classes=getClasses();
|
||||
for_each(classes.begin(),classes.end(),mem_fun(&Class::computeProperties));
|
||||
}
|
||||
private:
|
||||
map<string,Class*> mClasses;
|
||||
string mName;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue