HepMC3 event record library
ReaderFactory.cc
Go to the documentation of this file.
1/**
2 * @file ReaderFactory.cc
3 * @brief Implementation of \b deduce_reader and related functions
4 *
5 */
6#include <memory>
7#include <string>
8#include <sys/stat.h>
9#include <string>
10
11#include "HepMC3/ReaderAscii.h"
13#include "HepMC3/ReaderHEPEVT.h"
14#include "HepMC3/ReaderLHEF.h"
15#include "HepMC3/ReaderPlugin.h"
16#include "HepMC3/ReaderFactory_fwd.h"
17
18namespace HepMC3 {
19/**
20 * @brief Class to hold generic information on the input
21 *
22 * Class to hold generic information on the input.
23 */
24
25/** @brief Constructor with filename*/
26InputInfo::InputInfo (const std::string &filename) {
27
28 if (filename.find("http://") != std::string::npos) m_remote = true;
29 if (filename.find("https://") != std::string::npos) m_remote = true;
30 if (filename.find("root://") != std::string::npos) m_remote = true;
31 if (filename.find("gsidcap://") != std::string::npos) m_remote = true;
32
33 if (!m_remote)
34 {
35 struct stat buffer {};
36#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
37 if (!(stat (filename.c_str(), &buffer) == 0))
38#else
39 if (!(stat (filename.c_str(), &buffer) == 0 && (S_ISFIFO(buffer.st_mode) || S_ISREG(buffer.st_mode) || S_ISLNK(buffer.st_mode))))
40#endif
41 {
42 HEPMC3_ERROR_LEVEL(100,"deduce_reader: file " << filename << " does not exist or is not a regular file/FIFO/link")
43 m_reader = std::shared_ptr<Reader> (nullptr);
44 m_error = true;
45 return;
46 }
47
48 std::shared_ptr< std::ifstream > file = std::make_shared< std::ifstream >(filename);
49 if (!file)
50 {
51 HEPMC3_ERROR_LEVEL(100,"deduce_reader could not open file for testing HepMC version: " << filename)
52 m_reader = std::shared_ptr<Reader> (nullptr);
53 m_error = true;
54 return;
55 }
56 if (!file->is_open()) {
57 HEPMC3_ERROR_LEVEL(100,"deduce_reader could not open file for testing HepMC version: " << filename)
58 file->close();
59 m_reader = std::shared_ptr<Reader> (nullptr);
60 m_error = true;
61 return;
62 }
63
64#if defined(__linux__) || defined(__darwin__)|| defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
65 m_pipe = S_ISFIFO(buffer.st_mode);
66 if (m_pipe) {
67 HEPMC3_DEBUG(10, "deduce_reader: the file " << filename << " is a pipe");
68 m_reader = deduce_reader(file);
69 m_init = true;
70 return;
71 }
72#endif
73
74 std::string line;
75 size_t nonempty = 0;
76 while (std::getline( *(file.get()), line) && nonempty < 3) {
77 if (line.empty()) continue;
78 nonempty++;
79 m_head.push_back(line);
80 }
81 file->close();
82 }
83 // Assure there are at least two elements in the vector:
84 m_head.emplace_back("");
85 m_head.emplace_back("");
86
87 classify();
88 m_init = true;
89}
90
91/** @brief The actuall classification routine */
92void InputInfo::classify() {
93
94 if ( strncmp(m_head.at(0).c_str(), "root", 4) == 0 ) m_root = true;
95 if ( strncmp(m_head.at(0).c_str(), "hmpb", 4) == 0 ) m_protobuf = true;
96 if ( strncmp(m_head.at(0).c_str(), "HepMC::Version", 14) == 0 && strncmp(m_head.at(1).c_str(), "HepMC::Asciiv3", 14) == 0 ) m_asciiv3 = true;
97 if ( strncmp(m_head.at(0).c_str(), "HepMC::Version", 14) == 0 && strncmp(m_head.at(1).c_str(), "HepMC::IO_GenEvent", 18) == 0 ) m_iogenevent = true;
98 if ( strncmp(m_head.at(0).c_str(), "<LesHouchesEvents", 17) == 0) m_lhef=true;
99
100 std::stringstream st_e(m_head.at(0));
101 char attr = ' ';
102 bool HEPEVT = true;
103 int m_i = 0;
104 int m_p = 0;
105 while (true)
106 {
107 if (!(st_e >> attr)) {
108 HEPEVT = false;
109 break;
110 }
111 if (attr == ' ') continue;
112 if (attr != 'E') {
113 HEPEVT = false;
114 break;
115 }
116 HEPEVT = static_cast<bool>(st_e >> m_i >> m_p);
117 break;
118 }
119 if (HEPEVT) m_hepevt=true;
120
121}
122
123
124/** @brief This function will deduce the type of input stream based on its content and will return appropriate Reader*/
125std::shared_ptr<Reader> deduce_reader(std::istream &stream)
126{
127 const size_t raw_header_size = 100;
128 std::string raw_header(raw_header_size + 1,'\0');
129 auto* fstream = dynamic_cast<std::ifstream*>(&stream);
130 if (fstream) {
131 fstream->read(&raw_header.front(), raw_header_size);
132 } else {
133 stream.read(&raw_header.front(), raw_header_size);
134 }
135 std::vector<std::string> head;
136 head.emplace_back("");
137 for ( size_t i = 0; i < raw_header_size; ++i) {
138 const char c = raw_header[i];
139 if (c == '\0') break;
140 if (c == '\n') {
141 if (head.back().length() != 0) {
142 head.emplace_back("");
143 }
144 } else {
145 head.back() += c;
146 }
147 }
148 head.emplace_back("");
149 if (fstream) {
150 for (size_t i = 0; i < raw_header_size; ++i) { static_cast<std::filebuf*>(fstream->rdbuf())->sungetc(); }
151 HEPMC3_DEBUG(10, "After sungetc() fstream->good()=" + std::to_string(fstream->good()));
152 } else {
153 for (size_t i = 0; i < raw_header_size; ++i) { stream.rdbuf()->sungetc(); }
154 HEPMC3_DEBUG(10, "After sungetc() stream.good()=" + std::to_string(stream.good()));
155 }
156 if (!stream)
157 {
158 HEPMC3_WARNING_LEVEL(100,"Input stream is too short or invalid.")
159 return {};
160 }
161 InputInfo input;
162 input.m_head = head;
163 input.classify();
164 if (input.m_protobuf) {
165 return std::make_shared<ReaderPlugin>(stream,libHepMC3protobufIO,std::string("newReaderprotobufstream"));
166 }
167 return input.native_reader(stream);
168}
169/** @brief This function will deduce the type of input stream based on its content and will return appropriate Reader*/
170std::shared_ptr<Reader> deduce_reader(std::shared_ptr<std::istream> stream)
171{
172 if (!stream)
173 {
174 HEPMC3_WARNING_LEVEL(100,"Input stream is too short or invalid.")
175 return {};
176 }
177 const size_t raw_header_size = 100;
178 std::string raw_header(raw_header_size + 1,'\0');
179 auto fstream = std::dynamic_pointer_cast<std::ifstream>(stream);
180 if (fstream) {
181 fstream->read(&raw_header.front(), raw_header_size);
182 } else {
183 stream->read(&raw_header.front(), raw_header_size);
184 }
185 std::vector<std::string> head;
186 head.emplace_back("");
187 for ( size_t i = 0; i < raw_header_size; ++i) {
188 const char c = raw_header[i];
189 if (c == '\0') break;
190 if (c == '\n') {
191 if (head.back().length() != 0) {
192 head.emplace_back("");
193 }
194 } else {
195 head.back() += c;
196 }
197 }
198 head.emplace_back("");
199 if (fstream) {
200 for (size_t i = 0; i < raw_header_size; ++i) { static_cast<std::filebuf*>(fstream->rdbuf())->sungetc(); }
201 HEPMC3_DEBUG(10, "After sungetc() fstream->good()="+ std::to_string(fstream->good()));
202 } else {
203 for (size_t i = 0; i < raw_header_size; ++i) { stream->rdbuf()->sungetc(); }
204 HEPMC3_DEBUG(10, "After sungetc() stream->good()="+ std::to_string(stream->good()));
205 }
206
207 if (!stream)
208 {
209 HEPMC3_WARNING_LEVEL(100,"Input stream is too short or invalid.")
210 return {};
211 }
212
213 InputInfo input;
214 input.m_head = head;
215 input.classify();
216 if (input.m_protobuf) {
217 return std::make_shared<ReaderPlugin>(stream,libHepMC3protobufIO,std::string("newReaderprotobufspstream"));
218 }
219 return input.native_reader(stream);
220}
221} //End namespace HepMC3
#define HEPMC3_WARNING_LEVEL(LEVEL, MESSAGE)
Macro for printing HEPMC3_HEPMC3_WARNING messages.
Definition Errors.h:34
#define HEPMC3_ERROR_LEVEL(LEVEL, MESSAGE)
Macro for printing error messages.
Definition Errors.h:27
#define HEPMC3_DEBUG(LEVEL, MESSAGE)
Macro for printing debug messages with appropriate debug level.
Definition Errors.h:41
Definition of class ReaderAsciiHepMC2.
Definition of class ReaderAscii.
Definition of class ReaderHEPEVT.
Definition of class ReaderLHEF.
Definition of class ReaderPlugin.
Base class for all I/O readers.
Definition Reader.h:25
HepMC3 main namespace.
std::shared_ptr< Reader > deduce_reader(const std::string &filename)
This function deduces the type of input file based on the name/URL and its content,...