HepMC3 event record library
ReaderFactory.h
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2021 The HepMC collaboration (see AUTHORS for details)
5//
6#ifndef HEPMC3_READERFACTORY_H
7#define HEPMC3_READERFACTORY_H
8
9#include <memory>
10#include <string>
11#include <sys/stat.h>
12#include <string.h>
13
14#include "HepMC3/ReaderAscii.h"
16#include "HepMC3/ReaderHEPEVT.h"
17#include "HepMC3/ReaderLHEF.h"
18#include "HepMC3/ReaderPlugin.h"
19#include "HepMC3/CompressedIO.h"
20
21namespace HepMC3 {
22
23
24std::shared_ptr<Reader> deduce_reader(std::istream &stream);
25
26std::shared_ptr<Reader> deduce_reader(std::shared_ptr<std::istream> stream);
27
28/**
29 * @brief This function deduces the type of input file based on the name/URL
30 * and its content, and will return an appropriate Reader object
31 *
32 * @todo Too big for inlining: move into a .cc implementation file?
33 * @todo Need a DEBUG verbosity flag
34 */
35std::shared_ptr<Reader> deduce_reader(const std::string &filename)
36{
37 std::string libHepMC3rootIO = "libHepMC3rootIO.so.3";
38#if defined(__darwin__) || defined(__APPLE__)
39 libHepMC3rootIO = "libHepMC3rootIO.dylib";
40#endif
41#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
42 libHepMC3rootIO = "HepMC3rootIO.dll";
43#endif
44 bool remote = false;
45 bool pipe = false;
46 if (filename.find("http://") != std::string::npos) remote = true;
47 if (filename.find("https://") != std::string::npos) remote = true;
48 if (filename.find("root://") != std::string::npos) remote = true;
49 if (filename.find("gsidcap://") != std::string::npos) remote = true;
50
51 std::vector<std::string> head;
52 if (!remote)
53 {
54 struct stat buffer;
55#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
56 if (!(stat (filename.c_str(), &buffer) == 0))
57#else
58 if (!(stat (filename.c_str(), &buffer) == 0 && (S_ISFIFO(buffer.st_mode) || S_ISREG(buffer.st_mode) || S_ISLNK(buffer.st_mode))))
59#endif
60 {
61 HEPMC3_ERROR("deduce_reader: file " << filename << " does not exist or is not a regular file/FIFO/link");
62 return std::shared_ptr<Reader> (nullptr);
63 }
64
65 std::ifstream* file= new std::ifstream(filename);
66 if (!file)
67 {
68 HEPMC3_ERROR("deduce_reader could not open file for testing HepMC version: " << filename);
69 return std::shared_ptr<Reader>(nullptr);
70 }
71 if (!file->is_open()) {
72 HEPMC3_ERROR("deduce_reader could not open file for testing HepMC version: " << filename);
73 file->close();
74 return std::shared_ptr<Reader>(nullptr);
75 }
76
77#if defined(__linux__) || defined(__darwin__)|| defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
78 pipe = S_ISFIFO(buffer.st_mode);
79 if (pipe) {
80 HEPMC3_DEBUG(0, "deduce_reader: the file " << filename << " is a pipe");
81 return deduce_reader(*file);
82 }
83#endif
84
85 std::string line;
86 size_t nonempty = 0;
87 while (std::getline(*file, line) && nonempty < 3) {
88 if (line.empty()) continue;
89 nonempty++;
90 head.push_back(line);
91 }
92 file->close();
93 delete file;
94 }
95 // Assure there are at least two elements in the vector:
96 head.push_back("");
97 head.push_back("");
98 HEPMC3_DEBUG(0, "deduce_reader: Attempt ReaderRootTree for " << filename);
99 if ( strncmp(head.at(0).c_str(), "root", 4) == 0 || remote)
100 return std::make_shared<ReaderPlugin>(filename,libHepMC3rootIO,std::string("newReaderRootTreefile"));
101 if (!remote)
102 {
103#if HEPMC3_USE_COMPRESSION
104 HEPMC3_DEBUG(0, "Attempt ReaderGZ for " << filename);
105 char buf[6];
106 snprintf(buf,6,"%s",head.at(0).c_str());
107 Compression det = detect_compression_type(buf, buf + 6);
108 if ( det != Compression::plaintext ) {
109 HEPMC3_DEBUG(0, "Detected supported compression " << std::to_string(det));
110 return deduce_reader(std::shared_ptr< std::istream >(new ifstream(filename.c_str())));
111 }
112#endif
113 HEPMC3_DEBUG(0, "Attempt ReaderAscii for " << filename);
114 if ( strncmp(head.at(0).c_str(),"HepMC::Version",14) == 0 && strncmp(head.at(1).c_str(), "HepMC::Asciiv3", 14) == 0 )
115 return std::shared_ptr<Reader>((Reader*) ( new ReaderAscii(filename)));
116 HEPMC3_DEBUG(0, "Attempt ReaderAsciiHepMC2 for " << filename);
117 if ( strncmp(head.at(0).c_str(),"HepMC::Version",14) == 0 && strncmp(head.at(1).c_str(), "HepMC::IO_GenEvent", 18) == 0 )
118 return std::shared_ptr<Reader>((Reader*) ( new ReaderAsciiHepMC2(filename)));
119 HEPMC3_DEBUG(0, "Attempt ReaderLHEF for " << filename);
120 if ( strncmp(head.at(0).c_str(), "<LesHouchesEvents", 17) == 0)
121 return std::shared_ptr<Reader>((Reader*) ( new ReaderLHEF(filename)));
122 HEPMC3_DEBUG(0, "Attempt ReaderHEPEVT for " << filename);
123 std::stringstream st_e(head.at(0).c_str());
124 char attr = ' ';
125 bool HEPEVT = true;
126 int m_i,m_p;
127 while (true)
128 {
129 if (!(st_e >> attr)) {
130 HEPEVT=false;
131 break;
132 }
133 if (attr == ' ') continue;
134 if (attr != 'E') {
135 HEPEVT = false;
136 break;
137 }
138 HEPEVT=static_cast<bool>(st_e >> m_i >> m_p);
139 break;
140 }
141 if (HEPEVT) return std::shared_ptr<Reader>((Reader*) ( new ReaderHEPEVT(filename)));
142 }
143 HEPMC3_DEBUG(0, "deduce_reader: all attempts failed for " << filename);
144 return std::shared_ptr<Reader>(nullptr);
145}
146
147
148/** @brief This function will deduce the type of input stream based on its content and will return appropriate Reader*/
149std::shared_ptr<Reader> deduce_reader(std::istream &stream)
150{
151 std::vector<std::string> head;
152 head.push_back("");
153 size_t back = 0;
154 size_t backnonempty = 0;
155 while ( (back < 200 && backnonempty < 100) && stream) {
156 char c = stream.get();
157 back++;
158 if (c == '\n') {
159 if (head.back().length() != 0) head.push_back("");
160 } else {
161 head.back() += c;
162 backnonempty++;
163 }
164 }
165 if (!stream)
166 {
167 HEPMC3_WARNING("Input stream is too short or invalid.");
168 return std::shared_ptr<Reader>(nullptr);
169 }
170
171 for (size_t i = 0; i < back; i++) stream.unget();
172
173 if ( strncmp(head.at(0).c_str(), "HepMC::Version", 14) == 0 && strncmp(head.at(1).c_str(), "HepMC::Asciiv3", 14) == 0 )
174 {
175 HEPMC3_DEBUG(0, "Attempt ReaderAscii");
176 return std::shared_ptr<Reader>((Reader*) ( new ReaderAscii(stream)));
177 }
178
179 if ( strncmp(head.at(0).c_str(), "HepMC::Version", 14) == 0 && strncmp(head.at(1).c_str(), "HepMC::IO_GenEvent", 18) == 0 )
180 {
181 HEPMC3_DEBUG(0, "Attempt ReaderAsciiHepMC2");
182 return std::shared_ptr<Reader>((Reader*) ( new ReaderAsciiHepMC2(stream)));
183 }
184
185 if ( strncmp(head.at(0).c_str(), "<LesHouchesEvents", 17) == 0)
186 {
187 HEPMC3_DEBUG(0, "Attempt ReaderLHEF");
188 return std::shared_ptr<Reader>((Reader*) ( new ReaderLHEF(stream)));
189 }
190 HEPMC3_DEBUG(0, "Attempt ReaderHEPEVT");
191 std::stringstream st_e(head.at(0).c_str());
192 char attr = ' ';
193 bool HEPEVT = true;
194 int m_i, m_p;
195 while (true)
196 {
197 if (!(st_e >> attr)) {
198 HEPEVT = false;
199 break;
200 }
201 if (attr == ' ') continue;
202 if (attr != 'E') {
203 HEPEVT = false;
204 break;
205 }
206 HEPEVT = static_cast<bool>(st_e >> m_i >> m_p);
207 break;
208 }
209 if (HEPEVT) return std::shared_ptr<Reader>((Reader*) ( new ReaderHEPEVT(stream)));
210 HEPMC3_DEBUG(0, "deduce_reader: all attempts failed");
211 return std::shared_ptr<Reader>(nullptr);
212}
213/** @brief This function will deduce the type of input stream based on its content and will return appropriate Reader*/
214std::shared_ptr<Reader> deduce_reader(std::shared_ptr<std::istream> stream)
215{
216 std::vector<std::string> head;
217 head.push_back("");
218 size_t back = 0;
219 size_t backnonempty = 0;
220 while ( (back < 200 && backnonempty < 100) && stream) {
221 char c = stream->get();
222 back++;
223 if (c == '\n') {
224 if (head.back().length() != 0) head.push_back("");
225 } else {
226 head.back() += c;
227 backnonempty++;
228 }
229 }
230 if (!stream)
231 {
232 HEPMC3_WARNING("Input stream is too short or invalid.");
233 return std::shared_ptr<Reader>(nullptr);
234 }
235
236 for (size_t i = 0; i < back; i++) stream->unget();
237
238 if ( strncmp(head.at(0).c_str(), "HepMC::Version", 14) == 0 && strncmp(head.at(1).c_str(), "HepMC::Asciiv3", 14) == 0 )
239 {
240 HEPMC3_DEBUG(0, "Attempt ReaderAscii");
241 return std::shared_ptr<Reader>((Reader*) ( new ReaderAscii(stream)));
242 }
243
244 if ( strncmp(head.at(0).c_str(), "HepMC::Version",14) == 0 && strncmp(head.at(1).c_str(), "HepMC::IO_GenEvent", 18) == 0 )
245 {
246 HEPMC3_DEBUG(0, "Attempt ReaderAsciiHepMC2");
247 return std::shared_ptr<Reader>((Reader*) ( new ReaderAsciiHepMC2(stream)));
248 }
249
250 if ( strncmp(head.at(0).c_str(), "<LesHouchesEvents", 17) == 0)
251 {
252 HEPMC3_DEBUG(0, "Attempt ReaderLHEF");
253 return std::shared_ptr<Reader>((Reader*) ( new ReaderLHEF(stream)));
254 }
255 HEPMC3_DEBUG(0, "Attempt ReaderHEPEVT");
256 std::stringstream st_e(head.at(0).c_str());
257 char attr = ' ';
258 bool HEPEVT = true;
259 int m_i,m_p;
260 while (true)
261 {
262 if (!(st_e >> attr)) {
263 HEPEVT = false;
264 break;
265 }
266 if (attr == ' ') continue;
267 if (attr != 'E') {
268 HEPEVT = false;
269 break;
270 }
271 HEPEVT = static_cast<bool>(st_e >> m_i >> m_p);
272 break;
273 }
274 if (HEPEVT) return std::shared_ptr<Reader>((Reader*) ( new ReaderHEPEVT(stream)));
275 HEPMC3_DEBUG(0, "deduce_reader: all attempts failed");
276 return std::shared_ptr<Reader>(nullptr);
277}
278}
279#endif
#define HEPMC3_WARNING(MESSAGE)
Macro for printing HEPMC3_HEPMC3_WARNING messages.
Definition: Errors.h:27
#define HEPMC3_DEBUG(LEVEL, MESSAGE)
Macro for printing debug messages with appropriate debug level.
Definition: Errors.h:33
#define HEPMC3_ERROR(MESSAGE)
Macro for printing error messages.
Definition: Errors.h:24
Definition of class ReaderAsciiHepMC2.
Definition of class ReaderAscii.
Definition of class ReaderHEPEVT.
Definition of class ReaderLHEF.
Definition of class ReaderPlugin.
Parser for HepMC2 I/O files.
GenEvent I/O parsing for structured text files.
Definition: ReaderAscii.h:29
GenEvent I/O parsing and serialization for HEPEVT files.
Definition: ReaderHEPEVT.h:33
GenEvent I/O parsing and serialization for LHEF files.
Definition: ReaderLHEF.h:35
Base class for all I/O readers.
Definition: Reader.h:25
HepMC3 main namespace.
std::shared_ptr< Reader > deduce_reader(std::istream &stream)
This function will deduce the type of input stream based on its content and will return appropriate R...
Fortran common block HEPEVT.