CMS 3D CMS Logo

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