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
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
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
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
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
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
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
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 }