📄 codegenerator.cpp
字号:
// ---------------------------------------------------------------------------// Includes// ---------------------------------------------------------------------------#include "CodeGenerator.hpp"#include <string.h>#include <stdlib.h>#include <assert.h>#include <fstream>#include <iostream>#include <sstream>#include <iomanip>#include <vector>#include <libxml/tree.h>#include <libxml/parser.h>#define HEAD 0#define CPP 1using namespace std;xmlNode *gRootNode = NULL;static void usage(){ cout << "\nUsage:\n" " cg [options] <XML file | List file>\n\n" "Options:\n" " -h Show this help.\n" " -t=xxx Type of generated file [hpp | cpp*].\n\n" " * = Default if not provided explicitly.\n" << endl;}/** * linear search the attributes list to * find the one whose name is n; * @attr : the list of attributes * @n : the expected name * @return : NULL/the value */static const char* matchAttribute(xmlAttr* attr, const char* n) { if (!attr) return NULL; for (xmlAttr* cur = attr; cur; cur = cur->next){ if (strcmp((const char*)cur->name,n) == 0) { xmlNode* value = cur->children; assert(value->type == XML_TEXT_NODE); return (const char*) value->content; } } return NULL;}/** * search the children of gRootNode whose id is n * return the first matched child */static xmlNode* searchNodeById(const char *n){ if (n == NULL) return NULL; xmlNode *child; for (child = gRootNode->children; child; child=child->next) { if (child->type == XML_ELEMENT_NODE && (strcmp(n,matchAttribute(child->properties,"id")) == 0)) return child; } return NULL;}// ---------------------------------------------------------------------------// given the DOMElement n,// return the Tag of the node// ---------------------------------------------------------------------------static const char* getTag(xmlNode* n){ return (const char*)(n->name);}/** * given node and attribute name; return attribute value * if not found, return NULL * @n : the xml element node * @a_name : the expected attribute name * @return : the attribute value / NULL if not found */static const char* getAttribute(xmlNode* n, const char* a_name){ return matchAttribute(n->properties,a_name);}/** * give the type node id, return the complete type name * when the type is pointer or array, the function will be called recursively * @asRef means this type is used as a reference */static string getTypeName(const char* tid, bool asRef=false, bool asConst=false){ xmlNode *n = NULL; string tcat,tname; char len[10]; n = searchNodeById(tid); if (n == NULL) return NULL; tcat = getTag(n); if (tcat == "FundamentalType" ) return "FundamentalType_tmpl<" + string(getAttribute(n,"name")) + ">"; if (tcat == "PointerType") return "PointerType_tmpl<" + getTypeName(getAttribute(n,"type")) + ">"; if (tcat == "ArrayType") { sprintf(len, "%d", atoi(getAttribute(n,"max")) + 1); return "ArrayType_tmpl<" + getTypeName(getAttribute(n,"type")) +"," + len + ">"; } if (tcat == "ReferenceType") { return getTypeName(getAttribute(n,"type"),true); } if (tcat == "CvQualifiedType") { return getTypeName(getAttribute(n,"type"),asRef,true); } if (tcat == "Class" ||tcat == "Typedef" || tcat == "Struct") { // find the namespace; xmlNode *context = searchNodeById(getAttribute(n,"context")); assert(context != NULL); string ns = getAttribute(context,"name"); if (ns == "::") ns = ""; else ns = ns + "::"; if (ns == "") return "ClassType_tmpl<" + string(asConst?"const ":"") + string(getAttribute(n,"name")) + string(asRef?"&":"") + ">"; else //for the class defined by the 3rd party like std return "FundamentalType_tmpl<" + string(asConst?"const ":"") + ns + string(getAttribute(n,"name")) + string(asRef?"&":"") + ">"; } printf("unsupported type defined in this namespace : %s\n", tcat.c_str()); assert(false); return "";}/** * given a node whose tag is <Field ...> * build a Xct_Field structure for convinience; * @n , the xml node whose tag is <Field...> * @return : the built Xct_Field structure; */static Xct_Field* buildField(xmlNode* n) { Xct_Field *f = new Xct_Field(); f->name = string(getAttribute(n,"name")); const char* ch = getAttribute(n,"access"); f->access = string(ch?ch:""); f->type = getTypeName(getAttribute(n,"type")); return f;}/** * given a node whose tag is <Method ...> * build a Xct_Method structure for convinience; * @n , the xml node whose tag is <Method...> * @return : the built Xct_Method structure; */static Xct_Method* buildMethod(xmlNode* node) { Xct_Method *m = new Xct_Method(); m->name = string(getAttribute(node,"name")); const char* ch = getAttribute(node,"access"); m->access = string(ch?ch:""); // return type m->ret_type = getTypeName(getAttribute(node,"returns")); // arguments if (node->children) { for (xmlNode* n = node->children; n; n=n->next) { if (strcmp(getTag(n),"Argument") == 0) m->arg_types.push_back(getTypeName(getAttribute(n,"type"))); } } return m;}/** * given a node whose tag is <Class ...> * build a Xct_Class structure for convinience; * @n , the xml node whose tag is <Class...> * @return : the built Xct_Class structure; */static Xct_Class* buildClass(xmlNode* n) { Xct_Class *c = new Xct_Class(); c->name = getAttribute(n,"name"); char* _id; xmlNode* tmp_n; if ((_id= const_cast<char*>(getAttribute(n,"bases"))) != NULL){ _id = strtok(_id," "); //a bug of gccxml,there is a extra " " at end of _id if ((tmp_n = searchNodeById(_id)) != NULL) c->baseClass = getAttribute(tmp_n,"name"); } char* _members; _members = const_cast<char*>(getAttribute(n,"members")); _id = strtok(_members, " "); while (_id != NULL) { if ((tmp_n = searchNodeById(_id)) != NULL) { if (strcmp(getTag(tmp_n), "Field") == 0) { c->fields.push_back(buildField(tmp_n)); } else if (strcmp(getTag(tmp_n), "Method") == 0) { c->methods.push_back(buildMethod(tmp_n)); } } _id = strtok(NULL, " "); } return c;}/** * given a method, generate teh declartion statement as below * MemberFunctionDcl001<D, FundamentalType_tmpl<void>, FundamentalType_tmpl<int>, &D::m1_void, D_strings::m_m1_void> * */static std::stringgetMemberFunctionDcl(const string& className, Xct_Method* m) { stringstream ss; // MemberFunctionDcl00x ss << "MemberFunctionDcl" << std::setw(3) << std::setfill('0') << m->arg_types.size(); // <D ss << "<" + className; // , return_type ss << ", " + m->ret_type; // , arg_type for (vector<string>::iterator it = m->arg_types.begin(); it != m->arg_types.end(); ++it) ss << "," + *it; // , &D::m1, D_strings::m_m1 ss <<", &" + className + "::" + m->name + ", " + className + "_strings::m_" + m->name; // ">" ss << ">"; return ss.str();}/** * given the Xct_Class * generate the Head file for the class */static void genHpp(Xct_Class* c){ vector<Xct_Field*>::const_iterator p; cout << "#ifndef CPP_REFLECT_" + c->name + "_H\n" << "#define CPP_REFLECT_" + c->name + "_H\n\n\n" << "#include <reflcpp/ArrayType.hpp>\n" << "#include <reflcpp/ClassType_tmpl.hpp>\n" << "#include <reflcpp/FundamentalType.hpp>\n" << "#include <reflcpp/PointerType.hpp>\n\n\n" << "#include <reflcpp/MemberFunctionDcl.hpp>\n" << "#include \"" + c->name + ".hpp\"\n"; if (!c->baseClass.empty()) cout << "#include \"" + c->baseClass + "_reflection.hpp\"\n"; //generator the #include class.hpp int sp,ep; for (p = c->fields.begin(); p != c->fields.end(); ++p) if ((sp = (*p)->type.find("ClassType_tmpl<")) != string::npos){ sp = sp + strlen("ClassType_tmpl<") - 1; ep = sp + 1; while ((*p)->type[ep] != '>') ep++; cout << "#include \"" + (*p)->type.substr(sp + 1, ep - sp - 1) + "_reflection.hpp\"\n"; } //generate #include for classes of method arguments vector<Xct_Method*>::const_iterator method_it; vector<string>::const_iterator arg_it;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -