00001 #include "FWCore/Utilities/interface/ReflexTools.h"
00002 #include "FWCore/Utilities/interface/Algorithms.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004
00005 #include "Api.h"
00006 #include "Reflex/Base.h"
00007 #include "Reflex/Member.h"
00008 #include "Reflex/TypeTemplate.h"
00009
00010 #include "TROOT.h"
00011
00012 #include "boost/algorithm/string.hpp"
00013 #include "boost/thread/tss.hpp"
00014
00015 #include <algorithm>
00016 #include <sstream>
00017
00018 using Reflex::Base;
00019 using Reflex::FINAL;
00020 using Reflex::Member;
00021 using Reflex::Object;
00022 using Reflex::SCOPED;
00023 using Reflex::Type;
00024 using Reflex::TypeTemplate;
00025 using Reflex::Type_Iterator;
00026
00027 namespace edm {
00028
00029 static StringSet foundTypes_;
00030 static StringSet missingTypes_;
00031
00032 Type get_final_type(Type t) {
00033 while(t.IsTypedef()) t = t.ToType();
00034 return t;
00035 }
00036
00037 bool
00038 find_nested_type_named(std::string const& nested_type,
00039 Type const& type_to_search,
00040 Type& found_type) {
00041
00042 for(Type_Iterator
00043 i = type_to_search.SubType_Begin(),
00044 e = type_to_search.SubType_End();
00045 i != e;
00046 ++i) {
00047 if(i->Name() == nested_type) {
00048 found_type = get_final_type(*i);
00049 return true;
00050 }
00051 }
00052 return false;
00053 }
00054
00055 bool
00056 is_RefVector(Reflex::Type const& possible_ref_vector,
00057 Reflex::Type& value_type) {
00058
00059 static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefVector", 3));
00060 static std::string member_type("member_type");
00061 TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00062 if(primary_template_id == ref_vector_template_id) {
00063 return find_nested_type_named(member_type, possible_ref_vector, value_type);
00064 }
00065 return false;
00066 }
00067
00068 bool
00069 is_PtrVector(Reflex::Type const& possible_ref_vector,
00070 Reflex::Type& value_type) {
00071
00072 static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::PtrVector", 1));
00073 static std::string member_type("member_type");
00074 static std::string val_type("value_type");
00075 TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00076 if(primary_template_id == ref_vector_template_id) {
00077 Reflex::Type ptrType;
00078 if(find_nested_type_named(val_type, possible_ref_vector, ptrType)) {
00079 return find_nested_type_named(val_type, ptrType, value_type);
00080 }
00081 }
00082 return false;
00083 }
00084
00085 bool
00086 is_RefToBaseVector(Reflex::Type const& possible_ref_vector,
00087 Reflex::Type& value_type) {
00088
00089 static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefToBaseVector", 1));
00090 static std::string member_type("member_type");
00091 TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00092 if(primary_template_id == ref_vector_template_id) {
00093 return find_nested_type_named(member_type, possible_ref_vector, value_type);
00094 }
00095 return false;
00096 }
00097
00098 namespace {
00099
00100 int const oneParamArraySize = 6;
00101 std::string const oneParam[oneParamArraySize] = {
00102 "vector",
00103 "basic_string",
00104 "set",
00105 "list",
00106 "deque",
00107 "multiset"
00108 };
00109 int const twoParamArraySize = 3;
00110 std::string const twoParam[twoParamArraySize] = {
00111 "map",
00112 "pair",
00113 "multimap"
00114 };
00115
00116
00117 bool
00118 hasCintDictionary(std::string const& name) {
00119 std::auto_ptr<G__ClassInfo> ci(new G__ClassInfo(name.c_str()));
00120 return(ci.get() && ci->IsLoaded());
00121 }
00122
00123
00124
00125
00126 void
00127 checkType(Type t, bool noComponents = false) {
00128
00129
00130
00131
00132
00133 Type null;
00134 for(Type x = t.ToType(); x != null && x != t; t = x, x = t.ToType()) {}
00135
00136 std::string name = t.Name(SCOPED);
00137 boost::trim(name);
00138
00139 if(foundTypes().end() != foundTypes().find(name) || missingTypes().end() != missingTypes().find(name)) {
00140
00141 return;
00142 }
00143
00144 if(name.empty() || t.IsFundamental() || t.IsEnum()) {
00145 foundTypes().insert(name);
00146 return;
00147 }
00148
00149 if(!bool(t)) {
00150 if(hasCintDictionary(name)) {
00151 foundTypes().insert(name);
00152 } else {
00153 missingTypes().insert(name);
00154 }
00155 return;
00156 }
00157
00158 foundTypes().insert(name);
00159 if(noComponents) return;
00160
00161 if(name.find("std::") == 0) {
00162 if(t.IsTemplateInstance()) {
00163 std::string::size_type n = name.find('<');
00164 int cnt = 0;
00165 if(std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, n - 5)) != oneParam + oneParamArraySize) {
00166 cnt = 1;
00167 } else if(std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, n - 5)) != twoParam + twoParamArraySize) {
00168 cnt = 2;
00169 }
00170 for(int i = 0; i < cnt; ++i) {
00171 checkType(t.TemplateArgumentAt(i));
00172 }
00173 }
00174 } else {
00175 int mcnt = t.DataMemberSize();
00176 for(int i = 0; i < mcnt; ++i) {
00177 Member m = t.DataMemberAt(i);
00178 if(m.IsTransient() || m.IsStatic()) continue;
00179 checkType(m.TypeOf());
00180 }
00181 int cnt = t.BaseSize();
00182 for(int i = 0; i < cnt; ++i) {
00183 checkType(t.BaseAt(i).ToType());
00184 }
00185 }
00186 }
00187 }
00188
00189 StringSet& missingTypes() {
00190 return missingTypes_;
00191 }
00192
00193 StringSet& foundTypes() {
00194
00195
00196 return foundTypes_;
00197 }
00198
00199 void checkDictionaries(std::string const& name, bool noComponents) {
00200 Type null;
00201 Type t = Type::ByName(name);
00202 if(t == null) {
00203 missingTypes().insert(name);
00204 return;
00205 }
00206 checkType(Type::ByName(name), noComponents);
00207 }
00208
00209 void throwMissingDictionariesException() {
00210 if(!missingTypes().empty()) {
00211 std::ostringstream ostr;
00212 for (StringSet::const_iterator it = missingTypes().begin(), itEnd = missingTypes().end();
00213 it != itEnd; ++it) {
00214 ostr << *it << "\n\n";
00215 }
00216 throw Exception(errors::DictionaryNotFound)
00217 << "No REFLEX data dictionary found for the following classes:\n\n"
00218 << ostr.str()
00219 << "Most likely each dictionary was never generated,\n"
00220 << "but it may be that it was generated in the wrong package.\n"
00221 << "Please add (or move) the specification\n"
00222 << "<class name=\"whatever\"/>\n"
00223 << "to the appropriate classes_def.xml file.\n"
00224 << "If the class is a template instance, you may need\n"
00225 << "to define a dummy variable of this type in classes.h.\n"
00226 << "Also, if this class has any transient members,\n"
00227 << "you need to specify them in classes_def.xml.";
00228 }
00229 }
00230
00231 void loadMissingDictionaries() {
00232 while (!missingTypes().empty()) {
00233 StringSet missing(missingTypes());
00234 for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00235 it != itEnd; ++it) {
00236 try {
00237 gROOT->GetClass(it->c_str(), kTRUE);
00238 }
00239
00240 catch(...) {}
00241 }
00242 missingTypes().clear();
00243 for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00244 it != itEnd; ++it) {
00245 checkDictionaries(*it);
00246 }
00247 if (missingTypes() == missing) {
00248 break;
00249 }
00250 }
00251 if (missingTypes().empty()) {
00252 return;
00253 }
00254 throwMissingDictionariesException();
00255 }
00256
00257 void public_base_classes(Type const& type,
00258 std::vector<Type>& baseTypes) {
00259
00260 if(type.IsClass() || type.IsStruct()) {
00261
00262 int nBase = type.BaseSize();
00263 for(int i = 0; i < nBase; ++i) {
00264
00265 Base base = type.BaseAt(i);
00266 if(base.IsPublic()) {
00267
00268 Type baseType = type.BaseAt(i).ToType();
00269 if(bool(baseType)) {
00270
00271 while(baseType.IsTypedef() == true) {
00272 baseType = baseType.ToType();
00273 }
00274
00275
00276
00277 if(!search_all(baseTypes, baseType)) {
00278
00279 baseTypes.push_back(baseType);
00280 public_base_classes(baseType, baseTypes);
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 }
00303 }
00304 }
00305 }
00306 }
00307
00308 void const*
00309 reflex_pointer_adjust(void* raw,
00310 Type const& dynamicType,
00311 std::type_info const& toType) {
00312 Object obj(dynamicType, raw);
00313 return obj.CastObject(Type::ByTypeInfo(toType)).Address();
00314 }
00315 }