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"
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
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
00170
00171
00172 void
00173 checkType(Type t, bool noComponents = false) {
00174
00175
00176
00177 static boost::thread_specific_ptr<StringSet> s_types;
00178 if (0 == s_types.get()) {
00179 s_types.reset(new StringSet);
00180 }
00181
00182
00183
00184
00185
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
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 }
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
00297
00298 if (!search_all(baseTypes, baseType)) {
00299
00300 baseTypes.push_back(baseType);
00301 public_base_classes(baseType, baseTypes);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
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 }