HepMC3 event record library
ReaderFactory.h
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2020 The HepMC collaboration (see AUTHORS for details)
5//
6#ifndef HEPMC3_READERFACTORY_H
7#define HEPMC3_READERFACTORY_H
8
11#include "HepMC3/ReaderHEPEVT.h"
12#include "HepMC3/ReaderLHEF.h"
13#include "HepMC3/ReaderPlugin.h"
14
15#include <memory>
16#include <string>
17#include <sys/stat.h>
18#include <string.h>
19
20namespace HepMC3 {
21
22
23std::shared_ptr<Reader> deduce_reader(std::istream &stream);
24
25
26/**
27 * @brief This function deduces the type of input file based on the name/URL
28 * and its content, and will return an appropriate Reader object
29 *
30 * @todo Too big for inlining: move into a .cc implementation file?
31 * @todo Need a DEBUG verbosity flag
32 */
33std::shared_ptr<Reader> deduce_reader(const std::string &filename)
34{
35 std::string libHepMC3rootIO="libHepMC3rootIO.so.3";
36 #if defined(__darwin__) || defined(__APPLE__)
37 libHepMC3rootIO="libHepMC3rootIO.dydl";
38 #endif
39 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
40 libHepMC3rootIO="HepMC3rootIO.dll";
41 #endif
42 bool remote=false;
43 bool pipe=false;
44 if (filename.find("http://")!=std::string::npos) remote=true;
45 if (filename.find("https://")!=std::string::npos) remote=true;
46 if (filename.find("root://")!=std::string::npos) remote=true;
47 if (filename.find("gsidcap://")!=std::string::npos) remote=true;
48
49 std::vector<std::string> head;
50 if (!remote)
51 {
52 struct stat buffer;
53 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
54 if (!(stat (filename.c_str(), &buffer)==0))
55 #else
56 if (!(stat (filename.c_str(), &buffer)==0 && (S_ISFIFO(buffer.st_mode)|| S_ISREG(buffer.st_mode) || S_ISLNK(buffer.st_mode))))
57 #endif
58 {
59 HEPMC3_ERROR("deduce_reader: file " << filename << " does not exist or is not a regular file/FIFO/link");
60 return std::shared_ptr<Reader> (nullptr);
61 }
62
63 std::ifstream* file= new std::ifstream(filename);
64 if (!file)
65 {
66 HEPMC3_ERROR("deduce_reader could not open file for testing HepMC version: " << filename);
67 return std::shared_ptr<Reader>(nullptr);
68 }
69 if (!file->is_open()) {
70 HEPMC3_ERROR("deduce_reader could not open file for testing HepMC version: " << filename);
71 file->close();
72 return std::shared_ptr<Reader>(nullptr);
73 }
74
75 #if defined(__linux__) || defined(__darwin__)|| defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
76 pipe = S_ISFIFO(buffer.st_mode);
77 if (pipe) {
78 HEPMC3_DEBUG(0, "deduce_reader: the file " << filename << " is a pipe");
79 return deduce_reader(*file);
80 }
81 #endif
82
83 std::string line;
84 size_t nonempty = 0;
85 while (std::getline(*file, line) && nonempty < 3) {
86 if (line.empty()) continue;
87 nonempty++;
88 head.push_back(line);
89 }
90 file->close();
91 delete file;
92 }
93 // Assure there are at least two elements in the vector:
94 head.push_back("");
95 head.push_back("");
96 HEPMC3_DEBUG(0, "deduce_reader: Attempt ReaderRootTree for " << filename);
97 if ( strncmp(head.at(0).c_str(),"root",4) == 0||remote)
98 return std::make_shared<ReaderPlugin>(filename,libHepMC3rootIO,std::string("newReaderRootTreefile"));
99 if (!remote)
100 {
101 HEPMC3_DEBUG(0, "Attempt ReaderAscii for " << filename);
102 if ( strncmp(head.at(0).c_str(),"HepMC::Version",14) == 0 && strncmp(head.at(1).c_str(),"HepMC::Asciiv3",14)==0 )
103 return std::shared_ptr<Reader>((Reader*) ( new ReaderAscii(filename)));
104 HEPMC3_DEBUG(0, "Attempt ReaderAsciiHepMC2 for " << filename);
105 if ( strncmp(head.at(0).c_str(),"HepMC::Version",14) == 0 && strncmp(head.at(1).c_str(),"HepMC::IO_GenEvent",18)==0 )
106 return std::shared_ptr<Reader>((Reader*) ( new ReaderAsciiHepMC2(filename)));
107 HEPMC3_DEBUG(0, "Attempt ReaderLHEF for " << filename);
108 if ( strncmp(head.at(0).c_str(),"<LesHouchesEvents",17) == 0)
109 return std::shared_ptr<Reader>((Reader*) ( new ReaderLHEF(filename)));
110 HEPMC3_DEBUG(0, "Attempt ReaderHEPEVT for " << filename);
111 std::stringstream st_e(head.at(0).c_str());
112 char attr=' ';
113 bool HEPEVT=true;
114 int m_i,m_p;
115 while (true)
116 {
117 if (!(st_e>>attr)) {
118 HEPEVT=false;
119 break;
120 }
121 if (attr==' ') continue;
122 if (attr!='E') {
123 HEPEVT=false;
124 break;
125 }
126 HEPEVT=static_cast<bool>(st_e>>m_i>>m_p);
127 break;
128 }
129 if (HEPEVT) return std::shared_ptr<Reader>((Reader*) ( new ReaderHEPEVT(filename)));
130 }
131 HEPMC3_DEBUG(0, "deduce_reader: all attempts failed for " << filename);
132 return std::shared_ptr<Reader>(nullptr);
133}
134
135
136/** @brief This function will deduce the type of input stream based on its content and will return appropriate Reader*/
137std::shared_ptr<Reader> deduce_reader(std::istream &stream)
138{
139 std::vector<std::string> head;
140 head.push_back("");
141 size_t back=0;
142 size_t backnonempty=0;
143 while ( (back < 200 && backnonempty < 100) && stream) {
144 char c = stream.get(); back++;
145 if (c=='\n') {
146 if (head.back().length()!=0) head.push_back("");
147 } else {
148 head.back()+=c; backnonempty++;
149 }
150 }
151 if (!stream)
152 {
153 HEPMC3_WARNING("Input stream is too short or invalid.");
154 return std::shared_ptr<Reader>(nullptr);
155 }
156
157 for (size_t i=0; i<back; i++) stream.unget();
158
159 if ( strncmp(head.at(0).c_str(),"HepMC::Version",14) == 0 && strncmp(head.at(1).c_str(),"HepMC::Asciiv3",14)==0 )
160 {
161 HEPMC3_DEBUG(0, "Attempt ReaderAscii");
162 return std::shared_ptr<Reader>((Reader*) ( new ReaderAscii(stream)));
163 }
164
165 if ( strncmp(head.at(0).c_str(),"HepMC::Version",14) == 0 && strncmp(head.at(1).c_str(),"HepMC::IO_GenEvent",18)==0 )
166 {
167 HEPMC3_DEBUG(0, "Attempt ReaderAsciiHepMC2");
168 return std::shared_ptr<Reader>((Reader*) ( new ReaderAsciiHepMC2(stream)));
169 }
170
171 if ( strncmp(head.at(0).c_str(),"<LesHouchesEvents",17) == 0)
172 {
173 HEPMC3_DEBUG(0, "Attempt ReaderLHEF");
174 return std::shared_ptr<Reader>((Reader*) ( new ReaderLHEF(stream)));
175 }
176 HEPMC3_DEBUG(0, "Attempt ReaderHEPEVT");
177 std::stringstream st_e(head.at(0).c_str());
178 char attr=' ';
179 bool HEPEVT=true;
180 int m_i,m_p;
181 while (true)
182 {
183 if (!(st_e>>attr)) {
184 HEPEVT=false;
185 break;
186 }
187 if (attr==' ') continue;
188 if (attr!='E') {
189 HEPEVT=false;
190 break;
191 }
192 HEPEVT=static_cast<bool>(st_e>>m_i>>m_p);
193 break;
194 }
195 if (HEPEVT) return std::shared_ptr<Reader>((Reader*) ( new ReaderHEPEVT(stream)));
196 HEPMC3_DEBUG(0, "deduce_reader: all attempts failed");
197 return std::shared_ptr<Reader>(nullptr);
198}
199}
200#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.