CMS 3D CMS Logo

ReflexTools.cc

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

Generated on Tue Jun 9 17:36:49 2009 for CMSSW by  doxygen 1.5.4