📄 util.cpp
字号:
}}//----------------------------------------------------------------------------/*! takes the \a buf of the given lenght \a len and converts CR LF (DOS) * or CR (MAC) line ending to LF (Unix). Returns the length of the * converted content (i.e. the same as \a len (Unix, MAC) or * smaller (DOS). */int filterCRLF(char *buf,int len){ int src = 0; // source index int dest = 0; // destination index char c; // current character while (src<len) { c = buf[src++]; // Remember the processed character. if (c == '\r') // CR to be solved (MAC, DOS) { c = '\n'; // each CR to LF if (src<len && buf[src] == '\n') ++src; // skip LF just after CR (DOS) } buf[dest++] = c; // copy the (modified) character to dest } return dest; // length of the valid part of the buf}/*! reads a file with name \a name and returns it as a string. If \a filter * is TRUE the file will be filtered by any user specified input filter. * If \a name is "-" the string will be read from standard input. */QCString fileToString(const char *name,bool filter){ if (name==0 || name[0]==0) return 0; QFile f; bool fileOpened=FALSE; if (name[0]=='-' && name[1]==0) // read from stdin { fileOpened=f.open(IO_ReadOnly,stdin); if (fileOpened) { const int bSize=4096; QCString contents(bSize); int totalSize=0; int size; while ((size=f.readBlock(contents.data()+totalSize,bSize))==bSize) { totalSize+=bSize; contents.resize(totalSize+bSize); } totalSize = filterCRLF(contents.data(),totalSize+size)+2; contents.resize(totalSize); contents.at(totalSize-2)='\n'; // to help the scanner contents.at(totalSize-1)='\0'; return contents; } } else // read from file { QFileInfo fi(name); if (!fi.exists() || !fi.isFile()) { err("Error: file `%s' not found\n",name); return ""; } if (Config_getString("INPUT_FILTER").isEmpty() || !filter) { f.setName(name); fileOpened=f.open(IO_ReadOnly); if (fileOpened) { int fsize=f.size(); QCString contents(fsize+2); f.readBlock(contents.data(),fsize); if (fsize==0 || contents[fsize-1]=='\n') contents[fsize]='\0'; else contents[fsize]='\n'; // to help the scanner contents[fsize+1]='\0'; f.close(); int newSize = filterCRLF(contents.data(),fsize+2); if (newSize!=fsize+2) { contents.resize(newSize); } return contents; } } else // filter the input { QCString cmd=Config_getString("INPUT_FILTER")+" "+name; FILE *f=popen(cmd,"r"); if (!f) { err("Error: could not execute filter %s\n",Config_getString("INPUT_FILTER").data()); return ""; } const int bSize=4096; QCString contents(bSize); int totalSize=0; int size; while ((size=fread(contents.data()+totalSize,1,bSize,f))==bSize) { totalSize+=bSize; contents.resize(totalSize+bSize); } totalSize = filterCRLF(contents.data(),totalSize+size)+2; contents.resize(totalSize); contents.at(totalSize-2)='\n'; // to help the scanner contents.at(totalSize-1)='\0'; pclose(f); return contents; } } if (!fileOpened) { err("Error: cannot open file `%s' for reading\n",name); } return "";}QCString dateToString(bool includeTime){ if (includeTime) { return convertToQCString(QDateTime::currentDateTime().toString()); } else { const QDate &d=QDate::currentDate(); QCString result; result.sprintf("%d %s %d", d.day(), convertToQCString(d.monthName(d.month())).data(), d.year()); return result; } //QDate date=dt.date(); //QTime time=dt.time(); //QCString dtString; //dtString.sprintf("%02d:%02d, %04d/%02d/%02d", // time.hour(),time.minute(),date.year(),date.month(),date.day()); //return dtString;}//----------------------------------------------------------------------// recursive function that returns the number of branches in the // inheritance tree that the base class `bcd' is below the class `cd'int minClassDistance(ClassDef *cd,ClassDef *bcd,int level){ if (cd==bcd) return level; BaseClassListIterator bcli(*cd->baseClasses()); int m=maxInheritanceDepth; for ( ; bcli.current() ; ++bcli) { m=QMIN(minClassDistance(bcli.current()->classDef,bcd,level+1),m); } return m;}//static void printArgList(ArgumentList *al)//{// if (al==0) return;// ArgumentListIterator ali(*al);// Argument *a;// printf("(");// for (;(a=ali.current());++ali)// {// printf("t=`%s' n=`%s' v=`%s' ",a->type.data(),!a->name.isEmpty()>0?a->name.data():"",!a->defval.isEmpty()>0?a->defval.data():""); // }// printf(")");//}// strip any template specifiers that follow className in string sstatic QCString trimTemplateSpecifiers( const QCString &namespaceName, const QCString &className, const QCString &s){ //printf("trimTemplateSpecifiers(%s,%s,%s)\n",namespaceName.data(),className.data(),s.data()); QCString scopeName=mergeScopes(namespaceName,className); ClassDef *cd=getClass(scopeName); if (cd==0) return s; // should not happen, but guard anyway. QCString result=s; int i=className.length()-1; if (i>=0 && className.at(i)=='>') // template specialization { // replace unspecialized occurrences in s, with their specialized versions. int count=1; int cl=i+1; while (i>=0) { char c=className.at(i); if (c=='>') count++,i--; else if (c=='<') { count--; if (count==0) break; } else i--; } QCString unspecClassName=className.left(i); int l=i; int p=0; while ((i=result.find(unspecClassName,p))!=-1) { if (result.at(i+l)!='<') // unspecialized version { result=result.left(i)+className+result.right(result.length()-i-l); l=cl; } p=i+l; } } //printf("result after specialization: %s\n",result.data()); QCString qualName=cd->qualifiedNameWithTemplateParameters(); //printf("QualifiedName = %s\n",qualName.data()); // We strip the template arguments following className (if any) if (!qualName.isEmpty()) // there is a class name { int is,ps=0; int p=0,l,i; while ((is=getScopeFragment(qualName,ps,&l))!=-1) { QCString qualNamePart = qualName.right(qualName.length()-is); //printf("qualNamePart=%s\n",qualNamePart.data()); while ((i=result.find(qualNamePart,p))!=-1) { int ql=qualNamePart.length(); result=result.left(i)+cd->name()+result.right(result.length()-i-ql); p=i+cd->name().length(); } ps=is+l; } } //printf("result=%s\n",result.data()); return result;}// removes the (one and only) occurrence of name:: from s.static QCString trimScope(const QCString &name,const QCString &s){ int scopeOffset=name.length(); QCString result=s; do // for each scope { QCString tmp; QCString scope=name.left(scopeOffset)+"::"; //printf("Trying with scope=`%s'\n",scope.data()); int i,p=0; while ((i=result.find(scope,p))!=-1) // for each occurrence { tmp+=result.mid(p,i-p); // add part before pattern p=i+scope.length(); } tmp+=result.right(result.length()-p); // add trailing part scopeOffset=name.findRev("::",scopeOffset-1); result = tmp; } while (scopeOffset>0); //printf("trimScope(name=%s,scope=%s)=%s\n",name.data(),s.data(),result.data()); return result;}void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0){ //printf("trimBaseClassScope level=%d `%s'\n",level,s.data()); BaseClassListIterator bcli(*bcl); BaseClassDef *bcd; for (;(bcd=bcli.current());++bcli) { ClassDef *cd=bcd->classDef; //printf("Trying class %s\n",cd->name().data()); int spos=s.find(cd->name()+"::"); if (spos!=-1) { s = s.left(spos)+s.right( s.length()-spos-cd->name().length()-2 ); } //printf("base class `%s'\n",cd->name().data()); if (cd->baseClasses()->count()>0) trimBaseClassScope(cd->baseClasses(),s,level+1); }}/*! if either t1 or t2 contains a namespace scope, then remove that * scope. If neither or both have a namespace scope, t1 and t2 remain * unchanged. */static void trimNamespaceScope(QCString &t1,QCString &t2,const QCString &nsName){ int p1=t1.length(); int p2=t2.length(); for (;;) { int i1=p1==0 ? -1 : t1.findRev("::",p1); int i2=p2==0 ? -1 : t2.findRev("::",p2); if (i1==-1 && i2==-1) { return; } if (i1!=-1 && i2==-1) // only t1 has a scope { QCString scope=t1.left(i1); int so=nsName.length(); do { QCString fullScope=nsName.left(so); if (!fullScope.isEmpty() && !scope.isEmpty()) fullScope+="::"; fullScope+=scope; if (!fullScope.isEmpty() && Doxygen::namespaceSDict[fullScope]!=0) // scope is a namespace { t1 = t1.right(t1.length()-i1-2); return; } if (so==0) { so=-1; } else if ((so=nsName.findRev("::",so-1))==-1) { so=0; } } while (so>=0); } else if (i1==-1 && i2!=-1) // only t2 has a scope { QCString scope=t2.left(i2); int so=nsName.length(); do { QCString fullScope=nsName.left(so); if (!fullScope.isEmpty() && !scope.isEmpty()) fullScope+="::"; fullScope+=scope; if (!fullScope.isEmpty() && Doxygen::namespaceSDict[fullScope]!=0) // scope is a namespace { t2 = t2.right(t2.length()-i2-2); return; } if (so==0) { so=-1; } else if ((so=nsName.findRev("::",so-1))==-1) { so=0; } } while (so>=0); } p1 = QMAX(i1-2,0); p2 = QMAX(i2-2,0); }}/*! According to the C++ spec and Ivan Vecerina: Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. So the following example, show what is stripped by this routine for const. The same is done for volatile. \code const T param -> T param // not relevant const T& param -> const T& param // const needed T* const param -> T* param // not relevant const T* param -> const T* param // const needed \endcode */void stripIrrelevantConstVolatile(QCString &s){ int i; if (s=="const") { s.resize(0); return; } if (s=="volatile") { s.resize(0); return; } i = s.find("const "); if (i!=-1) { // no & or * after the const if (s.find('*',i+6)==-1 && s.find('&',i+6)==-1) { s=s.left(i)+s.right(s.length()-i-6); } } i = s.find("volatile "); if (i!=-1) { // no & or * after the volatile if (s.find('*',i+9)==-1 && s.find('&',i+9)==-1) { s=s.left(i)+s.right(s.length()-i-9); } }}#if 0 // should be done differentlystatic QCString resolveTypeDefs(const QCString &s){ QCString result; static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*"); int p=0,l,i; while ((i=re.match(s,p,&l))!=-1) { result += s.mid(p,i-p); result += resolveTypeDef(s.mid(i,l)); p=i+l; } result+=s.right(s.length()-p); return result;}#endif// a bit of debug support for matchArguments#define MATCH#define NOMATCH//#define MATCH printf("Match at line %d\n",__LINE__);//#define NOMATCH printf("Nomatch at line %d\n",__LINE__);static bool matchArgument(const Argument *srcA,const Argument *dstA, const QCString &className, const QCString &namespaceName, NamespaceList *usingNamespaces, ClassList *usingClasses){ //printf("match argument start %s:%s <-> %s:%s\n", // srcA->type.data(),srcA->name.data(), // dstA->type.data(),dstA->name.data()); // TODO: resolve any typedefs names that are part of srcA->type // before matching. This should use className and namespaceName
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -