00001 #include <algorithm>
00002 #include <sstream>
00003
00004 #include "boost/algorithm/string.hpp"
00005 #include "boost/thread/tss.hpp"
00006
00007 #include "Reflex/Base.h"
00008 #include "Reflex/Member.h"
00009 #include "Reflex/TypeTemplate.h"
00010 #include "Api.h"
00011
00012 #include "FWCore/Utilities/interface/ReflexTools.h"
00013 #include "FWCore/Utilities/interface/Algorithms.h"
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
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 if_edm_ref_get_value_type(Type const& possible_ref,
00051 Type& result) {
00052 TypeTemplate primary_template_id(possible_ref.TemplateFamily());
00053 if (primary_template_id == TypeTemplate::ByName("edm::Ref", 3)) {
00054 (void)value_type_of(possible_ref, result);
00055 return true;
00056 } else {
00057 result = possible_ref;
00058 return false;
00059 }
00060 }
00061
00062 bool
00063 if_edm_ptr_get_value_type(Type const& possible_ref,
00064 Type& result) {
00065 TypeTemplate primary_template_id(possible_ref.TemplateFamily());
00066 if (primary_template_id == TypeTemplate::ByName("edm::Ptr", 1)) {
00067 (void)value_type_of(possible_ref, result);
00068 return true;
00069 } else {
00070 result = possible_ref;
00071 return false;
00072 }
00073 }
00074
00075 bool
00076 if_edm_refToBase_get_value_type(Type const& possible_ref,
00077 Type& result) {
00078 TypeTemplate primary_template_id(possible_ref.TemplateFamily());
00079 if (primary_template_id == TypeTemplate::ByName("edm::RefToBase", 1)) {
00080 (void)value_type_of(possible_ref, result);
00081 return true;
00082 } else {
00083 result = possible_ref;
00084 return false;
00085 }
00086 }
00087
00088 bool
00089 is_sequence_wrapper(Type const& possible_sequence_wrapper,
00090 Type& found_sequence_value_type) {
00091 Type possible_sequence;
00092 if (!edm::wrapper_type_of(possible_sequence_wrapper, possible_sequence)) {
00093 return false;
00094 }
00095
00096 Type outer_value_type;
00097 if (!edm::value_type_of(possible_sequence, outer_value_type)) {
00098 return false;
00099 }
00100
00101 if (!if_edm_ref_get_value_type(outer_value_type,
00102 found_sequence_value_type)) {
00103
00104 if (!if_edm_ptr_get_value_type(outer_value_type,
00105 found_sequence_value_type)) {
00106
00107 if_edm_refToBase_get_value_type(outer_value_type,
00108 found_sequence_value_type);
00109 }
00110 }
00111 return true;
00112 }
00113
00114 bool
00115 is_RefVector(Reflex::Type const& possible_ref_vector,
00116 Reflex::Type& value_type) {
00117
00118 static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefVector", 3));
00119 static std::string member_type("member_type");
00120 TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00121 if (primary_template_id == ref_vector_template_id) {
00122 return find_nested_type_named(member_type, possible_ref_vector, value_type);
00123 }
00124 return false;
00125 }
00126
00127 bool
00128 is_PtrVector(Reflex::Type const& possible_ref_vector,
00129 Reflex::Type& value_type) {
00130
00131 static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::PtrVector", 1));
00132 static std::string member_type("member_type");
00133 static std::string val_type("value_type");
00134 TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00135 if (primary_template_id == ref_vector_template_id) {
00136 Reflex::Type ptrType;
00137 if (find_nested_type_named(val_type, possible_ref_vector, ptrType)) {
00138 return find_nested_type_named(val_type, ptrType, value_type);
00139 }
00140 }
00141 return false;
00142 }
00143
00144 bool
00145 is_RefToBaseVector(Reflex::Type const& possible_ref_vector,
00146 Reflex::Type& value_type) {
00147
00148 static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefToBaseVector", 1));
00149 static std::string member_type("member_type");
00150 TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
00151 if (primary_template_id == ref_vector_template_id) {
00152 return find_nested_type_named(member_type, possible_ref_vector, value_type);
00153 }
00154 return false;
00155 }
00156
00157 namespace {
00158
00159 int const oneParamArraySize = 6;
00160 std::string const oneParam[oneParamArraySize] = {
00161 "vector",
00162 "basic_string",
00163 "set",
00164 "list",
00165 "deque",
00166 "multiset"
00167 };
00168 int const twoParamArraySize = 3;
00169 std::string const twoParam[twoParamArraySize] = {
00170 "map",
00171 "pair",
00172 "multimap"
00173 };
00174
00175
00176 bool
00177 hasCintDictionary(std::string const& name) {
00178 std::auto_ptr<G__ClassInfo> ci(new G__ClassInfo(name.c_str()));
00179 return (ci.get() && ci->IsLoaded());
00180 }
00181
00182
00183
00184
00185 void
00186 checkType(Type t, bool noComponents = false) {
00187
00188
00189
00190 static boost::thread_specific_ptr<StringSet> found_types;
00191 if (0 == found_types.get()) {
00192 found_types.reset(new StringSet);
00193 }
00194
00195
00196
00197
00198
00199 Type null;
00200 for (Type x = t.ToType(); x != null && x != t; t = x, x = t.ToType()) {}
00201
00202 std::string name = t.Name(SCOPED);
00203 boost::trim(name);
00204
00205 if (found_types->end() != found_types->find(name) || missingTypes().end() != missingTypes().find(name)) {
00206
00207 return;
00208 }
00209
00210 if (name.empty() || t.IsFundamental() || t.IsEnum()) {
00211 found_types->insert(name);
00212 return;
00213 }
00214
00215 if (!bool(t)) {
00216 if (hasCintDictionary(name)) {
00217 found_types->insert(name);
00218 } else {
00219 missingTypes().insert(name);
00220 }
00221 return;
00222 }
00223
00224 found_types->insert(name);
00225 if (noComponents) return;
00226
00227 if (name.find("std::") == 0) {
00228 if (t.IsTemplateInstance()) {
00229 std::string::size_type n = name.find('<');
00230 int cnt = 0;
00231 if (std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, n - 5)) != oneParam + oneParamArraySize) {
00232 cnt = 1;
00233 } else if (std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, n - 5)) != twoParam + twoParamArraySize) {
00234 cnt = 2;
00235 }
00236 for(int i = 0; i < cnt; ++i) {
00237 checkType(t.TemplateArgumentAt(i));
00238 }
00239 }
00240 } else {
00241 int mcnt = t.DataMemberSize();
00242 for(int i = 0; i < mcnt; ++i) {
00243 Member m = t.DataMemberAt(i);
00244 if(m.IsTransient() || m.IsStatic()) continue;
00245 checkType(m.TypeOf());
00246 }
00247 int cnt = t.BaseSize();
00248 for(int i = 0; i < cnt; ++i) {
00249 checkType(t.BaseAt(i).ToType());
00250 }
00251 }
00252 }
00253 }
00254
00255 StringSet& missingTypes() {
00256 static boost::thread_specific_ptr<StringSet> missingTypes_;
00257 if (0 == missingTypes_.get()) {
00258 missingTypes_.reset(new StringSet);
00259 }
00260 return *missingTypes_.get();
00261 }
00262
00263 void checkDictionaries(std::string const& name, bool noComponents) {
00264 Type null;
00265 Type t = Type::ByName(name);
00266 if (t == null) {
00267 missingTypes().insert(name);
00268 return;
00269 }
00270 checkType(Type::ByName(name), noComponents);
00271 }
00272
00273 void public_base_classes(const Type& type,
00274 std::vector<Type>& baseTypes) {
00275
00276 if (type.IsClass() || type.IsStruct()) {
00277
00278 int nBase = type.BaseSize();
00279 for (int i = 0; i < nBase; ++i) {
00280
00281 Base base = type.BaseAt(i);
00282 if (base.IsPublic()) {
00283
00284 Type baseType = type.BaseAt(i).ToType();
00285 if (bool(baseType)) {
00286
00287 while (baseType.IsTypedef() == true) {
00288 baseType = baseType.ToType();
00289 }
00290
00291
00292
00293 if (!search_all(baseTypes, baseType)) {
00294
00295 baseTypes.push_back(baseType);
00296 public_base_classes(baseType, baseTypes);
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 }
00319 }
00320 }
00321 }
00322 }
00323
00324 void const*
00325 reflex_pointer_adjust(void* raw,
00326 Type const& dynamicType,
00327 std::type_info const& toType)
00328 {
00329 Object obj(dynamicType, raw);
00330 return obj.CastObject(Type::ByTypeInfo(toType)).Address();
00331 }
00332 }