CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/GeneratorInterface/LHEInterface/src/LHEReader.cc

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include <iostream>
00003 #include <sstream>
00004 #include <fstream>
00005 #include <cstring>
00006 #include <string>
00007 #include <vector>
00008 
00009 #include <boost/bind.hpp>
00010 
00011 #include <xercesc/sax2/Attributes.hpp>
00012 #include <xercesc/dom/DOM.hpp>
00013 
00014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00015 #include "FWCore/Utilities/interface/Exception.h"
00016 
00017 #include "GeneratorInterface/LHEInterface/interface/LHEReader.h"
00018 #include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h"
00019 #include "GeneratorInterface/LHEInterface/interface/LHEEvent.h"
00020 
00021 #include "Utilities/StorageFactory/interface/IOTypes.h"
00022 #include "Utilities/StorageFactory/interface/Storage.h"
00023 #include "Utilities/StorageFactory/interface/StorageFactory.h"
00024 
00025 #include "XMLUtils.h"
00026 
00027 XERCES_CPP_NAMESPACE_USE
00028 
00029 namespace lhef {
00030 
00031 class LHEReader::Source {
00032     public:
00033         Source() {}
00034         virtual ~Source() {}
00035         virtual XMLDocument *createReader(XMLDocument::Handler &handler) = 0;
00036 };
00037 
00038 class LHEReader::FileSource : public LHEReader::Source {
00039     public:
00040         FileSource(const std::string &fileURL)
00041         {
00042                 Storage *storage =
00043                         StorageFactory::get()->open(fileURL,
00044                                                     IOFlags::OpenRead);
00045 
00046                 if (!storage)
00047                         throw cms::Exception("FileOpenError")
00048                                 << "Could not open LHE file \""
00049                                 << fileURL << "\" for reading"
00050                                 << std::endl;
00051 
00052                 fileStream.reset(new StorageWrap(storage));
00053         }
00054 
00055         ~FileSource() {}
00056 
00057         XMLDocument *createReader(XMLDocument::Handler &handler)
00058         { return new XMLDocument(fileStream, handler); }
00059 
00060     private:
00061         std::auto_ptr<StorageWrap>      fileStream;
00062 };
00063 
00064 class LHEReader::XMLHandler : public XMLDocument::Handler {
00065     public:
00066         XMLHandler() :
00067                 impl(0), gotObject(kNone), mode(kNone),
00068                 xmlHeader(0), headerOk(false) {}
00069         ~XMLHandler()
00070         { if (xmlHeader) xmlHeader->release(); }
00071 
00072         enum Object {
00073                 kNone = 0,
00074                 kHeader,
00075                 kInit,
00076                 kComment,
00077                 kEvent
00078         };
00079 
00080         void reset() { headerOk = false; }
00081 
00082     protected:
00083         void startElement(const XMLCh *const uri,
00084                           const XMLCh *const localname,
00085                           const XMLCh *const qname,
00086                           const Attributes &attributes);
00087 
00088         void endElement(const XMLCh *const uri,
00089                         const XMLCh *const localname,
00090                         const XMLCh *const qname);
00091 
00092         void characters(const XMLCh *const data, const unsigned int length);
00093         void comment(const XMLCh *const data, const unsigned int length);
00094 
00095     private:
00096         friend class LHEReader;
00097 
00098         DOMImplementation               *impl;
00099         std::string                     buffer;
00100         Object                          gotObject;
00101         Object                          mode;
00102         DOMDocument                     *xmlHeader;
00103         std::vector<DOMElement*>        xmlNodes;
00104         bool                            headerOk;
00105         std::vector<LHERunInfo::Header> headers;
00106 };
00107 
00108 static void attributesToDom(DOMElement *dom, const Attributes &attributes)
00109 {
00110         for(unsigned int i = 0; i < attributes.getLength(); i++) {
00111                 const XMLCh *name = attributes.getQName(i);
00112                 const XMLCh *value = attributes.getValue(i);
00113 
00114                 dom->setAttribute(name, value);
00115         }
00116 }
00117 
00118 static void fillHeader(LHERunInfo::Header &header, const char *data,
00119                        int len = -1)
00120 {
00121         const char *end = len >= 0 ? (data + len) : 0;
00122         while(*data && (!end || data < end)) {
00123                 std::size_t len = std::strcspn(data, "\r\n");
00124                 if (end && data + len > end)
00125                         len = end - data;
00126                 if (data[len] == '\r' && data[len + 1] == '\n')
00127                         len += 2;
00128                 else if (data[len])
00129                         len++;
00130                 header.addLine(std::string(data, len));
00131                 data += len;
00132         }
00133 }
00134 
00135 void LHEReader::XMLHandler::startElement(const XMLCh *const uri,
00136                                          const XMLCh *const localname,
00137                                          const XMLCh *const qname,
00138                                          const Attributes &attributes)
00139 {
00140         std::string name((const char*)XMLSimpleStr(qname));
00141 
00142         if (!headerOk) {
00143                 if (name != "LesHouchesEvents")
00144                         throw cms::Exception("InvalidFormat")
00145                                 << "LHE file has invalid header" << std::endl;
00146                 headerOk = true;
00147                 return;
00148         }
00149 
00150         if (mode == kHeader) {
00151                 DOMElement *elem = xmlHeader->createElement(qname);
00152                 attributesToDom(elem, attributes);
00153                 xmlNodes.back()->appendChild(elem);
00154                 xmlNodes.push_back(elem);
00155                 return;
00156         } else if (mode != kNone)
00157                 throw cms::Exception("InvalidFormat")
00158                         << "LHE file has invalid format" << std::endl;
00159 
00160         if (name == "header") {
00161                 if (!impl)
00162                         impl = DOMImplementationRegistry::getDOMImplementation(
00163                                                         XMLUniStr("Core"));
00164                 xmlHeader = impl->createDocument(0, qname, 0);
00165                 xmlNodes.resize(1);
00166                 xmlNodes[0] = xmlHeader->getDocumentElement();
00167                 mode = kHeader;
00168         } if (name == "init")
00169                 mode = kInit;
00170         else if (name == "event")
00171                 mode = kEvent;
00172 
00173         if (mode == kNone)
00174                 throw cms::Exception("InvalidFormat")
00175                         << "LHE file has invalid format" << std::endl;
00176 
00177         buffer.clear();
00178 }
00179 
00180 void LHEReader::XMLHandler::endElement(const XMLCh *const uri,
00181                                        const XMLCh *const localname,
00182                                        const XMLCh *const qname)
00183 {
00184         if (mode) {
00185                 if (mode == kHeader && xmlNodes.size() > 1) {
00186                         xmlNodes.resize(xmlNodes.size() - 1);
00187                         return;
00188                 } else if (mode == kHeader) {
00189                         std::auto_ptr<DOMWriter> writer(
00190                                 static_cast<DOMImplementationLS*>(
00191                                                 impl)->createDOMWriter());
00192                         writer->setEncoding(XMLUniStr("UTF-8"));
00193 
00194                         for(DOMNode *node = xmlNodes[0]->getFirstChild();
00195                             node; node = node->getNextSibling()) {
00196                                 XMLSimpleStr buffer(
00197                                         writer->writeToString(*node));
00198 
00199                                 std::string type;
00200                                 const char *p, *q;
00201                                 DOMElement *elem;
00202 
00203                                 switch(node->getNodeType()) {
00204                                     case DOMNode::ELEMENT_NODE:
00205                                         elem = static_cast<DOMElement*>(node);
00206                                         type = (const char*)XMLSimpleStr(
00207                                                         elem->getTagName());
00208                                         p = std::strchr((const char*)buffer,
00209                                                         '>') + 1;
00210                                         q = std::strrchr(p, '<');
00211                                         break;
00212                                     case DOMNode::COMMENT_NODE:
00213                                         type = "";
00214                                         p = buffer + 4;
00215                                         q = buffer + strlen(buffer) - 3;
00216                                         break;
00217                                     default:
00218                                         type = "<>";
00219                                         p = buffer +
00220                                             std::strspn(buffer, " \t\r\n");
00221                                         if (!*p)
00222                                                 continue;
00223                                         q = p + strlen(p);
00224                                 }
00225 
00226                                 LHERunInfo::Header header(type);
00227                                 fillHeader(header, p, q - p);
00228                                 headers.push_back(header);
00229                         }
00230 
00231                         xmlHeader->release();
00232                         xmlHeader = 0;
00233                 }
00234 
00235                 if (gotObject != kNone)
00236                         throw cms::Exception("InvalidState")
00237                                 << "Unexpected pileup in"
00238                                     " LHEReader::XMLHandler::endElement"
00239                                 << std::endl;
00240 
00241                 gotObject = mode;
00242                 mode = kNone;
00243         }
00244 }
00245 
00246 void LHEReader::XMLHandler::characters(const XMLCh *const data_,
00247                                        const unsigned int length)
00248 {
00249         if (mode == kHeader) {
00250                 DOMText *text = xmlHeader->createTextNode(data_);
00251                 xmlNodes.back()->appendChild(text);
00252                 return;
00253         }
00254 
00255         if (XMLSimpleStr::isAllSpaces(data_, length))
00256                 return;
00257 
00258         unsigned int offset = 0;
00259         while(offset < length && XMLSimpleStr::isSpace(data_[offset]))
00260                 offset++;
00261 
00262         XMLSimpleStr data(data_ + offset);
00263 
00264         if (mode == kNone)
00265                 throw cms::Exception("InvalidFormat")
00266                         << "LHE file has invalid format" << std::endl;
00267 
00268         buffer.append(data);
00269 }
00270 
00271 void LHEReader::XMLHandler::comment(const XMLCh *const data_,
00272                                     const unsigned int length)
00273 {
00274         if (mode == kHeader) {
00275                 DOMComment *comment = xmlHeader->createComment(data_);
00276                 xmlNodes.back()->appendChild(comment);
00277                 return;
00278         }
00279 
00280         XMLSimpleStr data(data_);
00281 
00282         LHERunInfo::Header header;
00283         fillHeader(header, data);
00284         headers.push_back(header);
00285 }
00286 
00287 LHEReader::LHEReader(const edm::ParameterSet &params) :
00288         fileURLs(params.getUntrackedParameter< std::vector<std::string> >("fileNames")),
00289         firstEvent(params.getUntrackedParameter<unsigned int>("skipEvents", 0)),
00290         maxEvents(params.getUntrackedParameter<int>("limitEvents", -1)),
00291         curIndex(0), handler(new XMLHandler())
00292 {
00293 }
00294 
00295 LHEReader::LHEReader(const std::vector<std::string> &fileNames,
00296                      unsigned int firstEvent) :
00297         fileURLs(fileNames), firstEvent(firstEvent), maxEvents(-1),
00298         curIndex(0), handler(new XMLHandler())
00299 {
00300 }
00301 
00302 LHEReader::~LHEReader()
00303 {
00304 }
00305 
00306 boost::shared_ptr<LHEEvent> LHEReader::next()
00307 {
00308         while(curDoc.get() || curIndex < fileURLs.size()) {
00309                 if (!curDoc.get()) {
00310                         curSource.reset(new FileSource(fileURLs[curIndex++]));
00311                         handler->reset();
00312                         curDoc.reset(curSource->createReader(*handler));
00313                         curRunInfo.reset();
00314                 }
00315 
00316                 XMLHandler::Object event = handler->gotObject;
00317                 handler->gotObject = XMLHandler::kNone;
00318 
00319                 std::istringstream data;
00320                 if (event != XMLHandler::kNone) {
00321                         data.str(handler->buffer);
00322                         handler->buffer.clear();
00323                 }
00324 
00325                 switch(event) {
00326                     case XMLHandler::kNone:
00327                         if (!curDoc->parse())
00328                                 curDoc.reset();
00329                         break;
00330 
00331                     case XMLHandler::kHeader:
00332                         break;
00333 
00334                     case XMLHandler::kInit:
00335                         curRunInfo.reset(new LHERunInfo(data));
00336                         
00337                         std::for_each(handler->headers.begin(),
00338                                       handler->headers.end(),
00339                                       boost::bind(&LHERunInfo::addHeader,
00340                                                   curRunInfo.get(), _1));
00341                         handler->headers.clear();
00342                         break;
00343 
00344                     case XMLHandler::kComment:
00345                         break;
00346 
00347                     case XMLHandler::kEvent:
00348                         if (!curRunInfo.get())
00349                                 throw cms::Exception("InvalidState")
00350                                         << "Got LHE event without"
00351                                            " initialization." << std::endl;
00352 
00353                         if (firstEvent > 0) {
00354                                 firstEvent--;
00355                                 continue;
00356                         }
00357 
00358                         if (maxEvents == 0)
00359                                 return boost::shared_ptr<LHEEvent>();
00360                         else if (maxEvents > 0)
00361                                 maxEvents--;
00362 
00363                         return boost::shared_ptr<LHEEvent>(
00364                                         new LHEEvent(curRunInfo, data));
00365                 }
00366         }
00367 
00368         return boost::shared_ptr<LHEEvent>();
00369 }
00370 
00371 } // namespace lhef