CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/CondCore/ORA/src/ClassUtils.cc

Go to the documentation of this file.
00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "CondCore/ORA/interface/Reference.h"
00003 #include "CondCore/ORA/interface/NamedRef.h"
00004 #include "FWCore/PluginManager/interface/PluginCapabilities.h"
00005 #include "ClassUtils.h"
00006 //
00007 #include <cxxabi.h>
00008 // externals
00009 #include "Reflex/Object.h"
00010 #include "Reflex/Base.h"
00011 
00012 ora::RflxDeleter::RflxDeleter( const Reflex::Type& type ):
00013   m_type( type ){
00014 }
00015 
00016 ora::RflxDeleter::RflxDeleter( const RflxDeleter& rhs ):
00017   m_type( rhs.m_type ){
00018 }
00019 
00020 ora::RflxDeleter::~RflxDeleter(){
00021 }
00022 
00023 void ora::RflxDeleter::operator()( void* ptr ){
00024   m_type.Destruct( ptr );
00025 }
00026 
00027 void ora::ClassUtils::loadDictionary( const std::string& className ){
00028   try {
00029     static std::string const prefix("LCGReflex/");
00030     edmplugin::PluginCapabilities::get()->load(prefix + className);
00031   } catch (...){
00032     throwException( "Failure while loading dictionary for class \""+className+"\".","ClassUtils::loadDictionary" );
00033   }
00034 }
00035 
00036 void* ora::ClassUtils::upCast( const Reflex::Type& type,
00037                                void* ptr,
00038                                const Reflex::Type& castType ){
00039   void* ret = 0;
00040   if( type == castType ){
00041     ret = ptr;
00042   } else if( type.HasBase( castType )){
00043     Reflex::Object theObj( type, ptr );
00044     ret = theObj.CastObject( castType ).Address();
00045   }
00046   return ret;
00047 }
00048 
00049 bool ora::ClassUtils::isType( const Reflex::Type& type,
00050                               const Reflex::Type& baseType ){
00051   bool ret = false;
00052   if( type == baseType || type.HasBase( baseType )){
00053     ret = true;
00054   }
00055   return ret;
00056 }
00057 
00058 bool ora::ClassUtils::findBaseType( Reflex::Type& type, Reflex::Type& baseType, Reflex::OffsetFunction& func ){
00059   bool found = false;
00060   for ( unsigned int i=0;i<type.BaseSize() && !found; i++){
00061      Reflex::Base base = type.BaseAt(i);
00062      Reflex::Type bt = resolvedType( base.ToType() );
00063      if( bt == baseType ){
00064        func = base.OffsetFP();
00065        found = true;
00066      } else {
00067        found = findBaseType( bt, baseType, func );
00068      }
00069   }
00070   return found;
00071 }
00072 
00073 std::string ora::ClassUtils::demangledName( const std::type_info& typeInfo ){
00074   int status = 0;
00075   std::string ret("");
00076   char* realname = abi::__cxa_demangle( typeInfo.name(), 0, 0, &status);
00077   if( status == 0 && realname ){
00078     ret  = realname;
00079     free(realname);
00080   }
00081   return ret;
00082 }
00083 
00084 Reflex::Type ora::ClassUtils::lookupDictionary( const std::type_info& typeInfo, bool throwFlag ){
00085   Reflex::Type type = Reflex::Type::ByTypeInfo( typeInfo );
00086   if( typeInfo == typeid(std::string) ){
00087     // ugly, but no other way with Reflex...
00088     type = Reflex::Type::ByName("std::string");
00089   }
00090   if( !type ){
00091     loadDictionary( demangledName(typeInfo) );
00092     type = Reflex::Type::ByTypeInfo( typeInfo );
00093   }
00094   if( !type && throwFlag ){
00095     throwException( "Class \""+demangledName(typeInfo)+"\" has not been found in the dictionary.",
00096                     "ClassUtils::lookupDictionary" );
00097   }
00098   return type;
00099 }
00100 
00101 Reflex::Type ora::ClassUtils::lookupDictionary( const std::string& className, bool throwFlag   ){
00102   Reflex::Type type = Reflex::Type::ByName( className );
00103   if( className == "std::basic_string<char>" ){
00104     // ugly, but no other way with Reflex...
00105     type = Reflex::Type::ByName("std::string");
00106   }
00107   if( !type ){
00108     loadDictionary( className );
00109     type = Reflex::Type::ByName( className );
00110   }
00111   if( !type && throwFlag ){
00112     throwException( "Class \""+className+"\" has not been found in the dictionary.",
00113                     "ClassUtils::lookupDictionary" );
00114   }
00115   return type;
00116 }
00117 
00118 void* ora::ClassUtils::constructObject( const Reflex::Type& typ ){
00119   void* ptr = 0;
00120   if( typ.Name(Reflex::SCOPED)=="std::string"){
00121     ptr = new std::string("");
00122   } else {
00123     ptr = typ.Construct().Address();
00124   }
00125   return ptr;
00126 }
00127 
00128 bool ora::ClassUtils::isTypeString(const Reflex::Type& typ){
00129   std::string name = typ.Name(Reflex::SCOPED|Reflex::FINAL);
00130   return ( name == "std::string" ||
00131            name == "std::basic_string<char>" );
00132 }
00133 
00134 bool ora::ClassUtils::isTypePrimitive(const Reflex::Type& typ){
00135   return ( typ.IsFundamental() || typ.IsEnum() || isTypeString( typ ) );
00136 }
00137 
00138 bool ora::ClassUtils::isTypeContainer(const Reflex::Type& typ){
00139   Reflex::TypeTemplate templ = typ.TemplateFamily();
00140   if (! templ) {
00141     return false;
00142   } else {
00143     std::string contName = templ.Name(Reflex::SCOPED|Reflex::FINAL); 
00144     if(  contName == "std::vector"              ||
00145          contName == "std::list"                ||
00146          contName == "std::deque"               ||
00147          contName == "std::stack"               ||
00148          contName == "std::set"                 ||
00149          contName == "std::multiset"            ||
00150          contName == "__gnu_cxx::hash_set"      ||
00151          contName == "__gnu_cxx::hash_multiset" ||
00152          contName == "std::map"                 ||
00153          contName == "std::multimap"            ||
00154          contName == "__gnu_cxx::hash_map"      ||
00155          contName == "__gnu_cxx::hash_multimap" ||
00156          contName == "ora::PVector"            ||
00157          contName == "ora::QueryableVector" ){
00158        return true;
00159     }
00160   }
00161   return false;
00162 }
00163 
00164 bool ora::ClassUtils::isTypeKeyedContainer(const Reflex::Type& typ){
00165   Reflex::TypeTemplate tt = typ.TemplateFamily();
00166   if (! tt) {
00167     return false;
00168   } else {
00169     std::string contName = tt.Name(Reflex::SCOPED|Reflex::FINAL); 
00170     if(  contName == "std::map"                 ||
00171          contName == "std::multimap"            ||
00172          contName == "std::set"                 ||
00173          contName == "std::multiset"            ||
00174          contName == "__gnu_cxx::hash_set"      ||
00175          contName == "__gnu_cxx::hash_multiset" ||
00176          contName == "__gnu_cxx::hash_map"      ||
00177          contName == "__gnu_cxx::hash_multimap" ){
00178       return true;
00179     }
00180   }  
00181   return false;
00182 }
00183 
00184 bool ora::ClassUtils::isTypeNonKeyedContainer(const Reflex::Type& typ){
00185   Reflex::TypeTemplate templ = typ.TemplateFamily();
00186   if (! templ) {
00187     return false;
00188   } else {
00189     std::string contName = templ.Name(Reflex::SCOPED|Reflex::FINAL); 
00190     if(  contName == "std::vector"              ||
00191          contName == "std::list"                ||
00192          contName == "std::deque"               ||
00193          contName == "std::stack"               ||
00194          contName == "ora::PVector"            ||
00195          contName == "ora::QueryableVector" ){
00196        return true;
00197     }
00198   }
00199   return false;
00200 }
00201  
00202 bool ora::ClassUtils::isTypeAssociativeContainer(const Reflex::Type& typ){
00203   Reflex::TypeTemplate tt = typ.TemplateFamily();
00204   if (! tt) {
00205     return false;
00206   } else {
00207     std::string contName = tt.Name(Reflex::SCOPED|Reflex::FINAL); 
00208     if(  contName == "std::map"            ||
00209          contName == "std::multimap"       ||
00210          contName == "__gnu_cxx::hash_map" ||
00211          contName == "__gnu_cxx::hash_multimap" ){
00212       return true;
00213     }
00214   }  
00215   return false;
00216 }
00217 
00218 bool ora::ClassUtils::isTypeNonAssociativeContainer(const Reflex::Type& typ){
00219   Reflex::TypeTemplate tt = typ.TemplateFamily();
00220   if (! tt) {
00221     return false;
00222   } else {
00223     std::string contName = tt.Name(Reflex::SCOPED|Reflex::FINAL); 
00224     if(  contName == "std::vector"              ||
00225          contName == "std::list"                ||
00226          contName == "std::deque"               ||
00227          contName == "std::stack"               ||
00228          contName == "std::set"                 ||
00229          contName == "std::multiset"            ||
00230          contName == "__gnu_cxx::hash_set"      ||
00231          contName == "__gnu_cxx::hash_multiset" ||
00232          contName == "ora::PVector"            ||
00233          contName == "ora::QueryableVector"){
00234        return true;
00235     }
00236   }
00237   return false;
00238 }
00239 
00240 
00241 bool ora::ClassUtils::isTypeOraPointer( const Reflex::Type& typ){
00242   Reflex::TypeTemplate templ = typ.TemplateFamily();
00243   if (! templ) {
00244     return false;
00245   } else {
00246     std::string contName = templ.Name(Reflex::SCOPED|Reflex::FINAL); 
00247     if(  contName == "ora::Ptr" ){
00248        return true;
00249     }
00250   }
00251   return false;  
00252 }
00253 
00254 bool ora::ClassUtils::isTypeOraReference( const Reflex::Type& typ){
00255   return typ.HasBase(Reflex::Type::ByTypeInfo(typeid(ora::Reference)));
00256 }
00257 
00258 bool ora::ClassUtils::isTypeNamedReference( const Reflex::Type& typ){
00259   return typ.HasBase(Reflex::Type::ByTypeInfo(typeid(ora::NamedReference)));
00260 }
00261 
00262 bool ora::ClassUtils::isTypeUniqueReference( const Reflex::Type& typ){
00263   Reflex::TypeTemplate templ = typ.TemplateFamily();
00264   if (! templ) {
00265     return false;
00266   } else {
00267     std::string contName = templ.Name(Reflex::SCOPED|Reflex::FINAL); 
00268     if(  contName == "ora::UniqueRef" ){
00269        return true;
00270     }
00271   }
00272   return false;  
00273 }
00274 
00275 bool ora::ClassUtils::isTypePVector( const Reflex::Type& typ){
00276   Reflex::TypeTemplate templ = typ.TemplateFamily();
00277   if (! templ) {
00278     return false;
00279   } else {
00280     std::string contName = templ.Name(Reflex::SCOPED|Reflex::FINAL); 
00281     if(  contName == "ora::PVector" ){
00282        return true;
00283     }
00284   }
00285   return false;  
00286 }
00287 
00288 bool ora::ClassUtils::isTypeQueryableVector( const Reflex::Type& typ){
00289   Reflex::TypeTemplate templ = typ.TemplateFamily();
00290   if (! templ) {
00291     return false;
00292   } else {
00293     std::string contName = templ.Name(Reflex::SCOPED|Reflex::FINAL); 
00294     if(  contName == "ora::QueryableVector" ){
00295        return true;
00296     }
00297   }
00298   return false;  
00299 }
00300 
00301 bool ora::ClassUtils::isTypeObject( const Reflex::Type& typ){
00302   Reflex::Type resType = ClassUtils::resolvedType( typ );
00303   if( isTypePrimitive( resType ) ) {
00304     //if ( resType.IsFundamental() || resType.IsEnum() || isTypeString(resType) ) {
00305     return false;
00306   } else {
00307     if( resType.IsArray() ) return false;
00308     if( isTypeContainer( resType ) ) return false;
00309     if( isTypeOraPointer( resType ) ) return false;
00310     if( isTypeUniqueReference( resType ) ) return false;
00311     if( isTypePVector( resType ) ) return false;
00312     if( isTypeQueryableVector( resType ) ) return false;
00313   }
00314   return true;
00315 }
00316 
00317 Reflex::Type ora::ClassUtils::containerValueType(const Reflex::Type& typ){
00318   Reflex::Type valueType;
00319   // find the iterator return type as the member value_type of the containers  
00320   size_t subTypeSize = typ.SubTypeSize();
00321   size_t i=0;
00322   while(i<subTypeSize){
00323     Reflex::Type sti = typ.SubTypeAt(i);    
00324     if(sti.Name()=="value_type") {
00325       valueType = sti;
00326       break;
00327     }    
00328     i++;
00329   }
00330   return valueType;
00331 }
00332 
00333 Reflex::Type ora::ClassUtils::containerKeyType(const Reflex::Type& typ){
00334   Reflex::Type keyType;
00335   // find the iterator return type as the member value_type of the containers  
00336   size_t subTypeSize = typ.SubTypeSize();
00337   size_t i=0;
00338   while(i<subTypeSize){
00339     Reflex::Type sti = typ.SubTypeAt(i);    
00340     if(sti.Name()=="key_type") {
00341       keyType = sti;
00342       break;
00343     }    
00344     i++;
00345   }
00346   return keyType;
00347 }
00348 
00349 Reflex::Type ora::ClassUtils::containerDataType(const Reflex::Type& typ){
00350   Reflex::Type dataType;
00351   // find the iterator return type as the member value_type of the containers  
00352   size_t subTypeSize = typ.SubTypeSize();
00353   size_t i=0;
00354   while(i<subTypeSize){
00355     Reflex::Type sti = typ.SubTypeAt(i);    
00356     if(sti.Name()=="mapped_type") {
00357       dataType = sti;
00358       break;
00359     }    
00360     i++;
00361   }
00362   return dataType;
00363 }
00364 
00365 Reflex::Type ora::ClassUtils::containerSubType(const Reflex::Type& typ, const std::string& subTypeName){
00366   Reflex::Type subType;
00367   size_t subTypeSize = typ.SubTypeSize();
00368   size_t i=0;
00369   while(i<subTypeSize){
00370     Reflex::Type sti = typ.SubTypeAt(i);
00371     if(sti.Name()==subTypeName) {
00372       subType = sti;
00373       break;
00374     }
00375     i++;
00376   }
00377   return resolvedType(subType);
00378 }
00379 
00380 Reflex::Type ora::ClassUtils::resolvedType(const Reflex::Type& typ){
00381   Reflex::Type resolvedType = typ;
00382   while(resolvedType.IsTypedef()){
00383     resolvedType = resolvedType.ToType();
00384   }
00385   return resolvedType;
00386 }