TClassEdit.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TClassEdit.cxx 35344 2010-09-16 21:34:21Z pcanal $
00002 // Author: Victor Perev   04/10/2003
00003 //         Philippe Canal 05/2004
00004 
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <assert.h>
00008 #include "TClassEdit.h"
00009 #include <ctype.h>
00010 #include "Rstrstream.h"
00011 #include <set>
00012 
00013 // CINT's API.
00014 #include "Api.h"
00015 
00016 namespace std {} using namespace std;
00017 
00018 //______________________________________________________________________________
00019 TClassEdit::TSplitType::TSplitType(const char *type2split, EModType mode) : fName(type2split), fNestedLocation(0)
00020 {
00021    // default constructor
00022    TClassEdit::GetSplit(type2split, fElements, fNestedLocation, mode);
00023 }
00024 
00025 //______________________________________________________________________________
00026 int TClassEdit::TSplitType::IsSTLCont(int testAlloc) const
00027 {
00028    //  type     : type name: vector<list<classA,allocator>,allocator>
00029    //  testAlloc: if true, we test allocator, if it is not default result is negative
00030    //  result:    0          : not stl container
00031    //             abs(result): code of container 1=vector,2=list,3=deque,4=map
00032    //                           5=multimap,6=set,7=multiset
00033    //             positive val: we have a vector or list with default allocator to any depth
00034    //                   like vector<list<vector<int>>>
00035    //             negative val: STL container other than vector or list, or non default allocator
00036    //                           For example: vector<deque<int>> has answer -1
00037 
00038    
00039    if (fElements[0].empty()) return 0;
00040    int numb = fElements.size();
00041    if (!fElements[numb-1].empty() && fElements[numb-1][0]=='*') --numb;
00042    
00043    if ( fNestedLocation ) {
00044       // The type has been defined inside another namespace and/or class
00045       // this couldn't possibly be an STL container
00046       return 0;
00047    }
00048    
00049    int kind = STLKind(fElements[0].c_str());
00050    
00051    if (kind==kVector || kind==kList ) {
00052       
00053       int nargs = STLArgs(kind);
00054       if (testAlloc && (numb-1 > nargs) && !IsDefAlloc(fElements[numb-1].c_str(),fElements[1].c_str())) {
00055          
00056          // We have a non default allocator,
00057          // let's return a negative value.
00058          
00059          kind = -kind;
00060          
00061       } else {
00062          
00063          // We has a default allocator, let's continue to
00064          // look inside the argument list.
00065          int k = TClassEdit::IsSTLCont(fElements[1].c_str(),testAlloc);
00066          if (k<0) kind = -kind;
00067          
00068       }
00069    }
00070    
00071    // We return a negative value for anything which is not a vector or a list.
00072    if(kind>2) kind = - kind;
00073    return kind;
00074 }
00075 
00076 //______________________________________________________________________________
00077 void TClassEdit::TSplitType::ShortType(std::string &answ, int mode)
00078 {
00079    /////////////////////////////////////////////////////////////////////////////
00080    // Return the absolute type of typeDesc into the string answ.
00081    
00082    // E.g.: typeDesc = "class const volatile TNamed**", returns "TNamed**".
00083    // if (mode&1) remove last "*"s                     returns "TNamed"
00084    // if (mode&2) remove default allocators from STL containers
00085    // if (mode&4) remove all     allocators from STL containers
00086    // if (mode&8) return inner class of stl container. list<innerClass>
00087    // if (mode&16) return deapest class of stl container. vector<list<deapest>>
00088    // if (mode&kDropAllDefault) remove default template arguments
00089    /////////////////////////////////////////////////////////////////////////////
00090 
00091    answ.erase(0,999);
00092    int narg = fElements.size();
00093    int tailLoc = 0;
00094    
00095    //      fprintf(stderr,"calling ShortType %d for %s with narg %d\n",mode,typeDesc,narg);
00096    //      {for (int i=0;i<narg;i++) fprintf(stderr,"calling ShortType %d for %s with %d %s \n",
00097    //                                        mode,typeDesc,i,arglist[i].c_str());
00098    //      }
00099    if (fElements[narg-1].empty() == false && fElements[narg-1][0]=='*') {
00100       if ((mode&1)==0) tailLoc = narg-1;
00101       narg--;
00102    }
00103    mode &= (~1);
00104    
00105    if (fNestedLocation) narg--;
00106    
00107    //    fprintf(stderr,"calling ShortType %d for %s with narg %d tail %d\n",imode,typeDesc,narg,tailLoc);
00108    
00109    //kind of stl container
00110    int kind = STLKind(fElements[0].c_str());
00111    int iall = STLArgs(kind);
00112    
00113    // Only class is needed
00114    if (mode&(8|16)) {
00115       while(narg-1>iall) { fElements.pop_back(); narg--;}
00116       if (!fElements[0].empty() && tailLoc) {
00117          tailLoc = 0;
00118       }
00119       fElements[0].erase(0,999);
00120       mode&=(~8);
00121    }
00122    
00123    if (mode & kDropStlDefault) mode |= kDropDefaultAlloc;
00124    
00125    if (kind) {
00126       bool allocRemoved = false;
00127       
00128       if ( mode & (kDropDefaultAlloc|kDropAlloc) ) {
00129          // remove allocators
00130          
00131          
00132          if (narg-1 == iall+1) {
00133             // has an allocator specified
00134             bool dropAlloc = false;
00135             if (mode & kDropAlloc) {
00136                
00137                dropAlloc = true;
00138                
00139             } else if (mode & kDropDefaultAlloc) {
00140                switch (kind) {
00141                   case kVector:
00142                   case kList:
00143                   case kDeque:
00144                   case kSet:
00145                   case kMultiSet:
00146                      dropAlloc = IsDefAlloc(fElements[iall+1].c_str(),fElements[1].c_str());
00147                      break;
00148                   case kMap:
00149                   case kMultiMap:
00150                      dropAlloc = IsDefAlloc(fElements[iall+1].c_str(),fElements[1].c_str(),fElements[2].c_str());
00151                      break;
00152                   default:
00153                      dropAlloc = false;
00154                }
00155                
00156             }
00157             if (dropAlloc) {
00158                narg--;
00159                allocRemoved = true;
00160             }
00161          } else {
00162             // has no allocator specified (hence it is already removed!)
00163             allocRemoved = true;
00164          }
00165       }
00166       
00167       if ( allocRemoved && (mode & kDropStlDefault) && narg-1 == iall) { // remove default comparator
00168          if ( IsDefComp( fElements[iall].c_str(), fElements[1].c_str() ) ) {
00169             narg--;
00170          }
00171       } else if ( mode & kDropComparator ) {
00172          
00173          switch (kind) {
00174             case kVector:
00175             case kList:
00176             case kDeque:
00177                break;
00178             case kSet:
00179             case kMultiSet:
00180             case kMap:
00181             case kMultiMap:
00182                if (!allocRemoved && narg-1 == iall+1) {
00183                   narg--;
00184                   allocRemoved = true;
00185                }
00186                if (narg-1 == iall) narg--;
00187                break;
00188             default:
00189                break;
00190          }
00191       }
00192    }
00193    
00194    //   do the same for all inside
00195    for (int i=1;i<narg; i++) {
00196       if (strchr(fElements[i].c_str(),'<')==0) continue;
00197       bool hasconst = 0==strncmp("const ",fElements[i].c_str(),6);
00198       //NOTE: Should we also check the end of the type for 'const'?
00199       fElements[i] = TClassEdit::ShortType(fElements[i].c_str(),mode);
00200       if (hasconst) {
00201          fElements[i] = "const " + fElements[i];
00202       }
00203    }
00204    
00205    if (!fElements[0].empty()) {answ += fElements[0]; answ +="<";}
00206    
00207    if (mode & kDropAllDefault) {
00208       int nargNonDefault = 0;
00209       std::string nonDefName = answ;
00210       // "superlong" because tLong might turn fName into an even longer name
00211       std::string nameSuperLong = fName;
00212       G__TypedefInfo td;
00213       td.Init(nameSuperLong.c_str());
00214       if (td.IsValid())
00215          nameSuperLong = td.TrueName();
00216       while (++nargNonDefault < narg) {
00217          // If T<a> is a "typedef" (aka default template params)
00218          // to T<a,b> then we can strip the "b".
00219          const char* closeTemplate = " >";
00220          if (nonDefName[nonDefName.length() - 1] != '>')
00221             ++closeTemplate;
00222          td.Init((nonDefName + closeTemplate).c_str());
00223          if (td.IsValid() && nameSuperLong == td.TrueName())
00224             break;
00225          if (nargNonDefault>1) nonDefName += ",";
00226          nonDefName += fElements[nargNonDefault];
00227       }
00228       if (nargNonDefault < narg)
00229          narg = nargNonDefault;
00230    }
00231    
00232    
00233    { for (int i=1;i<narg-1; i++) { answ += fElements[i]; answ+=",";} }
00234    if (narg>1) { answ += fElements[narg-1]; }
00235    
00236    if (!fElements[0].empty()) {
00237       if ( answ.at(answ.size()-1) == '>') {
00238          answ += " >";
00239       } else {
00240          answ += '>';
00241       }
00242    }
00243    if (fNestedLocation) answ += fElements[fNestedLocation];
00244    if (tailLoc) answ += fElements[tailLoc];
00245    
00246 }   
00247    
00248 
00249 
00250 //______________________________________________________________________________
00251 int   TClassEdit::STLKind(const char *type)
00252 {
00253 //      Converts STL container name to number. vector -> 1, etc..
00254 
00255    unsigned char offset = 0;
00256    if (strncmp(type,"std::",5)==0) { offset = 5; }
00257 
00258    static const char *stls[] =                  //container names
00259    {"any","vector","list","deque","map","multimap","set","multiset","bitset",0};
00260 
00261 //              kind of stl container
00262    for(int k=1;stls[k];k++) {if (strcmp(type+offset,stls[k])==0) return k;}
00263    return 0;
00264 }
00265 
00266 //______________________________________________________________________________
00267 int   TClassEdit::STLArgs(int kind)
00268 {
00269 //      Return number of arguments for STL container before allocator
00270 
00271    static const char  stln[] =// min number of container arguments
00272    {    1,       1,     1,      1,    3,         3,    2,        2 };
00273 
00274    return stln[kind];
00275 }
00276 
00277 //______________________________________________________________________________
00278 bool TClassEdit::IsDefAlloc(const char *allocname, const char *classname)
00279 {
00280    // return whether or not 'allocname' is the STL default allocator for type
00281    // 'classname'
00282 
00283    string a = allocname;
00284    if (strncmp(a.c_str(),"std::",5)==0) {
00285       a.erase(0,5);
00286    }
00287    string k = classname;
00288    if (a=="alloc")                              return true;
00289    if (a=="__default_alloc_template<true,0>")   return true;
00290    if (a=="__malloc_alloc_template<0>")         return true;
00291 
00292    string ts("allocator<"); ts += k; ts+=">";
00293    if (a==ts) return true;
00294 
00295    ts = "allocator<"; ts += k; ts+=" >";
00296    if (a==ts) return true;
00297 
00298    return false;
00299 }
00300 
00301 //______________________________________________________________________________
00302 bool TClassEdit::IsDefAlloc(const char *allocname,
00303                             const char *keyclassname,
00304                             const char *valueclassname)
00305 {
00306    // return whether or not 'allocname' is the STL default allocator for a key
00307    // of type 'keyclassname' and a value of type 'valueclassname'
00308 
00309    if (IsDefAlloc(allocname,keyclassname)) return true;
00310 
00311 
00312    string a = allocname;
00313    if (strncmp(a.c_str(),"std::",5)==0) {
00314       a.erase(0,5);
00315    }
00316    string k = keyclassname;
00317    string v = valueclassname;
00318 
00319    string stem("allocator<pair<");
00320    stem += k;
00321    stem += ",";
00322    stem += v;
00323 
00324    string ts(stem);
00325    ts += "> >";
00326 
00327    if (a==ts) return true;
00328 
00329    ts = stem;
00330    ts += " > >";
00331 
00332    if (a==ts) return true;
00333 
00334    stem = "allocator<pair<const ";
00335    stem += k;
00336    stem += ",";
00337    stem += v;
00338 
00339    ts = stem;
00340    ts += "> >";
00341 
00342    if (a==ts) return true;
00343 
00344    ts = stem;
00345    ts += " > >";
00346 
00347    if (a==ts) return true;
00348 
00349    if ( keyclassname[strlen(keyclassname)-1] == '*' ) {
00350 
00351       stem = "allocator<pair<";
00352       stem += k;
00353       stem += "const";
00354       stem += ",";
00355       stem += v;
00356 
00357       string tss(stem);
00358       tss += "> >";
00359 
00360       if (a==tss) return true;
00361 
00362       tss = stem;
00363       tss += " > >";
00364 
00365       if (a==tss) return true;
00366 
00367       stem = "allocator<pair<const ";
00368       stem += k;
00369       stem += "const";
00370       stem += ",";
00371       stem += v;
00372 
00373       tss = stem;
00374       tss += "> >";
00375 
00376       if (a==tss) return true;
00377 
00378       tss = stem;
00379       tss += " > >";
00380 
00381       if (a==tss) return true;
00382 
00383    }
00384 
00385    return false;
00386 }
00387 
00388 //______________________________________________________________________________
00389 bool TClassEdit::IsDefComp(const char *compname, const char *classname)
00390 {
00391    // return whether or not 'compare' is the STL default comparator for type
00392    // 'classname'
00393 
00394    string c = compname;
00395    string k = classname;
00396 
00397    // The default compartor is std::less<classname> which is usually stored
00398    // in CINT as less<classname>
00399 
00400    string stdless("less<");
00401    stdless += k;
00402    if (stdless[stdless.size()-1]=='>') stdless += " >";
00403    else stdless += ">";
00404 
00405    if (stdless == c) return true;
00406 
00407    stdless.insert(0,"std::");
00408    if (stdless == c) return true;
00409 
00410    return false;
00411 }
00412 
00413 //______________________________________________________________________________
00414 string TClassEdit::GetLong64_Name(const string& original)
00415 {
00416    // Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'
00417 
00418    static const char* longlong_s  = "long long";
00419    static const char* ulonglong_s = "unsigned long long";
00420    static const unsigned int longlong_len  = strlen(longlong_s);
00421    static const unsigned int ulonglong_len = strlen(ulonglong_s);
00422 
00423    string result = original;
00424 
00425    int pos = 0;
00426    while( (pos = result.find(ulonglong_s,pos) ) >=0 ) {
00427       result.replace(pos, ulonglong_len, "ULong64_t");
00428    }
00429    pos = 0;
00430    while( (pos = result.find(longlong_s,pos) ) >=0 ) {
00431       result.replace(pos, longlong_len, "Long64_t");
00432    }
00433    return result;
00434 }
00435 
00436 //______________________________________________________________________________
00437 int TClassEdit::GetSplit(const char *type, vector<string>& output, int &nestedLoc, EModType mode)
00438 {
00439    ///////////////////////////////////////////////////////////////////////////
00440    //  Stores in output (after emptying it) the splited type.
00441    //  Stores the location of the tail (nested names) in nestedLoc (0 indicates no tail).
00442    //  Return the number of elements stored.
00443    //
00444    //  First in list is the template name or is empty
00445    //         "vector<list<int>,alloc>**" to "vector" "list<int>" "alloc" "**"
00446    //   or    "TNamed*" to "" "TNamed" "*"
00447    ///////////////////////////////////////////////////////////////////////////
00448 
00449    nestedLoc = 0;
00450    output.clear();
00451    if (strlen(type)==0) return 0;
00452   
00453    string full( mode & kLong64 ? TClassEdit::GetLong64_Name( CleanType(type, 1 /* keepInnerConst */) )
00454                : CleanType(type, 1 /* keepInnerConst */) );
00455    const char *t = full.c_str();
00456    const char *c = strchr(t,'<');
00457 
00458    string stars;
00459    const unsigned int tlen( full.size() );
00460    if ( tlen > 0 ) {
00461       const char *starloc = t + tlen - 1;
00462       if ( (*starloc)=='*' ) {
00463          while( (*(starloc-1))=='*' ) { starloc--; }
00464          stars = starloc;
00465          const unsigned int starlen = strlen(starloc);
00466          full.erase(tlen-starlen,starlen);
00467       }
00468    }
00469 
00470    if (c) {
00471       //we have 'something<'
00472       output.push_back(string(full,0,c-t));
00473 
00474       const char *cursor;
00475       int level = 0;
00476       for(cursor = c + 1; *cursor != '\0' && !(level==0 && *cursor == '>'); ++cursor) {
00477          switch (*cursor) {
00478             case '<': ++level; break;
00479             case '>': --level; break; 
00480             case ',': 
00481                if (level == 0) {
00482                   output.push_back(std::string(c+1,cursor));
00483                   c = cursor;
00484                }
00485                break;
00486          }
00487       }
00488       if (*cursor=='>') {
00489          if (*(cursor-1) == ' ') {
00490             output.push_back(std::string(c+1,cursor-1));
00491          } else {
00492             output.push_back(std::string(c+1,cursor));            
00493          }
00494          // See what's next!
00495          if (*(cursor+1)==':') {
00496             // we have a name specified inside the class/namespace
00497             // For now we keep it in one piece
00498             nestedLoc = output.size();
00499             output.push_back((cursor+1));
00500          }
00501       }
00502    } else {
00503       //empty
00504       output.push_back(string());
00505       output.push_back(full);
00506    }
00507 
00508    if (stars.length()) output.push_back(stars);
00509    return output.size();
00510 }
00511 
00512 
00513 //______________________________________________________________________________
00514 string TClassEdit::CleanType(const char *typeDesc, int mode, const char **tail)
00515 {
00516    ///////////////////////////////////////////////////////////////////////////
00517    //      Cleanup type description, redundant blanks removed
00518    //      and redundant tail ignored
00519    //      return *tail = pointer to last used character
00520    //      if (mode==0) keep keywords
00521    //      if (mode==1) remove keywords outside the template params
00522    //      if (mode>=2) remove the keywords everywhere.
00523    //      if (tail!=0) cut before the trailing *
00524    //
00525    //      The keywords currently are: "const" , "volatile" removed
00526    //
00527    //
00528    //      CleanType(" A<B, C< D, E> > *,F,G>") returns "A<B,C<D,E> >*"
00529    ///////////////////////////////////////////////////////////////////////////
00530 
00531    static const char* remove[] = {"class","const","volatile",0};
00532    static bool isinit = false;
00533    static std::vector<size_t> lengths;
00534    if (!isinit) {
00535       for (int k=0; remove[k]; ++k) {
00536          lengths.push_back(strlen(remove[k]));
00537       }
00538       isinit = true;
00539    }
00540 
00541    string result;
00542    result.reserve(strlen(typeDesc)*2);
00543    int lev=0,kbl=1;
00544    const char* c;
00545 
00546    for(c=typeDesc;*c;c++) {
00547       if (c[0]==' ') {
00548          if (kbl)       continue;
00549          if (!isalnum(c[ 1]) && c[ 1] !='_')    continue;
00550       }
00551       if (kbl && (mode>=2 || lev==0)) { //remove "const' etc...
00552          int done = 0;
00553          int n = (mode) ? 999 : 1;
00554 
00555          // loop on all the keywords we want to remove
00556          for (int k=0; k<n && remove[k]; k++) {
00557             int rlen = lengths[k];
00558 
00559             // Do we have a match
00560             if (strncmp(remove[k],c,rlen)) continue;
00561 
00562             // make sure that the 'keyword' is not part of a longer indentifier
00563             if (isalnum(c[rlen]) || c[rlen]=='_' ||  c[rlen]=='$') continue;
00564 
00565             c+=rlen-1; done = 1; break;
00566          }
00567          if (done) continue;
00568       }
00569 
00570       kbl = (!isalnum(c[ 0]) && c[ 0]!='_' && c[ 0]!='$' && c[0]!='[' && c[0]!=']' && c[0]!='-' && c[0]!='@');
00571       // '@' is special character used only the artifical class name used by ROOT to implement the
00572       // I/O customization rules that requires caching of the input data.
00573       
00574       if (*c == '<')   lev++;
00575       if (lev==0 && !isalnum(*c)) {
00576          if (!strchr("*:_$ []-@",*c)) break;
00577       }
00578       if (c[0]=='>' && result.size() && result[result.size()-1]=='>') result+=" ";
00579 
00580       result += c[0];
00581 
00582       if (*c == '>')    lev--;
00583    }
00584    if(tail) *tail=c;
00585    return result;
00586 }
00587 
00588 //______________________________________________________________________________
00589 string TClassEdit::ShortType(const char *typeDesc, int mode)
00590 {
00591    /////////////////////////////////////////////////////////////////////////////
00592    // Return the absolute type of typeDesc.
00593    // E.g.: typeDesc = "class const volatile TNamed**", returns "TNamed**".
00594    // if (mode&1) remove last "*"s                     returns "TNamed"
00595    // if (mode&2) remove default allocators from STL containers
00596    // if (mode&4) remove all     allocators from STL containers
00597    // if (mode&8) return inner class of stl container. list<innerClass>
00598    // if (mode&16) return deapest class of stl container. vector<list<deapest>>
00599    // if (mode&kDropAllDefault) remove default template arguments
00600    /////////////////////////////////////////////////////////////////////////////
00601 
00602    string answer;
00603 
00604    // get list of all arguments
00605    TSplitType arglist(typeDesc, (EModType) mode);
00606    arglist.ShortType(answer, mode);
00607    
00608    return answer;
00609 }
00610 
00611 //______________________________________________________________________________
00612 bool TClassEdit::IsSTLBitset(const char *classname)
00613 {
00614    // Return true is the name is std::bitset<number> or bitset<number>
00615 
00616    if ( strncmp(classname,"bitset<",strlen("bitset<"))==0) return true;
00617    if ( strncmp(classname,"std::bitset<",strlen("std::bitset<"))==0) return true;
00618    return false;
00619 }
00620 
00621 //______________________________________________________________________________
00622 int TClassEdit::IsSTLCont(const char *type,int testAlloc)
00623 {
00624    //  type     : type name: vector<list<classA,allocator>,allocator>
00625    //  testAlloc: if true, we test allocator, if it is not default result is negative
00626    //  result:    0          : not stl container
00627    //             abs(result): code of container 1=vector,2=list,3=deque,4=map
00628    //                           5=multimap,6=set,7=multiset
00629    //             positive val: we have a vector or list with default allocator to any depth
00630    //                   like vector<list<vector<int>>>
00631    //             negative val: STL container other than vector or list, or non default allocator
00632    //                           For example: vector<deque<int>> has answer -1
00633 
00634    if (strchr(type,'<')==0) return 0;
00635 
00636    TSplitType arglist( type );
00637    return arglist.IsSTLCont(testAlloc);
00638 }
00639 
00640 //______________________________________________________________________________
00641 bool TClassEdit::IsStdClass(const char *classname)
00642 {
00643    // return true if the class belond to the std namespace
00644 
00645    if ( strncmp(classname,"std::",5)==0 ) classname += 5;
00646    if ( strcmp(classname,"string")==0 ) return true;
00647    if ( strncmp(classname,"bitset<",strlen("bitset<"))==0) return true;
00648    if ( strncmp(classname,"pair<",strlen("pair<"))==0) return true;
00649    if ( strcmp(classname,"allocator")==0) return true;
00650    if ( strncmp(classname,"allocator<",strlen("allocator<"))==0) return true;
00651    if ( strncmp(classname,"greater<",strlen("greater<"))==0) return true;
00652    if ( strncmp(classname,"auto_ptr<",strlen("auto_ptr<"))==0) return true;
00653 
00654    return IsSTLCont(classname) != 0;
00655 
00656 }
00657 
00658 
00659 //______________________________________________________________________________
00660 bool TClassEdit::IsVectorBool(const char *name) {
00661    TSplitType splitname( name );
00662 
00663    return ( TClassEdit::STLKind( splitname.fElements[0].c_str() ) == TClassEdit::kVector)
00664       && ( splitname.fElements[1] == "bool" || splitname.fElements[1]=="Bool_t");
00665 };
00666 
00667 //______________________________________________________________________________
00668 namespace {
00669    static bool ShouldReplace(const char *name)
00670    {
00671       // This helper function indicates whether we really want to replace
00672       // a type.
00673 
00674       const char *excludelist [] = {"Char_t","Short_t","Int_t","Long_t","Float_t",
00675                                     "Int_t","Double_t","Double32_t","Float16_t",
00676                                     "UChar_t","UShort_t","UInt_t","ULong_t","UInt_t",
00677                                     "Long64_t","ULong64_t","Bool_t"};
00678 
00679       for (unsigned int i=0; i < sizeof(excludelist)/sizeof(excludelist[0]); ++i) {
00680          if (strcmp(name,excludelist[i])==0) return false;
00681       }
00682 
00683       return true;
00684    }
00685 }
00686 
00687 //______________________________________________________________________________
00688 string TClassEdit::ResolveTypedef(const char *tname, bool resolveAll)
00689 {
00690 
00691    // Return the name of type 'tname' with all its typedef components replaced
00692    // by the actual type its points to
00693    // For example for "typedef MyObj MyObjTypedef;"
00694    //    vector<MyObjTypedef> return vector<MyObj>
00695    //
00696 
00697    if ( tname==0 || tname[0]==0 ) return "";
00698 
00699    if ( strchr(tname,'<')==0 && (tname[strlen(tname)-1]!='*') ) {
00700 
00701       if ( strchr(tname,':')!=0 ) {
00702          // We have a namespace an we have to check it first :(
00703 
00704          int slen = strlen(tname);
00705          for(int k=0;k<slen;++k) {
00706             if (tname[k]==':') {
00707                if (k+1>=slen || tname[k+1]!=':') {
00708                   // we expected another ':'
00709                   return tname;
00710                }
00711                if (k) {
00712                   string base(tname, 0, k);
00713                   if (base=="std") {
00714                      // std is not declared but is also ignored by CINT!
00715                      tname += 5;
00716                      break;
00717                   } else {
00718                      G__ClassInfo info(base.c_str());
00719                      if (!info.IsLoaded()) {
00720                         // the nesting namespace is not declared
00721                         return tname;
00722                      }
00723                   }
00724                }
00725             }
00726          }
00727       }
00728 
00729       // We have a very simple type
00730 
00731       if (resolveAll || ShouldReplace(tname)) {
00732          G__TypedefInfo t;
00733          t.Init(tname);
00734          if (t.IsValid()) return t.TrueName();
00735       }
00736       return tname;
00737    }
00738 
00739    int len = strlen(tname);
00740    string input(tname);
00741 #ifdef R__SSTREAM
00742    // This is the modern implementation
00743    stringstream answ;
00744 #else
00745    // This is deprecated in the C++ standard
00746    strstream answ;
00747 #endif
00748 
00749    int prev = 0;
00750    for (int i=0; i<len; ++i) {
00751       switch (tname[i]) {
00752          case '<':
00753          case '>':
00754          case '*':
00755          case ' ':
00756          case '&':
00757          case ',':
00758          {
00759             char keep = input[i];
00760             string temp( input, prev,i-prev );
00761 
00762             if ( (resolveAll&&(temp!="Double32_t")&&(temp!="Float16_t")) || ShouldReplace(temp.c_str())) {
00763                answ << ResolveTypedef( temp.c_str(), resolveAll);
00764             } else {
00765                answ << temp;
00766             }
00767             answ << keep;
00768             prev = i+1;
00769          }
00770       }
00771    }
00772    const char *last = &(input.c_str()[prev]);
00773    if ((resolveAll&&(strcmp(last,"Double32_t")!=0)&&(strcmp(last,"Float16_t")!=0)) || ShouldReplace(last)) {
00774       answ << ResolveTypedef( last, resolveAll);
00775    } else {
00776       answ << last;
00777    }
00778 #ifndef R__SSTREAM
00779    // Deprecated case
00780    answ << ends;
00781    std::string ret = answ.str();
00782    answ.freeze(false);
00783    return ret;
00784 #else
00785    return answ.str();
00786 #endif
00787 
00788 }
00789 
00790 
00791 //______________________________________________________________________________
00792 string TClassEdit::InsertStd(const char *tname)
00793 {
00794 
00795    // Return the name of type 'tname' with all STL classes prepended by "std::".
00796    // For example for "vector<set<auto_ptr<int*> > >" it returns
00797    //    "std::vector<std::set<std::auto_ptr<int*> > >"
00798    //
00799 
00800    static const char* sSTLtypes[] = {
00801       "allocator",
00802       "auto_ptr",
00803       "bad_alloc",
00804       "bad_cast",
00805       "bad_exception",
00806       "bad_typeid",
00807       "basic_filebuf",
00808       "basic_fstream",
00809       "basic_ifstream",
00810       "basic_ios",
00811       "basic_iostream",
00812       "basic_istream",
00813       "basic_istringstream",
00814       "basic_ofstream",
00815       "basic_ostream",
00816       "basic_ostringstream",
00817       "basic_streambuf",
00818       "basic_string",
00819       "basic_stringbuf",
00820       "basic_stringstream",
00821       "binary_function",
00822       "binary_negate",
00823       "bitset",
00824       "char_traits",
00825       "codecvt_byname",
00826       "codecvt",
00827       "collate",
00828       "collate_byname",
00829       "compare",
00830       "complex",
00831       "ctype_byname",
00832       "ctype",
00833       "deque",
00834       "divides",
00835       "domain_error",
00836       "equal_to",
00837       "exception",
00838       "fpos",
00839       "greater_equal",
00840       "greater",
00841       "gslice_array",
00842       "gslice",
00843       "indirect_array",
00844       "invalid_argument",
00845       "ios_base",
00846       "istream_iterator",
00847       "istreambuf_iterator",
00848       "istrstream",
00849       "iterator_traits",
00850       "iterator",
00851       "length_error",
00852       "less_equal",
00853       "less",
00854       "list",
00855       "locale",
00856       "localedef utility",
00857       "locale utility",
00858       "logic_error",
00859       "logical_and",
00860       "logical_not",
00861       "logical_or",
00862       "map",
00863       "mask_array",
00864       "mem_fun",
00865       "mem_fun_ref",
00866       "messages",
00867       "messages_byname",
00868       "minus",
00869       "modulus",
00870       "money_get",
00871       "money_put",
00872       "moneypunct",
00873       "moneypunct_byname",
00874       "multimap",
00875       "multiplies",
00876       "multiset",
00877       "negate",
00878       "not_equal_to",
00879       "num_get",
00880       "num_put",
00881       "numeric_limits",
00882       "numpunct",
00883       "numpunct_byname",
00884       "ostream_iterator",
00885       "ostreambuf_iterator",
00886       "ostrstream",
00887       "out_of_range",
00888       "overflow_error",
00889       "pair",
00890       "plus",
00891       "pointer_to_binary_function",
00892       "pointer_to_unary_function",
00893       "priority_queue",
00894       "queue",
00895       "range_error",
00896       "raw_storage_iterator",
00897       "reverse_iterator",
00898       "runtime_error",
00899       "set",
00900       "slice_array",
00901       "slice",
00902       "stack",
00903       "string",
00904       "strstream",
00905       "strstreambuf",
00906       "time_get_byname",
00907       "time_get",
00908       "time_put_byname",
00909       "time_put",
00910       "unary_function",
00911       "unary_negate",
00912       "underflow_error",
00913       "valarray",
00914       "vector",
00915       "wstring"
00916    };
00917    static set<string> sSetSTLtypes;
00918 
00919    if (tname==0 || tname[0]==0) return "";
00920 
00921    if (sSetSTLtypes.empty()) {
00922       // set up static set
00923       const size_t nSTLtypes = sizeof(sSTLtypes) / sizeof(const char*);
00924       for (size_t i = 0; i < nSTLtypes; ++i)
00925          sSetSTLtypes.insert(sSTLtypes[i]);
00926    }
00927 
00928    size_t b = 0;
00929    size_t len = strlen(tname);
00930    string ret;
00931    ret.reserve(len + 20); // expect up to 4 extra "std::" to insert
00932    string id;
00933    while (b < len) {
00934       // find beginning of next identifier
00935       bool precScope = false; // whether the identifier was preceded by "::"
00936       while (!(isalnum(tname[b]) || tname[b] == '_') && b < len) {
00937          precScope = (b < len - 2) && (tname[b] == ':') && (tname[b + 1] == ':');
00938          if (precScope) {
00939             ret += "::";
00940             b += 2;
00941          } else
00942             ret += tname[b++];
00943       }
00944 
00945       // now b is at the beginning of an identifier or len
00946       size_t e = b;
00947       // find end of identifier
00948       id.clear();
00949       while (e < len && (isalnum(tname[e]) || tname[e] == '_'))
00950          id += tname[e++];
00951       if (!id.empty()) {
00952          if (!precScope) {
00953             set<string>::const_iterator iSTLtype = sSetSTLtypes.find(id);
00954             if (iSTLtype != sSetSTLtypes.end())
00955                ret += "std::";
00956          }
00957 
00958          ret += id;
00959          b = e;
00960       }
00961    }
00962    return ret;
00963 }
00964 
00965 

Generated on Tue Jul 5 14:11:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1