CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
XMLOutputModule.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Modules
4 // Class : XMLOutputModule
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Chris Jones
10 // Created: Fri Aug 4 20:45:44 EDT 2006
11 //
12 
13 // system include files
14 #include <fstream>
15 #include <string>
16 #include <iomanip>
17 #include <map>
18 #include <sstream>
19 #include <algorithm>
20 
21 #include "Reflex/Base.h"
22 #include "Reflex/Member.h"
23 
27 
31 
36 
37 // user include files
38 
39 //
40 // constants, enums and typedefs
41 //
42 
43 namespace edm {
44  class XMLOutputModule : public OutputModule {
45 
46  public:
48  virtual ~XMLOutputModule();
49  static void fillDescriptions(ConfigurationDescriptions& descriptions);
50 
51  // ---------- const member functions ---------------------
52 
53  // ---------- static member functions --------------------
54 
55  // ---------- member functions ---------------------------
56 
57  private:
58  virtual void write(EventPrincipal const& e);
60  virtual void writeRun(RunPrincipal const&) {}
61 
62  XMLOutputModule(XMLOutputModule const&); // stop default
63 
64  XMLOutputModule const& operator=(XMLOutputModule const&); // stop default
65 
66  // ---------- member data --------------------------------
67  std::ofstream stream_;
68  std::string indentation_;
69  };
70 
71  namespace {
72  void doNotDelete(void*) {}
73  void callDestruct(Reflex::Object* iObj) {
74  iObj->Destruct();
75  }
76  //Handle memory for calls to Reflex Invoke
77  // We handle Ref's by using an external void* buffer (which we do not delete) while everything else
78  // we ask Reflex to create the proper object (and therefore must ask Reflex to delete it)
79  boost::shared_ptr<Reflex::Object> initReturnValue(Reflex::Member const& iMember,
80  Reflex::Object* iObj,
81  void** iRefBuffer) {
82  Reflex::Type returnType = iMember.TypeOf().ReturnType();
83  if(returnType.IsReference()) {
84  *iObj = Reflex::Object(returnType, iRefBuffer);
85  return boost::shared_ptr<Reflex::Object>(iObj, doNotDelete);
86  }
87  *iObj = returnType.Construct();
88  return boost::shared_ptr<Reflex::Object>(iObj, callDestruct);
89  }
90 
91  //remove characters from a string which are not allowed to be used in XML
92  std::string formatXML(std::string const& iO) {
93  std::string result(iO);
94  static std::string const kSubs("<>&");
95  static std::string const kLeft("&lt;");
96  static std::string const kRight("&gt;");
97  static std::string const kAmp("&");
98 
100  while(std::string::npos != (i = result.find_first_of(kSubs, i))) {
101  switch(result.at(i)) {
102  case '<':
103  result.replace(i, 1, kLeft);
104  break;
105  case '>':
106  result.replace(i, 1, kRight);
107  break;
108  case '&':
109  result.replace(i, 1, kAmp);
110  }
111  ++i;
112  }
113  return result;
114  }
115 
116  char const* kNameValueSep = "\">";
117  char const* kContainerOpen = "<container size=\"";
118  char const* kContainerClose = "</container>";
119  std::string const kObjectOpen = "<object type=\"";
120  std::string const kObjectClose = "</object>";
122  #define FILLNAME(_type_) s_toName[typeid(_type_).name()]= #_type_;
123  std::string const& typeidToName(std::type_info const& iID) {
124  static std::map<std::string, std::string> s_toName;
125  if(s_toName.empty()) {
126  FILLNAME(short);
127  FILLNAME(int);
128  FILLNAME(long);
129  FILLNAME(long long);
130 
131  FILLNAME(unsigned short);
132  FILLNAME(unsigned int);
133  FILLNAME(unsigned long);
134  FILLNAME(unsigned long long);
135 
136  FILLNAME(double);
137  FILLNAME(float);
138  }
139  return s_toName[iID.name()];
140  }
141 
142  template<typename T>
143  void doPrint(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
144  oStream << iIndent << iPrefix << typeidToName(typeid(T)) << kNameValueSep
145  << *reinterpret_cast<T*>(iObject.Address()) << iPostfix << "\n";
146  }
147 
148  template<>
149  void doPrint<char>(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
150  oStream << iIndent << iPrefix << "char" << kNameValueSep
151  << static_cast<int>(*reinterpret_cast<char*>(iObject.Address())) << iPostfix << "\n";
152  }
153 
154  template<>
155  void doPrint<unsigned char>(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
156  oStream << iIndent << iPrefix << "unsigned char" << kNameValueSep << static_cast<unsigned int>(*reinterpret_cast<unsigned char*>(iObject.Address())) << iPostfix << "\n";
157  }
158 
159  template<>
160  void doPrint<bool>(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
161  oStream << iIndent << iPrefix << "bool" << kNameValueSep
162  << ((*reinterpret_cast<bool*>(iObject.Address()))?"true":"false") << iPostfix << "\n";
163  }
164 
165 
166  typedef void(*FunctionType)(std::ostream&, std::string const&,
167  std::string const&, Reflex::Object const&, std::string const&);
168  typedef std::map<std::string, FunctionType> TypeToPrintMap;
169 
170  template<typename T>
171  void addToMap(TypeToPrintMap& iMap){
172  iMap[typeid(T).name()]=doPrint<T>;
173  }
174 
175  bool printAsBuiltin(std::ostream& oStream,
176  std::string const& iPrefix,
177  std::string const& iPostfix,
178  Reflex::Object const iObject,
179  std::string const& iIndent){
180  typedef void(*FunctionType)(std::ostream&, std::string const&, std::string const&, Reflex::Object const&, std::string const&);
181  typedef std::map<std::string, FunctionType> TypeToPrintMap;
182  static TypeToPrintMap s_map;
183  static bool isFirst = true;
184  if(isFirst){
185  addToMap<bool>(s_map);
186  addToMap<char>(s_map);
187  addToMap<short>(s_map);
188  addToMap<int>(s_map);
189  addToMap<long>(s_map);
190  addToMap<unsigned char>(s_map);
191  addToMap<unsigned short>(s_map);
192  addToMap<unsigned int>(s_map);
193  addToMap<unsigned long>(s_map);
194  addToMap<float>(s_map);
195  addToMap<double>(s_map);
196  isFirst=false;
197  }
198  TypeToPrintMap::iterator itFound =s_map.find(iObject.TypeOf().TypeInfo().name());
199  if(itFound == s_map.end()){
200 
201  return false;
202  }
203  itFound->second(oStream, iPrefix, iPostfix, iObject, iIndent);
204  return true;
205  }
206 
207  bool printAsContainer(std::ostream& oStream,
208  std::string const& iPrefix,
209  std::string const& iPostfix,
210  Reflex::Object const& iObject,
211  std::string const& iIndent,
212  std::string const& iIndentDelta);
213 
214  void printDataMembers(std::ostream& oStream,
215  Reflex::Object const& iObject,
216  Reflex::Type const& iType,
217  std::string const& iIndent,
218  std::string const& iIndentDelta);
219 
220  void printObject(std::ostream& oStream,
221  std::string const& iPrefix,
222  std::string const& iPostfix,
223  Reflex::Object const& iObject,
224  std::string const& iIndent,
225  std::string const& iIndentDelta) {
226  Reflex::Object objectToPrint = iObject;
227  std::string indent(iIndent);
228  if(iObject.TypeOf().IsPointer()) {
229  oStream << iIndent << iPrefix << formatXML(iObject.TypeOf().Name(Reflex::SCOPED)) << "\">\n";
230  indent +=iIndentDelta;
231  int size = (0!=iObject.Address()) ? (0!=*reinterpret_cast<void**>(iObject.Address())?1:0) : 0;
232  oStream << indent << kContainerOpen << size << "\">\n";
233  if(size) {
234  std::string indent2 = indent + iIndentDelta;
235  Reflex::Object obj(iObject.TypeOf().ToType(), *reinterpret_cast<void**>(iObject.Address()));
236  obj = obj.CastObject(obj.DynamicType());
237  printObject(oStream, kObjectOpen, kObjectClose, obj, indent2, iIndentDelta);
238  }
239  oStream << indent << kContainerClose << "\n";
240  oStream << iIndent << iPostfix << "\n";
241  Reflex::Type pointedType = iObject.TypeOf().ToType();
242  if(Reflex::Type::ByName("void") == pointedType || pointedType.IsPointer() || iObject.Address()==0) {
243  return;
244  }
245  return;
246  /*
247  //have the code that follows print the contents of the data to which the pointer points
248  objectToPrint = Reflex::Object(pointedType, iObject.Address());
249  //try to convert it to its actual type (assuming the original type was a base class)
250  objectToPrint = Reflex::Object(objectToPrint.CastObject(objectToPrint.DynamicType()));
251  indent +=iIndentDelta;
252  */
253  }
254  std::string typeName(objectToPrint.TypeOf().Name(Reflex::SCOPED));
255  if(typeName.empty()){
256  typeName="{unknown}";
257  }
258 
259  //see if we are dealing with a typedef
260  Reflex::Type objectType = objectToPrint.TypeOf();
261  bool wasTypedef = false;
262  while(objectType.IsTypedef()) {
263  objectType = objectType.ToType();
264  wasTypedef = true;
265  }
266  if(wasTypedef){
267  Reflex::Object tmp(objectType, objectToPrint.Address());
268  objectToPrint = tmp;
269  }
270  if(printAsBuiltin(oStream, iPrefix, iPostfix, objectToPrint, indent)) {
271  return;
272  }
273  if(printAsContainer(oStream, iPrefix, iPostfix, objectToPrint, indent, iIndentDelta)){
274  return;
275  }
276 
277  oStream << indent << iPrefix << formatXML(typeName) << "\">\n";
278  printDataMembers(oStream, objectToPrint, objectType, indent+iIndentDelta, iIndentDelta);
279  oStream << indent << iPostfix << "\n";
280 
281  }
282 
283  void printDataMembers(std::ostream& oStream,
284  Reflex::Object const& iObject,
285  Reflex::Type const& iType,
286  std::string const& iIndent,
287  std::string const& iIndentDelta) {
288  //print all the base class data members
289  for(Reflex::Base_Iterator itBase = iType.Base_Begin();
290  itBase != iType.Base_End();
291  ++itBase) {
292  printDataMembers(oStream, iObject.CastObject(itBase->ToType()), itBase->ToType(), iIndent, iIndentDelta);
293  }
294  static std::string const kPrefix("<datamember name=\"");
295  static std::string const ktype("\" type=\"");
296  static std::string const kPostfix("</datamember>");
297 
298  for(Reflex::Member_Iterator itMember = iType.DataMember_Begin();
299  itMember != iType.DataMember_End();
300  ++itMember){
301  //std::cout << " debug " << itMember->Name() << " " << itMember->TypeOf().Name() << "\n";
302  if (itMember->IsTransient()) {
303  continue;
304  }
305  try {
306  std::string prefix = kPrefix + itMember->Name() + ktype;
307  printObject(oStream,
308  prefix,
309  kPostfix,
310  itMember->Get(iObject),
311  iIndent,
312  iIndentDelta);
313  }catch(std::exception& iEx) {
314  std::cout << iIndent << itMember->Name() << " <exception caught("
315  << iEx.what() << ")>\n";
316  }
317  }
318  }
319 
320  bool printContentsOfStdContainer(std::ostream& oStream,
321  std::string const& iPrefix,
322  std::string const& iPostfix,
323  Reflex::Object iBegin,
324  Reflex::Object const& iEnd,
325  std::string const& iIndent,
326  std::string const& iIndentDelta){
327  size_t size = 0;
328  std::ostringstream sStream;
329  if(iBegin.TypeOf() != iEnd.TypeOf()) {
330  std::cerr << " begin (" << iBegin.TypeOf().Name(Reflex::SCOPED) << ") and end ("
331  << iEnd.TypeOf().Name(Reflex::SCOPED) << ") are not the same type" << std::endl;
332  throw std::exception();
333  }
334  try {
335  Reflex::Member compare(iBegin.TypeOf().MemberByName("operator!="));
336  if(!compare) {
337  //std::cerr << "no 'operator!=' for " << iBegin.TypeOf().Name() << std::endl;
338  return false;
339  }
340  Reflex::Member incr(iBegin.TypeOf().MemberByName("operator++"));
341  if(!incr) {
342  //std::cerr << "no 'operator++' for " << iBegin.TypeOf().Name() << std::endl;
343  return false;
344  }
345  Reflex::Member deref(iBegin.TypeOf().MemberByName("operator*"));
346  if(!deref) {
347  //std::cerr << "no 'operator*' for " << iBegin.TypeOf().Name() << std::endl;
348  return false;
349  }
350 
351  std::string indexIndent = iIndent+iIndentDelta;
352  int dummy=0;
353  //std::cerr << "going to loop using iterator " << iBegin.TypeOf().Name(Reflex::SCOPED) << std::endl;
354 
355  std::vector<void*> compareArgs = Reflex::Tools::MakeVector((iEnd.Address()));
356  std::vector<void*> incrArgs = Reflex::Tools::MakeVector(static_cast<void*>(&dummy));
357  bool compareResult;
358  Reflex::Object objCompareResult(Reflex::Type::ByTypeInfo(typeid(bool)), &compareResult);
359  Reflex::Object objIncr;
360  void* objIncrRefBuffer;
361  boost::shared_ptr<Reflex::Object> incrMemHolder = initReturnValue(incr, &objIncr, &objIncrRefBuffer);
362  for(;
363  compare.Invoke(iBegin, &objCompareResult, compareArgs), compareResult;
364  incr.Invoke(iBegin, &objIncr, incrArgs), ++size) {
365  //std::cerr << "going to print" << std::endl;
366  Reflex::Object iTemp;
367  void* derefRefBuffer;
368  boost::shared_ptr<Reflex::Object> derefMemHolder = initReturnValue(deref, &iTemp, &derefRefBuffer);
369  deref.Invoke(iBegin, &iTemp);
370  if(iTemp.TypeOf().IsReference()) {
371  iTemp = Reflex::Object(iTemp.TypeOf(), derefRefBuffer);
372  }
373  printObject(sStream, kObjectOpen, kObjectClose, iTemp, indexIndent, iIndentDelta);
374  //std::cerr << "printed" << std::endl;
375  }
376  } catch(std::exception const& iE) {
377  std::cerr << "while printing std container caught exception " << iE.what() << std::endl;
378  return false;
379  }
380  oStream << iPrefix << iIndent << kContainerOpen << size << "\">\n";
381  oStream << sStream.str();
382  oStream << iIndent << kContainerClose << std::endl;
383  oStream << iPostfix;
384  //std::cerr << "finished loop" << std::endl;
385  return true;
386  }
387 
388  bool printAsContainer(std::ostream& oStream,
389  std::string const& iPrefix, std::string const& iPostfix,
390  Reflex::Object const& iObject,
391  std::string const& iIndent,
392  std::string const& iIndentDelta) {
393  Reflex::Object sizeObj;
394  try {
395  size_t temp; //used to hold the memory for the return value
396  sizeObj = Reflex::Object(Reflex::Type::ByTypeInfo(typeid(size_t)), &temp);
397  iObject.Invoke("size", &sizeObj);
398 
399  if(sizeObj.TypeOf().TypeInfo() != typeid(size_t)) {
400  throw std::exception();
401  }
402  size_t size = *reinterpret_cast<size_t*>(sizeObj.Address());
403  Reflex::Member atMember;
404  atMember = iObject.TypeOf().MemberByName("at");
405  if(!atMember) {
406  throw std::exception();
407  }
408  std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
409  if(typeName.empty()){
410  typeName="{unknown}";
411  }
412 
413  oStream << iIndent << iPrefix << formatXML(typeName) << "\">\n"
414  << iIndent << kContainerOpen << size << "\">\n";
415  Reflex::Object contained;
416  std::string indexIndent=iIndent+iIndentDelta;
417  for(size_t index = 0; index != size; ++index) {
418  void* atRefBuffer;
419  boost::shared_ptr<Reflex::Object> atMemHolder = initReturnValue(atMember, &contained, &atRefBuffer);
420 
421  atMember.Invoke(iObject, &contained, Reflex::Tools::MakeVector(static_cast<void*>(&index)));
422  if(contained.TypeOf().IsReference()) {
423  contained = Reflex::Object(contained.TypeOf(), atRefBuffer);
424  }
425  //std::cout << "invoked 'at'" << std::endl;
426  try {
427  printObject(oStream, kObjectOpen, kObjectClose, contained, indexIndent, iIndentDelta);
428  }catch(std::exception& iEx) {
429  std::cout << iIndent << " <exception caught("
430  << iEx.what() << ")>\n";
431  }
432  }
433  oStream << iIndent << kContainerClose << std::endl;
434  oStream << iIndent << iPostfix << std::endl;
435  return true;
436  } catch(std::exception const& x){
437  //std::cerr << "failed to invoke 'at' because " << x.what() << std::endl;
438  try {
439  //oStream << iIndent << iPrefix << formatXML(typeName) << "\">\n";
440  std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
441  if(typeName.empty()){
442  typeName="{unknown}";
443  }
444  Reflex::Object iObjBegin;
445  void* beginRefBuffer;
446  Reflex::Member beginMember = iObject.TypeOf().MemberByName("begin");
447  boost::shared_ptr<Reflex::Object> beginMemHolder = initReturnValue(beginMember, &iObjBegin, &beginRefBuffer);
448  Reflex::Object iObjEnd;
449  void* endRefBuffer;
450  Reflex::Member endMember = iObject.TypeOf().MemberByName("end");
451  boost::shared_ptr<Reflex::Object> endMemHolder = initReturnValue(endMember, &iObjEnd, &endRefBuffer);
452 
453  beginMember.Invoke(iObject, &iObjBegin);
454  endMember.Invoke(iObject, &iObjEnd);
455  if(printContentsOfStdContainer(oStream,
456  iIndent+iPrefix+formatXML(typeName)+"\">\n",
457  iIndent+iPostfix,
458  iObjBegin,
459  iObjEnd,
460  iIndent,
461  iIndentDelta)) {
462  if(typeName.empty()){
463  typeName="{unknown}";
464  }
465  return true;
466  }
467  } catch(std::exception const& x) {
468  }
469  return false;
470  }
471  return false;
472  }
473 
474  void printObject(std::ostream& oStream,
475  Event const& iEvent,
476  std::string const& iClassName,
477  std::string const& iModuleLabel,
478  std::string const& iInstanceLabel,
479  std::string const& iIndent,
480  std::string const& iIndentDelta) {
481  try {
482  GenericHandle handle(iClassName);
483  }catch(edm::Exception const&) {
484  std::cout << iIndent << " \"" << iClassName << "\"" << " is an unknown type" << std::endl;
485  return;
486  }
487  GenericHandle handle(iClassName);
488  iEvent.getByLabel(iModuleLabel, iInstanceLabel, handle);
489  std::string className = formatXML(iClassName);
490  printObject(oStream, kObjectOpen, kObjectClose, *handle, iIndent, iIndentDelta);
491  }
492  }
493 
494  //
495  // static data member definitions
496  //
497 
498  //
499  // constructors and destructor
500  //
502  OutputModule(iPSet),
503  stream_(iPSet.getUntrackedParameter<std::string>("fileName").c_str()),
504  indentation_(" ") {
505  if(!stream_){
506  throw edm::Exception(errors::Configuration) << "failed to open file " << iPSet.getUntrackedParameter<std::string>("fileName");
507  }
508  stream_ << "<cmsdata>" << std::endl;
509  }
510 
511  // XMLOutputModule::XMLOutputModule(XMLOutputModule const& rhs)
512  // {
513  // // do actual copying here;
514  // }
515 
517  stream_ << "</cmsdata>" << std::endl;
518  }
519 
520  //
521  // assignment operators
522  //
523  // XMLOutputModule const& XMLOutputModule::operator=(XMLOutputModule const& rhs)
524  // {
525  // //An exception safe implementation is
526  // XMLOutputModule temp(rhs);
527  // swap(rhs);
528  //
529  // return *this;
530  // }
531 
532  //
533  // member functions
534  //
535  void
537  ModuleDescription desc;
538  Event event(const_cast<EventPrincipal&>(iEP), desc);
539  stream_ << "<event run=\"" << event.id().run() << "\" number=\"" << event.id().event() << "\" >\n";
540  std::string startIndent = indentation_;
541  for(Selections::const_iterator itBD = keptProducts()[InEvent].begin(), itBDEnd = keptProducts()[InEvent].end();
542  itBD != itBDEnd;
543  ++itBD) {
544  stream_ << "<product type=\"" << (*itBD)->friendlyClassName()
545  << "\" module=\"" << (*itBD)->moduleLabel()
546  << "\" productInstance=\"" << (*itBD)->productInstanceName() << "\">\n";
547  printObject(stream_,
548  event,
549  (*itBD)->className(),
550  (*itBD)->moduleLabel(),
551  (*itBD)->productInstanceName(),
552  startIndent,
553  indentation_);
554  stream_ << "</product>\n";
555  }
556  stream_ << "</event>" << std::endl;
557  }
558 
559  void
562  desc.setComment("Prints event information into a file in XML format.");
563  desc.addUntracked<std::string>("fileName");
565  descriptions.add("XMLoutput", desc);
566  }
567 }
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
virtual void writeRun(RunPrincipal const &)
SelectionsArray const & keptProducts() const
Definition: OutputModule.h:56
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
bool isFirst(HepMC::GenParticle *x)
virtual void write(EventPrincipal const &e)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
XMLOutputModule const & operator=(XMLOutputModule const &)
virtual void writeLuminosityBlock(LuminosityBlockPrincipal const &)
uint16_t size_type
Type returnType(const Member &mem)
Definition: returnType.cc:9
XMLOutputModule(ParameterSet const &)
void setComment(std::string const &value)
int iEvent
Definition: GenABIO.cc:243
T::value_type deref(T &iT)
static void doNotDelete(cms::Exception *)
Definition: ESHandle.cc:26
#define FILLNAME(_type_)
convert the object information to the correct type and print it
tuple result
Definition: query.py:137
tuple handle
Definition: patZpeak.py:22
#define end
Definition: vmac.h:38
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
static void fillDescriptions(ConfigurationDescriptions &descriptions)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
static void fillDescription(ParameterSetDescription &desc)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
#define begin
Definition: vmac.h:31
tuple cout
Definition: gather_cfg.py:121
x
Definition: VDTMath.h:216
long double T
tuple size
Write out results.
std::string className(const T &t)
Definition: ClassName.h:30