CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ReflexTools.cc
Go to the documentation of this file.
1 #include <algorithm>
2 #include <sstream>
3 
4 #include "boost/algorithm/string.hpp"
5 #include "boost/thread/tss.hpp"
6 
7 #include "Reflex/Base.h"
8 #include "Reflex/Member.h"
9 #include "Reflex/TypeTemplate.h"
10 #include "Api.h" // for G__ClassInfo
11 
14 
15 using Reflex::Base;
16 using Reflex::FINAL;
17 using Reflex::Member;
18 using Reflex::Object;
19 using Reflex::SCOPED;
20 using Reflex::Type;
21 using Reflex::TypeTemplate;
22 using Reflex::Type_Iterator;
23 
24 namespace edm {
25 
27  while (t.IsTypedef()) t = t.ToType();
28  return t;
29  }
30 
31  bool
32  find_nested_type_named(std::string const& nested_type,
33  Type const& type_to_search,
34  Type& found_type) {
35  // Look for a sub-type named 'nested_type'
36  for (Type_Iterator
37  i = type_to_search.SubType_Begin(),
38  e = type_to_search.SubType_End();
39  i != e;
40  ++i) {
41  if (i->Name() == nested_type) {
42  found_type = get_final_type(*i);
43  return true;
44  }
45  }
46  return false;
47  }
48 
49  bool
50  if_edm_ref_get_value_type(Type const& possible_ref,
51  Type& result) {
52  TypeTemplate primary_template_id(possible_ref.TemplateFamily());
53  if (primary_template_id == TypeTemplate::ByName("edm::Ref", 3)) {
54  (void)value_type_of(possible_ref, result);
55  return true;
56  } else {
57  result = possible_ref;
58  return false;
59  }
60  }
61 
62  bool
63  if_edm_ptr_get_value_type(Type const& possible_ref,
64  Type& result) {
65  TypeTemplate primary_template_id(possible_ref.TemplateFamily());
66  if (primary_template_id == TypeTemplate::ByName("edm::Ptr", 1)) {
67  (void)value_type_of(possible_ref, result);
68  return true;
69  } else {
70  result = possible_ref;
71  return false;
72  }
73  }
74 
75  bool
77  Type& result) {
78  TypeTemplate primary_template_id(possible_ref.TemplateFamily());
79  if (primary_template_id == TypeTemplate::ByName("edm::RefToBase", 1)) {
80  (void)value_type_of(possible_ref, result);
81  return true;
82  } else {
83  result = possible_ref;
84  return false;
85  }
86  }
87 
88  bool
89  is_sequence_wrapper(Type const& possible_sequence_wrapper,
90  Type& found_sequence_value_type) {
91  Type possible_sequence;
92  if (!edm::wrapper_type_of(possible_sequence_wrapper, possible_sequence)) {
93  return false;
94  }
95 
96  Type outer_value_type;
97  if (!edm::value_type_of(possible_sequence, outer_value_type)) {
98  return false;
99  }
100 
101  if (!if_edm_ref_get_value_type(outer_value_type,
102  found_sequence_value_type)) {
103 
104  if (!if_edm_ptr_get_value_type(outer_value_type,
105  found_sequence_value_type)) {
106 
107  if_edm_refToBase_get_value_type(outer_value_type,
108  found_sequence_value_type);
109  }
110  }
111  return true;
112  }
113 
114  bool
115  is_RefVector(Reflex::Type const& possible_ref_vector,
117 
118  static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefVector", 3));
119  static std::string member_type("member_type");
120  TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
121  if (primary_template_id == ref_vector_template_id) {
122  return find_nested_type_named(member_type, possible_ref_vector, value_type);
123  }
124  return false;
125  }
126 
127  bool
128  is_PtrVector(Reflex::Type const& possible_ref_vector,
130 
131  static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::PtrVector", 1));
132  static std::string member_type("member_type");
133  static std::string val_type("value_type");
134  TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
135  if (primary_template_id == ref_vector_template_id) {
136  Reflex::Type ptrType;
137  if (find_nested_type_named(val_type, possible_ref_vector, ptrType)) {
138  return find_nested_type_named(val_type, ptrType, value_type);
139  }
140  }
141  return false;
142  }
143 
144  bool
145  is_RefToBaseVector(Reflex::Type const& possible_ref_vector,
147 
148  static TypeTemplate ref_vector_template_id(TypeTemplate::ByName("edm::RefToBaseVector", 1));
149  static std::string member_type("member_type");
150  TypeTemplate primary_template_id(possible_ref_vector.TemplateFamily());
151  if (primary_template_id == ref_vector_template_id) {
152  return find_nested_type_named(member_type, possible_ref_vector, value_type);
153  }
154  return false;
155  }
156 
157  namespace {
158 
159  int const oneParamArraySize = 6;
160  std::string const oneParam[oneParamArraySize] = {
161  "vector",
162  "basic_string",
163  "set",
164  "list",
165  "deque",
166  "multiset"
167  };
168  int const twoParamArraySize = 3;
169  std::string const twoParam[twoParamArraySize] = {
170  "map",
171  "pair",
172  "multimap"
173  };
174 
175 
176  bool
177  hasCintDictionary(std::string const& name) {
178  std::auto_ptr<G__ClassInfo> ci(new G__ClassInfo(name.c_str()));
179  return (ci.get() && ci->IsLoaded());
180  }
181 
182  // Checks if there is a Reflex dictionary for the Type t.
183  // If noComponents is false, checks members and base classes recursively.
184  // If noComponents is true, checks Type t only.
185  void
186  checkType(Type t, bool noComponents = false) {
187 
188  // The only purpose of this cache is to stop infinite recursion.
189  // Reflex maintains its own internal cache.
190  static boost::thread_specific_ptr<StringSet> found_types;
191  if (0 == found_types.get()) {
192  found_types.reset(new StringSet);
193  }
194 
195  // ToType strips const, volatile, array, pointer, reference, etc.,
196  // and also translates typedefs.
197  // To be safe, we do this recursively until we either get a null type
198  // or the same type.
199  Type null;
200  for (Type x = t.ToType(); x != null && x != t; t = x, x = t.ToType()) {}
201 
202  std::string name = t.Name(SCOPED);
203  boost::trim(name);
204 
205  if (found_types->end() != found_types->find(name) || missingTypes().end() != missingTypes().find(name)) {
206  // Already been processed. Prevents infinite loop.
207  return;
208  }
209 
210  if (name.empty() || t.IsFundamental() || t.IsEnum()) {
211  found_types->insert(name);
212  return;
213  }
214 
215  if (!bool(t)) {
216  if (hasCintDictionary(name)) {
217  found_types->insert(name);
218  } else {
219  missingTypes().insert(name);
220  }
221  return;
222  }
223 
224  found_types->insert(name);
225  if (noComponents) return;
226 
227  if (name.find("std::") == 0) {
228  if (t.IsTemplateInstance()) {
229  std::string::size_type n = name.find('<');
230  int cnt = 0;
231  if (std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, n - 5)) != oneParam + oneParamArraySize) {
232  cnt = 1;
233  } else if (std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, n - 5)) != twoParam + twoParamArraySize) {
234  cnt = 2;
235  }
236  for(int i = 0; i < cnt; ++i) {
237  checkType(t.TemplateArgumentAt(i));
238  }
239  }
240  } else {
241  int mcnt = t.DataMemberSize();
242  for(int i = 0; i < mcnt; ++i) {
243  Member m = t.DataMemberAt(i);
244  if(m.IsTransient() || m.IsStatic()) continue;
245  checkType(m.TypeOf());
246  }
247  int cnt = t.BaseSize();
248  for(int i = 0; i < cnt; ++i) {
249  checkType(t.BaseAt(i).ToType());
250  }
251  }
252  }
253  } // end unnamed namespace
254 
256  static boost::thread_specific_ptr<StringSet> missingTypes_;
257  if (0 == missingTypes_.get()) {
258  missingTypes_.reset(new StringSet);
259  }
260  return *missingTypes_.get();
261  }
262 
263  void checkDictionaries(std::string const& name, bool noComponents) {
264  Type null;
265  Type t = Type::ByName(name);
266  if (t == null) {
267  missingTypes().insert(name);
268  return;
269  }
270  checkType(Type::ByName(name), noComponents);
271  }
272 
274  std::vector<Type>& baseTypes) {
275 
276  if (type.IsClass() || type.IsStruct()) {
277 
278  int nBase = type.BaseSize();
279  for (int i = 0; i < nBase; ++i) {
280 
281  Base base = type.BaseAt(i);
282  if (base.IsPublic()) {
283 
284  Type baseType = type.BaseAt(i).ToType();
285  if (bool(baseType)) {
286 
287  while (baseType.IsTypedef() == true) {
288  baseType = baseType.ToType();
289  }
290 
291  // Check to make sure this base appears only once in the
292  // inheritance heirarchy.
293  if (!search_all(baseTypes, baseType)) {
294  // Save the type and recursive look for its base types
295  baseTypes.push_back(baseType);
296  public_base_classes(baseType, baseTypes);
297  }
298  // For now just ignore it if the class appears twice,
299  // After some more testing we may decide to uncomment the following
300  // exception.
301  /*
302  else {
303  throw edm::Exception(edm::errors::UnimplementedFeature)
304  << "DataFormats/Common/src/ReflexTools.cc in function public_base_classes.\n"
305  << "Encountered class that has a public base class that appears\n"
306  << "multiple times in its inheritance heirarchy.\n"
307  << "Please contact the EDM Framework group with details about\n"
308  << "this exception. It was our hope that this complicated situation\n"
309  << "would not occur. There are three possible solutions. 1. Change\n"
310  << "the class design so the public base class does not appear multiple\n"
311  << "times in the inheritance heirarchy. In many cases, this is a\n"
312  << "sign of bad design. 2. Modify the code that supports Views to\n"
313  << "ignore these base classes, but not supply support for creating a\n"
314  << "View of this base class. 3. Improve the View infrastructure to\n"
315  << "deal with this case. Class name of base class: " << baseType.Name() << "\n\n";
316  }
317  */
318  }
319  }
320  }
321  }
322  }
323 
324  void const*
326  Type const& dynamicType,
327  std::type_info const& toType)
328  {
329  Object obj(dynamicType, raw);
330  return obj.CastObject(Type::ByTypeInfo(toType)).Address();
331  }
332 }
bool if_edm_ref_get_value_type(Reflex::Type const &possible_ref, Reflex::Type &value_type)
tuple base
Main Program
Definition: newFWLiteAna.py:92
type
Definition: HCALResponse.h:22
int i
Definition: DBlmapReader.cc:9
void public_base_classes(const Reflex::Type &type, std::vector< Reflex::Type > &baseTypes)
bool is_RefToBaseVector(Reflex::Type const &possible_ref_vector, Reflex::Type &value_type)
Definition: ReflexTools.cc:145
bool is_sequence_wrapper(Reflex::Type const &possible_sequence_wrapper, Reflex::Type &found_sequence_value_type)
bool is_PtrVector(Reflex::Type const &possible_ref_vector, Reflex::Type &value_type)
Definition: ReflexTools.cc:128
bool value_type_of(Reflex::Type const &t, Reflex::Type &found_type)
Definition: ReflexTools.h:31
void const * reflex_pointer_adjust(void *raw, Reflex::Type const &dynamicType, std::type_info const &toType)
Container::value_type value_type
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
uint16_t size_type
tuple obj
Example code starts here #.
Definition: VarParsing.py:655
StringSet & missingTypes()
Definition: ReflexTools.cc:255
bool if_edm_ptr_get_value_type(Reflex::Type const &possible_ref, Reflex::Type &value_type)
bool wrapper_type_of(Reflex::Type const &possible_wrapper, Reflex::Type &found_wrapped_type)
Definition: ReflexTools.h:39
std::set< std::string > StringSet
Definition: ReflexTools.h:22
tuple result
Definition: query.py:137
void checkDictionaries(std::string const &name, bool noComponents=false)
Definition: ReflexTools.cc:263
bool find_nested_type_named(std::string const &nested_type, Reflex::Type const &type_to_search, Reflex::Type &found_type)
bool if_edm_refToBase_get_value_type(Reflex::Type const &possible_ref, Reflex::Type &value_type)
bool search_all(ForwardSequence const &s, Datum const &d)
Definition: Algorithms.h:46
bool is_RefVector(Reflex::Type const &possible_ref_vector, Reflex::Type &value_type)
Definition: ReflexTools.cc:115
Type get_final_type(Type t)
Definition: ReflexTools.cc:26