CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/FWCore/Utilities/src/ReflexTools.cc

Go to the documentation of this file.
00001 #include "FWCore/Utilities/interface/ReflexTools.h"
00002 #include "FWCore/Utilities/interface/Algorithms.h"
00003 
00004 #include "Api.h" // for G__ClassInfo
00005 #include "Reflex/Base.h"
00006 #include "Reflex/Member.h"
00007 #include "Reflex/TypeTemplate.h"
00008 
00009 #include "boost/algorithm/string.hpp"
00010 #include "boost/thread/tss.hpp"
00011 
00012 #include <algorithm>
00013 #include <sstream>
00014 
00015 using Reflex::Base;
00016 using Reflex::FINAL;
00017 using Reflex::Member;
00018 using Reflex::Object;
00019 using Reflex::SCOPED;
00020 using Reflex::Type;
00021 using Reflex::TypeTemplate;
00022 using Reflex::Type_Iterator;
00023 
00024 namespace edm {
00025 
00026   Type get_final_type(Type t) {
00027     while(t.IsTypedef()) t = t.ToType();
00028     return t;
00029   }
00030 
00031   bool
00032   find_nested_type_named(std::string const& nested_type,
00033                          Type const& type_to_search,
00034                          Type& found_type) {
00035     // Look for a sub-type named 'nested_type'
00036     for(Type_Iterator
00037            i = type_to_search.SubType_Begin(),
00038            e = type_to_search.SubType_End();
00039            i != e;
00040            ++i) {
00041       if(i->Name() == nested_type) {
00042         found_type = get_final_type(*i);
00043         return true;
00044       }
00045     }
00046     return false;
00047   }
00048 
00049   bool
00050   is_RefVector(Reflex::Type const& possible_ref_vector,
00051                Reflex::Type& value_type) {
00052 
00053     static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefVector", 3));
00054     static std::string member_type("member_type");
00055     TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00056     if(primary_template_id == ref_vector_template_id) {
00057       return find_nested_type_named(member_type, possible_ref_vector, value_type);
00058     }
00059     return false;
00060   }
00061 
00062   bool
00063   is_PtrVector(Reflex::Type const& possible_ref_vector,
00064                Reflex::Type& value_type) {
00065 
00066     static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::PtrVector", 1));
00067     static std::string member_type("member_type");
00068     static std::string val_type("value_type");
00069     TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00070     if(primary_template_id == ref_vector_template_id) {
00071       Reflex::Type ptrType;
00072       if(find_nested_type_named(val_type, possible_ref_vector, ptrType)) {
00073         return find_nested_type_named(val_type, ptrType, value_type);
00074       }
00075     }
00076     return false;
00077   }
00078 
00079   bool
00080   is_RefToBaseVector(Reflex::Type const& possible_ref_vector,
00081                      Reflex::Type& value_type) {
00082 
00083     static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefToBaseVector", 1));
00084     static std::string member_type("member_type");
00085     TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00086     if(primary_template_id == ref_vector_template_id) {
00087       return find_nested_type_named(member_type, possible_ref_vector, value_type);
00088     }
00089     return false;
00090   }
00091 
00092   namespace {
00093 
00094     int const oneParamArraySize = 6;
00095     std::string const oneParam[oneParamArraySize] = {
00096       "vector",
00097       "basic_string",
00098       "set",
00099       "list",
00100       "deque",
00101       "multiset"
00102     };
00103     int const twoParamArraySize = 3;
00104     std::string const twoParam[twoParamArraySize] = {
00105       "map",
00106       "pair",
00107       "multimap"
00108     };
00109 
00110 
00111     bool
00112     hasCintDictionary(std::string const& name) {
00113       std::auto_ptr<G__ClassInfo> ci(new G__ClassInfo(name.c_str()));
00114         return(ci.get() && ci->IsLoaded());
00115     }
00116 
00117     // Checks if there is a Reflex dictionary for the Type t.
00118     // If noComponents is false, checks members and base classes recursively.
00119     // If noComponents is true, checks Type t only.
00120     void
00121     checkType(Type t, bool noComponents = false) {
00122 
00123       // The only purpose of this cache is to stop infinite recursion.
00124       // Reflex maintains its own internal cache.
00125       static boost::thread_specific_ptr<StringSet> found_types;
00126       if(0 == found_types.get()) {
00127         found_types.reset(new StringSet);
00128       }
00129 
00130       // ToType strips const, volatile, array, pointer, reference, etc.,
00131       // and also translates typedefs.
00132       // To be safe, we do this recursively until we either get a null type
00133       // or the same type.
00134       Type null;
00135       for(Type x = t.ToType(); x != null && x != t; t = x, x = t.ToType()) {}
00136 
00137       std::string name = t.Name(SCOPED);
00138       boost::trim(name);
00139 
00140       if(found_types->end() != found_types->find(name) || missingTypes().end() != missingTypes().find(name)) {
00141         // Already been processed. Prevents infinite loop.
00142         return;
00143       }
00144 
00145       if(name.empty() || t.IsFundamental() || t.IsEnum()) {
00146         found_types->insert(name);
00147         return;
00148       }
00149 
00150       if(!bool(t)) {
00151         if(hasCintDictionary(name)) {
00152           found_types->insert(name);
00153         } else {
00154           missingTypes().insert(name);
00155         }
00156         return;
00157       }
00158 
00159       found_types->insert(name);
00160       if(noComponents) return;
00161 
00162       if(name.find("std::") == 0) {
00163         if(t.IsTemplateInstance()) {
00164           std::string::size_type n = name.find('<');
00165           int cnt = 0;
00166           if(std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, n - 5)) != oneParam + oneParamArraySize) {
00167             cnt = 1;
00168           } else if(std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, n - 5)) != twoParam + twoParamArraySize) {
00169             cnt = 2;
00170           }
00171           for(int i = 0; i < cnt; ++i) {
00172             checkType(t.TemplateArgumentAt(i));
00173           }
00174         }
00175       } else {
00176         int mcnt = t.DataMemberSize();
00177         for(int i = 0; i < mcnt; ++i) {
00178           Member m = t.DataMemberAt(i);
00179           if(m.IsTransient() || m.IsStatic()) continue;
00180           checkType(m.TypeOf());
00181         }
00182         int cnt = t.BaseSize();
00183         for(int i = 0; i < cnt; ++i) {
00184           checkType(t.BaseAt(i).ToType());
00185         }
00186       }
00187     }
00188   } // end unnamed namespace
00189 
00190   StringSet& missingTypes() {
00191     static boost::thread_specific_ptr<StringSet> missingTypes_;
00192     if(0 == missingTypes_.get()) {
00193       missingTypes_.reset(new StringSet);
00194     }
00195     return *missingTypes_.get();
00196   }
00197 
00198   void checkDictionaries(std::string const& name, bool noComponents) {
00199     Type null;
00200     Type t = Type::ByName(name);
00201     if(t == null) {
00202       missingTypes().insert(name);
00203       return;
00204     }
00205     checkType(Type::ByName(name), noComponents);
00206   }
00207 
00208   void public_base_classes(Type const& type,
00209                            std::vector<Type>& baseTypes) {
00210 
00211     if(type.IsClass() || type.IsStruct()) {
00212 
00213       int nBase = type.BaseSize();
00214       for(int i = 0; i < nBase; ++i) {
00215 
00216         Base base = type.BaseAt(i);
00217         if(base.IsPublic()) {
00218 
00219           Type baseType = type.BaseAt(i).ToType();
00220           if(bool(baseType)) {
00221 
00222             while(baseType.IsTypedef() == true) {
00223               baseType = baseType.ToType();
00224             }
00225 
00226             // Check to make sure this base appears only once in the
00227             // inheritance heirarchy.
00228             if(!search_all(baseTypes, baseType)) {
00229               // Save the type and recursive look for its base types
00230               baseTypes.push_back(baseType);
00231               public_base_classes(baseType, baseTypes);
00232             }
00233             // For now just ignore it if the class appears twice,
00234             // After some more testing we may decide to uncomment the following
00235             // exception.
00236             /*
00237             else {
00238               throw Exception(errors::UnimplementedFeature)
00239                 << "DataFormats/Common/src/ReflexTools.cc in function public_base_classes.\n"
00240                 << "Encountered class that has a public base class that appears\n"
00241                 << "multiple times in its inheritance heirarchy.\n"
00242                 << "Please contact the EDM Framework group with details about\n"
00243                 << "this exception. It was our hope that this complicated situation\n"
00244                 << "would not occur. There are three possible solutions. 1. Change\n"
00245                 << "the class design so the public base class does not appear multiple\n"
00246                 << "times in the inheritance heirarchy. In many cases, this is a\n"
00247                 << "sign of bad design. 2. Modify the code that supports Views to\n"
00248                 << "ignore these base classes, but not supply support for creating a\n"
00249                 << "View of this base class. 3. Improve the View infrastructure to\n"
00250                 << "deal with this case. Class name of base class: " << baseType.Name() << "\n\n";
00251             }
00252             */
00253           }
00254         }
00255       }
00256     }
00257   }
00258 
00259   void const*
00260   reflex_pointer_adjust(void* raw,
00261                         Type const& dynamicType,
00262                         std::type_info const& toType) {
00263     Object obj(dynamicType, raw);
00264     return obj.CastObject(Type::ByTypeInfo(toType)).Address();
00265   }
00266 }