Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:48:37

0001 #include <iostream>
0002 #include <memory>
0003 #include <string>
0004 #include <vector>
0005 #include <cstring>
0006 
0007 #include "Utilities/Xerces/interface/Xerces.h"
0008 #include <xercesc/util/XMLString.hpp>
0009 #include <xercesc/util/XMLUni.hpp>
0010 #include <xercesc/sax2/SAX2XMLReader.hpp>
0011 #include <xercesc/sax2/XMLReaderFactory.hpp>
0012 
0013 #include "FWCore/Utilities/interface/Exception.h"
0014 #include "FWCore/Utilities/interface/EDMException.h"
0015 
0016 #include "Utilities/StorageFactory/interface/IOTypes.h"
0017 #include "Utilities/StorageFactory/interface/Storage.h"
0018 
0019 #include "XMLUtils.h"
0020 
0021 XERCES_CPP_NAMESPACE_USE
0022 
0023 using namespace edm::storage;
0024 namespace lhef {
0025 
0026   StorageWrap::StorageWrap(std::unique_ptr<Storage> storage) : storage(std::move(storage)) {}
0027 
0028   StorageWrap::~StorageWrap() { storage->close(); }
0029 
0030   unsigned int XMLDocument::XercesPlatform::instances = 0;
0031 
0032   XMLDocument::XercesPlatform::XercesPlatform() {
0033     if (!instances++) {
0034       try {
0035         cms::concurrency::xercesInitialize();
0036       } catch (const XMLException &e) {
0037         throw cms::Exception("XMLDocument") << "cms::concurrency::xercesInitialize failed "
0038                                                "because of: "
0039                                             << XMLSimpleStr(e.getMessage()) << std::endl;
0040       }
0041     }
0042   }
0043 
0044   XMLDocument::XercesPlatform::~XercesPlatform() {
0045     if (!--instances)
0046       cms::concurrency::xercesTerminate();
0047   }
0048 
0049   XMLDocument::XMLDocument(std::unique_ptr<std::istream> &in, Handler &handler)
0050       : platform(new XercesPlatform()),
0051         source(new STLInputSource(in)),
0052         parser(XMLReaderFactory::createXMLReader()),
0053         done(false) {
0054     init(handler);
0055   }
0056 
0057   XMLDocument::XMLDocument(std::unique_ptr<StorageWrap> &in, Handler &handler)
0058       : platform(new XercesPlatform()),
0059         source(new StorageInputSource(in)),
0060         parser(XMLReaderFactory::createXMLReader()),
0061         done(false) {
0062     init(handler);
0063   }
0064 
0065   void XMLDocument::init(Handler &handler) {
0066     try {
0067       parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
0068       parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);
0069       parser->setFeature(XMLUni::fgXercesSchema, false);
0070       parser->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
0071 
0072       parser->setContentHandler(&handler);
0073       parser->setLexicalHandler(&handler);
0074       parser->setErrorHandler(&handler);
0075 
0076       if (!parser->parseFirst(*source, token))
0077         throw cms::Exception("XMLParseError") << "SAXParser::parseFirst failed" << std::endl;
0078     } catch (const XMLException &e) {
0079       throw cms::Exception("XMLDocument")
0080           << "cms::concurrency::xercesInitialize failed because of " << XMLSimpleStr(e.getMessage()) << std::endl;
0081     } catch (const SAXException &e) {
0082       throw cms::Exception("XMLDocument")
0083           << "XML parser reported: " << XMLSimpleStr(e.getMessage()) << "." << std::endl;
0084     }
0085   }
0086 
0087   XMLDocument::~XMLDocument() {}
0088 
0089   bool XMLDocument::parse() {
0090     try {
0091       if (done || parser->getErrorCount())
0092         return false;
0093 
0094       done = !parser->parseNext(token);
0095     } catch (const XMLException &e) {
0096       throw cms::Exception("XMLDocument")
0097           << "cms::concurrency::xercesInitialize failed because of " << XMLSimpleStr(e.getMessage()) << std::endl;
0098     } catch (const SAXException &e) {
0099       throw cms::Exception("XMLDocument")
0100           << "XML parser reported: " << XMLSimpleStr(e.getMessage()) << "." << std::endl;
0101     }
0102 
0103     return !done;
0104   }
0105 
0106   CBInputStream::Reader::~Reader() {}
0107 
0108   CBInputStream::CBInputStream(Reader &reader) : reader(reader) {}
0109 
0110   CBInputStream::~CBInputStream() {}
0111 
0112   XMLSize_t CBInputStream::readBytes(XMLByte *const buf, const XMLSize_t size) {
0113     char *rawBuf = reinterpret_cast<char *>(buf);
0114     unsigned int bytes = size * sizeof(XMLByte);
0115     unsigned int read = 0;
0116 
0117     while (read < bytes) {
0118       if (buffer.empty()) {
0119         buffer = reader.data();
0120         if (buffer.empty())
0121           break;
0122       }
0123 
0124       unsigned int len = buffer.length();
0125       unsigned int rem = bytes - read;
0126       if (rem < len) {
0127         std::memcpy(rawBuf + read, buffer.c_str(), rem);
0128         buffer.erase(0, rem);
0129         read += rem;
0130         break;
0131       }
0132 
0133       std::memcpy(rawBuf + read, buffer.c_str(), len);
0134       buffer.clear();
0135       read += len;
0136     }
0137 
0138     read /= sizeof(XMLByte);
0139     pos += read;
0140 
0141     return read;
0142   }
0143 
0144   STLInputStream::STLInputStream(std::istream &in) : in(in) {
0145     if (in.bad())
0146       throw cms::Exception("FileStreamError") << "I/O stream bad in STLInputStream::STLInputStream()" << std::endl;
0147   }
0148 
0149   STLInputStream::~STLInputStream() {}
0150 
0151   XMLSize_t STLInputStream::readBytes(XMLByte *const buf, const XMLSize_t size) {
0152     char *rawBuf = reinterpret_cast<char *>(buf);
0153     unsigned int bytes = size * sizeof(XMLByte);
0154     in.read(rawBuf, bytes);
0155     unsigned int readBytes = in.gcount();
0156 
0157     if (in.bad())
0158       throw cms::Exception("FileStreamError") << "I/O stream bad in STLInputStream::readBytes()" << std::endl;
0159 
0160     unsigned int read = (unsigned int)(readBytes / sizeof(XMLByte));
0161     unsigned int rest = (unsigned int)(readBytes % sizeof(XMLByte));
0162     for (unsigned int i = 1; i <= rest; i++)
0163       in.putback(rawBuf[readBytes - i]);
0164 
0165     pos += read;
0166     return read;
0167   }
0168 
0169   StorageInputStream::StorageInputStream(StorageWrap &in)
0170       : in(in), lstr(LZMA_STREAM_INIT), compression_(false), lasttotal_(0) {
0171     buffer_.reserve(bufferSize_);
0172     // Check the kind of file.
0173     char header[6];
0174     /*unsigned int s = */ in->read(header, 6);
0175     in->position(0, Storage::SET);
0176     // Let's use lzma to start with.
0177     if (header[1] == '7' && header[2] == 'z' && header[3] == 'X' && header[4] == 'Z') {
0178       compression_ = true;
0179       lstr = LZMA_STREAM_INIT;
0180       // We store the beginning of the outBuffer to make sure
0181       // we can always update previous results.
0182 
0183 #if LZMA_VERSION <= UINT32_C(49990030)
0184       int ret = lzma_auto_decoder(&lstr, NULL, NULL);
0185 #else
0186       int ret = lzma_auto_decoder(&lstr, -1, 0);
0187 #endif
0188 
0189       if (ret != LZMA_OK) {
0190         lzma_end(&lstr);
0191         throw cms::Exception("IO") << "Error while reading compressed LHE file";
0192       }
0193     }
0194   }
0195 
0196   StorageInputStream::~StorageInputStream() { lzma_end(&(lstr)); }
0197 
0198   XMLSize_t StorageInputStream::readBytes(XMLByte *const buf, const XMLSize_t size) {
0199     // Compression code is not able to handle sizeof(XMLByte) > 1.
0200     assert(sizeof(XMLByte) == sizeof(unsigned char));
0201 
0202     if (!(buffLoc_ < buffTotal_)) {
0203       int rd = in->read((void *)&buffer_[0], buffer_.capacity());
0204       // Storage layer is supposed to throw exceptions instead of returning errors; just-in-case
0205       if (rd < 0) {
0206         edm::Exception ex(edm::errors::FileReadError);
0207         ex << "Error while reading buffered LHE file";
0208         throw ex;
0209       }
0210       buffLoc_ = 0;
0211       buffTotal_ = rd;
0212       if (buffTotal_ == 0) {
0213         return 0;
0214       }
0215     }
0216     unsigned int dataRead;
0217     if (!compression_) {
0218       dataRead = std::min(buffTotal_ - buffLoc_, static_cast<unsigned int>(size));
0219       memcpy(buf, &buffer_[buffLoc_], dataRead);
0220       buffLoc_ += dataRead;
0221     } else {
0222       dataRead = buffTotal_ - buffLoc_;
0223       lstr.next_in = &buffer_[buffLoc_];
0224       lstr.avail_in = dataRead;
0225       lstr.next_out = buf;
0226       lstr.avail_out = size;
0227       int ret = lzma_code(&lstr, LZMA_RUN);
0228       if (ret != LZMA_OK && ret != LZMA_STREAM_END) { /* decompression error */
0229         lzma_end(&lstr);
0230         throw cms::Exception("IO") << "Error while reading compressed LHE file (error code " << ret << ")";
0231       }
0232       dataRead -= lstr.avail_in;
0233       buffLoc_ += dataRead;
0234       // Decoder was unable to make progress; reset stream and try again.
0235       // If this becomes problematic, we can make the buffer circular.
0236       if (!dataRead) {
0237         // NOTE: lstr.avail_in == buffTotal-buffLoc_
0238         in->position(-(IOOffset)(lstr.avail_in), Storage::CURRENT);
0239         buffLoc_ = 0;
0240         buffTotal_ = 0;
0241         return readBytes(buf, size);
0242       }
0243       dataRead = (size - lstr.avail_out);
0244     }
0245     return dataRead;
0246   }
0247 
0248 }  // namespace lhef