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  std::string typeName(objectToPrint.TypeOf().Name(Reflex::SCOPED));
254  if(typeName.empty()){
255  typeName="{unknown}";
256  }
257 
258  //see if we are dealing with a typedef
259  Reflex::Type objectType = objectToPrint.TypeOf();
260  bool wasTypedef = false;
261  while(objectType.IsTypedef()) {
262  objectType = objectType.ToType();
263  wasTypedef = true;
264  }
265  if(wasTypedef){
266  Reflex::Object tmp(objectType, objectToPrint.Address());
267  objectToPrint = tmp;
268  }
269  if(printAsBuiltin(oStream, iPrefix, iPostfix, objectToPrint, indent)) {
270  return;
271  }
272  if(printAsContainer(oStream, iPrefix, iPostfix, objectToPrint, indent, iIndentDelta)){
273  return;
274  }
275 
276  oStream << indent << iPrefix << formatXML(typeName) << "\">\n";
277  printDataMembers(oStream, objectToPrint, objectType, indent+iIndentDelta, iIndentDelta);
278  oStream << indent << iPostfix << "\n";
279 
280  }
281 
282  void printDataMembers(std::ostream& oStream,
283  Reflex::Object const& iObject,
284  Reflex::Type const& iType,
285  std::string const& iIndent,
286  std::string const& iIndentDelta) {
287  //print all the base class data members
288  for(Reflex::Base_Iterator itBase = iType.Base_Begin();
289  itBase != iType.Base_End();
290  ++itBase) {
291  printDataMembers(oStream, iObject.CastObject(itBase->ToType()), itBase->ToType(), iIndent, iIndentDelta);
292  }
293  static std::string const kPrefix("<datamember name=\"");
294  static std::string const ktype("\" type=\"");
295  static std::string const kPostfix("</datamember>");
296 
297  for(Reflex::Member_Iterator itMember = iType.DataMember_Begin();
298  itMember != iType.DataMember_End();
299  ++itMember){
300  //std::cout << " debug " << itMember->Name() << " " << itMember->TypeOf().Name() << "\n";
301  if (itMember->IsTransient()) {
302  continue;
303  }
304  try {
305  std::string prefix = kPrefix + itMember->Name() + ktype;
306  printObject(oStream,
307  prefix,
308  kPostfix,
309  itMember->Get(iObject),
310  iIndent,
311  iIndentDelta);
312  }catch(std::exception& iEx) {
313  std::cout << iIndent << itMember->Name() << " <exception caught("
314  << iEx.what() << ")>\n";
315  }
316  }
317  }
318 
319  bool printContentsOfStdContainer(std::ostream& oStream,
320  std::string const& iPrefix,
321  std::string const& iPostfix,
322  Reflex::Object iBegin,
323  Reflex::Object const& iEnd,
324  std::string const& iIndent,
325  std::string const& iIndentDelta){
326  size_t size = 0;
327  std::ostringstream sStream;
328  if(iBegin.TypeOf() != iEnd.TypeOf()) {
329  std::cerr << " begin (" << iBegin.TypeOf().Name(Reflex::SCOPED) << ") and end ("
330  << iEnd.TypeOf().Name(Reflex::SCOPED) << ") are not the same type" << std::endl;
331  throw std::exception();
332  }
333  try {
334  Reflex::Member compare(iBegin.TypeOf().MemberByName("operator!="));
335  if(!compare) {
336  //std::cerr << "no 'operator!=' for " << iBegin.TypeOf().Name() << std::endl;
337  return false;
338  }
339  Reflex::Member incr(iBegin.TypeOf().MemberByName("operator++"));
340  if(!incr) {
341  //std::cerr << "no 'operator++' for " << iBegin.TypeOf().Name() << std::endl;
342  return false;
343  }
344  Reflex::Member deref(iBegin.TypeOf().MemberByName("operator*"));
345  if(!deref) {
346  //std::cerr << "no 'operator*' for " << iBegin.TypeOf().Name() << std::endl;
347  return false;
348  }
349 
350  std::string indexIndent = iIndent+iIndentDelta;
351  int dummy=0;
352  //std::cerr << "going to loop using iterator " << iBegin.TypeOf().Name(Reflex::SCOPED) << std::endl;
353 
354  std::vector<void*> compareArgs = Reflex::Tools::MakeVector((iEnd.Address()));
355  std::vector<void*> incrArgs = Reflex::Tools::MakeVector(static_cast<void*>(&dummy));
356  bool compareResult;
357  Reflex::Object objCompareResult(Reflex::Type::ByTypeInfo(typeid(bool)), &compareResult);
358  Reflex::Object objIncr;
359  void* objIncrRefBuffer;
360  boost::shared_ptr<Reflex::Object> incrMemHolder = initReturnValue(incr, &objIncr, &objIncrRefBuffer);
361  for(;
362  compare.Invoke(iBegin, &objCompareResult, compareArgs), compareResult;
363  incr.Invoke(iBegin, &objIncr, incrArgs), ++size) {
364  //std::cerr << "going to print" << std::endl;
365  Reflex::Object iTemp;
366  void* derefRefBuffer;
367  boost::shared_ptr<Reflex::Object> derefMemHolder = initReturnValue(deref, &iTemp, &derefRefBuffer);
368  deref.Invoke(iBegin, &iTemp);
369  if(iTemp.TypeOf().IsReference()) {
370  iTemp = Reflex::Object(iTemp.TypeOf(), derefRefBuffer);
371  }
372  printObject(sStream, kObjectOpen, kObjectClose, iTemp, indexIndent, iIndentDelta);
373  //std::cerr << "printed" << std::endl;
374  }
375  } catch(std::exception const& iE) {
376  std::cerr << "while printing std container caught exception " << iE.what() << std::endl;
377  return false;
378  }
379  oStream << iPrefix << iIndent << kContainerOpen << size << "\">\n";
380  oStream << sStream.str();
381  oStream << iIndent << kContainerClose << std::endl;
382  oStream << iPostfix;
383  //std::cerr << "finished loop" << std::endl;
384  return true;
385  }
386 
387  bool printAsContainer(std::ostream& oStream,
388  std::string const& iPrefix, std::string const& iPostfix,
389  Reflex::Object const& iObject,
390  std::string const& iIndent,
391  std::string const& iIndentDelta) {
392  Reflex::Object sizeObj;
393  try {
394  size_t temp; //used to hold the memory for the return value
395  sizeObj = Reflex::Object(Reflex::Type::ByTypeInfo(typeid(size_t)), &temp);
396  iObject.Invoke("size", &sizeObj);
397 
398  if(sizeObj.TypeOf().TypeInfo() != typeid(size_t)) {
399  throw std::exception();
400  }
401  size_t size = *reinterpret_cast<size_t*>(sizeObj.Address());
402  Reflex::Member atMember;
403  atMember = iObject.TypeOf().MemberByName("at");
404  if(!atMember) {
405  throw std::exception();
406  }
407  std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
408  if(typeName.empty()){
409  typeName="{unknown}";
410  }
411 
412  oStream << iIndent << iPrefix << formatXML(typeName) << "\">\n"
413  << iIndent << kContainerOpen << size << "\">\n";
414  Reflex::Object contained;
415  std::string indexIndent=iIndent+iIndentDelta;
416  for(size_t index = 0; index != size; ++index) {
417  void* atRefBuffer;
418  boost::shared_ptr<Reflex::Object> atMemHolder = initReturnValue(atMember, &contained, &atRefBuffer);
419 
420  atMember.Invoke(iObject, &contained, Reflex::Tools::MakeVector(static_cast<void*>(&index)));
421  if(contained.TypeOf().IsReference()) {
422  contained = Reflex::Object(contained.TypeOf(), atRefBuffer);
423  }
424  //std::cout << "invoked 'at'" << std::endl;
425  try {
426  printObject(oStream, kObjectOpen, kObjectClose, contained, indexIndent, iIndentDelta);
427  }catch(std::exception& iEx) {
428  std::cout << iIndent << " <exception caught("
429  << iEx.what() << ")>\n";
430  }
431  }
432  oStream << iIndent << kContainerClose << std::endl;
433  oStream << iIndent << iPostfix << std::endl;
434  return true;
435  } catch(std::exception const& x){
436  //std::cerr << "failed to invoke 'at' because " << x.what() << std::endl;
437  try {
438  //oStream << iIndent << iPrefix << formatXML(typeName) << "\">\n";
439  std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
440  if(typeName.empty()){
441  typeName="{unknown}";
442  }
443  Reflex::Object iObjBegin;
444  void* beginRefBuffer;
445  Reflex::Member beginMember = iObject.TypeOf().MemberByName("begin");
446  boost::shared_ptr<Reflex::Object> beginMemHolder = initReturnValue(beginMember, &iObjBegin, &beginRefBuffer);
447  Reflex::Object iObjEnd;
448  void* endRefBuffer;
449  Reflex::Member endMember = iObject.TypeOf().MemberByName("end");
450  boost::shared_ptr<Reflex::Object> endMemHolder = initReturnValue(endMember, &iObjEnd, &endRefBuffer);
451 
452  beginMember.Invoke(iObject, &iObjBegin);
453  endMember.Invoke(iObject, &iObjEnd);
454  if(printContentsOfStdContainer(oStream,
455  iIndent+iPrefix+formatXML(typeName)+"\">\n",
456  iIndent+iPostfix,
457  iObjBegin,
458  iObjEnd,
459  iIndent,
460  iIndentDelta)) {
461  if(typeName.empty()){
462  typeName="{unknown}";
463  }
464  return true;
465  }
466  } catch(std::exception const& x) {
467  }
468  return false;
469  }
470  return false;
471  }
472 
473  void printObject(std::ostream& oStream,
474  Event const& iEvent,
475  std::string const& iClassName,
476  std::string const& iModuleLabel,
477  std::string const& iInstanceLabel,
478  std::string const& iIndent,
479  std::string const& iIndentDelta) {
480  try {
481  GenericHandle handle(iClassName);
482  }catch(edm::Exception const&) {
483  std::cout << iIndent << " \"" << iClassName << "\"" << " is an unknown type" << std::endl;
484  return;
485  }
486  GenericHandle handle(iClassName);
487  iEvent.getByLabel(iModuleLabel, iInstanceLabel, handle);
488  std::string className = formatXML(iClassName);
489  printObject(oStream, kObjectOpen, kObjectClose, *handle, iIndent, iIndentDelta);
490  }
491  }
492 
493  //
494  // static data member definitions
495  //
496 
497  //
498  // constructors and destructor
499  //
501  OutputModule(iPSet),
502  stream_(iPSet.getUntrackedParameter<std::string>("fileName").c_str()),
503  indentation_(" ") {
504  if(!stream_){
505  throw edm::Exception(errors::Configuration) << "failed to open file " << iPSet.getUntrackedParameter<std::string>("fileName");
506  }
507  stream_ << "<cmsdata>" << std::endl;
508  }
509 
510  // XMLOutputModule::XMLOutputModule(XMLOutputModule const& rhs)
511  // {
512  // // do actual copying here;
513  // }
514 
516  stream_ << "</cmsdata>" << std::endl;
517  }
518 
519  //
520  // assignment operators
521  //
522  // XMLOutputModule const& XMLOutputModule::operator=(XMLOutputModule const& rhs)
523  // {
524  // //An exception safe implementation is
525  // XMLOutputModule temp(rhs);
526  // swap(rhs);
527  //
528  // return *this;
529  // }
530 
531  //
532  // member functions
533  //
534  void
536  ModuleDescription desc;
537  Event event(const_cast<EventPrincipal&>(iEP), desc);
538  stream_ << "<event run=\"" << event.id().run() << "\" number=\"" << event.id().event() << "\" >\n";
539  std::string startIndent = indentation_;
540  for(Selections::const_iterator itBD = keptProducts()[InEvent].begin(), itBDEnd = keptProducts()[InEvent].end();
541  itBD != itBDEnd;
542  ++itBD) {
543  stream_ << "<product type=\"" << (*itBD)->friendlyClassName()
544  << "\" module=\"" << (*itBD)->moduleLabel()
545  << "\" productInstance=\"" << (*itBD)->productInstanceName() << "\">\n";
546  printObject(stream_,
547  event,
548  (*itBD)->className(),
549  (*itBD)->moduleLabel(),
550  (*itBD)->productInstanceName(),
551  startIndent,
552  indentation_);
553  stream_ << "</product>\n";
554  }
555  stream_ << "</event>" << std::endl;
556  }
557 
558  void
561  desc.setComment("Prints event information into a file in XML format.");
562  desc.addUntracked<std::string>("fileName");
564  descriptions.add("XMLoutput", desc);
565  }
566 }
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:57
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
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
tuple obj
Example code starts here #.
Definition: VarParsing.py:655
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:41
tuple size
Write out results.
std::string className(const T &t)
Definition: ClassName.h:30