TMakeProject.cxx

Go to the documentation of this file.
00001 // @(#)root/io:$Id: TMakeProject.cxx 36707 2010-11-16 20:00:58Z pcanal $
00002 // Author: Rene Brun   12/10/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TMakeProject                                                         //
00015 //                                                                      //
00016 // Helper class implementing the TFile::MakeProject.                    //
00017 //                                                                      //
00018 //////////////////////////////////////////////////////////////////////////
00019 
00020 #include <ctype.h>
00021 #include "TMakeProject.h"
00022 #include "TClass.h"
00023 #include "TClassEdit.h"
00024 #include "TROOT.h"
00025 #include "TMD5.h"
00026 #include "TStreamerInfo.h"
00027 #include "TStreamerElement.h"
00028 #include "TError.h"
00029 
00030 //______________________________________________________________________________
00031 void TMakeProject::AddUniqueStatement(FILE *fp, const char *statement, char *inclist)
00032 {
00033    // Add an include statement, if it has not already been added.
00034 
00035    if (!strstr(inclist, statement)) {
00036       if (strlen(inclist)+strlen(statement) >= 50000) {
00037          Fatal("AddUniqueStatement","inclist too short need %u instead of 500000",UInt_t(strlen(inclist)+strlen(statement)));
00038       }
00039       strcat(inclist, statement);
00040       fprintf(fp, "%s", statement);
00041    }
00042 }
00043 
00044 //______________________________________________________________________________
00045 void TMakeProject::AddInclude(FILE *fp, const char *header, Bool_t system, char *inclist)
00046 {
00047    // Add an include statement, if it has not already been added.
00048 
00049    TString what;
00050    if (system) {
00051       what.Form("#include <%s>\n", header);
00052    } else {
00053       what.Form("#include \"%s\"\n", header);
00054    }
00055    AddUniqueStatement(fp, what.Data(), inclist);
00056 }
00057 
00058 //______________________________________________________________________________
00059 void TMakeProject::ChopFileName(TString &name, Int_t limit)
00060 {
00061    // Chop the name by replacing the ending (before a potential extension) with
00062    // a md5 summary of the name.
00063 
00064    if (name.Length() >= limit) {
00065       bool has_extension = (strcmp(name.Data() + name.Length() - 2, ".h") == 0);
00066       if (has_extension) {
00067          name.Remove(name.Length()-2);
00068       }
00069       TMD5 md;
00070       md.Update((const UChar_t*)name.Data(),name.Length());
00071       md.Final();
00072       name.Remove( limit - 32 - 5); // Chop the part longer than 255 and keep space for the md5 and leave space for an extension
00073       name.Append( md.AsString() );
00074       if (has_extension) {
00075          name.Append( ".h" );
00076       }
00077    }
00078 
00079 }
00080 
00081 //______________________________________________________________________________
00082 TString TMakeProject::GetHeaderName(const char *in_name, const TList *extrainfos, Bool_t includeNested)
00083 {
00084    //Return the header name containing the description of name
00085    TString result;
00086    std::string strname( TClassEdit::GetLong64_Name( in_name ) );
00087    const char *name = strname.c_str();
00088    Int_t len = strlen(name);
00089    Int_t nest = 0;
00090    for (Int_t i = 0; i < len; ++i) {
00091       switch (name[i]) {
00092          case '<':
00093             ++nest;
00094             result.Append('_');
00095             break;
00096          case '>':
00097             --nest;
00098             result.Append('_');
00099             break;
00100          case ':':
00101             if (nest == 0 && name[i+1] == ':') {
00102                TString nsname(name, i);
00103                TClass *cl = gROOT->GetClass(nsname);
00104                Bool_t definedInParent = !includeNested && cl && (cl->Size() != 0 || (cl->Size()==0 && cl->GetClassInfo()==0 /*empty 'base' class on file*/));
00105                if (!definedInParent && cl==0 && extrainfos!=0) {
00106                   TStreamerInfo *clinfo = (TStreamerInfo*)extrainfos->FindObject(nsname);
00107                   if (clinfo && clinfo->GetClassVersion() == -5) {
00108                      definedInParent = kTRUE;
00109                   }
00110                }
00111                if (definedInParent) {
00112                   // The requested class is actually nested inside
00113                   // the class whose name we already 'copied' to
00114                   // result.  The declaration will be in the same
00115                   // header file as the outer class.
00116                   if (strcmp(name + strlen(name) - 2, ".h") == 0) {
00117                      result.Append(".h");
00118                   }
00119                   ChopFileName(result,255);
00120                   return result;
00121                }
00122             }
00123             result.Append('_');
00124             break;
00125          case ',':
00126          case '*':
00127          case '[':
00128          case ']':
00129          case ' ':
00130          case '(':
00131          case ')':
00132             result.Append('_');
00133             break;
00134          case '/':
00135          case '\\':
00136          default:
00137             result.Append(name[i]);
00138       }
00139    }
00140    ChopFileName(result,255);
00141    return result;
00142 }
00143 
00144 //______________________________________________________________________________
00145 UInt_t TMakeProject::GenerateClassPrefix(FILE *fp, const char *clname, Bool_t top, TString &protoname,
00146       UInt_t *numberOfClasses, Int_t implementEmptyClass, Bool_t needGenericTemplate)
00147 {
00148    // Write the start of the class (forward) declaration.
00149    // if 'implementEmptyClass' is 3 then never add a #pragma
00150 
00151    // First open the namespace (if any)
00152    Int_t numberOfNamespaces = 0;
00153    const char *fullname = clname;
00154 
00155    Bool_t istemplate = kFALSE;
00156    if (strchr(clname, ':')) {
00157       // We might have a namespace in front of the classname.
00158       Int_t len = strlen(clname);
00159       const char *name = clname;
00160       UInt_t nest = 0;
00161       for (Int_t cur = 0; cur < len; ++cur) {
00162          switch (clname[cur]) {
00163             case '<':
00164                ++nest;
00165                istemplate = kTRUE;
00166                break;
00167             case '>':
00168                --nest;
00169                break;
00170             case ':': {
00171                   if (nest == 0 && clname[cur+1] == ':') {
00172                      // We have a scope
00173                      TString nsname(clname, cur);
00174                      TClass *cl = gROOT->GetClass(nsname);
00175                      if (top) {
00176                         if (cl == 0 || (cl && cl->Size() == 0)) {
00177                            TString last(name, cur - (name - clname));
00178                            if ((numberOfClasses == 0 || *numberOfClasses == 0) && strchr(last.Data(), '<') == 0) {
00179                               fprintf(fp, "namespace %s {\n", last.Data());
00180                               ++numberOfNamespaces;
00181                            } else {
00182                               TString headername(GetHeaderName(last,0));
00183                               fprintf(fp, "#ifndef %s_h\n", headername.Data());
00184                               fprintf(fp, "#define %s_h\n", headername.Data());
00185                               GenerateClassPrefix(fp, last.Data(), top, protoname, 0);
00186                               fprintf(fp, "{\n");
00187                               fprintf(fp, "public:\n");
00188                               if (numberOfClasses) ++(*numberOfClasses);
00189                               istemplate = kFALSE;
00190                            }
00191                            name = clname + cur + 2;
00192                         }
00193                      } else {
00194                         istemplate = kFALSE;
00195                         name = clname + cur + 2;
00196                      }
00197                   }
00198                   break;
00199                }
00200          }
00201       }
00202       clname = name;
00203    } else {
00204       istemplate = strstr(clname, "<") != 0;
00205    }
00206 
00207    protoname = clname;
00208 
00209    if (implementEmptyClass==1) {
00210       TString headername(GetHeaderName(fullname,0));
00211       fprintf(fp, "#ifndef %s_h\n", headername.Data());
00212       fprintf(fp, "#define %s_h\n", headername.Data());
00213    }
00214    if (istemplate) {
00215       std::vector<const char*> argtype;
00216 
00217       Ssiz_t pos = protoname.First('<');
00218       UInt_t nparam = 1;
00219       if (pos != kNPOS) {
00220          if (isdigit(protoname[pos+1])) {
00221             argtype.push_back("int");
00222          } else {
00223             argtype.push_back("typename");
00224          }
00225          UInt_t nest = 0;
00226          for (Ssiz_t i = pos; i < protoname.Length(); ++i) {
00227             switch (protoname[i]) {
00228                case '<':
00229                   ++nest;
00230                   break;
00231                case '>':
00232                   --nest;
00233                   break;
00234                case ',':
00235                   if (nest == 1) {
00236                      if (isdigit(protoname[i+1])) {
00237                         argtype.push_back("int");
00238                      } else {
00239                         argtype.push_back("typename");
00240                      }
00241                      ++nparam;
00242                   }
00243                   break;
00244             }
00245          }
00246          protoname.Remove(pos);
00247       }
00248 
00249       // Forward declaration of template.
00250       fprintf(fp, "template <");
00251       for (UInt_t p = 0; p < nparam; ++p) {
00252          if (p >= argtype.size() ) {
00253             fprintf(fp, "/* missing */ T%d", p);
00254          } else {
00255             fprintf(fp, "%s T%d", argtype[p], p);
00256          }
00257          if (p != (nparam - 1)) fprintf(fp, ", ");
00258       }
00259       if (needGenericTemplate) {
00260          fprintf(fp, "> class %s", protoname.Data());
00261       } else {
00262          fprintf(fp, "> class %s;\n", protoname.Data());
00263          fprintf(fp, "template <> ");
00264       }
00265    }
00266 
00267    if (implementEmptyClass) {
00268       if (istemplate) {
00269          if (!needGenericTemplate) {
00270             fprintf(fp, "class %s", clname);
00271          }
00272          fprintf(fp, " {\n");
00273          if (numberOfClasses) ++(*numberOfClasses);
00274          fprintf(fp, "public:\n");
00275          fprintf(fp, "operator int() { return 0; };\n");
00276       } else {
00277          fprintf(fp, "enum %s { kDefault_%s };\n", clname, clname);
00278          // The nesting space of this class may not be #pragma declared (and without
00279          // the dictionary is broken), so for now skip those
00280          if (implementEmptyClass==1) {
00281             if (strchr(fullname, ':') == 0) {
00282                // yes this is too aggressive, this needs to be fixed properly by moving the #pragma out of band.
00283                fprintf(fp, "%s", Form("#ifdef __MAKECINT__\n#pragma link C++ class %s+;\n#endif\n", fullname));
00284             }
00285             fprintf(fp, "#endif\n");
00286          }
00287       }
00288    } else {
00289       if (!(istemplate && needGenericTemplate)) {
00290           fprintf(fp, "class %s", clname);
00291       }
00292    }
00293    return numberOfNamespaces;
00294 }
00295 
00296 //______________________________________________________________________________
00297 void TMakeProject::GenerateMissingStreamerInfo(TList *extrainfos, const char *clname, Bool_t iscope)
00298 {
00299    // Generate an empty StreamerInfo for the given type (no recursion) if it is not
00300    // not known in the list of class.   If the type itself is a template,
00301    // we mark it with version 1 (a class) otherwise we mark it as version -3 (an enum).
00302 
00303    if (!TClassEdit::IsStdClass(clname) && !TClass::GetClass(clname) && gROOT->GetType(clname) == 0) {
00304 
00305       TStreamerInfo *info = (TStreamerInfo*)extrainfos->FindObject(clname);
00306       if (!info) {
00307          // The class does not exist, let's create it
00308          TStreamerInfo *newinfo = new TStreamerInfo();
00309          newinfo->SetName(clname);
00310          if (clname[strlen(clname)-1]=='>') {
00311             newinfo->SetTitle("Generated by MakeProject as an empty class template instantiation");
00312             newinfo->SetClassVersion(1);
00313          } else if (iscope) {
00314             newinfo->SetTitle("Generated by MakeProject as a namespace");
00315             newinfo->SetClassVersion(-4 /*namespace*/);
00316          } else {
00317             newinfo->SetTitle("Generated by MakeProject as an enum");
00318             newinfo->SetClassVersion(-3 /*enum*/);
00319          }
00320          extrainfos->Add(newinfo);
00321       } else {
00322          if (iscope) {
00323             if (info->GetClassVersion() == -3) {
00324                // This was marked as an enum but is also used as a scope,
00325                // so it was actually a class.
00326                info->SetTitle("Generated by MakeProject as an empty class");
00327                info->SetClassVersion(-5 /*class*/);
00328             }
00329          } else {
00330             if (info->GetClassVersion() == -4) {
00331                // This was marked as a 'namespace' but it is also used as a template parameter,
00332                // so it was actually a class.
00333                info->SetTitle("Generated by MakeProject as an empty class");
00334                info->SetClassVersion(-5 /*class*/);
00335             }
00336          }
00337       }
00338    }
00339 }
00340 
00341 //______________________________________________________________________________
00342 void TMakeProject::GenerateMissingStreamerInfos(TList *extrainfos, const char *clname)
00343 {
00344    // Generate an empty StreamerInfo for types that are used in templates parameters
00345    // but are not known in the list of class.   If the type itself is a template,
00346    // we mark it with version 1 (a class) otherwise we mark it as version -3 (an enum).
00347 
00348    UInt_t len = strlen(clname);
00349    UInt_t nest = 0;
00350    UInt_t last = 0;
00351    Bool_t istemplate = kFALSE; // mark whether the current right most entity is a class template.
00352 
00353    for (UInt_t i = 0; i < len; ++i) {
00354       switch (clname[i]) {
00355          case ':':
00356             if (nest == 0 && clname[i+1] == ':') {
00357                TString incName(clname, i);
00358                GenerateMissingStreamerInfo(extrainfos, incName.Data(), kTRUE);
00359                istemplate = kFALSE;
00360             }
00361             break;
00362          case '<':
00363             ++nest;
00364             if (nest == 1) last = i + 1;
00365             break;
00366          case '>':
00367             --nest; /* intentional fall throught to the next case */
00368          case ',':
00369             if ((clname[i] == ',' && nest == 1) || (clname[i] == '>' && nest == 0)) {
00370                TString incName(clname + last, i - last);
00371                incName = TClassEdit::ShortType(incName.Data(), TClassEdit::kDropTrailStar | TClassEdit::kLong64);
00372                if (clname[i] == '>' && nest == 1) incName.Append(">");
00373 
00374                if (isdigit(incName[0])) {
00375                   // Not a class name, nothing to do.
00376                } else {
00377                   GenerateMissingStreamerInfos(extrainfos,incName.Data());
00378                }
00379                last = i + 1;
00380             }
00381       }
00382    }
00383    GenerateMissingStreamerInfo(extrainfos,TClassEdit::ShortType(clname, TClassEdit::kDropTrailStar | TClassEdit::kLong64).c_str(),kFALSE);
00384 }
00385 
00386 //______________________________________________________________________________
00387 void TMakeProject::GenerateMissingStreamerInfos(TList *extrainfos, TStreamerElement *element)
00388 {
00389    // Generate an empty StreamerInfo for types that are used in templates parameters
00390    // but are not known in the list of class.   If the type itself is a template,
00391    // we mark it with version 1 (a class) otherwise we mark it as version -3 (an enum).
00392 
00393    if (element->IsBase()) {
00394       GenerateMissingStreamerInfos(extrainfos,element->GetClassPointer()->GetName());
00395    } else {
00396       GenerateMissingStreamerInfos(extrainfos,element->GetTypeName());
00397    }
00398 
00399 }
00400 
00401 //______________________________________________________________________________
00402 UInt_t TMakeProject::GenerateForwardDeclaration(FILE *fp, const char *clname, char *inclist, Bool_t implementEmptyClass, Bool_t needGenericTemplate, const TList *extrainfos)
00403 {
00404    // Insert a (complete) forward declaration for the class 'clname'
00405 
00406    UInt_t ninc = 0;
00407 
00408    if (strchr(clname, '<')) {
00409       ninc += GenerateIncludeForTemplate(fp, clname, inclist, kTRUE, extrainfos);
00410    }
00411    TString protoname;
00412    UInt_t numberOfClasses = 0;
00413    UInt_t numberOfNamespaces = GenerateClassPrefix(fp, clname, kTRUE, protoname, &numberOfClasses, implementEmptyClass, needGenericTemplate);
00414 
00415    if (!implementEmptyClass) fprintf(fp, ";\n");
00416    for (UInt_t i = 0;i < numberOfClasses;++i) {
00417       fprintf(fp, "}; // end of class.\n");
00418       fprintf(fp, "#endif\n");
00419    }
00420    for (UInt_t i = 0;i < numberOfNamespaces;++i) {
00421       fprintf(fp, "} // end of namespace.\n");
00422    }
00423 
00424    return ninc;
00425 }
00426 
00427 //______________________________________________________________________________
00428 UInt_t TMakeProject::GenerateIncludeForTemplate(FILE *fp, const char *clname, char *inclist, Bool_t forward, const TList *extrainfos)
00429 {
00430    // Add to the header file, the #include needed for the argument of
00431    // this template.
00432 
00433    UInt_t ninc = 0;
00434    UInt_t len = strlen(clname);
00435    UInt_t nest = 0;
00436    UInt_t last = 0;
00437 
00438 
00439    for (UInt_t i = 0; i < len; ++i) {
00440       switch (clname[i]) {
00441          case '<':
00442             ++nest;
00443             if (nest == 1) last = i + 1;
00444             break;
00445          case '>':
00446             --nest; /* intentional fall throught to the next case */
00447          case ',':
00448             if ((clname[i] == ',' && nest == 1) || (clname[i] == '>' && nest == 0)) {
00449                TString incName(clname + last, i - last);
00450                incName = TClassEdit::ShortType(incName.Data(), TClassEdit::kDropTrailStar | TClassEdit::kLong64);
00451                if (clname[i] == '>' && nest == 1) incName.Append(">");
00452                Int_t stlType;
00453                if (isdigit(incName[0])) {
00454                   // Not a class name, nothing to do.
00455                } else if ((stlType = TClassEdit::IsSTLCont(incName))) {
00456                   const char *what = "";
00457                   switch (TMath::Abs(stlType))  {
00458                      case TClassEdit::kVector:
00459                         what = "vector";
00460                         break;
00461                      case TClassEdit::kList:
00462                         what = "list";
00463                         break;
00464                      case TClassEdit::kDeque:
00465                         what = "deque";
00466                         break;
00467                      case TClassEdit::kMap:
00468                         what = "map";
00469                         break;
00470                      case TClassEdit::kMultiMap:
00471                         what = "map";
00472                         break;
00473                      case TClassEdit::kSet:
00474                         what = "set";
00475                         break;
00476                      case TClassEdit::kMultiSet:
00477                         what = "set";
00478                         break;
00479                      case TClassEdit::kBitSet:
00480                         what = "bitset";
00481                         break;
00482                      default:
00483                         what = "undetermined_stl_container";
00484                         break;
00485                   }
00486                   AddInclude(fp, what, kTRUE, inclist);
00487                   fprintf(fp, "namespace std {} using namespace std;\n");
00488                   ninc += GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
00489                } else if (strncmp(incName.Data(), "pair<", strlen("pair<")) == 0) {
00490                   AddInclude(fp, "utility", kTRUE, inclist);
00491                   ninc += GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
00492                } else if (strncmp(incName.Data(), "auto_ptr<", strlen("auto_ptr<")) == 0) {
00493                   AddInclude(fp, "memory", kTRUE, inclist);
00494                   ninc += GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
00495                } else if (TClassEdit::IsStdClass(incName)) {
00496                   // Do nothing.
00497                } else {
00498                   TClass *cl = gROOT->GetClass(incName);
00499                   if (!forward && cl) {
00500                      if (cl->GetClassInfo()) {
00501                         // We have the real dictionary for this class.
00502 
00503                         const char *include = cl->GetDeclFileName();
00504                         if (include && strlen(include) != 0) {
00505 
00506                            if (strncmp(include, "include/", 8) == 0) {
00507                               include += 8;
00508                            }
00509                            if (strncmp(include, "include\\", 9) == 0) {
00510                               include += 9;
00511                            }
00512                            TMakeProject::AddInclude(fp, include, kFALSE, inclist);
00513                         }
00514                         GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
00515                      } else {
00516                         incName = GetHeaderName(incName,extrainfos);
00517                         incName.Append(".h");
00518                         AddInclude(fp, incName, kFALSE, inclist);
00519                      }
00520                   } else if (incName.Length() && incName[0] != ' ' && gROOT->GetType(incName) == 0) {
00521                      Bool_t emptyclass = !cl;
00522                      if (emptyclass && extrainfos) {
00523                         TStreamerInfo *info = (TStreamerInfo*)extrainfos->FindObject(incName);
00524                         if (info && info->GetClassVersion() == -5) {
00525                            emptyclass = kFALSE;
00526                         }
00527                      }
00528                      GenerateForwardDeclaration(fp, incName, inclist, emptyclass, kFALSE, extrainfos);
00529                   }
00530                }
00531                last = i + 1;
00532             }
00533       }
00534    }
00535 
00536    Int_t stlType = TClassEdit::IsSTLCont(clname);
00537    if (stlType) {
00538       std::vector<std::string> inside;
00539       int nestedLoc;
00540       TClassEdit::GetSplit( clname, inside, nestedLoc, TClassEdit::kLong64 );
00541       Int_t stlkind =  TClassEdit::STLKind(inside[0].c_str());
00542       TClass *key = TClass::GetClass(inside[1].c_str());
00543       if (key) {
00544          TString what;
00545          switch (stlkind)  {
00546             case TClassEdit::kMap:
00547             case TClassEdit::kMultiMap: {
00548                   what = "pair<";
00549                   what += UpdateAssociativeToVector( inside[1].c_str() );
00550                   what += ",";
00551                   what += UpdateAssociativeToVector( inside[2].c_str() );
00552                   what += " >";
00553                   what.ReplaceAll("std::","");
00554                   // Only ask for it if needed.
00555                   TClass *paircl = TClass::GetClass(what.Data());
00556                   if (paircl == 0 || paircl->GetClassInfo() == 0) {
00557                      AddUniqueStatement(fp, Form("#ifdef __MAKECINT__\n#pragma link C++ class %s+;\n#endif\n", what.Data()), inclist);
00558                   }
00559                   break;
00560                }
00561          }
00562       }
00563    }
00564 
00565    if (strncmp(clname, "auto_ptr<", strlen("auto_ptr<")) == 0) {
00566       AddUniqueStatement(fp, Form("#ifdef __MAKECINT__\n#pragma link C++ class %s+;\n#endif\n", clname), inclist);
00567    }
00568    return ninc;
00569 }
00570 
00571 
00572 //______________________________________________________________________________
00573 void TMakeProject::GeneratePostDeclaration(FILE *fp, const TVirtualStreamerInfo *info, char *inclist)
00574 {
00575    // Add to the header file anything that need to appear after the class
00576    // declaration (this includes some #pragma link).
00577  
00578    TIter next(info->GetElements());
00579    TStreamerElement *element;
00580    while( (element = (TStreamerElement*)next()) ) {      
00581       Int_t stlType = TClassEdit::IsSTLCont(element->GetTypeName());      
00582       if (stlType) {
00583          std::vector<std::string> inside;
00584          int nestedLoc;
00585          TClassEdit::GetSplit( element->GetTypeName(), inside, nestedLoc, TClassEdit::kLong64 );
00586          Int_t stlkind =  TClassEdit::STLKind(inside[0].c_str());
00587          TClass *key = TClass::GetClass(inside[1].c_str());
00588          TString what;
00589          if (strncmp(inside[1].c_str(),"pair<",strlen("pair<"))==0) {
00590             what = inside[1].c_str();
00591          } else if (key) {
00592             switch (stlkind)  {
00593                case TClassEdit::kMap:
00594                case TClassEdit::kMultiMap: 
00595                {
00596                   // Already done (see GenerateIncludeForTemplate
00597                   break;
00598                }
00599                default:
00600                   break;
00601             }
00602          }
00603          if (what.Length()) {
00604             AddUniqueStatement(fp, Form("#ifdef __MAKECINT__\n#pragma link C++ class %s+;\n#endif\n",what.Data()), inclist);               
00605          }
00606       }
00607    }
00608 }
00609    
00610 //______________________________________________________________________________
00611 TString TMakeProject::UpdateAssociativeToVector(const char *name)
00612 {
00613    // If we have a map, multimap, set or multiset,
00614    // and the key is a class, we need to replace the
00615    // container by a vector since we don't have the
00616    // comparator function.
00617    // The 'name' is modified to return the change in the name,
00618    // if any.
00619    TString newname( name );
00620 
00621    if (strchr(name,'<')!=0) {
00622       std::vector<std::string> inside;
00623       int nestedLoc;
00624       unsigned int narg = TClassEdit::GetSplit( name, inside, nestedLoc, TClassEdit::kLong64 );
00625       if (nestedLoc) --narg;
00626       Int_t stlkind =  TMath::Abs(TClassEdit::STLKind(inside[0].c_str()));
00627 
00628       for(unsigned int i = 1; i<narg; ++i) {
00629          inside[i] = UpdateAssociativeToVector( inside[i].c_str() );
00630       }
00631       // Remove default allocator if any.
00632       switch (stlkind) {
00633          case TClassEdit::kVector:
00634          case TClassEdit::kList:
00635          case TClassEdit::kDeque:
00636             if (narg>2 && strncmp(inside[2].c_str(),"std::allocator<",strlen("std::allocator<"))==0) {
00637                --narg;
00638             }
00639             break;
00640          case TClassEdit::kSet:
00641          case TClassEdit::kMultiSet:
00642          case TClassEdit::kMap:
00643          case TClassEdit::kMultiMap:
00644             if (narg>4 && strncmp(inside[4].c_str(),"std::allocator<",strlen("std::allocator<"))==0) {
00645                --narg;
00646             }
00647             break;
00648       }
00649       if (stlkind!=0) {
00650          TClass *key = TClass::GetClass(inside[1].c_str());
00651 
00652          if (key) {
00653             // We only need to translate to a vector is the key is a class
00654             // (for which we do not know the sorting).
00655             std::string what;
00656             switch ( stlkind )  {
00657                case TClassEdit::kMap:
00658                case TClassEdit::kMultiMap: {
00659                   what = "std::pair<";
00660                   what += inside[1];
00661                   what += ",";
00662                   what += inside[2];
00663                   if (what[what.size()-1]=='>') {
00664                      what += " >";
00665                   } else {
00666                      what += ">";
00667                   }
00668                   inside.clear();
00669                   inside.push_back("std::vector");
00670                   inside.push_back(what);
00671                   narg = 2;
00672                   break;
00673                }
00674                case TClassEdit::kSet:
00675                case TClassEdit::kMultiSet:
00676                   inside[0] = "std::vector";
00677                   break;
00678             }
00679          }
00680          if (strncmp(inside[0].c_str(),"std::",5) != 0) {
00681             inside[0] = "std::" + inside[0];
00682          }
00683       } else {
00684          static const char *stlnames[] = { "pair", "greater", "less", "allocator" };
00685          for(unsigned int in = 0; in < sizeof(stlnames)/sizeof(stlnames[0]); ++in) {
00686             if (strncmp( inside[0].c_str(), stlnames[in], strlen(stlnames[in])) == 0 ) {
00687                inside[0] = "std::" + inside[0];
00688                break;
00689             }
00690          }
00691       }
00692       newname = inside[0];
00693       newname.Append("<");
00694       newname.Append(inside[1]);
00695       for(unsigned int j=2; j<narg; ++j) {
00696          newname.Append(",");
00697          newname.Append(inside[j]);
00698       }
00699       if (newname[newname.Length()-1]=='>') {
00700          newname.Append(" >");
00701       } else {
00702          newname.Append(">");
00703       }
00704       if (nestedLoc) newname.Append(inside[nestedLoc]);
00705    } else if ( newname == "string" ) {
00706       newname = "std::string";
00707    }
00708    return newname;
00709 }

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