RStl.cxx

Go to the documentation of this file.
00001 // @(#)root/utils:$Id: RStl.cxx 35344 2010-09-16 21:34:21Z pcanal $
00002 // Author: Philippe Canal 27/08/2003
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2003, Rene Brun, Fons Rademakers, and al.          *
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 #include "RConfigure.h"
00013 #include "RConfig.h"
00014 #include "Api.h"
00015 
00016 #include "RStl.h"
00017 #include "TClassEdit.h"
00018 using namespace TClassEdit;
00019 #include <stdio.h>
00020 
00021 // From the not-existing yet rootcint.h
00022 void WriteClassInit(G__ClassInfo &cl);
00023 void WriteAuxFunctions(G__ClassInfo &cl);
00024 int ElementStreamer(G__TypeInfo &ti,const char *R__t,int rwmode,const char *tcl=0);
00025 
00026 #ifndef ROOT_Varargs
00027 #include "Varargs.h"
00028 #endif
00029 void Error(const char *location, const char *va_(fmt), ...);
00030 void Warning(const char *location, const char *va_(fmt), ...);
00031 
00032 //
00033 // ROOT::RStl is the rootcint STL handling class.
00034 //
00035 
00036 ROOT::RStl& ROOT::RStl::inst()
00037 {
00038    // Return the singleton ROOT::RStl.
00039 
00040    static ROOT::RStl instance;
00041    return instance;
00042 
00043 }
00044 
00045 void ROOT::RStl::GenerateTClassFor(const string& stlclassname)
00046 {
00047    // Force the generation of the TClass for the given class.
00048 
00049    G__ClassInfo cl(TClassEdit::ShortType(stlclassname.c_str(),
00050                                          TClassEdit::kDropTrailStar).c_str());
00051 
00052    if ( ! cl.IsValid() ) {
00053       Error("RStl::GenerateTClassFor","%s not in the CINT dictionary",
00054             stlclassname.c_str());
00055       return;
00056    }
00057 
00058    string registername( TClassEdit::ShortType(cl.Name(),
00059                                               TClassEdit::kDropStlDefault ) );
00060 
00061 //      fprintf(stderr,"registering %s as %s %s\n",
00062 //              stlclassname.c_str(), cl.Name(), registername.c_str());
00063 
00064    int nestedLoc=0;
00065    vector<string> splitName;
00066    TClassEdit::GetSplit(registername.c_str(),splitName,nestedLoc);
00067 
00068    if ( TClassEdit::STLKind( splitName[0].c_str() ) == TClassEdit::kVector ) {
00069       if ( splitName[1] == "bool" || splitName[1]=="Bool_t") {
00070          Warning("std::vector<bool>", " is not fully supported yet!\nUse std::vector<char> or std::deque<bool> instead.\n");
00071       }
00072    }
00073 
00074    fList.insert(registername);
00075 
00076    // We also should register the template arguments if they are STL.
00077    for(unsigned int i=1 ; i<splitName.size(); ++i) {
00078       if ( TClassEdit::IsSTLCont( splitName[i].c_str()) != 0 ) {
00079          GenerateTClassFor( splitName[i] );
00080       }
00081    }
00082 
00083 
00084 //    fprintf(stderr,"ROOT::RStl registered %s as %s\n",stlclassname.c_str(),registername.c_str());
00085 }
00086 
00087 void ROOT::RStl::Print()
00088 {
00089    // Print the content of the object
00090    fprintf(stderr,"ROOT::RStl singleton\n");
00091    set<string>::iterator iter;
00092    for(iter = fList.begin(); iter != fList.end(); ++iter) {
00093       fprintf(stderr, "need TClass for %s\n", (*iter).c_str());
00094    }
00095 }
00096 
00097 string ROOT::RStl::DropDefaultArg(const string &classname)
00098 {
00099    // Remove the default argument from the stl container.
00100 
00101    G__ClassInfo cl(classname.c_str());
00102 
00103    if ( cl.TmpltName() == 0 ) return classname;
00104 
00105    if ( TClassEdit::STLKind( cl.TmpltName() ) == 0 ) return classname;
00106 
00107    return TClassEdit::ShortType( cl.Fullname(),
00108                                  TClassEdit::kDropStlDefault );
00109 
00110 }
00111 
00112 void ROOT::RStl::WriteClassInit(FILE* /*file*/)
00113 {
00114    // This function writes the TGeneraticClassInfo initialiser
00115    // and the auxiliary functions (new and delete wrappers) for
00116    // each of the STL containers that have been registered
00117 
00118    set<string>::iterator iter;
00119    G__ClassInfo cl;
00120    for(iter = fList.begin(); iter != fList.end(); ++iter) {
00121       cl.Init( (*iter).c_str() );
00122 
00123       ::WriteClassInit( cl );
00124       ::WriteAuxFunctions( cl );
00125    }
00126 }
00127 
00128 void ROOT::RStl::WriteStreamer(FILE *file, G__ClassInfo &stlcl)
00129 {
00130    // Write the free standing streamer function for the given
00131    // STL container class.
00132 
00133    string streamerName = "stl_streamer_";
00134 
00135    string shortTypeName = GetLong64_Name( TClassEdit::ShortType(stlcl.Name(),TClassEdit::kDropStlDefault) );
00136    string noConstTypeName( TClassEdit::CleanType(shortTypeName.c_str(),2) );
00137 
00138    streamerName += G__map_cpp_name((char *)shortTypeName.c_str());
00139    string typedefName = G__map_cpp_name((char *)shortTypeName.c_str());
00140 
00141    int nestedLoc=0;
00142    vector<string> splitName;
00143    TClassEdit::GetSplit(shortTypeName.c_str(),splitName,nestedLoc);
00144 
00145    int stltype = TClassEdit::STLKind(splitName[0].c_str());
00146 
00147    G__TypeInfo firstType(splitName[1].c_str());
00148    G__TypeInfo secondType;
00149    const char *tclFirst=0,*tclSecond=0;
00150    string firstFullName, secondFullName;
00151 
00152    if (ElementStreamer(firstType,0,0)) {
00153       tclFirst = "R__tcl1";
00154       const char *name = firstType.Fullname();
00155       if (name) {
00156          // the value return by ti.Fullname is a static buffer
00157          // so we have to copy it immeditately
00158          firstFullName = TClassEdit::ShortType(name,TClassEdit::kDropStlDefault);
00159       } else {
00160          // ti is a simple type name
00161          firstFullName = firstType.TrueName();
00162       }
00163    }
00164    if (stltype==kMap || stltype==kMultiMap) {
00165       secondType.Init( splitName[2].c_str());
00166 
00167       if (ElementStreamer(secondType,0,0)) {
00168          tclSecond="R__tcl2";
00169          const char *name = secondType.Fullname();
00170          if (name) {
00171             // the value return by ti.Fullname is a static buffer
00172             // so we have to copy it immeditately
00173             secondFullName = TClassEdit::ShortType(name,TClassEdit::kDropStlDefault);
00174          } else {
00175             // ti is a simple type name
00176             secondFullName = secondType.TrueName();
00177          }
00178       }
00179    }
00180 
00181    fprintf(file, "//___________________________________________________________");
00182    fprintf(file, "_____________________________________________________________\n");
00183    fprintf(file, "namespace ROOT {\n");
00184    fprintf(file, "   typedef %s %s;\n",shortTypeName.c_str(), typedefName.c_str());
00185    fprintf(file, "   static void %s(TBuffer &R__b, void *R__p)\n",streamerName.c_str());
00186    fprintf(file, "   {\n");
00187    fprintf(file, "      if (gDebug>1) Info(__FILE__,\"Running compiled streamer for %s at %%p\",R__p);\n",shortTypeName.c_str());
00188    fprintf(file, "      %s &R__stl = *(%s *)R__p;\n",shortTypeName.c_str(),shortTypeName.c_str());
00189    fprintf(file, "      if (R__b.IsReading()) {\n");
00190    fprintf(file, "         R__stl.clear();\n");
00191 
00192    if (tclFirst)
00193       fprintf(file, "         TClass *R__tcl1 = TBuffer::GetClass(typeid(%s));\n",
00194               firstFullName.c_str());
00195    if (tclSecond)
00196       fprintf(file, "         TClass *R__tcl2 = TBuffer::GetClass(typeid(%s));\n",
00197               secondFullName.c_str());
00198 
00199    fprintf(file, "         int R__i, R__n;\n");
00200    fprintf(file, "         R__b >> R__n;\n");
00201 
00202    if (stltype==kVector) {
00203       fprintf(file,"         R__stl.reserve(R__n);\n");
00204    }
00205    fprintf(file, "         for (R__i = 0; R__i < R__n; R__i++) {\n");
00206 
00207    ElementStreamer(firstType,"R__t",0,tclFirst);
00208    if (stltype == kMap || stltype == kMultiMap) {     //Second Arg
00209       ElementStreamer(secondType,"R__t2",0,tclSecond);
00210    }
00211    switch (stltype) {
00212 
00213       case kMap:
00214       case kMultiMap:
00215          fprintf(file, "            R__stl.insert(make_pair(R__t,R__t2));\n");
00216          break;
00217       case kSet:
00218       case kMultiSet:
00219          fprintf(file, "            R__stl.insert(R__t);\n");
00220          break;
00221       case kVector:
00222       case kList:
00223       case kDeque:
00224          fprintf(file, "            R__stl.push_back(R__t);\n");
00225          break;
00226 
00227       default:
00228             assert(0);
00229    }
00230    fprintf(file, "         }\n");
00231 
00232    fprintf(file, "      } else {\n");
00233 
00234    fprintf(file, "         int R__n=(&R__stl) ? int(R__stl.size()) : 0;\n");
00235    fprintf(file, "         R__b << R__n;\n");
00236    fprintf(file, "         if(R__n) {\n");
00237 
00238    if (tclFirst) {
00239       fprintf(file, "            TClass *R__tcl1 = TBuffer::GetClass(typeid(%s));\n",
00240               firstFullName.c_str());
00241       fprintf(file, "            if (R__tcl1==0) {\n");
00242       fprintf(file, "               Error(\"%s streamer\",\"Missing the TClass object for %s!\");\n",
00243               shortTypeName.c_str(), firstFullName.c_str());
00244       fprintf(file, "               return;\n");
00245       fprintf(file, "            }\n");
00246    }
00247    if (tclSecond) {
00248       fprintf(file, "            TClass *R__tcl2 = TBuffer::GetClass(typeid(%s));\n",
00249               secondFullName.c_str());
00250       fprintf(file, "            if (R__tcl2==0) {\n");
00251       fprintf(file, "               Error(\"%s streamer\",\"Missing the TClass object for %s!\");\n",
00252               shortTypeName.c_str(), secondFullName.c_str());
00253       fprintf(file, "               return;\n");
00254       fprintf(file, "            }\n");
00255    }
00256    fprintf(file, "            %s::iterator R__k;\n", shortTypeName.c_str());
00257    fprintf(file, "            for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {\n");
00258 
00259    if (stltype == kMap || stltype == kMultiMap) {
00260       ElementStreamer(firstType ,"((*R__k).first )",1,tclFirst);
00261       ElementStreamer(secondType,"((*R__k).second)",1,tclSecond);
00262    } else {
00263       ElementStreamer(firstType ,"(*R__k)"         ,1,tclFirst);
00264    }
00265 
00266    fprintf(file, "            }\n");
00267    fprintf(file, "         }\n");
00268 
00269    fprintf(file, "      }\n");
00270    fprintf(file, "   } // end of %s streamer\n",stlcl.Fullname());
00271    fprintf(file, "} // close namespace ROOT\n\n");
00272 
00273    fprintf(file, "// Register the streamer (a typedef is used to avoid problem with macro parameters\n");
00274 
00275    //if ( 0 != ::getenv("MY_ROOT") && ::getenv("MY_ROOT")[0]>'1' )  {
00276    //  fprintf(file, "// Disabled due customized build:\n// ");
00277    //}
00278    fprintf(file, "RootStlStreamer(%s,%s)\n", typedefName.c_str(), streamerName.c_str());
00279    fprintf(file, "\n");
00280 
00281 }
00282 
00283 void ROOT::RStl::WriteStreamer(FILE *file)
00284 {
00285    // Write the free standing streamer function for the registereed
00286    // STL container classes
00287 
00288    set<string>::iterator iter;
00289    G__ClassInfo cl;
00290    for(iter = fList.begin(); iter != fList.end(); ++iter) {
00291       cl.Init( (*iter).c_str() );
00292       WriteStreamer(file,cl);
00293    }
00294 }

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